Comment fonctionne EOF() d'ifstream?

#include <iostream>
#include <fstream>

int main() {
    std::fstream inf( "ex.txt", std::ios::in );
    while( !inf.eof() ) {
        std::cout << inf.get() << "n";
    }
    inf.close();
    inf.clear();
    inf.open( "ex.txt", std::ios::in );
    char c;
    while( inf >> c ) {
        std::cout << c << "n";
    }
    return 0;
}

Je suis vraiment confus au sujet de la fonction eof(). Supposons que mon ex.le contenu de txt était:

abc

Il lit toujours un caractère supplémentaire et affiche -1 lors de la lecture en utilisant eof(). Mais le inf >> c a donné la sortie correcte qui était 'abc'? Quelqu'un peut-il m'aider à expliquer cela?

36
demandé sur jww 2010-12-26 10:21:52

4 réponses

-1 est la façon de get de dire que vous avez atteint la fin du fichier. Comparez-le en utilisant le std::char_traits<char>::eof() (ou std::istream::traits_type::eof()) - évitez -1, c'est un nombre magique. (Bien que l'autre est un peu verbeux - vous pouvez toujours appeler istream::eof)

L'indicateur EOF n'est défini qu'une fois qu'une lecture a essayé de lire après la fin du fichier . Si j'ai un fichier de 3 octets, et que je ne lis que 3 octets, EOF est false, parce que je n'ai pas encore essayé de lire après la fin du fichier. Bien que cela semble déroutant pour les fichiers, qui généralement connaître leur taille, EOF n'est pas connu jusqu'à ce qu'une lecture soit tentée sur certains périphériques, tels que les tuyaux et les sockets réseau.

Le deuxième exemple fonctionne comme inf >> foo retournera toujours inf, avec l'effet secondaire de tenter de lire quelque chose et de le stocker dans foo. inf, un if ou while, permettra d'évaluer à true si le fichier est "bon": pas d'erreurs, pas d'expressions du FOLKLORE. Ainsi, lorsqu'une lecture échoue, inf evaule à false, et votre boucle s'arrête correctement. Cependant, prenez cette erreur commune:

while(!inf.eof())  // EOF is false here
{
    inf >> x;      // read fails, EOF becomes true, x is not set
    // use x       // we use x, despite our read failing.
}

Cependant, ce:

while(inf >> x)  // Attempt read into x, return false if it fails
{
    // will only be entered if read succeeded.
}

, Qui est ce que nous voulons.

62
répondu Thanatos 2010-12-26 07:52:49

Iostream ne sais pas, c'est à la fin du fichier jusqu'à ce qu'il essaie de lire ce premier caractère après la fin du fichier.

Le Exemple de code à cplusplus.com dit de le faire comme ceci: (mais vous ne devriez pas le faire de cette façon)

  while (is.good())     // loop while extraction from file is possible
  {
    c = is.get();       // get character from file
    if (is.good())
      cout << c;
  }

Un meilleur idiome est de déplacer la lecture dans la condition de boucle, comme ceci: (Vous pouvez le faire avec all istream Lire les opérations qui renvoient *this, y compris l'opérateur >>)

  char c;
  while(is.get(c))
    cout << c;
7
répondu Ken Bloom 2014-09-17 19:14:46

L'indicateur EOF n'est défini qu'après une opération de lecture qui tente de lire après la fin du fichier. get() retourne la constante symbolique traits::eof() (qui arrive juste à égaler -1) parce qu'elle a atteint la fin du fichier et n'a pas pu lire plus de données, et seulement à ce stade sera eof() vrai. Si vous voulez vérifier cette condition, vous pouvez faire quelque chose comme ceci:

int ch;
while ((ch = inf.get()) != EOF) {
    std::cout << static_cast<char>(ch) << "\n";
}
5
répondu Justin Spahr-Summers 2010-12-26 07:46:37

EOF () vérifie l'eofbit dans l'état du flux.

À chaque opération de lecture, si la position est à la fin du flux et que plus de données doivent être lues, eofbit est défini sur true. Par conséquent, vous allez obtenir un caractère supplémentaire avant d'obtenir eofbit=1.

La bonne façon est de vérifier si les expressions du folklore a été atteint (ou, si l'opération de lecture a réussi) après la lecture. C'est ce que fait votre deuxième version - vous faites une opération de lecture, puis utilisez le résultat référence d'objet de flux (qui >> renvoie) en tant que valeur booléenne, ce qui entraîne une vérification de fail().

2
répondu zeuxcg 2010-12-26 08:12:26