Jump to content
  • Advertisement
Sign in to follow this  
FlaiseSaffron

Error handling with cin [solved]

This topic is 4090 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

The following code breaks if I type anything other than a number:
map options = ...;

int choice;
while(true) {
	cout << "Input selection:\n> ";
	cin >> choice;
	if(options.count(choice) > 0)
		return choice;
	cout << "Invalid selection.\n";
}


----------Output---------- Input selection: > 489 Invalid selection. Input selection: > No. Invalid selection. Input selection: > Invalid selection Input selection: > Invalid selection Input selection: > Invalid selection Input selection: > Invalid selection Input selection: > Invalid selection Input selection: > Invalid selection Input selection: > Invalid selection Input selection: > Invalid selection Input selection: > Invalid selection Input selection: > Invalid selection (repeats until program is terminated) How do I make my program reject non-digits instead of breaking like this? [Edited by - Dathgale on July 13, 2007 8:59:06 PM]

Share this post


Link to post
Share on other sites
Advertisement
Set choice to 0 after each loop.

while(true) {
cout << "Input selection:\n> ";
cin >> choice;
if(options.count(choice) > 0)
return choice;
cout << "Invalid selection.\n";
choice = 0;
}

Share this post


Link to post
Share on other sites
Stormtrooper, thanks, but that does not do anything because the line 'cin >> choice;' overwrites the 0. I just tried it to make sure.

EDIT:
Durfy, can you reword that as a series of steps so a noob can understand? I have little experience with C++.

Share this post


Link to post
Share on other sites
1) #include<sstream.h>
or #include<sstream>
using namespace std;


2) sstream ss;
cout<<"Enter a number:";
cin>>ss;
if (ss (wierd parsing stuff here)) {
cout<<"Thats not a number dummy!";
}
else {
cout<<"Thank you for following instructions!";
}

3) Go to msdn.com and search string stream and there is much more info there as i haven't used it in a while and am not totally sure I used it right;
-durfy

Share this post


Link to post
Share on other sites
You can check a stream for a parsing problem on extraction by testing the stream object as a boolean value. Ex:

int i;
std::cin >> i;
if (!std::cin) {
// not an int, do stuff
} else {
// an int do other stuff
}

Share this post


Link to post
Share on other sites
In addition to what SiCrane said, operator>> for std::cin actually returns an istream object, which enables you to do the following:

#include <limits>

while (std::cout << "Input selection:\n> " && (!(std::cin >> choice) || options.count(choice) <= 0))
{
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

std::cout << "Invalid selection.\n";
}

return choice;


Note that you need to clear the bad state of the stream in the case of bad input, or else it won't allow further input and the loop will become endless. For further information, see this website.

Hope this helps.

Share this post


Link to post
Share on other sites
That worked. Using cin.clear() by itself had no apparent effect, but I didn't realize that I had to ignore the extra characters left over after attempting to parse a number. Thanks a lot.

Share this post


Link to post
Share on other sites
Quote:
Original post by Stormtrooper
Set choice to 0 after each loop.

while(true) {
cout << "Input selection:\n> ";
cin >> choice;
if(options.count(choice) > 0)
return choice;
cout << "Invalid selection.\n";
choice = 0;
}


Wrong. The problem is with the state of std::cin, not the contents of choice.

Quote:
Original post by Durfy
You have to set it up as a string stream... then parse based on that.
-durfy


Wrong; although this approach generally makes things easier, it's not mandatory; and besides, actually remembering how to set it up would be more useful.

Quote:
Original post by Dathgale
Stormtrooper, thanks, but that does not do anything because the line 'cin >> choice;' overwrites the 0. I just tried it to make sure.


Wrong about why it's wrong. Reading from cin is skipped as long as the stream is in the invalid state, so it will just use the existing 0 value immediately - if there's no 0 in your map, it won't get returned. (Also, using .count() on something you know to be a map is a little strange, although valid; the usual way to look things up is with .find() or the operator[]. The .count() function is really only provided for std::map for people who want to write template code that works with both ordinary maps and multimaps.)

Quote:
Original post by SiCrane
You can check a stream for a parsing problem on extraction by testing the stream object as a boolean value. Ex:

int i;
std::cin >> i;
if (!std::cin) {
// not an int, do stuff
} else {
// an int do other stuff
}


Right, but not enough information to be useful.

Quote:
Original post by Darklighter
In addition to what SiCrane said, operator>> for std::cin actually returns an istream object, which enables you to do the following:

*** Source Snippet Removed ***

Note that you need to clear the bad state of the stream in the case of bad input, or else it won't allow further input and the loop will become endless. For further information, see this website.

Hope this helps.


Right, and finishes off being useful WRT that approach.

For the stringstream approach:


#include <sstream> // in addition to whatever else you had

while (true) {
std::cout << "Input selection:\n> ";
std::string input;
std::getline(std::cin, input);
// "If we can read from an input-stringstream constructed from input, into choice, and"
int choice; // declare variables near first use, please.
if ((std::istringstream(input) >> choice) &&
// "the result of looking for choice is not the end iterator (which is returned to indicate not-found)"
(options.find(choice) != options.end())) {
return choice;
}
std::cout << "Invalid selection.\n";
}

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!