Sign in to follow this  
gah_ribaldi

Surely there's a way to... - c++

Recommended Posts

int price;
cout << "Enter amount of gold to send to Fred: "
cin >> price;

it looks so simple. But then the user enters 27u or something else which doesn't match the expected type, and before you know it the program falls over and starts stabbing itself in the eye. Is there a nice neat way to just reprompt?

Share this post


Link to post
Share on other sites
One way would be:

int price;
do {
std::cout << "Enter amount of gold to send to Fred: ";
if (!std::cin) {
std::cin.clear();
std::cin.ignore(std::cin.rdbuf()->in_avail());
}
std::cin >> price;
} while (!std::cin);

Though your code would accept "27u" as an input. It would parse it as 27 and leave the "u" in the input stream. To take that into account you can read by line and parse out via a stringstream. Ex:

int price;
for (;;) {
std::cout << "Enter amount of gold to send to Fred: ";
std::string text;
std::getline(std::cin, text);
std::istringstream sstr(text);
sstr >> price;
if (!sstr.fail() && !sstr.rdbuf()->in_avail()) break;
}

Share this post


Link to post
Share on other sites
Quote:
Original post by SiCrane
One way would be:

int price;
do {
std::cout << "Enter amount of gold to send to Fred: ";
if (!std::cin) {
std::cin.clear();
std::cin.ignore(std::cin.rdbuf()->in_avail());
}
std::cin >> price;
} while (!std::cin);

Though your code would accept "27u" as an input. It would parse it as 27 and leave the "u" in the input stream. To take that into account you can read by line and parse out via a stringstream. Ex:

int price;
for (;;) {
std::cout << "Enter amount of gold to send to Fred: ";
std::string text;
std::getline(std::cin, text);
std::istringstream sstr(text);
sstr >> price;
if (!sstr.fail() && !sstr.rdbuf()->in_avail()) break;
}


Nice. Would that code cope with 2u7 though?

Share this post


Link to post
Share on other sites
Quote:
Original post by SiCrane
What do you think? In particular, what do you think this line does?

if (!sstr.fail() && !sstr.rdbuf()->in_avail()) break;


Well, I'm not familiar with stringstreams and would have to do a bit of digging to fully understand the command but that looks like it'll only break out of the infinite loop you made if the stringstream didn't fail (not sure what activates fail since I'm unfamiliar with it) AND there's nothing left for it to run through.

So... the code runs through the string throwing away any unwanted characters and when it gets to the end exits gracefully leaving me with what I want.

Yes? Hmm. Maybe "not quite". I'm not sure what would happen if the user typed in "abc"

Share this post


Link to post
Share on other sites
fail() will return true if any formatted extraction operations didn't succeed. So putting in "abc" will cause fail() to return true, so the loop would repeat from the top. The in_avail() would check to see if there are any characters unused when reading the integer. So when reading "2u7" it would stuff the 2 into price, but fail() wouldn't return true since it managed to read some integer, but "u7" would be left in the buffer, so in_avail() would return 2, and the loop would repeat from the top.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this