117 votes

La lecture de fichier texte jusqu'à ce que EOF répète la dernière ligne

La suite C++ code utilise un ifstream objet à lire des nombres entiers à partir d'un fichier texte (qui a un nombre par ligne) jusqu'à ce qu'il frappe expressions du FOLKLORE. Pourquoi faut-il lire en entier sur la dernière ligne deux fois? Comment résoudre ce problème?

Code:

#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

Sortie:

10  
20  
30  
30

Note: j'ai sauté tous d'erreur de code de vérification de garder l'extrait de code de de petites. La au-dessus de comportement est visible sur Windows (Visual C++), cygwin (gcc) et Linux (gcc).

119voto

wilhelmtell Points 25504

Il suffit de suivre de près la suite des événements.

  • Prenez 10
  • Prenez 20
  • Prenez 30
  • Prenez EOF

Regardez la deuxième à la dernière itération. Vous attrapé 30, alors menées pour vérifier les expressions du FOLKLORE. Vous n'avez pas atteint EOF parce que les expressions du FOLKLORE marque n'a pas été encore lire ("binarically" parlant, de sa conception de l'emplacement est juste après le 30 ligne). Donc vous continuez à la prochaine itération. x est toujours de 30 à partir de la précédente itération. Maintenant vous lire à partir du flux et vous obtenez des expressions du FOLKLORE. x reste 30 et le ios::eofbit est soulevée. Sortie stderr x (qui est de 30, tout comme dans l'itération précédente). Ensuite, vous vérifiez pour les expressions du FOLKLORE dans la condition de la boucle, et cette fois, vous êtes hors de la boucle.

Essayez ceci:

while (true) {
    int x;
    iFile >> x;
    if( iFile.eof() ) break;
    cerr << x << endl;
}

Par ailleurs, il y a un autre bug dans votre code. Avez-vous déjà essayer de l'exécuter sur un fichier vide? Le comportement que vous obtenez est pour exactement la même raison.

34voto

Patrick Loz Points 297

J'aime cet exemple, ce qui pour l'instant, laisse le chèque que vous pourriez ajouter à l'intérieur de la tout en bloc:

ifstream iFile("input.txt");        // input.txt has integers, one per line
int x;

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

Pas sûr de savoir comment il est sûr...

15voto

wilhelmtell Points 25504

Il y a une approche alternative à ceci:

#include <iterator>
#include <algorithm>

// ...

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

5voto

Solostaran14 Points 759

Sans trop de modifications du code original, il pourrait devenir :

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

mais je préfère les deux autres solutions ci-dessus en général.

2voto

user1384482 Points 9
int x;
ifile >> x

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X