Question

J'ai récemment rencontré un problème lié à l'utilisation de fstream :: eof (). J'ai lu la ligne suivante de ici :

  

La fonction eof () renvoie true si la fin du fichier d'entrée associé a été atteinte, false sinon.

et a supposé (par erreur) que cela signifiait que si j'utilisais fstream :: read () et que je lisais après la fin du fichier, la fonction eof () me le dirait. J'ai donc fait quelque chose comme ça (très généralisé):

for(int i = 0; i < max && !file.eof(); i++)
{
     file.read(mything, sizeof(mything));
}

Le problème vient de ce qui est expliqué plus loin sur la page liée ci-dessus (que je n'avais pas lue au départ, grâce au premier paragraphe trompeur):

  

Inversement, le flux ne passe pas à l'état EOF s'il reste des espaces après le dernier jeton, mais toute tentative de lecture d'un autre jeton échouera. Par conséquent, l'indicateur EOF ne peut pas être utilisé comme test dans une boucle destinée à lire tout le contenu du flux jusqu'à EOF. Au lieu de cela, il convient de rechercher la condition d'échec après une tentative de lecture.

Donc, j'ai changé, et maintenant ma boucle vérifie contre file.fail () plutôt que file.eof (), et je comprends comment eof () fonctionne. Ma question est la suivante: pourquoi cela fonctionne-t-il? Y a-t-il des situations où cela est souhaitable? Il me semble qu’une fois passé EOF, vous avez réussi EOF et eof () devrait retourner vrai.

MISE À JOUR Merci pour les réponses, je pense que je l'ai. La seule opération que j'effectue est read (), et je vérifie immédiatement fail (), alors je pense que tout va bien. Ma question est la suivante: pour quoi puis-je utiliser eof ()?

?
Était-ce utile?

La solution

Parce que cela permet de détecter EOF sans connaître la taille du fichier. Il suffit simplement d’essayer de lire et si la lecture est courte (mais pas une erreur), vous avez atteint la fin du fichier.

Ceci reflète la fonctionnalité de l'appel système read , le fichier que l'IO finit généralement par appeler (les commandes win32 peuvent appeler ReadFile mais je pense que la fonctionnalité est similaire).

A partir de la page de manuel read " VALEUR RENVOYÉE " section (non souligné dans l'original):

  

En cas de succès, nombre d'octets lus   est renvoyé (zéro indique la fin de   fichier) , et la position du fichier est   avancé de ce nombre. Ce n'est pas un   erreur si ce nombre est inférieur à   le nombre d'octets demandés; ce   peut arriver par exemple parce que moins   les octets sont actuellement disponibles   (peut-être parce que nous étions proches de   fin de fichier, ou parce que nous lisons   d'un tuyau ou d'un terminal), ou   parce que read () a été interrompu par un   signal. En cas d'erreur, -1 est renvoyé et   errno est réglé correctement. Dans ce   cas, il est laissé indéterminé si   la position du fichier (le cas échéant) change.

BTW: un bon moyen d'écrire ce que vous vouliez serait comme ceci:

T something;
while(file.read(something, sizeof(something))) {
    // process your 'something'
}

Cela fonctionne car file.read (comme de nombreux membres de iostream) renvoie une référence à iostream lui-même. Tous ont un opérateur surchargé pour permettre de tester l'état du flux. De même, pour lire std :: cin , tandis que (std :: cin > > x) {...} fonctionne également.

MODIFIER: , vous devez savoir que les tests d'échec peuvent être tout aussi faux pour la même raison. À partir de la page que vous avez liée à fail () , si l'opération précédente a échoué. , cela signifie que vous devez effectuer une lecture ou une autre opération pertinente avant de la tester.

Autres conseils

int n;
std::cin >> n >> std::stripws;

corrige ce problème. à ce stade, vous pouvez utiliser .good () ou .eof (). J'aime utiliser .good (), car s'il y a un mauvais bloc de disque, .good () le détectera. mais c'est moi. .eof () ne le fera pas, vous devrez également ajouter .fail () || .bad ().

Je viens de le découvrir après de sérieuses études sur le problème de la consommation d’espace. J'allais proposer un ECO à iostream et si courant-temps, et voilà, c'est déjà fait. :-D

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top