2008-08-22 12 views
104

निम्नलिखित सी ++ कोड एक ifstream वस्तु का उपयोग करता है एक पाठ फ़ाइल से पूर्णांकों को पढ़ने के लिए (जो प्रत्येक पंक्ति में एक संख्या है) जब तक यह EOF हिट को दोहराता है। यह अंतिम पंक्ति पर दो बार पूर्णांक क्यों पढ़ता है? इसे कैसे ठीक करें?EOF जब तक पाठ फ़ाइल से पढ़ना अंतिम पंक्ति

कोड:

#include <iostream> 
#include <fstream> 
using namespace std; 

int main() 
{ 
    ifstream iFile("input.txt"); // input.txt has integers, one per line 

    while (!iFile.eof()) 
    { 
     int x; 
     iFile >> x; 
     cerr << x << endl; 
    } 

    return 0; 
} 

input.txt:

10 
20 
30 

आउटपुट:

10 
20 
30 
30 

नोट: कोड स्निपेट को छोटा रखने के लिए मैंने सभी त्रुटि जांच कोड छोड़ दिए हैं। उपर्युक्त व्यवहार विंडोज (विजुअल सी ++), साइगविन (जीसीसी) और लिनक्स (जीसीसी) पर देखा जाता है।

उत्तर

109

बस घटनाओं की श्रृंखला का बारीकी से पालन करें।

  • ले लो 10
  • ले लो 20
  • ले लो 30
  • ले लो EOF

दूसरे करने के लिए पिछले यात्रा देखें। आपने 30 को पकड़ लिया, फिर ईओएफ की जांच के लिए आगे बढ़े। आप ईओएफ तक नहीं पहुंचे हैं क्योंकि ईओएफ मार्क अभी तक नहीं पढ़ा गया है ("द्विपक्षीय रूप से" बोल रहा है, इसका वैचारिक स्थान 30 लाइन के ठीक बाद है)। इसलिए आप अगले पुनरावृत्ति पर जाते हैं। एक्स पिछले पुनरावृत्ति से अभी भी 30 है। अब आप स्ट्रीम से पढ़ते हैं और आपको ईओएफ मिलता है। एक्स 30 बनी हुई है और आईओएस :: eofbit उठाया गया है। आप stderr x (जो 30 है, पिछले पुनरावृत्ति की तरह) के लिए आउटपुट। इसके बाद आप लूप स्थिति में ईओएफ की जांच करें, और इस बार आप लूप से बाहर हैं। वैसे

while (true) { 
    int x; 
    iFile >> x; 
    if(iFile.eof()) break; 
    cerr << x << endl; 
} 

, आपकी कोड में एक और बग है:

इस प्रयास करें। क्या आपने कभी इसे खाली फ़ाइल पर चलाने का प्रयास किया था? आपको जो व्यवहार मिलता है वह वही कारण है।

ifstream iFile("input.txt");  // input.txt has integers, one per line 
int x; 

while (iFile >> x) 
{ 
    cerr << x << endl; 
} 

सुनिश्चित नहीं हैं कि यह कैसे सुरक्षित है ...

+40

'जबकि (iFile >> x)' का उपयोग करें। यह पूर्णांक पढ़ता है और स्ट्रीम देता है। जब एक धारा का उपयोग बूल वैल्यू के रूप में किया जाता है तो यह देखने के लिए जांच करता है कि स्ट्रीम मान्य है या नहीं। मान्य मतलब है eof() और खराब() दोनों झूठे हैं। http://stackoverflow.com/questions/21647/c-reading-from-text-file-until-eof-repeats-last-line#21666 –

+3

समान भावना के रूप में टिप्पणी: 'जबकि (सत्य)' के बजाय, यह लिखने के लिए बेहतर लगता है 'file (ood.good)) ' – PHF

+1

यदि आप सुनिश्चित नहीं हैं कि फ़ाइल की त्रुटि या अंत तक फ़ाइल को कैसे पढ़ा जाए, तो इस आलेख को पढ़ें (बहुत अच्छी व्याख्या) https://gehrcke.de/2011/06/रीडिंग-फाइल-इन-सी-उपयोग-इस्टस्ट्रीम-डीलिंग-सही-बैडबिट-असफल-ईफिट-एंड-पेरर/ – stviper

29

मैं इस उदाहरण है, जो अब के लिए, जांच करते हैं कि आप जबकि ब्लॉक के अंदर जोड़ सकता है बाहर छोड़ देता है पसंद यह करने के लिए:

#include <iterator> 
#include <algorithm> 

// ... 

    copy(istream_iterator<int>(iFile), istream_iterator<int>(), 
     ostream_iterator<int>(cerr, "\n")); 
+0

क्या होगा यदि 0 मान्य मान है, जैसे एक्स == 0? – harryngh

+4

@harryngh अगर मैं सही ढंग से समझता हूं, 'iFile >> x' स्ट्रीम को वापस लौटाता है, न कि' x'। धारा को फिर से 'बूल' में परिवर्तित कर दिया जाता है, जो ईओएफ के लिए परीक्षण करता है। – wchargin

16

वहाँ एक वैकल्पिक दृष्टिकोण है:

5
मूल कोड के बहुत संशोधनों के बिना

, यह हो सकता है:

while (!iFile.eof()) 
{ 
    int x; 
    iFile >> x; 
    if (!iFile.eof()) break; 
    cerr << x << endl; 
} 

लेकिन मैं आम तौर पर उपरोक्त दो अन्य समाधान पसंद करता हूं।

5

ईओएफ पैटर्न को ईओएफ जांच प्रक्रिया 'बूटस्ट्रैप' के लिए एक प्रमुख पढ़ने की आवश्यकता है। ध्यान दें कि खाली फ़ाइल में प्रारंभिक रूप से पहले पढ़ने तक अपना ईओएफ सेट नहीं होगा। प्राइम रीड इस उदाहरण में ईओएफ को पकड़ लेगा और लूप को पूरी तरह से छोड़ देगा।

आपको यहां याद रखने की आवश्यकता है कि फ़ाइल के उपलब्ध डेटा को पिछले पढ़ने के पहले प्रयास तक आपको EOF नहीं मिलता है। डेटा की सटीक मात्रा को पढ़ना ईओएफ को ध्वजांकित नहीं करेगा।

मुझे यह इंगित करना चाहिए कि फ़ाइल खाली थी या नहीं, आपका दिया गया कोड मुद्रित होगा क्योंकि ईओएफ ने लूप में प्रवेश पर एक्स को सेट करने से रोक दिया होगा।

तो एक प्रमुख पढ़ने जोड़ सकते हैं और ले जाने के पाश के अंत करने के लिए पढ़ें:

int x; 

iFile >> x; // prime read here 
while (!iFile.eof()) { 
    cerr << x << endl; 
    iFile >> x; 
} 
2

अंतिम पंक्ति के अंत में, आप एक नई लाइन चरित्र है, जो >> ऑपरेटर द्वारा नहीं पढ़ा जाता है और यह फ़ाइल का अंत नहीं है। कृपया, एक प्रयोग करें और नई लाइन (फ़ाइल में कलाकार चरित्र) को हटाएं - आपको डुप्लिकेशन नहीं मिलेगा। एक लचीला कोड और अवांछित प्रभाव से बचने के लिए बस अन्य उपयोगकर्ताओं द्वारा दिए गए किसी भी समाधान को लागू करें।

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