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

Started by
4 comments, last by SiCrane 16 years, 3 months ago

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?
Advertisement
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;  }
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?
What do you think? In particular, what do you think this line does?
if (!sstr.fail() && !sstr.rdbuf()->in_avail()) break;
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"
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.

This topic is closed to new replies.

Advertisement