CS 12 - Lab 1 Supplement


CS 12 Homepage

Streams: True or False?

So you may be wondering how to write a program that takes in all inputs and yet still knows when to quit. What input do you give it to tell it to quit? Won't we just wind up in an infinite loop?

Let us look at some other programs that do similar things. Try running the Unix program wc (short for word count), a program that counts the number of words, lines, and characters you type (or in a file if you specify one.)
> wc
testing testing one two three
hello, this is a test
is anybody home?



quit
exit
stop
EXIT
Nothing we type seems to be terminating the program. If we read the man page for wc, we will see that it expects to run until there is no more input. So the question is how to we specify to wc that there is no more input, and then how to we use that in our program?

The secret is actually one simple key combination: Ctrl+D. Ctrl+D (also written as ^D) tells the operating system "I am done typing, I will not give this program any further input." The operating system then informs the program that you are done by closing off the input to the program, which the program can then notice and terminate on its own. Try it on wc and see that it does actually work.

The natural question is then this: how do we write a program that can notice when the input to the program has been closed? Look back at the title of this section, and try to remember how I/O in C++ works. (If you don't recall the CS10 lectures on "streams", don't worry too much. If you do, think back to them, it'll help you some here.)

When the input to your program is closed, cin can never give you anything of use. The people that wrote the I/O libraries for C++ know this, and took advantage of it. If you happen to test the truth value of cin (like in an if statement or a loop conditional), then cin will return true if input is still open or false if the input is closed.

Let's look at an example snippet of code (you can fill in the rest of the code as needed if you want to see this compile in action):
// While the input is still open
while(cin)
{
   // Get the input
   cin >> myinput;
   cout << "Got " << myinput << endl;   
   

   // Process the input
   ...
}
What happens when we run this? (Every other line is input to the program and output from the program):
hello
Got hello
42
Got 42
camera
Got camera
^D
Got camera
Why did it do that? We didn't type "camera" twice. Examine the loop, bit by bit, remembering that unless we are insanely fast typists, the program is always waiting at the cin statement for more input (it takes maybe a thousandth of a second to execute the rest of the loop). When we hit ^D, cin is told to terminate and not return anything, so our variable does not get changed, and the loop has to continue until we check the looping condition again. Which explains why we get the bogus output.

So lets try something a little sneaky. Let's make sure that we get the input right before we check the looping condition. Try this:
cin >> myinput;
while (cin)
{
   cout << "Got " << myinput << endl;
   
   // Process the input
   ...

   cin >> myinput;
}
Now every time that we are waiting for input from cin, we immediately check the loop condition right afterward, and can terminate appropriately. This technique will help you both in this lab and in your first programming project. Keep it in mind in the future, it can be very helpful.

But it turns out we can do even better than this. istream >> has been written to return "false" when a read fails. So the code
while (cin >> myinput)
{
    // Process the input
    ...
}
also works correctly, and is even easier to remember, so long as you remember that streams return false when a read fails.

© 2003 UC Riverside Department of Computer Science & Engineering. All rights reserved.