Beim Testen von stream.good() oder !stream.eof() wird die letzte Zeile zweimal gelesen [duplicate]

Lesezeit: 3 Minuten

Beim Testen von streamgood oder streameof wird die letzte Zeile
Prabhu

Mögliches Duplikat:

Warum wird iostream::eof innerhalb einer Schleifenbedingung als falsch angesehen?

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 kann ich es beheben?

Etwas sehr ähnliches passiert mit:

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

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

    – Jerry Jeremia

    15. Mai 2014 um 21:51 Uhr


  • @JerryJeremiah Es ist das gleiche allgemeine Problem beim Versuch, den aktuellen Stream-Status zu überprüfen (z .good(), .eof(), .fail()), um den Erfolg zukünftiger Lesevorgänge vorherzusagen (z getline, >>). Dies funktioniert nicht, da der Stream-Status Ihnen mitteilt, ob ein vorheriger Lesevorgang fehlgeschlagen ist / das Ende der Eingabe erreicht hat; es sagt nichts über zukünftige Leseversuche aus.

    – Melpomen

    4. Mai 2019 um 10:09 Uhr

1646886609 91 Beim Testen von streamgood oder streameof wird die letzte Zeile
Fred Nurk

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 sich gerade bei EOF befindet, nicht unbedingt, dass die letzte Eingabeoperation fehlgeschlagen ist; Umgekehrt bedeutet das Nichtbefinden bei EOF nicht, dass die letzte Eingabe erfolgreich war.

Alle Stream-Statusfunktionen – fail, bad, eof und good – teilen Ihnen den aktuellen Status des Streams mit, anstatt den Erfolg einer zukünftigen Operation vorherzusagen. Überprüfen Sie den Stream selbst (was einer invertierten Fehlerprüfung entspricht) nach der gewünschten 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);

So lesen und verarbeiten Sie alle Zeilen:

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

Deutlich gesagt ist good() falsch benannt und entspricht nicht dem Testen des Streams selbst (was die obigen Beispiele tun).

  • Der Teil über die Überprüfung von eof ist korrekt, aber der Vorschlag, den Stream selbst zu überprüfen, ist etwas daneben. good() bedeutet, dass weder eofbit, badbit noch failbit gesetzt sind. fail() bedeutet, dass entweder Badbit oder Failbit gesetzt ist. Das Überprüfen des Streams (entweder mit der Konvertierung void* oder dem Operator !) ist genau dasselbe wie das Aufrufen der Member-Funktion fail().

    – KeithB

    1. Dezember 2010 um 15:19 Uhr

  • @KeithB: Sie werden vielleicht bemerken, dass ich Fail aus der Gruppe “sollte selten überprüft werden” gelassen habe. Ein fehlgeschlagener Stream ist wichtig, und das Überprüfen des Streams selbst ist fast immer bequemer als das entsprechende fail(). Vergleichen Sie getline(stream, line) mit !getline(stream, line).fail().

    – Fred Nurk

    1. Dezember 2010 um 15:46 Uhr


1646886610 983 Beim Testen von streamgood oder streameof wird die letzte Zeile
Fred Fu

Benutz einfach

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

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

  • Mir ist gerade erst aufgefallen, warum das funktioniert: Der letzte erfolgreiche Aufruf von getline() könnte einstellen eof, wenn die letzte Zeile am Ende keinen Zeilenumbruch hat. Die Scheitern Bit wird nur gesetzt, wenn getline() nicht erfolgreich aufgerufen wird. Also wir nicht möchte die Schleife bei beenden eofaber wir wollen es beenden bei Scheitern.

    – Aaron McDaid

    19. Mai 2011 um 23:27 Uhr


  • Eine weitere Sache … hatte ich getan while(f.peek() != EOF) { ... }. Ich denke das ist richtig? Aber ich werde Ihre Antwort in Zukunft verwenden.

    – Aaron McDaid

    19. Mai 2011 um 23:34 Uhr


Es hat die letzte Zeile nicht zweimal gelesen, aber da es beim Erreichen von eof nicht gelesen werden konnte, hat Ihre Zeichenfolge line den Wert, den sie zuvor hatte.

Das liegt daran, dass f nicht mehr “gut” ist, wenn es EOF gelesen hat, nicht wenn es dabei ist, es zu lesen.

986170cookie-checkBeim Testen von stream.good() oder !stream.eof() wird die letzte Zeile zweimal gelesen [duplicate]

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy