24. November 2012
Bottom-line top: Mit der richtigen Handhabung von white-space, das folgende ist, wie eof
verwendet werden kann (und sogar zuverlässiger sein als fail()
für die Fehlerprüfung):
while( !(in>>std::ws).eof() ) {
int data;
in >> data;
if ( in.fail() ) /* handle with break or throw */;
// now use data
}
(Dank Tony D für die Anregung zu markieren die Antwort. Siehe sein Kommentar unten für ein Beispiel, warum dies ist robuster.)
Das wichtigste argument gegen die Verwendung von eof()
scheint zu sein, fehlt eine wichtige Feinheit, über die Rolle der weißen Raum. Mein Vorschlag ist, dass die überprüfung eof()
explizit ist nicht nur nicht "immer falsch"- das scheint zu einem überwiegenden Meinung in diesen und ähnlichen SO threads --, aber mit der richtigen Handhabung von white-space, sorgt es für eine saubere und zuverlässige Fehlerbehandlung, und ist das immer die richtige Lösung (obwohl, nicht unbedingt die tersest).
Um zusammenzufassen, was wird vorgeschlagen, die als die "richtige" Kündigung und lese-Reihenfolge ist folgende:
int data;
while(in >> data) { /* ... */ }
// which is equivalent to
while( !(in >> data).fail() ) { /* ... */ }
Das scheitern aufgrund von lese-Versuch über eof als Abbruchbedingung. Dies bedeutet, dass es keine einfache Möglichkeit, zu unterscheiden zwischen einem erfolgreichen stream-und eine, die wirklich scheitert aus anderen Gründen als der eof. Nehmen Sie die folgenden Ströme:
1 2 3 4 5<eof>
1 2 a 3 4 5<eof>
a<eof>
while(in>>data)
endet mit einem set failbit
für alle drei geben. In der ersten und Dritten, eofbit
eingestellt. Also vorbei an den loop braucht man sehr hässlich zusätzliche Logik zu unterscheiden, dem richtigen input (1.) durch unsachgemäße lieben (2. und 3.).
In der Erwägung, dass, nehmen Sie die folgenden:
while( !in.eof() )
{
int data;
in >> data;
if ( in.fail() ) /* handle with break or throw */;
// now use data
}
Hier in.fail()
überprüft, ob, wie lange, wie es ist, etwas zu Lesen, es ist die richtige. Es ist Ziel ist nicht eine bloße while-loop-terminator.
So weit so gut, aber was passiert, wenn es Leerzeichen im stream -- was sich anhört wie die großen Bedenken gegen eof()
als terminator?
Wir brauchen nicht zu kapitulieren unsere Fehler-handling; einfach nur Essen, bis die white-space:
while( !in.eof() )
{
int data;
in >> data >> ws; // eat whitespace with std::ws
if ( in.fail() ) /* handle with break or throw */;
// now use data
}
std::ws
überspringt alle Potenzial (null oder mehr) Leerzeichen in den Strom während der Einstellung der eofbit
und nicht failbit
. Also, in.fail()
funktioniert wie erwartet, solange es mindestens einen Daten zu Lesen. Wenn alle-leer-streams sind auch in Ordnung, dann die richtige form ist:
while( !(in>>ws).eof() )
{
int data;
in >> data;
if ( in.fail() ) /* handle with break or throw */;
/* this will never fire if the eof is reached cleanly */
// now use data
}
Zusammenfassung: Ein richtig konstruiertes while(!eof)
ist nicht nur möglich und nicht falsch, sondern es erlaubt, Daten lokalisiert werden, die in Umfang, und liefert eine sauberere Trennung der Fehlerprüfung von business as usual. That being said, while(!fail)
ist unbestritten ein häufiger und knappe Sprache, und kann bevorzugt in einfacher (single-Daten-per-Lesen-Typ-Szenarien).