I did another test and the original code I posted doesn’t work in any situation. I did another one which is more complicated but works. It picks up 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 entry. And as it is done through specialized function, do not need to worry about the state of 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;
}
Behold working in the ideone. And in the repl it.. Also put on the Github for future reference.
Note that I did a test with a string more than one character. This failed in the previous code.
The code is hard to understand because it is not indented wrong. It may sound silly but it makes a huge difference to understand the code.
There is part that will never be executed. And in fact there is no logic to get out of loop unless you type 1 or 2. And in these cases the execution of the function.
But the same problem is that you are not releasing the state of stream. When an error occurs a flag error is arrow to let you know that there was a problem when you tried to pick up a valid amount. When you type something that cannot be converted into the expected type, in case a int
, in addition to the number being converted to 0, is flag stays arrow and only if you explicitly clean up can you go back to work with the stream. If the flag is arrow the stream doesn’t work.
Another problem occurs that the typed data is still in the buffer and you need to ignore what’s in it.
That is, the stream state guard and you have to settle this.
I took advantage and made an improvement to 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;
}
Behold working in the ideone. And in the repl it.. Also put on the Github for future reference.
There are other ways to treat this but I think for the simple example you gave there’s no reason to do anything more complex than this.
Note that I simplified the loop also. There was no reason for that control in this case.
What specifically are you typing? Why do you consider that you are in loop? Why do you keep saying "ACTION INVALIDA"? Well, this is what the code is telling you to do, every time you have something invalid it gives you this message and asks again. If you have another intention, describe it in the question.
– Maniero
the user has to choose an action, and is presented to him on screen 2 Choices, or 1 or 2 for him to type, and then returns to my main the result typed by the user, in this case I am filtering errors if the user type something wrong, let’s assume that he accidentally type a letter, the code has to filter this error, which is not what is happening... I need to filter if he type a string
– user17270
I think I got it, I’ll answer.
– Maniero