Infinite Loop when typing a character

I am doing error testing in my "Monkey test" program and it goes into infinite loop when I type a character on the keyboard that is not number.

int ActionGenerator() {

    bool Verify;
    int Action;
    Verify = true;

    while(Verify){
        cout << "\nSELECIONE UMA ACTION: " << endl;
        cout << "[1 = ActionX]\n[2 = ActionZ]" << endl;
        cin >> Action;

        if (Action == 1 || Action == 2){
            return Action;
            Verify = false;

        }else {
            cout << "\nACTION INVALIDA !" << endl;
        }
    }
}
Author: Maniero, 2014-11-25

3 answers

I did another test and the original code I posted doesn't work in any situation. I made 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, now it treats any invalid input. And as it is done through specialized function, no need to worry about the state of the stream default.

#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 working No ideone. E no repl.it. also I put on 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 difficult to understand because it is not badly indented. It may sound silly but this makes a huge difference to understanding the code.

Has part that will never be executed. And in fact there is no logic to leave do loop unless you type 1 or 2. And in these cases the execution of the function is terminated.

But the very problem is that you are not releasing the state of the stream. When an error occurs a error flag is Set to let you know there was a problem when you tried to pick up a valid value. When you type something that cannot be converted to the expected type, in case a int, in addition to the number being converted to 0, is flag is Set and only if you explicitly clear this can you get back to working with the stream. If the flag is set the stream does not work.

Another problem occurs that the typed data is still in the buffer and you need to ignore what is in it.

That is, the stream Guards 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 working on ideone. E no repl.it. also I put on GitHub for future reference .

There are other ways to deal with this but I don't think for the simple example you gave you have to do anything more complex than this.

Note that I simplified the loop as well. There was no reason to have that control in this case.

 2
Author: Maniero, 2020-09-11 17:45:55
int ActionGenerator() {

    int opcao;
    char *CleanBuffer;


    do{
        cout << "\nSELECIONE UMA ACTION: " << endl;
        cout << "[1 = ActionX]\n[2 = ActionZ]" << endl;
        scanf("%d", &opcao);
        scanf("%c", &CleanBuffer);

        if (opcao = 1) {
            return opcao;


        }else if(opcao = 2){

            return opcao;

        }

        else {
            cout << "\nACTION INVALIDA !" << endl;
        }

    }while(opcao != 3)


    return 0;
}
 0
Author: , 2014-12-05 17:37:42

The cin>> command does not handle invalid entries. Action is an integer, if someone enters a string, it generates an untreated exception, which ends up generating the infinite loop. You have to generate a code to handle this exception. You have to capture an input of type array of characters (char[]), convert it to numbers, with exception treatment for invalid entries, type:

if ( char[0] != '1' )
    ThrowException(); //Seu método para tratar e exceção
else
    number += 1 * (decimalPlace ); // primeira casa decimal neste caso.

Note: verify = false after return Action will never run.

 -1
Author: Paulo, 2014-11-25 22:10:14