¿Cómo funciona Ifstream’s eof ()?

#include  #include  int main() { std::fstream inf( "ex.txt", std::ios::in ); while( !inf.eof() ) { std::cout << inf.get() <> c ) { std::cout << c << "\n"; } return 0; } 

Estoy realmente confundido acerca de la función eof() . Supongamos que el contenido de mi ex.txt fue:

 abc 

Siempre lee un carácter adicional y muestra -1 cuando lee usando eof() . Pero el inf >> c dio la salida correcta que era ‘abc’? ¿Alguien puede ayudarme a explicar esto?

-1 es la manera en que get dice que has llegado al final del archivo. Compárelo usando std::char_traits::eof() (o std::istream::traits_type::eof() ) – evite -1, es un número mágico. (Aunque el otro es un poco detallado, siempre puedes llamar a istream::eof )

El indicador EOF solo se establece una vez que una lectura intenta leer más allá del final del archivo . Si tengo un archivo de 3 bytes y solo leo 3 bytes, EOF es false , porque aún no he intentado leer más allá del final del archivo. Aunque esto parece confuso para los archivos, que normalmente conocen su tamaño, EOF no se conoce hasta que se intenta leer en algunos dispositivos, como las tomas de stream y los sockets de red.

El segundo ejemplo funciona como inf >> foo siempre devolverá inf , con el efecto secundario de intentar leer algo y almacenarlo en foo . inf , en un if o while , se evaluará como true si el archivo es “bueno”: sin errores, sin EOF. Por lo tanto, cuando falla una lectura, inf ula a false y su ciclo aborta correctamente. Sin embargo, tome este error común:

 while(!inf.eof()) // EOF is false here { inf >> x; // read fails, EOF becomes true, x is not set // use x // we use x, despite our read failing. } 

Sin embargo, esto:

 while(inf >> x) // Attempt read into x, return false if it fails { // will only be entered if read succeeded. } 

Que es lo que queremos

iostream no sabe que está al final del archivo hasta que intenta leer ese primer carácter más allá del final del archivo.

El código de muestra en cplusplus.com dice que debe hacerlo así: (Pero en realidad no debería hacerlo de esta manera)

  while (is.good()) // loop while extraction from file is possible { c = is.get(); // get character from file if (is.good()) cout << c; } 

Una mejor expresión es mover la lectura a la condición de bucle, así: (Puede hacer esto con todas las operaciones de lectura istream que devuelvan *this , incluido el operador >> )

  char c; while(is.get(c)) cout << c; 

El indicador EOF solo se establece después de que una operación de lectura intenta leer más allá del final del archivo. get() devuelve los traits::eof() constante simbólicos traits::eof() (que simplemente pasa a ser igual a -1) porque llegó al final del archivo y no pudo leer más datos, y solo en ese punto eof() será verdadero . Si desea verificar esta condición, puede hacer algo como lo siguiente:

 int ch; while ((ch = inf.get()) != EOF) { std::cout << static_cast(ch) << "\n"; } 

eof () comprueba el eofbit en el estado de la secuencia.

En cada operación de lectura, si la posición está al final de la secuencia y se deben leer más datos, eofbit se establece en verdadero. Por lo tanto, obtendrás un personaje extra antes de obtener eofbit = 1.

La forma correcta es verificar si se alcanzó el eof (o si la operación de lectura fue exitosa) después de la operación de lectura. Esto es lo que hace su segunda versión: realiza una operación de lectura y luego usa la referencia de objeto de secuencia resultante (que >> devuelve) como un valor booleano, lo que da como resultado la comprobación de fail ().