user82216
user82216

Reputation:

How is (cin) evaluated?

In Bjarne Stroustrup's Programming Principles and Practice Using C++ (Sixth Printing, November 2012), if (cin) and if (!cin) are introduced on p.148 and used in earnest on p.178. while (cin) is introduced on p.183 and used in earnest on p.201.

However, I feel I don't fully understand how these constructs work, so I'm exploring them.

If I compile and run this:

int main()
{
        int i = 0 ;
        while (cin) {
                cout << "> ";
                cin >> i ;
                cout << i << '\n';
        }
}

I get something like:

$ ./spike_001
> 42
42
> foo
0
$

Alternatively, if I run and compile this:

int main()
{
        int i = 0 ;
        while (true) {
                cout << "> ";
                cin >> i ;
                cout << i << '\n';
        }
}

I get something like:

$ ./spike_001
> 42
42
> foo
> 0
> 0
...

The last part of user input here is foo. After that is entered, the line > 0 is printed to stdout repeatedly by the program, until it is stopped with Ctrl+C.

This is using g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3.

I'm sorry for such a long question, but I think it all boils down to, "How is cin evaluated?"

Upvotes: 0

Views: 144

Answers (2)

Shoe
Shoe

Reputation: 76280

Well, std::cin (or more precisely std::basic_ios) has an operator bool to implicitly convert the std::cin object to a bool when requested (for example in your if evaluation).

The semantic is as follows:

Checks whether the stream has no errors. Returns true if the stream has no errors and is ready for I/O operations. Specifically, returns !fail().


Why is it that entering "foo" apparently causes i to be set to 0?

Again, why is it that entering "foo" apparently causes i to be set to 0?

Because operator>> on an int expects an integer in the string.

From cppreference:

If extraction fails (e.g. if a letter was entered where a digit is expected), value is left unmodified and failbit is set.


Why is it that entering "foo" causes cin to be set to false?

Because the fail bit is set, therefore leading fail() to return true.


Why is it that the user is not prompted for a new value for i on the next iteration of the while loop after foo was entered?

That is because std::cin has the fail bit set, therefore it fails to get the input and just prints the old value of i which is 0.

Upvotes: 1

Corbin
Corbin

Reputation: 33457

When you use the >> operator on a stream, it attempts to extract a value of that type from the string. In other words, when you do cin >> i where i is an int, the stream attempts to pull an int from the stream. If this succeeds, i is set to the extracted value, and all is well. If it fails, the stream's badbit is set. This is important because treating a stream as a bool is equivalent to checking if it's badbit is set (if (cin) is like if (cin.good())).

So anyway... what's happening is that foo is setting the badbit since the extraction fails. Really, you should be checking if the extraction succeeds directly:

if (cin >> i) { /* success */ }

On a code quality note, I suspect you're using using namespace std;. Please be aware that this can be harmful.

Upvotes: 1

Related Questions