Cuando un principiante comienza a leer ifstreams, su instinto es leer el archivo usando un bucle que generalmente se ve así:
while (!ifstream.eof()
{
...
}
Sin embargo, cuando usé este código, noté que no se detenía hasta que había leído la última línea del archivo dos veces. Los programadores de C ++ notan que no es así como uno debería leer un archivo. En cambio, generalmente recomiendan que quien necesite leer un archivo use un bucle como este en su lugar:
while (ifstream >> someVar)
{
...
}
¿Por qué el primer fragmento de código siempre no funciona correctamente?
Respuestas:
El
while (!ifstream.eof())
bucle no funciona, porque las secuencias / archivos en C y C ++ no predicen cuándo ha llegado al final del archivo, sino que indican si ha intentado leer más allá del final del archivo.Si la última línea del archivo termina con un carácter de nueva línea (
\n
), la mayoría de las acciones de lectura dejarán de leer cuando se encuentren con ese carácter y no detecten que es el último carácter del archivo. En la siguiente acción de lectura, incluso puede ser que se hayan agregado más caracteres y que la lectura logre extraerlos.El bucle que usa el operador de extracción de flujo (
while (ifstream >> someVar)
) funciona porque el resultado del operador de extracción de flujo se evaluó como falso si no podía extraer un elemento del tipo correcto. Esto también sucede si no quedan caracteres para leer.fuente
Eso no es lo que está pasando. El
eofbit
no juega ningún papel en la conversión a un booleano (stream::operator bool
(ooperator void*
en c ++ anterior)). Solo losbadbit
yfailbit
están involucrados.Suponga que está leyendo un archivo que contiene números separados por espacios en blanco. Un bucle basado
cin.eof()
inevitablemente será incorrecto o estará lleno deif
pruebas. No estás leyendo hasta EOF. Estás leyendo números. Entonces, haga que su código exprese esa lógica:Esto funcionará si la última línea del archivo termina con
0 42\n
o solo0 42
(no hay una nueva línea al final de la última línea en el archivo). Si el archivo termina con0 42\n
, la última lectura correcta recuperará el valor 42 y leerá ese marcador final de final de línea. Tenga en cuenta que el marcador EOF aún no se ha leído. La funciónprocess_value
se llama con42
. La siguiente llamada al operador de extracción de flujo >> lee el EOF, y dado que no se ha extraído nada, se establecerán amboseofbit
yfailbit
.Supongamos, por otro lado, que el archivo termina con
0 42
(sin nueva línea al final de la última línea). La última lectura correcta recuperará el valor 42 que termina en el marcador EOF. Presumiblemente desea procesar ese 42. Es por esoeofbit
que no juega un papel en el operador de conversión booleana de flujo de entrada. En la próxima llamada al operador de extracción de flujo >>, la maquinaria subyacente rápidamente ve queeofbit
ya está configurado. Esto resulta rápidamente en la configuración defailbit
.Porque no deberías estar buscando EOF como condición de bucle. La condición del bucle debe expresar lo que está intentando hacer, que es (por ejemplo), extraer números de una secuencia.
fuente