utiliza sirve que para libreria funcion dev cerr biblioteca c++ iostream c++-faq

c++ - sirve - ¿Por qué se considera incorrecto iostream:: eof dentro de una condición de bucle?



iostream h en c (4)

Porque iostream::eof solo devolverá true después de leer el final de la transmisión. No indica que la próxima lectura será el final de la transmisión.

Considere esto (y suponga que la próxima lectura será al final de la transmisión):

while(!inStream.eof()){ int data; // yay, not end of stream yet, now read ... inStream >> data; // oh crap, now we read the end and *only* now the eof bit will be set (as well as the fail bit) // do stuff with (now uninitialized) data }

Contra esto:

int data; while(inStream >> data){ // when we land here, we can be sure that the read was successful. // if it wasn''t, the returned stream from operator>> would be converted to false // and the loop wouldn''t even be entered // do stuff with correctly initialized data (hopefully) }

Y en tu segunda pregunta: Porque

if(scanf("...",...)!=EOF)

es lo mismo que

if(!(inStream >> data).eof())

y no es lo mismo que

if(!inStream.eof()) inFile >> data

Acabo de encontrar un comentario en this respuesta que dice que el uso de iostream::eof en una condición de bucle es "casi seguro que está mal". Generalmente uso algo así como while(cin>>n) , que supongo que comprueba implícitamente la EOF, ¿por qué la comprobación de eof utilizando explícitamente iostream::eof incorrecta?

¿En qué se diferencia del uso de scanf("...",...)!=EOF en C (que a menudo utilizo sin problemas)?


Porque si los programadores no escriben while(stream >> n) , posiblemente escriban esto:

while(!stream.eof()) { stream >> n; //some work on n; }

Aquí el problema es que no puede realizar ningún some work on n sin verificar primero si la lectura de la secuencia tuvo éxito, ya que si no tuviera éxito, su some work on n produciría un resultado no deseado.

El punto principal es que, eofbit , badbit o failbit se establecen después de que se realiza un intento de lectura de la secuencia. Por lo tanto, si stream >> n falla, entonces eofbit , badbit o failbit se configuran de inmediato, por lo que es más idiomático si escribe while (stream >> n) , porque la stream objetos devueltos se convierte en false si hubo algún error en la lectura de El flujo y por lo tanto el bucle se detiene. Y se convierte en true si la lectura fue exitosa y el bucle continúa.


Línea inferior superior: con el manejo adecuado del espacio en blanco, lo siguiente es cómo se puede usar eof (e incluso, ser más confiable que fail() para la comprobación de errores):

while( !(in>>std::ws).eof() ) { int data; in >> data; if ( in.fail() ) /* handle with break or throw */; // now use data }

( Gracias a Tony D por la sugerencia de resaltar la respuesta. Vea su comentario a continuación para ver un ejemplo de por qué esto es más sólido ) .

El principal argumento en contra del uso de eof() parece que falta una sutileza importante sobre el papel del espacio en blanco. Mi propuesta es que verificar eof() explícitamente no solo no es " siempre incorrecto ", lo que parece ser una opinión primordial en este y otros hilos similares, sino que, con el manejo adecuado del espacio en blanco, proporciona un limpiador y un manejo de errores más confiable, y es la solución siempre correcta (aunque no necesariamente la más tersa).

Para resumir lo que se sugiere como la terminación "correcta" y el orden de lectura es lo siguiente:

int data; while(in >> data) { /* ... */ } // which is equivalent to while( !(in >> data).fail() ) { /* ... */ }

La falla debida al intento de lectura más allá de eof se toma como condición de terminación. Esto significa que no hay una manera fácil de distinguir entre una transmisión exitosa y otra que realmente falla por otras razones además de eof. Tome las siguientes corrientes:

  • 1 2 3 4 5<eof>
  • 1 2 a 3 4 5<eof>
  • a<eof>

while(in>>data) termina con un conjunto de failbit para las tres entradas. En el primero y el tercero, eofbit también se establece. Por lo tanto, más allá del bucle, se necesita una lógica extra muy fea para distinguir una entrada correcta (1ª) de una incorrecta (2ª y 3ª).

Considerando que, tome lo siguiente:

while( !in.eof() ) { int data; in >> data; if ( in.fail() ) /* handle with break or throw */; // now use data }

Aquí, in.fail() verifica que siempre que haya algo para leer, este sea el correcto. Su propósito no es un simple terminador de bucle while.

Hasta ahora todo bien, pero ¿qué sucede si hay un espacio final en la secuencia? ¿ eof() la principal preocupación contra eof() como terminador?

No necesitamos rendir nuestro manejo de errores; solo come el espacio en blanco:

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 omite cualquier espacio al final potencial (cero o más) en el flujo al configurar el eofbit , y no el failbit . Por lo tanto, in.fail() funciona como se espera, siempre que haya al menos un dato para leer. Si también se aceptan flujos en blanco, la forma correcta es:

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 }

Resumen: Un momento correctamente construido while(!eof) no solo es posible y no es incorrecto, sino que permite que los datos se localicen dentro del alcance, y proporciona una separación más clara de la verificación de errores de la actividad habitual. Dicho esto, while(!fail) es indudablemente un lenguaje más común y conciso, y puede preferirse en escenarios simples (datos únicos por tipo de lectura).


1 while (!read.fail()) { 2 cout << ch; 3 read.get(ch); 4 }

Si usa la línea 2 en 3 y la línea 3 en 2, se imprimirá ch dos veces. Así que cout antes de leer.