Skip to main content
GameDev.net gamedev.net
🔒 Locked

noob needs help with input validation in c/c++

Started by Liam78 Sep 3, 2005 at 11:25 PM 4 replies 700+ views
Original Post
Liam78
Liam78
The following piece of code works if the user enters an interger, but... How can i make it so the program will not crash when a user enters a char? for example the user enters "g" and instead of crashing it displays "invalid choice pick again" int validation(void) { int menu_choice; while(1) { cin >> menu_choice; if(menu_choice == 1 || menu_choice == 2 || menu_choice == 3) { return(menu_choice); } else { cout<<"invalid choice pick again "; } } }
Fruny
Fruny
cin >> menu_choice;// If menu_choice couldn't be readif(cin.fail()){   // Discard the remainder of the line    // numeric_limits is in <limits>   cin.ignore(numeric_limits<int>::max, '\n');   // Clear the flags   cin.clear()   // Print an error message   cout<<"invalid choice pick again ";   // Loop   continue;}
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
Zahlman
Zahlman
There also exists an idiom where you do the reading as part of the loop condition; the stream, after trying to read a value and failing to do so, is in a "failed state", and such a stream is considered "false" in a boolean context. The net result is that you can write, for example, "while (stream >> foo)", which reads as "while stream can be read into foo". This lets you do something like:

int getNumber() {  int result;  // For as long as we either can't read, or we could but the value is bad  while (!(cin >> result) || result < 1 || result > 3) {    // then we have some junk and must clean up.    cout << "invalid choice pick again" << endl;    cin.ignore(numeric_limits<int>::max, '\n');    cin.clear();  }  // Otherwise, we read in a valid value and can return it.  return result;}


This is useful enough that you'll want to make this function a bit more general in the future :)

Another approach is to read the data a full line at a time, and then re-parse the read lines. We do the parsing with a std::stringstream, and if it fails, no reset is required - we just try again by making a new stringstream with the next line of input.

int getNumber() {  string line;  // For as long as we can grab lines of input,  while (getline(cin, line)) {    // try to interpret the line beginning as an integer.    stringstream ss(line);    int result;    // and if we can do so, return the value.    if (ss >> result) return result;    // Otherwise, just let ss be destructed, and reconstructed for the next line.    // This approach also lets us easily check for garbage input after the    // number, if desired.  }  // Somehow we reached the end of input.  throw std::exception(); // TODO: make this more informative}
Liam78
Liam78
thx for the helps guys, one last thing how do i insert code blocks in the forums,,,
is it something like



example code here
SiCrane
SiCrane
You can use the [code] and [source][/source] tags. [source][/source] gives you the white box and [code] gives you tt formated text.
Thunder_Hawk
Thunder_Hawk
Alternatively you can use
cin.sync()
instead of
cin.ignore(numeric_limits<int>::max, '\n');


Besides being more concise to use (and not depending on the numeric limits header), I can't give you any advantages or drawbacks to this method as I haven't observed any thus far.
______________________________________________________________________________________The Phoenix shall arise from the ashes... ThunderHawk -- ¦þ"So. Any n00bs need some pointers? I have a std::vector<n00b*> right here..." - ZahlmanMySite | Forum FAQ | File Forma

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.