2010-01-27 2 views
9

Je suis en train d'utiliser des pratiques de sécurité dans le traitement d'entrée avec des chiffres uniquement en C++, donc j'utiliser un objet stringstream comme si:problème en réutilisant un objet stringstream

#include <iostream> 
#include <string> 
#include <sstream> 
using namespace std; 

int main() 
{ 
    int first, second; 
    string input; 

    stringstream sstream; 

    cout << "First integer: "; 
    getline(cin, input); 
    sstream.str(input); 
    sstream >> first; 

    cout << first << endl; //display user input in integers 

    cout << "Second integer: "; 
    getline(cin, input); 
    sstream.str(input); 
    sstream >> second; 

    cout << second << endl; //display user input in integers 

    getline(cin, input); //pause program 

    return 0; 
} 

Cependant, la deuxième fois il semble donner à la variable «second» une valeur arbitraire. Ceci est la sortie:

First integer: 1 
1 
Second integer: 2 
2293592 

Si je déclare deux objets stringstream et de les utiliser respectivement pour les deux variables, il semble fonctionner très bien. Est-ce que cela signifie que je ne peux pas réutiliser un objet stringstream de la manière que j'essaie de faire? Dans mon vrai programme, j'ai l'intention de gérer beaucoup plus que deux valeurs d'entrée de l'utilisateur, donc je veux juste m'assurer s'il y a une autre manière au lieu de faire plusieurs objets stringstream. Je doute que ce soit d'une grande pertinence, mais je suis sur Windows XP et j'utilise MinGW comme compilateur.

J'apprécie grandement toute aide.

Répondre

13

Utilisez sstream.clear(); après sstream >> first;.

+1

Juste ce que je cherchais J'adore les réponses rapides sur ce site – kaykun

4

Une meilleure façon de faire cette conversion entre les types de données serait d'utiliser boost::lexical_cast.

Vous trouverez des informations et des exemples sur le Boost Site. Vous trouverez ci-dessous un exemple de conversion de int en chaîne et de retour (string en int) comme ce que vous faites dans votre programme.

#include <string> 
#include <boost/lexcal_cast.hpp> 

int main(int argc, char *argv[]) 
{ 
    int i = 42; 
    std::string s = boost::lexical_cast<std::string>(i); 
    int j = boost::lexical_cast<int>(s); 

    return 1; 
} 
+1

Ou, si l'OP ne veut pas utiliser Boost, il peut écrire sa propre distribution lexicale dans environ cinq lignes de code (cf http://www.gotw.ca/ publications/mill19.htm) –

2
cout << "First integer: "; 
getline(cin, input); 
sstream.str(input); 
sstream >> first;  // state of sstream may be eof 

cout << "Second integer: "; 
getline(cin, input); 
sstream.str(input); 
sstream.clear();  // clear eof state 
sstream >> second; // input from sstream 
11

Vous devez réinitialiser l'état de la stringstream. En général, cela implique deux étapes: le tampon de compensation:

sstream.str(""); 

et la réinitialisation de l'état d'erreur: drapeaux

sstream.clear(); 

Si vous ne désactivez pas le tampon, si vous obtenez une entrée comme « 123abc » alors "abc" sera toujours dans le flux lorsque vous essaierez de le lire la prochaine fois.

Vous devez également vérifier l'état d'échec du flux (sstream.fail()) pour vous assurer que l'extraction a réussi. Si vous voulez être sûr que l'utilisateur a seulement entré un entier (ie, vous voulez empêcher l'utilisateur d'entrer, par exemple, "123abc", alors vous devriez tester pour vous assurer que sstream.eof() est vrai.)