Menu problem with given values from user

I have a menu that offers three options (1,2,3), with the last one being the exit option. The menu exists within a while(x != 3) loop and the x is int type.

Everything is ok until the stupid user decides to enter a non-number character. Then all hell breaks loose and the program crashes.

How can I solve this problem? Should I choose another type for x, and if yes, what type?
You don't have to change variable 'x' type.

1
2
3
4
5
6
while(!(cin>>x))
{
cout<<"It's not a number."<<endl;
cin.clear(); //clear error flag
cin.ignore(INT_MAX, '\n'); //remove invalid input
}
Last edited on
This is a common problem for beginners and there are several ways around this. I am still a beginner myself so I can't tell you a simple solution off the top of my head, but here is a post that I made that contains one solution that I have been working on.

http://www.cplusplus.com/forum/beginner/27195/

P. S. I like your style...
the stupid user

I like to say things like that in my programs, instead of just meaningless error messages.
One thing you could do is to improve my code is this:
1
2
3
if (!isdigit(c[0]) ) 
    { cout << "User Error.  Terminating...  \nPlease restart program and don't be stupid.  " << endl;  exit(1); }
  

Thank you both for the quick replies.


I found an article in another site about this problem. I will not include the link since I don't know if it is allowed, but I here's the part that helped me

Reading in numbers directly is problematic

* If std::cin is presented with input it cannot process, std::cin goes into a "fail" state
* The input it cannot process is left on the input stream.
* All input will be ignored by std::cin until the "fail" state is cleared: std::cin.clear()
* A routine that reads a number directly should:
1. Read in the number
2. Check to see that the input stream is still valid
3. If the input stream is not good (!std::cin)
1. Call std::cin.clear() to take the stream out of the "fail" state.
2. Remove from the stream the input that caused the problem: std::cin.ignore(...)
3. Get the input again if appropriate or otherwise handle the error

Inputing numbers directly, version 1:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
  #include<limits> //for numeric_limits
  float fl;
  int bad_input;
  do{
    bad_input=0;
    std::cin >> fl;
    if(!std::cin)
    {
      bad_input=1;
      std::cin.clear();
      std::cin.ignore(std::numeric_limits<streamsize>::max(),'\n');
    }

  }while(bad_input);

Inputing numbers directly, version 2:
1
2
3
4
5
6
7
  #include<limits> //for numeric_limits
  float fl;
  while(!(std::cin >> fl))
  {
    std::cin.clear();
    std::cin.ignore(std::numeric_limits<streamsize>::max(),'\n');
  }


A note on limits. If your compiler doesn't support std::numeric_limits<streamsize>::max(), an alternative is to use the c-style method for determining the maximum integer allowed:

1
2
3
#include<climits>
...
std::cin.ignore(INT_MAX, '\n');


PS: mtweeman : Your solution was also included in the article. Thanks.

PS2: wtf: Please restart program and don't be stupid. . I definitely like your style.
Last edited on
Or document the program. If the user don't use your program correctly, it's not your responsibility, so undefined behaviour.
This:

std::numeric_limits<int>::max()

do exactly the same what:

INT_MAX

If Iremember correctly, second version is C-style and first is C++ style. Anyway, it should work.

P.S. I haven't noticed that you wrote about C-style. So i was right.
Last edited on
Or document the program. If the user don't use your program correctly, it's not your responsibility, so undefined behaviour.

Hence the number of poorly-written, badly-documented programs that people have to work around constantly to avoid losing money.

Why not just take a second to write robust code to begin with? User input has always needed careful error handling.


std::number_limits<int>::max()

Since a stream can have a maximum of streamsize elements, you should specify
  std::numeric_limits<streamsize>::max()
This has portability advantages.


If you want something to handle user input for integers properly, you are best writing a function or a class or something to handle it properly. I've done a nice example of that here (lines 26-45 are of interest if you want a simpler/less flashy implementation):
http://www.cplusplus.com/forum/beginner/13044/page1.html#msg62827

Hope this helps.
Duoas: Hail to the king!!

Every time I read one of your posts I spend the next few hours trying to find out what happened. And every time I learn something new. By the way, the topic you suggested was great.
Thanks for your reply
Topic archived. No new replies allowed.