2010-12-01 2 views
16

Mögliche Duplizieren:
Why is iostream::eof inside a loop condition considered wrong?Testing stream.good() oder stream.eof() liest letzte Zeile zweimal

Ich habe das folgende Stück Code:

ifstream f("x.txt"); 
string line; 
while (f.good()) { 
    getline(f, line); 
    // Use line here. 
} 

Aber das liest die letzte Zeile zweimal. Warum passiert das und wie repariere ich es?

Etwas sehr Ähnliches geschieht mit:

ifstream f("x.txt"); 
string line; 
while (!f.eof()) { 
    getline(f, line); 
    // Use line here. 
} 
+1

Wie ist das ein Duplikat? Die andere Antwort erwähnt nicht einmal das Schleifen mit der Funktion good() als Test. –

Antwort

30

Sie wollen sehr, sehr selten schlecht, eof, und gut prüfen. Insbesondere für eof (da! Stream.eof() ein häufiger Fehler ist) bedeutet der Strom, der gerade bei EOF ist, nicht notwendigerweise, dass die letzte Eingabeoperation fehlgeschlagen ist; Umgekehrt heißt das nicht, dass die letzte Eingabe nicht erfolgreich war.

Alle Stream-Statusfunktionen - fail, bad, eof und good - informieren Sie über den aktuellen Status des Streams und nicht über den Erfolg einer zukünftigen Operation. Überprüfen Sie den Strom selbst (die mit einem invertierten Störungskontrolle äquivalent ist), nachdem die gewünschte Operation:

if (getline(stream, line)) { 
    use(line); 
} 
else { 
    handle_error(); 
} 

if (stream >> foo >> bar) { 
    use(foo, bar); 
} 
else { 
    handle_error(); 
} 

if (!(stream >> foo)) { // operator! is overloaded for streams 
    throw SomeException(); 
} 
use(foo); 

zu lesen und verarbeiten alle Linien:

for (std::string line; getline(stream, line);) { 
    process(line); 
} 

Pointedly, gut() misnamed ist und nicht entspricht dem Testen des Streams selbst (was die obigen Beispiele tun).

+0

Der Teil über die Überprüfung von eof ist korrekt, aber der Vorschlag, den Stream selbst zu überprüfen, ist ein bisschen aus. 'good()' bedeutet, dass weder eofbit noch badbit oder failbit gesetzt sind. 'fail()' bedeutet, dass entweder badbit oder failbit gesetzt ist. Das Überprüfen des Streams (entweder mit der void * -Verknüpfung oder dem Operator!) Entspricht genau dem Aufruf der Member-Funktion fail(). – KeithB

+2

@KeithB: Sie könnten bemerken, dass ich links aus der Gruppe "sollte selten überprüft werden". Ein fehlgeschlagener Stream ist wichtig, und das Überprüfen des Streams selbst ist fast immer praktischer als das Äquivalent fail(). Vergleichen Sie getline (stream, line) mit! Getline (stream, line) .fail(). –

8

Gerade

ifstream f("x.txt"); 
while (getline(f, line)) { 
    // whatever 
} 

verwenden Dies ist der idiomatische Weg, eine solche Schleife zu schreiben. Ich konnte den Fehler nicht reproduzieren (auf einem Linux-Rechner).

+0

Ich habe gerade erst begriffen, warum das funktioniert: Der letzte erfolgreiche Aufruf von getline() _might_ set ** eof **, wenn die letzte Zeile am Ende keinen Zeilenumbruch hat. Das ** fail ** -Bit wird nur gesetzt, wenn ein Aufruf von getline() fehlgeschlagen ist. Also wollen wir die Schleife nicht bei ** eof ** beenden, aber wir wollen sie bei ** fail ** beenden. –

+0

Noch eine Sache .. Ich hatte 'while (f.peek()! = EOF) {...}' gemacht. Ich denke, das ist richtig? Aber ich werde deine Antwort in Zukunft verwenden. –

1

Es hat die letzte Zeile nicht zweimal gelesen, aber weil es nicht gelesen hat, als es eof erreicht hat, hat Ihre Zeichenkette den Wert, den sie vorher hatte.

Das ist, weil f nicht mehr "gut" ist, wenn es EOF gelesen hat, nicht wenn es gerade gelesen wird.

Verwandte Themen