Char input causing infinite loop, can anyone help me out

I'm trying to do error checking for my program and I got it to work with numbers but not characters. Can anyone check out what I have and let me know what I can do to fix this?

Here is the header file

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
class menuClass
{

private:



public:
    int switchCase(int);
    int menuList();

};


int menuClass::menuList()
{
    //Choice
    int z;

    //Options
    cout << "Menu" << endl;
    cout << "1. New Order" << endl;
    cout << "2. Address List " << endl;
    //Start new segment of menu


    //cout << "3. "

    //Receive input
    cin >> z;

    //Return input
    return z;
}



int menuClass::switchCase(int menuChoice)
{
    if (menuChoice != 1 || menuChoice != 2)
        switchCase(menuList());
    //Conditions
    switch(menuChoice)
    {

    case 1:
        cout << "ok" << endl;
        break;
        return 0;

    case 2:
        cout << "exit" << endl;
        return 0;
        break;

    }




    //Error check

}



Here is the int main

1
2
3
4
5
6
int main()
{
   menuClass midWip;
   midWip.switchCase(midWip.menuList());
}



Maybe I should do the error check for the input of Z inside of the menuList?
Last edited on
So where is the problem? I don't see any char in use.
You certainly should. Because otherwise you will get infinite loop.

If you enter letter instead of number, read fails and no number is extracted. return value is either old value for old standard or 0 for new.
After that stream goes into failed state causing all subsequent reads to fail. On top of that, offending character is still in the buffer and will be extracted on next input operation.

You need to clear stream state: std::cin.clear();
Then you need to skip incorrect input. Here is the code which skips all characters in entered line:
1
2
3
#include <limits>
//...
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
if you run the program and enter a character it causes it to just keep looping the menu. my if statement here:

1
2
3
if (menuChoice != 1 || menuChoice != 2)
        switchCase(menuList());


This is supposed to check whether or not the value that was passed into the function (menuChoice), from menuList, is a 1 or a 2.

So far I have found one website with a similar question:

https://www.daniweb.com/software-development/cpp/threads/314840/infinite-loop-due-to-char-input


His question is almost completely identical to mine, (his code at least) and the replies list some solutions like reading it as a string and then checking the string for characters, or some stuff about cin "error flags" that get set off. I'm just checking it out right now but if anyone can give me a solution specific to what I'm doing, or at least tell me what I'm doing wrong, that'd be great.

Ah looks like this solution may work, I'll test it out:

1
2
3
4
5
6
7
8
9
10
11
int getInt(const char *msg){
 cout << msg ;
 int n = 0;
 while(!(cin >> n)){
    cout <<  "Input failed...try again\n";
    cin.clear();
    while(cin.get() != '\n');
 }
 return n;
}



"Basically, the while(!(cin>>n)) checks the cin gets what we are expecting it to get. We are expecting it to get an int, so if a letter is entered, cin will fail and set its fail flags. Thus the reason why we did cin.clear(). That clears the flags, and resets the stream. Now all thats left is to discard the invalid input in the stream. To do that, we did while(cin.get() != '\n');. That code discards the invalid character inputted until it reads a newline character."


Last edited on
You also have a logic error at line 40.
if (menuChoice != 1 || menuChoice != 2)
That condition will always evaluate true. i.e. If menuChoice is 1, menuChoice != 2 will be true and if menuChoice is 2, menuChoice !=1 will be true. You want &&, not ||.
if (menuChoice != 1 && menuChoice != 2)

Also, you're not using recursion correctly at line 41. If menuChoice is not valid, you make a nested call to switchCase. The problem arises when you return from switchCase, you fall through to line 43 which tests menuChoice. menuChoice still has the invalid value from line 38.

While recursion can be made to work here, it is not the best practice. As you can see, it is easy to get it wrong. You're also going to nest as deeply as the the number of times the users enters an invalid value. Not the best design.


Oh thank you, I wrote out a long response to this and it just gave me an error saying permission denied, turns out I had been logged out. That sucks. But I think I get what you're saying here, especially the logical error.

Here is a new method I have tried using inside of my menuList function:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
int menuClass::menuList()
{
    //Choice
    int z;

    //Options
    cout << "Menu" << endl;
    cout << "1. New Order" << endl;
    cout << "2. Address List " << endl;
    //Start new segment of menu


    //cout << "3. "

    //Receive input
    cin >> z;
    while (z != 1 && z != 2)
    {
        cout << "Please select an option from the menu. " << endl;
        cin >> z;
    }

    //Return input
    return z;
}



This is working so far with everything that I have thrown at it besides throwing a character at it. I can make my declared variable inside of menuList into a string or character type.
Please, read my explanation of what happens in previous post. I explained what happens and how to solve it. For additional information you can read this link (and the next article in it, use navigation menu on the left): http://www.parashift.com/c++-faq/stream-input-failure.html
Topic archived. No new replies allowed.