0

I currently have a function set up that asks the user for an int, obtains that int, and then checks to make sure that the input meets a certain specification. In this case, its expected that the input will be an integer between -10 and 100. As of now, if I input any string of letters E.G. "gfUIWYDUF", the function returns a 0. Why is this happening and how do I fix it?

int readUserInput() {

  cout << "What is the answer?: " << endl;

  int answer;

  do {
    cin >> answer;
    if (!cin || answer < -10 || answer > 100) {
      cout << "Invalid Input!" << endl;
      cout << "What is the answer?: " << endl;
      cin.clear();
      cin.ignore();
    }
  } while(!cin || answer < -10 || answer > 100);
  return answer;
}
  • 1
    `cin.ignore()` ignores 1 character, it would be better to ignore all the rest of the input – M.M Nov 19 '19 at 03:38
  • When `cin >> answer` encounters a character that cannot be interpreted as an `int` value, it stops reading and returns. The offending character is left in input. Before C++11, `answer` was left unmodified, since C++11 it is set to zero. Better to read a `std::string` from `std::cin` using `std::getline()` - then you can check the string, decide if it has input that represents an `int` value (e.g. digits, sign characters), discard any extraneous characters, and THEN extract the integral value from the string. – Peter Nov 19 '19 at 03:45

3 Answers3

0

If you play with the input values you will find that cin >> scans from left to right until it finds any non-numeric value. It then evaluates the numbers it did find.

For example, putting:

57gh5

Returns 57

If you enter only numeric characters, you have a score of 0.

If you cin >> string instead, then you will be able to parse/validate the string and convert a valid number into an int

Chris
  • 2,655
  • 2
  • 18
  • 22
0

The problem is that your validation loop for this type of input depends on the error state of std::cin. However, you clear that error state before the loop checks for it.

The simplest way to fix this is to move your reading from std::cin to after the clear() like this:

// Read first
cin >> answer;
do {

    if (!cin || answer < -10 || answer > 100) {
        cout << "Invalid Input!" << endl;
        cout << "What is the answer?: " << endl;
        cin.clear();
        cin.ignore();
        cin >> answer;
    }
} while(!cin || answer < -10 || answer > 100);

Though, I think I prefer using a regular while loop instead myself:

cin >> answer;

while(!cin || answer < -10 || answer > 100) {
    cout << "Invalid Input!" << endl;
    cout << "What is the answer?: " << endl;
    cin.clear();
    cin.ignore();
    cin >> answer;

}

This feels cleaner to me, but that's just me. Both loops will work.

0

0 is returned as the initial value of answer

You may use cin.fail() to check if the input is valid.

int readUserInput() {

  cout << "What is the answer?: " << endl;

  int answer;

  do {
    cin >> answer;
    if (cin.fail() || !cin || answer < -10 || answer > 100) {
      cout << "Invalid Input!" << endl;
      cout << "What is the answer?: " << endl;
      cin.clear();
      cin.ignore();
    }
  } while(cin.fail() || !cin || answer < -10 || answer > 100);
  return answer;
}
siusiulala
  • 1,040
  • 1
  • 12
  • 24
  • It's not the initial value -- there was no initial value. The 0 is set by istream in the case of parse failure. – M.M Nov 19 '19 at 03:38