2012-01-11 10 views
7

मेरे पास एक सी ++ होमवर्क है। होमवर्क एक सी प्रोग्राम को सी ++ में बदलने के लिए कह रहा है।सी से सी ++ (सरल त्रुटि लेकिन कैंट फिक्स) को परिवर्तित करने में मदद की ज़रूरत है

आप एक सी ++ समारोह में निम्नलिखित सी समारोह में परिवर्तित करने का अनुरोध किया और फिर एक पूर्ण कार्यक्रम में एम्बेड और परीक्षण कर रहे हैं: नीचे प्रश्न है। नोट कि यह फ़ंक्शन पूर्णांक की बाइनरी फ़ाइल कॉपी करता है और पाठ फ़ाइल नहीं। कार्यक्रम को कमांड लाइन से तर्क (प्रतिलिपि करने के लिए फ़ाइल और फ़ाइल कॉपी करने के लिए) स्वीकार करना होगा।

/* ==================== cpyFile ===================== 

This function copies the contents of a binary file 
of integers to a second file. 
Pre fp1 is file pointer to open read file 
fp2 is file pointer to open write file 
Post file copied 
Return 1 is successful or zero if error 
*/ 
int cpyFile (FILE *fp1, FILE *fp2) 
{ 
    /* Local Definitions */ 
    int data; 

    /* Statements */ 
    fseek (fp1, 0, SEEK_END); 
    if (!ftell (fp1)) 
    { 
    printf ("\n\acpyFile Error : file empty\n\n"); 
    return 0; 
    } /* if open error */ 
    if (fseek (fp1, 0, SEEK_SET)) 
    return 0; 
    if (fseek (fp2, 0, SEEK_SET)) 
    return 0; 

    while (fread (&data, sizeof (int), 1, fp1)) 
    fwrite (&data, sizeof (int), 1, fp2); 
    return 1; 
} /* cpyFile */ 

मैं अपना सर्वश्रेष्ठ किया था और परिवर्तित करने में कामयाब रहे, लेकिन दुर्भाग्य से जब मैं यह उपयोग कर रहा हूँ, फ़ाइल है कि मैं नकल के बाद मिलता है खाली है। नीचे मेरी जवाब है:

#include <fstream> 
#include <cstdlib> 
#include <iostream> 
using namespace std; 
int main(int argc,char* argv[]) 
{ 
    if(argc!=3) 
    {cerr<<"invalid number of arguments. must be 3."<<endl;exit(1);} 

    fstream fp1(argv[1],ios::in); 
    if(!fp1)+{cerr<<argv[1]<<" could not be opened"<<endl;exit(1);} 

    fstream fp2(argv[2],ios::out); 
    if(!fp2)+{cerr<<"file could not be found."<<endl;exit(1);} 


    int data; 

    fp1.seekg (0,ios::end); 
    if (!fp1.tellg()) 
    { 
    cout<<"\n\acpyFile Error : file empty\n\n"; 
    return 0; 
    } /* if open error */ 
    if (fp1.seekg (0, ios::beg)) 
    return 0; 
    if (fp2.seekg (0, ios::beg)) 
    return 0; 

    while (fp1.read (reinterpret_cast<char*>(&data), sizeof (int))) 
    { 
    fp2.seekp(0); 
    fp2.write (reinterpret_cast<char*>(&data), sizeof (int)); 
    } 
    return 1; 
} 

मैंने किया था मेरी सबसे अच्छी और सब कुछ ठीक काम कर रहा है, सिवाय इसके कि जब मैं एक बाइनरी फ़ाइल, फ़ाइल है कि मैं पाने के रिक्त है कॉपी और मैं पता नहीं क्यों है। , fstream fp1(argv[1], ios::in | ios::binary);

+5

एक अच्छा प्रयास, मैं आपको एक सभ्य जाने के लिए सराहना करता हूं बल्कि धन्यवाद कि किसी और से यह आपके लिए ऐसा करने के लिए कहें। – dreamlax

+3

अपने होमवर्क पर ऐसा न करें, लेकिन भविष्य के संदर्भ के लिए: 'std :: ofstream (argv [2]) << std :: ifstream (argv [1]);' –

+0

आपके पास 'fp2.seekp क्यों है (0) * * लूप में? – celtschk

उत्तर

7

आप द्विआधारी मोड में फ़ाइल खोलने के लिए, के रूप में दूसरों

fstream fp1(argv[1], ios::in | ios::binary); // combine ios::in with ios::binary 

fstream fp2(argv[2], ios::out | ios::binary); // combine ios::out with ios::binary 

या ऐसा करके, ने कहा है कि आप और ofstream (बाहर फ़ाइल (केवल पढ़ने के लिए फ़ाइल धारा में) उन्हें ifstream कर सकते हैं की जरूरत है धारा, केवल लिखने के लिए) और क्योंकि ifstream तात्पर्य ios::in और ofstreamios::in और ios::out हटाने का तात्पर्य ios::out:

ifstream fp1(argv[1], ios::binary); 

ofstream fp2(argv[2], ios::binary); 

आप क्योंकि अगर तुम नहीं, फ़ाइल अनुवाद किया जाएगा ऐसा करने की जरूरत है जब आप \r\n या \r सिर्फ \n करने, आदि से लाइन अंत मोड़ जैसी चीजों के लिए से पढ़ सकते हैं या इसे करने के लिए लिखते हैं, जो गंदगी होगा अपने बाइनरी डेटा जो उन बाइट्स में हो सकता है।

