0

So I am trying to allow a user to make a selection but Im having issue. the following lines

cout << "\nWhat would you like to do? " << endl
    << "(1) Display the entire List" << endl
    << "(2) to exit" << endl;

getline(cin,answer);
answerint=stoi(answer);
switch (answerint) {
    case 1:
        showLIST(myLIst);
        break;
    case 2:
        return;
    default:
        cout << "\nPlease choose from the list";
   }

So this works fine if the user chooses a integer, but it barfs if a character is received. How can I make this less breakable?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Rob McNeil
  • 51
  • 8
  • perhaps avoid converting arbitrary input to an int? Or catch the thrown exception and handle it gracefully? – Matt Coubrough Nov 04 '14 at 01:41
  • You need to check the values and make sure they are valid before you work with them. –  Nov 04 '14 at 01:42
  • Related: http://stackoverflow.com/questions/24504582/test-whether-stringstream-operator-has-parsed-a-bad-type?noredirect=1#comment37965807_24504582 – πάντα ῥεῖ Nov 04 '14 at 01:43
  • Im a bit novice to C++ so Im looking for a better practice if there is one or a way to make this more practical. @hosch250 what do you recommend to check for its validity? – Rob McNeil Nov 04 '14 at 01:49
  • Put the values in a `string` and iterate over each character to make sure there are no invalid characters in the string. If there are, either remove them or make the use input another value. Then, you can convert it to an `int`. –  Nov 04 '14 at 01:52
  • @hosch250 That's one of the worser advices. _@RobMcNeil_ Check out that linked Q&A I've mentioned. – πάντα ῥεῖ Nov 04 '14 at 01:59
  • OK, I agree that the Q/A you linked to is better advice. –  Nov 04 '14 at 02:02

2 Answers2

1

It seems you want something like this:

if (std::cin >> answerint) {
    switch (answerint) {
        // ...
    }
}

Converting the integer directly from the stream puts the stream into failure state in case something different than an int is entered. You may want to add a manipulator to make sure there are no non-space characters on the end of the line.

Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380
0
std::string answer;
int answerint;
while (std::getline(std::cin, answer))
{
    std::istringstream iss(answer);
    char c; // seek non-whitespace after the number?
    if (!(iss >> answerint) || (iss >> c))
        answerint = 0;
    switch (answerint)
    {
      ...as you had...
    }
}

The code above uses getline to ensure a complete line of text is parsed into answer, after which it creates a distinct std::istringstream from that single line. That way, we can use >> knowing it won't skip over newlines are consume or wait for further input.

if (!(iss >> answerint) || (iss >> c)) checks whether there isn't a number to parse into answerint, or after having parsed a number an additional non-whitespace character appears on the line. For example, the line typed might have been 2r - we'll consider that an error and reprompt for a selection, assigning 0 to answerint to ensure we reach the default label in the switch, thereby printing cout << "\nPlease choose from the list"; which seems as appropriate for 2r as for 99 or whatever....

Using getline and a separate istringstream this way, you can reliably attempt parsing of the next line of input from a known state.

Tony Delroy
  • 102,968
  • 15
  • 177
  • 252