How to deal with EVERY bad input?

Hello guys~
I am new in this forum, but I've been studying (by my self) C++ for 4 months.
The question is:
In the code below I am running a very simple program that outpt 'spelled-out' numbers when you input any integer between 1 and 10.
It works fine.

Now! How can I instruct the program to act sensibly with bad inputs?

I can say "if the number is negative then bla bla.." but how about a string??

If you input "a" in this simple code, the program crashes. I'd rather like it to come up wih somthing like "error, please input a number"
How can perform that "check"?
If the program is waiting for a string, the check will never fail,because even "3" can be read as a string.

Please, could somebody help me? (no complicated answers, I am a bit stupid, only simple but good ideas. I might not even need any code, I'd appreciate so much any quick explanation on what to do in these situations)


int nmb=0;
string exit="";
vector<string>nmbs(10);
nmbs[0]="zero";
nmbs[1]="one";
nmbs[2]="two";
nmbs[3]="three";
nmbs[4]="four";
nmbs[5]="five";
nmbs[6]="six";
nmbs[7]="seven";
nmbs[8]="eight";
nmbs[9]="nine";

cout<<"\nenter an integer between 1 and 10\n\n";


while (cin>>nmb)
{
if (nmb>(-1) and nmb<10)
{for (int i=0;i<nmbs.size();i++)
if (nmb==i) cout<<"\n"<<nmbs[i]<<"\n\n";}

else cout<<"\nsorry, what the f**k was that?\n\n";
}



Also, 'same question' (but with a practical example)

Assuming I wanted to make a video-game one day, how can I make a loop "serching" accross the whole program for a particular string (a password, an exit) while I am prompting the user to input numbers?
while we ask for ints (for example) how can we also check that any string (in case of bad-input-protection) or one particular string (in case of a 'password' as an exit) is not being entered?

How can you allow players to exit at ANY point in time?

This is exactly what I have been trying to ask above! I noticed the C++ "feels" ONLY the "closest" loop, the last one, not the first one, the out-most loop..
Have I given you an idea of what I mean?

(the code below is an even sillier example, the "no-check" is ignored)


int nmb=0;
string exit="";

if (exit!="no")
while (int!="wow") {cin>>exit; cout<<"woah!!!";}
Last edited on
Well, I would suggest you this: Always scan for strings using getline, then convert the numbers into ints for a function, for example, saying something like "Invalid input" if it has other characters. I don't know many details about this, sorry.
so what you want to do is validate that the input is a number before continuing, if i understand you correctly.

#include <cctype> will be of interest to you http://www.cplusplus.com/reference/clibrary/cctype/

particularly the isdigit function.
at samrux

Thank you for your attempt at helping me! I appreciate that.

Do you mean:

I should prompt the user to input a STRING first, then check whether the string happens to be "one" "two "three" etc.. and turn ONLY those into numbers?

:)
Yes!
That is a good idea. thanks.
It solves my problem in this context.

But how about another context? where an infinte number of "fine" inputs is possible?

Still I have got a problem. :(
Last edited on
at georgewashere

Thanks!!
Yes, that is very good to know.
Now I can have that check any time.
I suppose I'll stick with that.

One last thing,
Would you know how to go about this without a function?
Like, for a (useless in terms of results) learning experience.

Or you reckon it's just impossible playing around with only basic functions and loops?
Last edited on
To avoid using the cctype library you could use a member function of the istream class ( cin is an object of class istream ) In case you are unaware cin(as in the thing you do cin >> input with) is actually an object of type istream (just like int x; where x is an object of type int.)

It may be a bit beyond what you are studying right now, but back to that member function. The link to the page is http://www.cplusplus.com/reference/iostream/ios/bad/

The way you would use it is you would get the input and then check if (cin.bad()) //some code here

If you want to see an example a similar question was asked and a solution was provided (again it may be to heavy for the moment so don't feel discouraged if it's just looks like abunch of gibberish)

http://stackoverflow.com/questions/2292202/while-loop-with-try-catch-fails-at-bad-cin-input

Good luck clodi.


edit: Whoops I only provided an alternative method, AFAIK you shouldn't be doing it any other way, but I suppose you could iterate through all your valid inputs ( as in 0 - 9 ) and if the user input doesn't match any one of them you could just re-prompt for valid input. This is an inefficient way to do this however.
Last edited on
Thank you so much.
Yea, I understand. It's my biggest limit.
I've just started and I want my little silly programs to be "bullet-proof".
I am having a look at that, and I will keep studying in the mean time :)
How can you allow players to exit at ANY point in time?


