PDA

Visualizza la versione completa : [c++] cin >> var; comportamento completamente errato


xnavigator
17-01-2010, 17:10
ragazzi ho scritto questo semplice codice:



#include <iostream>
using namespace std;

int main()
{
int a;

while(1) {
cout << "Fai la tua scelta [1 oppure 2]?" <<endl;
cin >> a;
if (a==1) {
cout << "Hai scelto 1" <<endl;
} else if (a==2) {
cout << "Hai scelto 2" << endl;
} else {
cout << "Scelta sbagliata, riprova."<< endl;
}
}

cout << endl;
return 0;
}


praticamente un semplice ciclo che chiede di inserire un valore che se corrisponde ad 1 o a 2 va bene atlrimenenti la scelta sbagltiata..

ma se provo ad inserigli una stringa (del tipo: ciao) mi va in un loop infinito senza mai fermarsi ed come se cin >> a; leggesse sempre quella stringa inserita all'inizio senza mai richiederne un nuovo inserimento
:dh: :dh: :dh: :dh: :dh:

soluzioni?

YuYevon
17-01-2010, 17:16
#include <iostream>

using namespace std;

int main()
{
int n;

cout << "Insert 1 or 2: " << endl;
while (!(cin >> n) || (n != 1 && n != 2))
{
cout << "LOL NIG" << endl;
cin.clear();
while( cin.peek() != '\n' ) cin.ignore();
}

return 0;
}

xnavigator
17-01-2010, 17:22
grazie... cosi ora mi va:



#include <iostream>

using namespace std;

int main()
{
int c;

cout << "Insert a or b: " << endl;
while (1)
{

cin >> c;

if (c == 1 || c == 2)
cout << "scelta esatta" << endl;
else
cout << "scelta errata, riprova" << endl;

cin.clear();
while( cin.peek() != '\n' ) cin.ignore();
}

return 0;
}



bisognava aggiungere quel

cin.clear();
while( cin.peek() != '\n' ) cin.ignore();

per risolvere il problema anceh se non mi chiarissimo perch cin fa quest'errore e devo usare questo piccolo accorgimento per "aggirarlo"

MItaly
17-01-2010, 17:39
un problema comune; leggi (http://forum.html.it/forum/showthread.php?s=&postid=12353466#post12353466).

YuYevon
17-01-2010, 17:39
Ti sapr spiegare meglio qualcuno pi esperto, comunque in sostanza quando provi a leggere un variabile con dati di tipo diversi da quelli dichiarati (nel tuo caso, una stringa anzich un intero) viene settato il flag failbit come spiegato qui (http://www.cplusplus.com/reference/iostream/istream/operator%3E%3E/). A quel punto prima viene richiamato il metodo clear() (http://www.cplusplus.com/reference/iostream/ios/clear/) sullo stream, metodo che di default (quando richiamato senza argomenti, come il prototipo mostra) azzera tutti i flag di errore e poi nel ciclo while si leggono tutti i caratteri nello stream con peek() (http://www.cplusplus.com/reference/iostream/istream/peek/) fino al carattere di newline (senza estrarli) e per ognuno di essi richiama il metodo ignore() (http://www.cplusplus.com/reference/iostream/istream/ignore/), che invece estrare proprio (e ignora) i caratteri dallo stream, ripulendolo.

E' probabile che esistano soluzioni migliori per gestire la cosa, anche se non mi pare che esistano funzioni e/o metodi standard per farlo, come in C del resto...

xnavigator
17-01-2010, 17:41
grazie mille...

:ciauz:

MItaly
17-01-2010, 17:43
Originariamente inviato da YuYevon
E' probabile che esistano soluzioni migliori per gestire la cosa, anche se non mi pare che esistano funzioni e/o metodi standard per farlo, come in C del resto...
Teoricamente esisterebbe il metodo sync(), ma lo standard non obbliga gli implementatori a fargli fare effettivament qualcosa (quindi ha praticamente lo stesso comportamento di fflush in C applicato ad uno stream di input).

xnavigator
17-01-2010, 17:49
ragazzi nietne da fare mi va sempre nel loop senza fine senza fermarsi per aspettare l'input dell'utente...

ho questo codice:



#include <iostream>
#include <string>

using namespace std;

int main()
{
int c;
string s;

while (1)
{
cout << "Insert 1 o 2: " << endl;
cin >> c;

if (c == 1 || c == 2) {
cout << "scelta esatta" << endl << "Inserisci la stringa: " << endl;
cin.ignore();
getline(cin,s);

cout << "Hai inserito: "<< s<< endl;
}
else {
cout << "scelta errata, riprova" << endl;
cin.clear();
while( cin.peek() != '\n' ) cin.ignore();
}

cout << endl << endl;


}

return 0;
}


inserisco la prfima volta o 1 o 2... a quel punto mi viene richeista di inserire una frase l'inserisco e viene stampata..
rinizia il ciclo da capo e mi esce: "inserisci 1 o 2"

ora provo ad inserire "c" e mi va nel loop infinito =/

se provo a scrivere "c" alla prima esecuzione si ferma correttametne.. in pratica quel metodo non sembra funzionare dopo che si sia fatta una lettura con getline (oppure il metodo ignore, non saprei dire quali dei 2) =/
:dh:

YuYevon
17-01-2010, 18:02
Prova 'n po' cos, a me va.



#include <iostream>
#include <string>

using namespace std;

int main()
{
int c;
string s;

while (1)
{
cout << "Insert 1 o 2: " << endl;

if(!(cin >> c)) {
cout << "scelta errata, riprova" << endl;
cin.clear();
while( cin.peek() != '\n' ) cin.ignore();
}
else if (c == 1 || c == 2) {
while( cin.peek() != '\n' ) cin.ignore();
cout << "scelta esatta" << endl << "Inserisci la stringa: " << endl;
getline(cin,s);

while( cin.peek() != '\n' ) cin.ignore();
cout << "Hai inserito: "<< s<< endl;
}

cout << endl << endl;
}

return 0;
}

xnavigator
17-01-2010, 18:05
grazie mille lo provo..

ma se a questo punto devo aggiungere tutto sto codice in pi a questo punto scrivo un avviso nel prompt "Inserire solo ed esclusivamente cifre."

e faccio prima :fagiano:

Loading