cin in a loop

So I've noticed something, and I've always just made a work around, but I would like to see if I could either get the issue solved so I don't have to make a workaround or at least figure out why it does what it does.

Basically I've noticed in my C++ books (C++ Primer 5th Ed.) that the author produces a lot of while loops with cin as the parameters. As an example:

1
2
3
4
while(cin >> intVar)
{
    cout << intVar << endl;
}


It was either read in the book or an assumption I made that if someone were to not enter a number, the loop would terminate and the program would go on to it's next set of tasks. Now, when I do this nothing happens. To get around this I've usually done something like this:

1
2
3
4
while(cin >> intVar && intVar != 7201993)
{
    cout << intVar << endl;
}


This would also happen with strings, which was fixed by simply using getline:

1
2
3
4
while(getline(cin, strVar))
{
    cout << strVar << endl;
}


Am I wrong to assume that the author intended the loop to terminate when no information is given but the user presses enter? If not, why is it not working on my end and how could I fix this?
The condition for a loop to break is a statement, whose value must evaluate to boolean value false. Now, in C++ almost any statement evaluates to something and that something can be casted to bool. The simplified rule is that everything evaluates to true, except 0, \0, null.

For this reason you may create a loop:
1
2
while (x) // and not neccessarily while(x > 0)
    x--;

and it will go x times, because when x = 0, it is casted to bool and returns false.

Now, you might not have been aware, that cin is not a simple keyword of C++ language. It is in fact a function that returns object of class istream:
http://www.cplusplus.com/reference/iostream/cin/ .

Now, consider the >> operator. Operator overloading mean anyhing to you yet? When you use >> with cin you are calling a function explained here:
http://www.cplusplus.com/reference/istream/istream/operator%3E%3E/
(Or more precisely one of these functions, depending on what type is the variable you try to save data to, like intVar.) This function is returning something. This something may be casted to bool, and the result will be either true or false.

Now, did you notice, that when you declare a variable of type int you cannot cin a letter into it? In such event the return value of operator>>(int) is a boolean false. It would cause the loop to break.

You assumed that while(cin >> var) will break if you simply press enter. In fact it would break whenever what user inputs cannot match the var's type - and makes the operator function return value that is boolean equivalent of false.

So in short - much depends on type of the var you cin into, and part of your problem may be that intVar is not quite a var of type int.

Notice that these two loops are much different:
1
2
3
4
5
6
7
8
9
10
11
12
int intVal;
char charVal;
while(cin >> intVal)
{
    cout << intVal; // mirrors your numbers
}
cout << endl << "Now the other loop" << endl;
while (cin >> charVal)
{
    cout << charVal; // mirrors single letters of what you type.
    // Breaks in different situations than the previous loop
}


Look how this would work when you input all digits, digits and letters, multiple letters and so on.
Last edited on
Using formatted extraction ignores leading whitespace and only extracts data that fits the type of the variable being used.

1
2
3
4
while(cin >> intVar)
{
    cout << intVar << endl;
}

If, for the above code, you enter "9\n" (ie. 9 followed by enter/return) line 1 extracts the 9 and leaves the newline in the buffer. If the loop condition evaluated to false whenever a newline was encountered, the loop would terminate on the next iteration of the loop.

The loop actually terminates when you enter text that cannot be interpreted as a number. Inputting "r\n" will cause cin to enter an error state and the expression in the loop condition will evaluate to false. Nothing will be extracted from the stream, because there was no data that fit the type of the variable being used.

Useful links:
http://www.parashift.com/c++-faq/input-output.html
There is a context where while (cin something) makes good sense. That is, when running a console program from the command line, instead of typing the input from the keyboard, the program may take its input from a file.
Simple example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>

using namespace std;

int main()
{
    int total = 0;
    int n;
    
    while (cin >> n)
        total += n;
        
    cout << total << endl; 

    return 0;
}

Suppose this program is compiled to give an executable program called sum. Suppose also that there is a text file containing a list of numbers, named numbers.txt

Then, on the command line, type this to run the program:
 
sum < numbers.txt

The program will read the numbers from the file, and print out their total.
Sorry for the late response, all three of these answers helped out a lot, thank you for them. As for Operator Overloading, I have not reached that part of my book yet, though I think it is coming up soon. I wasn't aware of why putting an int into a cin >> strVar would fail, just knew that it would. I checked out the link for istream::operator>>, thanks for the link.
Topic archived. No new replies allowed.