No magic function to quit at any time, you would have to code it in for every time you accept user input. The simplest way here is to include <cstdlib> and use the exit function:
http://www.cplusplus.com/reference/clibrary/cstdlib/exit/

I've just started and I want my little silly programs to be "bullet-proof".


while (cin >> nmb) is pretty close. Basically, the >> operator returns the cin object itself, so you're looping while >> works. The trick is to loop for the opposite (while it doesn't work), while (!(cin >> nmb)).

1
2
3
4
5
6
7
8
9
10
11
12
double getNum(void)
{
  double num;
  while (!(cin >> num)) //while the extraction breaks cin
  {
    cin.clear(); // fix cin
    cin.ignore(80, '\n');  // remove what broke it from the buffer
    cout << "Numbers only please.  Try Again: ";
  }
  cin.ignore(80, '\n');  // clear the buffer of any remaining characters
  return num;
}


Foolproof. It may act funny if you enter more than 80 characters, but will also resolve itself.

To get an integer specifically, think about the difference between a double and an int. An int doesn't have a decimal:
1
2
3
4
5
6
7
8
9
10
int getInt(void)
{
  double num = getNum(); // getNum() ensures a numerical input
  while (num != static_cast<int>(num))
  {
    cout << "Integers only please.  Try Again: ";
    num = getNum();
  }
  return static_cast<int>(num);
}


Which is then made something more menu friendly:
1
2
3
4
5
6
7
8
9
10
int getIntInRange(int low, int high)
{
  int num = getInt();  // Ensures a number and an integer
  while (num < low || num > high)
  {
    cout << "Integer must be from " << low << " to " << high << ".  Try Again: ";
    num = getInt();
  }
  return num;
}


Finally, incorporate into your menu:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int main(void)
{
  int choice;
  do
  {
    cout << "1) Play\n"
         << "2) Quit\n";
    cout << "Please make a choice: ";
    choice = getIntInRange(1, 2);
    switch (choice)
    {
    case 1: cout << "Play is good\n"; break;
    case 2: cout << "That was fun\n"; break;
    }
  }
  while (choice < 2);
  return 0;
}


Hope that helps a little.

edit: I (and the repliers of that post) don't like the use of exceptions there. I made this up for a more reasonable use:
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
#include <iostream>
using namespace std;

double getNum(void)
{
  double num;
  if (!(cin >> num))
  {
    cin.clear(); // fix cin
    cin.ignore(80, '\n');  // remove what broke it from the buffer
    throw  "Numbers only";
  }
  cin.ignore(80, '\n');  // clear the buffer of any remaining characters
  return num;
}

int getInt(void)
{
  double num = getNum(); // getNum() ensures a numerical input
  if (num != static_cast<int>(num))
  {
    throw "Integers only.";
  }
  return static_cast<int>(num);
}

int getIntInRange(int low, int high)
{
  int num = getInt();  // Ensures a number and an integer
  if (num < low || num > high)
  {
    throw "Integer out of range";
  }
  return num;
}

int main(){
int choice;
  do
  {
    cout << "1) Play\n"
         << "2) Quit\n";
    cout << "Please make a choice: ";
    
    try
    {
    choice = getIntInRange(1, 2);
    }
    catch (const char* error)
    {
      cout << error << endl;
      choice = 1;
    }
    switch (choice)
    {
    case 1: cout << "Play is good\n"; break;
    case 2: cout << "That was fun\n"; break;
    }
  }
  while (choice < 2);
    return 0;
}


What is to note is that the catch part of the code manages to make the program continue to run in a smooth fashion.



Last edited on
wow

that actually explains a lot thanks, and so far I have had quite a few trouble at understanding how to make the most of separate functions.
Now finally I get to see a little program that makes large use of them.
nice

Only one thing,
(num != static_cast<int>(num))

?? I think I don't get what this means.

Also, when you say:
edit: I (and the repliers of that post) don't like the use of exceptions there. I made this up for a more reasonable use:


I am not sure I get what you mean. I can't spot any dfference between the first code and the edit (apart from
throw
and
cout
and other minor things..

I am a bit confused.. :(
Topic archived. No new replies allowed.