c++ - salto - Lectura del archivo de texto hasta que EOF repite la última línea
manejo de archivos en c++ fstream (7)
Esta pregunta ya tiene una respuesta aquí:
El siguiente código C ++ utiliza un objeto ifstream para leer enteros de un archivo de texto (que tiene un número por línea) hasta que llegue a EOF . ¿Por qué lee el número entero en la última línea dos veces? ¿Cómo arreglar esto?
Código:
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
ifstream iFile("input.txt"); // input.txt has integers, one per line
while (!iFile.eof())
{
int x;
iFile >> x;
cerr << x << endl;
}
return 0;
}
input.txt :
10
20
30
Salida :
10
20
30
30
Nota : me salté todos los códigos de error para mantener el fragmento de código pequeño. El comportamiento anterior se ve en Windows (Visual C ++), cygwin (gcc) y Linux (gcc).
Al final de la última línea, tiene un nuevo carácter de línea, que no es leído por >> operador y no es un final de archivo. Haga un experimento y elimine la nueva línea (el último carácter en el archivo): no obtendrá la duplicación. Para tener un código flexible y evitar los efectos no deseados solo aplica cualquier solución dada por otros usuarios.
El patrón EOF necesita una lectura principal para ''arrancar'' el proceso de comprobación de EOF. Considere que el archivo vacío inicialmente no tendrá su EOF configurado hasta la primera lectura. La lectura principal captará el EOF en esta instancia y saltará el ciclo por completo.
Lo que debe recordar aquí es que no obtiene el EOF hasta el primer intento de leer más allá de los datos disponibles del archivo. Leer la cantidad exacta de datos no marcará el EOF.
Debo señalar que si el archivo estaba vacío, su código dado se hubiera impreso ya que el EOF impedirá que un valor se establezca en x al ingresar al ciclo.
- 0
Así que agrega una lectura principal y mueve la lectura del ciclo hasta el final:
int x;
iFile >> x; // prime read here
while (!iFile.eof()) {
cerr << x << endl;
iFile >> x;
}
Hay un enfoque alternativo a esto:
#include <iterator>
#include <algorithm>
// ...
copy(istream_iterator<int>(iFile), istream_iterator<int>(),
ostream_iterator<int>(cerr, "/n"));
Me gusta este ejemplo, que por ahora, deja fuera el cheque que se puede agregar dentro del bloque while:
ifstream iFile("input.txt"); // input.txt has integers, one per line
int x;
while (iFile >> x)
{
cerr << x << endl;
}
No estoy seguro de qué tan seguro es ...
Sin muchas modificaciones del código original, podría convertirse en:
while (!iFile.eof())
{
int x;
iFile >> x;
if (!iFile.eof()) break;
cerr << x << endl;
}
pero prefiero las otras dos soluciones anteriores en general.
Solo sigue de cerca la cadena de eventos.
- Agarra 10
- Agarra 20
- Agarra 30
- Agarrar EOF
Mire la penúltima iteración. Agarraste 30, y luego continuaste a buscar EOF. No ha llegado a EOF porque todavía no se ha leído la marca EOF (hablando "binariamente", su ubicación conceptual es justo después de la línea 30). Por lo tanto, continúe con la siguiente iteración. x sigue siendo 30 de la iteración anterior. Ahora lees de la transmisión y obtienes EOF. x permanece 30 y el ios :: eofbit aumenta. Usted saca a stderr x (que es 30, al igual que en la iteración anterior). A continuación, comprueba EOF en la condición de bucle, y esta vez estás fuera del circuito.
Prueba esto:
while (true) {
int x;
iFile >> x;
if( iFile.eof() ) break;
cerr << x << endl;
}
Por cierto, hay otro error en tu código. ¿Alguna vez trataste de ejecutarlo en un archivo vacío? El comportamiento que obtienes es por la misma razón.
int x;
ifile >> x
while (!iFile.eof())
{
cerr << x << endl;
iFile >> x;
}