1
#include<iostream>
#include<limits>

int main()
{
    int m;
    std::cin >> m;
    while (std::cin.fail() || m <= 0) {
        std::cin.clear();
        std::cin >> m;
    }
    return 0;
}

The above code is supposed to prompt for an input until a positive integer is entered. But even after entering a positive integer it keeps prompting for an input. For example, lets say I have the input as

abc
c4
-3
1
2
.
.

So in principle the moment I enter 1, the execution should be transferred out of the loop. But it keeps prompting for an input and looks like an infinite loop.

After looking around for a while, I modified it as

cin >> m;
while (cin.fail() || m <= 0) {
    cin.clear();
    cin.ignore(numeric_limits<streamsize>::max(),'\n');
    cin >> m;
}

As desired, entering a positive number terminates the loop. I didn't get it. Why the new line character is stuck in the input buffer? Suppose I have this

int a , b;
cin >> a;
cin >> b;

When my input is

1
2

It correctly sets a to 1 and b to 2, instead of setting b to \n. Why is the behaviour different in the two cases?

4
  • 1
    How would b get set to \n? b is an integer. Commented Oct 9, 2015 at 11:48
  • @KarolyHorvath variables have been defined. Sorry I forgot it Commented Oct 9, 2015 at 11:49
  • Don't "forget" it. Present your clear, concise and precise minimal testcase that demonstrates the issue so that we are not guessing/assuming at things that you may or may not have done. Commented Oct 9, 2015 at 11:50
  • @LightnessRacesinOrbit Then how in the very first code snippet, m is being set to \n Commented Oct 9, 2015 at 11:51

2 Answers 2

1

It's not that there's a stray newline, but that the entire input is still in the stream.

cin >> m fails immediately if it can't extract an integer.
It does not read the next "word" and see if it's an integer, and then stop after that "word" if it wasn't - the "read pointer" is left at the point of initial failure.

The ignore skips ahead to the end of the line and ignores everything up to that point.

To illustrate the difference, this program tries to read the input first as int and if that fails, reads the same input again as a std::string for use in the error message:

int main() {
    int n = 0;
    string s;
    while (!(cin >> n))
    {
        cin.clear();
        cin >> s;
        cout << "That wasn't an int, it was " << s << endl;
    }
    cout << "This is an int: " << n << endl;
}

The solution you found with ignore is pretty much the "standard" solution.

Sign up to request clarification or add additional context in comments.

2 Comments

That's what the ignore is for, no? Why extract the characters when you can skip over them? And how is this solution different from the OP's? At best, it is and you need to explain why. At worse, it isn't.
@LightnessRacesinOrbit I tried to make it clearer that the code wasn't an alternative solution so much as an illustration. (The question is why the behaviour is different, not what the best solution is.)
0

The newline will be eaten up when extraction succeeds (whether the extracted integer is positive or not).

It won't be eaten up when extraction fails.

7 Comments

So what exactly happens at cin >> m in the first code snippet.
I have no idea, because you did not demonstrate the issue showing your input. Why don't you simply step through the program in your debugger, examining the stream state and value of m at every step?
Let the input be abc
@ibrahim There is no positive integer in that input. Why would the program end? Demonstrate the issue. I won't tell you again.
@ibrahim5253: stackoverflow.com/help/mcve Not sure why you're having trouble following instructions.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.