यह:

if (fp1.seekg (0, ios::beg)) 
    return 0; 

if (fp2.seekg (0, ios::beg)) 
    return 0; 

हमेशा अपने कोड वापसी क्योंकि seekg वस्तु आप उस पर फोन रिटर्न देगा। यह इस संबंध में fseek के बराबर नहीं है क्योंकि fseek सफलता पर 0 देता है। तो आप कभी भी while पाश तक नहीं पहुंचते हैं।if बयान से बाहर उन लो इतना है कि यह इस तरह दिखता है:

fp1.seekg(0, ios::beg); 
fp2.seekg(0, ios::beg); 

या आप की जाँच करने के लिए है, तो आप इसके अलावा

if (!fp1.seekg (0, ios::beg)) // notice the added ! 
    return 0; 

if (!fp2.seekg (0, ios::beg)) // notice the added ! 
    return 0; 

ऐसा करने के लिए, चाहते हैं तो इस (अंदर while):

fp2.seekp(0); 

उस बिंदु को सेट कर रहा है जिसे आप फ़ाइल की शुरुआत में लिखने जा रहे हैं। तो आप फ़ाइल की शुरुआत में कुछ भी नहीं लिखेंगे। बस उस लाइन को पूरी तरह से हटा दें।

इसके अलावा, आपके पास लूप के अंदर return है जो इसे पहले पुनरावृत्ति पर वापस कर देता है। लूप के बाहर return 1; को ले जाएं ताकि आप लूप समाप्त होने के बाद ही लौट सकें। असामान्य ब्रेस शैली के कारण, गलत न हो।

+0

अद्भुत। मैंने जो किया वह मैंने किया और यह काम किया। धन्यवाद! – LebTech

0

बाइनरी फ़ाइलें विशेष रूप से बाइनरी मोड में खोला जा करने की जरूरत है, तो आप भी तो है कि यह करने के लिए एक ios :: द्विआधारी जोड़ना चाहिए जहां fstream fp1(argv[1],ios::in); है आप स्ट्रीम की शुरुआत में fp2 रिवाइंड करें, अनिवार्य रूप से जो आपने पहले ही fp2 पर लिखा है उसे छोड़ दें। अपने मुख्य पाश से fp2.seekp(0) को स्थानांतरित करने का प्रयास करें।

1

हर बार जब आप fp1 से एक नया डेटा ब्लॉक पढ़ें:

0

सी ++ कोड में आप प्रत्येक नंबर लिखने से पहले आउटपुट फ़ाइल की शुरुआत की मांग कर रहे हैं, और इसलिए आउटपुट फ़ाइल अधिकतम 2 बाइट लंबी होगी।

+1

यह * कम से कम * 2 बाइट लंबा होगा। 'Int' प्रकार तब तक कोई आकार हो सकता है जब तक कि यह 2 बाइट्स से अधिक या बराबर न हो। – dreamlax

+0

@dreamlax आप सही हैं। मुझे लगता है कि मेरे लिए सोने का समय है –

1

आपको कुछ समस्याएं हैं। मैं इस बिट फिक्सिंग से शुरू होगी:

if (fp1.seekg (0, ios::beg)) 
    return 0; 
if (fp2.seekg (0, ios::beg)) 
    return 0; 

seekg विधि istream इस पर कहा जाता है के लिए एक संदर्भ देता है, तो ऊपर इस के बराबर है:

fp1.seekg (0, ios::beg); 
if (fp1) // i.e., if fp1 is in a valid state (as opposed to e.g. end-of-file) 
    return 0; 
fp2.seekg (0, ios::beg); 
if (fp2) // i.e., if fp2 is in a valid state (as opposed to e.g. end-of-file) 
    return 0; 

जो स्पष्ट रूप से आप क्या नहीं है चाहते हैं।

अपने कोड को डीबग करने के लिए, आप यह पता लगाने के लिए std::cout << "Got to line " << __LINE__ << std::endl; जैसे बयान का उपयोग कर सकते हैं कि वास्तव में प्रोग्राम के कौन से हिस्से चल रहे हैं। इससे उपर्युक्त समस्या बहुत जल्दी मिल जाएगी।

+0

'__LINE__' के बारे में मत भूलना:' cout << "लाइन पर पहुंच गया" << __LINE__ << endl; ':) –

+0

@ सेठकार्नेगी: चोरी, धन्यवाद। ;-) मैं एक अलग प्रकार के संदेश का सुझाव देना शुरू कर दूंगा ('" ____ जबकि-लूप "प्राप्त हुआ), और फिर पोस्ट करने से पहले लाइन-आधारित दृष्टिकोण पर केवल आधा माइग्रेट किया गया। :-P – ruakh

+1

इस तरह डीबग बयान छोटे कार्यक्रमों के लिए उपयोगी हैं; बहुत से लोग हमेशा "डीबगर का उपयोग करना सीखते हैं" कहते हैं, लेकिन सच्चाई यह है कि इस चरण में हर कोई पहले से ही जानता है कि प्रिंट स्टेटमेंट का उपयोग कैसे करें ताकि समय के लिए ऐसा संभवतः अधिक उत्पादक हो। आखिरकार, डीबगर का उपयोग कैसे करना सीखना एक अमूल्य कौशल है, लेकिन कभी-कभी सेट अप ब्रेकपॉइंट्स, चर वैरिएबल इत्यादि की तुलना में 'प्रिंटफ' या' कोउट 'डालना आसान होता है। – dreamlax

संबंधित मुद्दे