6

New to C++. Having issues correctly looping while handling errors. I am trying to check if user input is an integer, and is positive.

do{
    cout << "Please enter an integer.";
    cin >> n;

    if (cin.good())
    {
        if (n < 0) {cout << "Negative.";}
        else {cout << "Positive.";}
    }
    else
    {
        cout << "Not an integer.";
        cin.clear();
        cin.ignore();
    }
}while (!cin.good() || n < 0);

cout << "\ndone.";

When a non-integer is entered, the loop breaks. I feel like I am misunderstanding the inherent usage of cin.clear() and cin.ignore() and the status of cin during this loop. If I remove the cin.ignore(), the loop becomes infinite. Why is this? What can I do to make this into an elegantly functioning loop? Thank you.

olevegard
  • 5,294
  • 1
  • 25
  • 29
xavi
  • 423
  • 4
  • 8
  • 13

2 Answers2

6

In your non-integer branch you are invoking further cin methods so cin.good() gets reset to true.

You could change your code to something like this:

while(1) { // <<< loop "forever"
    cout << "Please enter an integer.";
    cin >> n;

    if (cin.good())
    {
        if (n < 0) {cout << "Negative.";}
        else { cout << "Positive."; break; }
    }                            // ^^^^^ break out of loop only if valid +ve integer
    else
    {
        cout << "Not an integer.";
        cin.clear();
        cin.ignore(INT_MAX, '\n'); // NB: preferred method for flushing cin
    }
}

cout << "\ndone.";

or you can simplify it even further like this:

while (!(cin >> n) || n < 0) // <<< note use of "short circuit" logical operation here
{
    cout << "Bad input - try again: ";
    cin.clear();
    cin.ignore(INT_MAX, '\n'); // NB: preferred method for flushing cin
}

cout << "\ndone.";
Paul R
  • 208,748
  • 37
  • 389
  • 560
  • 1
    This works fantastically, thank you! I didn't even think that my choice of loop was holding me back. I appreciate the help and the explanation. – xavi Sep 02 '13 at 07:28
  • Wouldn't the second version result in an endless loop once the user entered junk (i.e. something like "abc")? You need to extract (or ignore) the junk before looping (but after the `clear()`). – James Kanze Sep 02 '13 at 09:16
  • 1
    @James: good catch - thanks - I've fixed it now (and actually tested it !). – Paul R Sep 02 '13 at 09:25
3
int n;

while (!(cin >> n)||n<0)//as long as the number entered is not an int or negative, keep checking
{
cout << "Wrong input. Please, try again: ";
cin.clear();//clear input buffer

}
//only gets executed when you've broken out of the while loop, so n must be an int
cout << "Positive.";

cout << "\ndone.";//finished!

Should do what you want.

imulsion
  • 8,820
  • 20
  • 54
  • 84