Infinite loop when typing a character

Asked

Viewed 1,404 times

1

I’m doing error tests on my "Monkey Test" program and it goes into loop infinite when I type a character on the keyboard other than 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;
        }
    }
}
  • 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.

  • 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

  • I think I got it, I’ll answer.

3 answers

2

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.

  • c.clear(); Cin.ignore(); solved, ball show thanks!

0


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;
}
  • You can do it any way you want, but I wouldn’t do it this way. First because it uses a feature that is no longer recommended by C++ and second because it validates the data enough. User errors will get beaten.

-1

The command cin>> does not treat invalid entries. Action is an integer, if someone types a string, generates an untreated exception, which ends up generating the infinite loop. You have to generate code to handle this exception. You have to capture an array type input (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.

Observing: verify = false after return Action will never be executed.

  • Notably the described code snippet is not functional. But it serves to give an idea of what can be done. In fact, for the question in context it is somewhat complex, but it is a great exercise for beginners.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.