I did another test and the original code I posted does not work in any situation. I did another one that is more complicated, but it works. It takes a string and tries to convert it to int
. If it fails, it is the same as if the number is invalid. Before it works when there was a specific error, it now handles any invalid input. And as it is done through specialized function, you do not have to worry about the state of the stream pattern.
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int ActionGenerator() {
int Action;
string Input = "";
while(true) {
cout << endl << "SELECIONE UMA ACTION: " << endl;
cout << "[1 = ActionX]" << endl << "[2 = ActionZ]" << endl;
getline(cin, Input);
stringstream myStream(Input);
if ((myStream >> Action) && (Action == 1 || Action == 2)){
return Action;
} else {
cout << endl << "ACTION INVALIDA !" << endl;
}
}
}
int main() {
cout << ActionGenerator() << endl << "ok" <<endl;
return 0;
}
See running on ideone . And no Coding Ground . Also I placed GitHub for future reference .
Note that I ran a test with a string more than one character. This failed in the previous code.
The code is difficult to understand because it is not badly indented. It may seem silly but this makes a huge difference to understanding the code.
There is a part that will never be executed. And in fact there is no logic to get out of loop unless you enter 1 or 2. And in these cases the function execution terminates.
But the problem is that you are not releasing the stream state. When an error occurs an error flag is set to let you know there was a problem when you tried to get a valid value. When you type something that can not be converted to the expected type, in the case a int
, in addition to the number being converted to 0, is flag set set and only if you explicitly clear this is that you can go back to working with stream . If the flag is set, the stream does not work.
Another problem is that the typed data is still in buffer and you need to ignore what is in it.
That is, the stream saves state and you have to solve this.
I took advantage of and made an improvement for this case:
#include <iostream>
using namespace std;
int ActionGenerator() {
int Action;
while(true) {
cout << endl << "SELECIONE UMA ACTION: " << endl;
cout << "[1 = ActionX]" << endl << "[2 = ActionZ]" << endl;
cin >> Action;
if (Action == 1 || Action == 2){
return Action;
} else {
cout << endl << "ACTION INVALIDA !" << endl;
cin.clear(); //Limpa a flag de erro quando há falha no parse do valor entrado
cin.ignore(); //Limpa o buffer
}
}
}
int main() {
cout << ActionGenerator() << endl << "ok" <<endl;
return 0;
}
See running on ideone . Also I placed GitHub for future reference .
There are other ways to handle this but I think for the simple example you gave you do not have to do anything more complex than this.
Note that I simplified the loop as well. There was no reason to exist that control in this case.