Leyendo desde un archivo de texto hasta que EOF repita la última línea [duplicado]

StackOverflow https://stackoverflow.com/questions/21647

  •  09-06-2019
  •  | 
  •  

Pregunta

La siguiente C++ El código utiliza un si corriente objeto para leer números enteros de un archivo de texto (que tiene un número por línea) hasta que llegue EOF.¿Por qué lee dos veces el número entero de la última línea?¿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;
}

entrada.txt:

10  
20  
30

Producción:

10  
20  
30  
30

Nota:Me salté todo el código de verificación de errores para mantener el fragmento de código pequeño.El comportamiento anterior se observa en Windows (Visual C++), cygwin (gcc) y Linux (gcc).

¿Fue útil?

Solución

Simplemente siga de cerca la cadena de eventos.

  • Agarra 10
  • Agarra 20
  • Agarra 30
  • Agarra EOF

Mire la penúltima iteración.Agarraste 30 y luego continuaste buscando EOF.No has llegado al EOF porque la marca EOF aún no se ha leído (hablando "binariamente", su ubicación conceptual está justo después de la línea 30).Por lo tanto, continúa con la siguiente iteración.x todavía es 30 de la iteración anterior.Ahora lees la transmisión y obtienes EOF.x sigue siendo 30 y se eleva el ios::eofbit.La salida es stderr x (que es 30, como en la iteración anterior).A continuación, verifica si hay EOF en la condición del bucle y esta vez sale del bucle.

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 intentaste ejecutarlo en un archivo vacío?El comportamiento que obtienes es exactamente por la misma razón.

Otros consejos

Me gusta este ejemplo, que por ahora omite la marca que podrías 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...

Hay un enfoque alternativo para esto:

#include <iterator>
#include <algorithm>

// ...

    copy(istream_iterator<int>(iFile), istream_iterator<int>(),
         ostream_iterator<int>(cerr, "\n"));

El patrón EOF necesita una lectura principal para "iniciar" el proceso de verificación de EOF.Considere que el archivo vacío no tendrá inicialmente su EOF configurado hasta la primera lectura.La lectura principal captará el EOF en este caso y omitirá correctamente el ciclo por completo.

Lo que debe recordar aquí es que no obtiene el EOF hasta el primer intento de leer los datos disponibles del archivo.Leer la cantidad exacta de datos no marcará el EOF.

Debo señalar que si el archivo estuviera vacío, el código proporcionado se habría impreso ya que el EOF habría impedido que un valor se estableciera en x al ingresar al ciclo.

  • 0

Así que agregue una lectura principal y mueva la lectura del bucle hasta el final:

int x;

iFile >> x; // prime read here
while (!iFile.eof()) {
    cerr << x << endl;
    iFile >> x;
}

Sin demasiadas 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.

int x;
ifile >> x

while (!iFile.eof())
{  
    cerr << x << endl;        
    iFile >> x;      
}

Al final de la última línea, tiene un carácter de nueva línea, que no es leído por el operador >> y no es un final de archivo.Por favor, haga un experimento y elimine la nueva línea (el último carácter del archivo); no obtendrá la duplicación.Para tener un código flexible y evitar efectos no deseados, simplemente aplique cualquier solución proporcionada por otros usuarios.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top