Lorsqu'un débutant commence à lire des ifstreams, son instinct est de lire le fichier en utilisant une boucle qui ressemble généralement à ceci:
while (!ifstream.eof()
{
...
}
Cependant, lorsque j'ai utilisé ce code, j'ai remarqué qu'il ne s'arrêtait pas avant d'avoir lu deux fois la dernière ligne du fichier. Les programmeurs C ++ notent que ce n'est pas vraiment la façon de lire un fichier. Au lieu de cela, ils recommandent généralement à quiconque a besoin de lire un fichier d'utiliser une boucle comme celle-ci:
while (ifstream >> someVar)
{
...
}
Pourquoi le premier morceau de code ne fonctionne-t-il pas toujours correctement?
Réponses:
La
while (!ifstream.eof())
boucle ne fonctionne pas, car les flux / fichiers en C et C ++ ne prédisent pas quand vous avez atteint la fin du fichier, mais indiquent plutôt si vous avez essayé de lire après la fin du fichier.Si la dernière ligne du fichier se termine par un caractère newline (
\n
), la plupart des actions de lecture s'arrêteront de lire lorsqu'elles auront rencontré ce caractère et elles ne détecteront pas qu'il s'agit du dernier caractère du fichier. Lors de la prochaine action de lecture, il se peut même que davantage de caractères aient été ajoutés et que la lecture réussisse à les extraire.La boucle utilisant l'opérateur d'extraction de flux (
while (ifstream >> someVar)
) fonctionne car le résultat de l'opérateur d'extraction de flux est évalué à faux s'il ne peut pas extraire un élément du bon type. Cela se produit également s'il ne reste aucun caractère à lire.la source
Ce n'est pas ce qui se passe. Le
eofbit
ne joue aucun rôle dans la conversion en booléen (stream::operator bool
(ouoperator void*
en ancien c ++)). Seuls lesbadbit
etfailbit
sont impliqués.Supposons que vous lisez un fichier contenant des nombres séparés par des espaces. Une boucle basée autour
cin.eof()
sera inévitablement soit fausse, soit remplie deif
tests. Vous ne lisez pas avant l'EOF. Vous lisez des chiffres. Alors, faites en sorte que votre code exprime cette logique:Cela fonctionnera que la dernière ligne du fichier se termine par
0 42\n
ou juste0 42
(pas de nouvelle ligne à la fin de la dernière ligne du fichier). Si le fichier se termine par0 42\n
, la dernière bonne lecture récupérera la valeur 42 et lira ce marqueur de fin de ligne final. Notez que le marqueur EOF n'a pas encore été lu. La fonctionprocess_value
est appelée avec42
. Le prochain appel à l'opérateur d'extraction de flux >> lit l'EOF, et puisque rien n'a été extrait, les deuxeofbit
etfailbit
seront définis.Supposons en revanche que le fichier se termine par
0 42
(pas de nouvelle ligne à la fin de la dernière ligne). La dernière bonne lecture récupérera la valeur 42 se terminant sur le marqueur EOF. Vraisemblablement, vous voulez traiter cela 42. C'est pourquoi leeofbit
ne joue pas de rôle dans l'opérateur de conversion booléen du flux d'entrée. Lors du prochain appel à l'opérateur d'extraction de flux >>, la machine sous-jacente voit rapidement que leeofbit
est déjà défini. Cela se traduit rapidement par la définition de lafailbit
.Parce que vous ne devriez pas rechercher EOF comme condition de boucle. La condition de boucle doit exprimer ce que vous essayez de faire, c'est-à-dire (par exemple), extraire des nombres d'un flux.
la source