2015-11-11 4 views
1

Vous vous demandez ce qui se passe ici. J'ai essayé de pousser ceci à travers gdb mais ne peux pas sembler obtenir une version de débogage/code de libstdC++, espérant ainsi que quelqu'un qui connait leurs flux puisse aider? Dans le code ci-dessous, le bit clé est la boucle while:C++ stringstream et fail vs eof

#include <iostream> 
#include <string> 
#include <vector> 
#include <algorithm> 
#include <iomanip> 
#include <sstream> 
using namespace std; 
void printer(int i) { 
     cout << i << ", "; 
} 
int main() 
{ 
     string s; 
     getline(cin, s); 
     stringstream input(s); 
     vector<int> v1; 
     int i; 
     while (!input.fail()) 
     { 
       input >> i; 
       v1.push_back(i); 
     } 
     for_each(v1.begin(), v1.end(), printer); 
     return 0; 
} 

Quand je lance cela et fournir un numéro, cela semble ajouter ce numéro deux fois au vecteur. Si je change la condition de la boucle while à eof() (par opposition à fail()) tout se comporte comme je l'aurais prévu. Donc, compte tenu de l'extraction operator>> est supposé extraire des valeurs d'un flux, comment est-il possible que les appels successifs continuent à produire le résultat?

Je devine que je ne pense pas à ce tout à fait raison (il est 02h30 localtime afin que pourrait avoir quelque chose à voir avec ça!)

En utilisant la version gcc 4.9.2 (Ubuntu 4.9.2 -0ubuntu1 ~ 12.04)

Répondre

4

Ceci est une version à peine déguisée du bug habituel incorrect use of eof().

La boucle doit être:

while (input >> i) 
    v1.push_back(i); 

Dans votre code réel que vous toujours push_back(i) même après la lecture a échoué.

Dans la version avec eof(), il peut ou non définir le drapeau eof en lisant la valeur précédente; vous ne pouvez pas compter sur ce que vous observez.

+0

Je vois - votre dernière édition répond à ma question de "pourquoi cela semble-t-il fonctionner avec eof()?" - merci - essentiellement si vous allez jamais extraire d'un flux dans une boucle, l'extraction qui se passe dans la condition de boucle est la façon canonique que je prends? – aho

+0

@aho Si ce n'est pas canonique, il est pour le moins extrêmement fortement recommandé. – user4581301

+1

@aho c'est généralement une bonne chose à faire, mais pour certains types de données, vous pouvez lire une valeur partielle puis échouer et frapper eof en même temps: avec les drapeaux d'états de flux restants comme pour une condition eof sans valeur partielle , il est difficile de reconnaître et de réagir à la valeur partielle bidon. Par exemple, si vous diffusez un 'double' et que le flux n'a que' 5E' - c'est une conversion qui échoue aussi bien qu'eof. Pour les cas où cela vous intéresse, vous pouvez utiliser 'while (entrée >> std :: skipws &&! Input.eof() && input >> my_double), alors le bit fail ne sera défini que si l'analyse échoue. –