2010-12-01 10 views
16

Duplicar posibles:
Why is iostream::eof inside a loop condition considered wrong?stream.good Testing() o stream.eof() lee la última línea dos veces

tengo el siguiente fragmento de código:

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

Pero esta lee la última línea dos veces. ¿Por qué sucede esto y cómo lo soluciono?

Algo muy similar ocurre con:

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

¿Cómo es esto un duplicado? La otra respuesta ni siquiera menciona el bucle con la función good() como prueba. –

Respuesta

30

Es muy, muy raro que desee comprobar mal, eof y bueno. En particular para eof (como! Stream.eof() es un error común), la corriente que está actualmente en EOF no necesariamente significa que la última operación de entrada falló; por el contrario, no estar en EOF no significa que la última entrada fue exitosa.

Todas las funciones de estado de la secuencia (fail, bad, eof y good) le informan el estado actual de la transmisión en lugar de predecir el éxito de una operación futura. Comprobar el flujo en sí (que es equivalente a una comprobación invertida fallar) después de la operación deseada:

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); 

Para leer y procesar todas las líneas:

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

Pointedly, buena() es mal llamada y no es equivalente a probar la transmisión en sí (que hacen los ejemplos anteriores).

+0

La parte sobre la comprobación de eof es correcta, pero la sugerencia de verificar la transmisión en sí está un poco desajustada. 'bueno()' significa que ninguno de eofbit, badbit o failbit están configurados. 'fail()' significa que se ha configurado badbit o failbit. Verificar la transmisión (ya sea usando la conversación nula *, o el operador!) Es exactamente lo mismo que llamar a la función de miembro fail(). – KeithB

+2

@KeithB: Es posible que observe que me salió el error del grupo "rara vez se debe verificar". Una secuencia fallida es lo que es importante, y la comprobación de la transmisión en sí casi siempre es más conveniente que el error equivalente(). Compare getline (stream, line) con! Getline (stream, line) .fail(). –

8

sólo tiene que utilizar

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

Ésta es la forma idiomática para escribir un bucle de este tipo. No he podido reproducir el error (en una máquina Linux).

+0

Me acabo de dar cuenta de por qué funciona: la última llamada exitosa a getline() _might_ fijó ** eof **, si la última línea no tiene una nueva línea al final. El bit ** fail ** se establece solo cuando hay una llamada fallida a getline(). Por lo tanto, no queremos finalizar el ciclo en ** eof **, pero sí queremos finalizarlo en ** error **. –

+0

Una cosa más ... He estado haciendo 'while (f.peek()! = EOF) {...}'. Creo que esto es correcto? Pero usaré tu respuesta en el futuro. –

1

No se leyó la última línea dos veces sino porque no se pudo leer cuando llegó a eof, su línea de cadena tiene el valor que tenía anteriormente.

Esto se debe a que f ya no es "bueno" cuando ha leído EOF, no cuando está a punto de leerlo.