First Next Previous Last Glossary About

An introduction to streams


Introduction

As with strings the current standard of C++ makes the handling of files very straightforward, it was much more difficult in C.

Essentially cout and cin are files, streams are files. According to Bruce Eckel "A stream is an object that formats and holds bytes" so streams can be things other than the conventional file.

Another look at cout and cin

We have used two streams:

//files_ex1.cc
#include <iostream>

int main()
{ char c;

  while (cin >> c)
   cout << c;
   
  return 0;
}
The output:
Sample 1
--------
   
INPUT -->    hello from me
OUTPUT ->    hellofromme

Here is a simple example of using cin and cout. The program works through a while loop. It reads a character from the cin stream and writes the character to the cout stream. If you compile and run the program you get the output shown here. You can see that whitespace has been stripped from the input. This is how cin behaves when reading simple data types, whitespace separates variables read from the standard input device.

The program is terminated by EOF (End Of File). On Linux this will be ^D (control D), on Win/DOS this will be ^Z (control Z). When cin encounters an EOF then the condition (cin >> c) becomes false and the while loop terminates.

You can see that in the while loop the program reads 1 character from stdin with the statement cin >> c and writes the same character (excluding whitespace) to stdout with the statement cout << c;.

If the while loop reads a character then writes a character, why does it take a line of input data and then echo the whole line? Why not a character at a time?

The reason is that the input is buffered and an EOLN (End Of Line - the enter key) terminates input. When input data is extracted from cin the program calls for a service from the operating system, in this case get a character from stdin. Since, when using stdin, you indicate the end of input by pressing the enter key a call to use cin won't return to the program until the enter key is pressed. Any data that is entered is kept in a data buffer that is external to the program.

The first time you run the program you type in several characters then press Enter. The example progam requests a single character at a time from cin so each use of cin in this example takes just one character from the external data buffer. Eventually EOLN is encountered and all the characters are displayed on stdout.



//files_ex2.cc
#include <iostream>
#include <string>

int main()
{
 string m;
 
//read a line from input stream
 while (getline(cin,m)) 
 //write a line to output stream
   cout << m
        << endl;    

 return 0;
}

This example shows how to get a complete line of input using a string and the getline() function. This function has two arguments, the first is the stream from which the line will be read, the second is the string which will contain the line.

The getline() function will read a complete line including whitespace but excluding the EOLN terminator. In UNIX the EOLN is a LF (linefeed) character. In Win/DOS the EOLN is a CR/LF pair (carriage return/linefeed).

As with the previous example an EOF terminates the program.

This is a line of input
This is a line of input


Redirecting the cout stream

Usually the cout stream destination is the computer display and the display is assigned to the standard output file - stdout. We can assign another destination by using the > (redirect output) operator on the command line.

./a.out > eliot
the winter evening settles down
to smells of steaks in passageways.
6 o'clock - the burnt-out ends of dusty days

This example shows output redirection. Now all the input for files_ex2.cc is written to a file called eliot rather than to the screen. You won't see any output on the screen.

As with the previous examples an EOF terminates the program.



Redirecting the cin stream

Just as the cout stream destination can be redirected so too the cin source. By default the cin stream is the keyboard which is assigned to the standard input device - stdin. It can be redirected by using the input redirection operator on the command line.

./a.out < eliot
the winter evening settles down
to smells of steaks in passageways.
6 o'clock - the burnt-out ends of dusty days.

Now the input comes from the file eliot and the ouput goes to the screen.



Redirecting both streams

Combining input and output redirection is simply a matter of using the two operators with appropriate files.

./a.out < eliot > prelude

This command line, again using the compiled file files_ex2.cc takes its input from the file eliot and writes its output to the file prelude.

This kind of operation could be used to carry out a file copy.



Sending output to other programs

Apart from redirecting program output and input to and from files or devices other than stdout and stdin, it is also possible to send program input and output to other programs. This is done by using the pipe operator | (broken vertical bar) on the command line. Here is an example:

1. compile and link files_ex2.cc to an executable called do_file:

g++ -o do_file files_ex2.cc

2. run do_file as shown here:

UNIX:
./do_file < eliot
the winter evening settles down
to smells of steaks in passageways.
6 o'clock - the burnt-out ends of dusty days

DOS:
do_file < eliot
the winter evening settles down
to smells of steaks in passageways.
6 o'clock - the burnt-out ends of dusty days

3. now try the command line shown here:

UNIX:
./do_file < eliot | sort
6 o'clock - the burnt-out ends of dusty days
the winter evening settles down
to smells of steaks in passageways.

DOS:
do_file < eliot | sort
6 o'clock - the burnt-out ends of dusty days
the winter evening settles down
to smells of steaks in passageways.

This command line now takes the output from do_file and "pipes" it to the input of the sort utility program. Both UNIX and DOS have a sort utility. The UNIX version has many more features.



In the next module we do much more work with files.

Return to top of page


Tutorial

Exercise 1.

David
Edward
Stella
Karen
Ellie
Clara
Rachel
Celia  

(a) Use the do_file program to create a file called names. It should contain the data shown here, one name per line.



#include <iostream>
#include <string>
#include <iomanip>

int main()
{
  int count = 0;
  string m;

  while (getline(cin, m))
  { ++count;
    cout << "Line number: "
         << setw(4)
         << count
         << " " + m
         << endl;
  }

}  

(b) Build this progam to an executable called counter (or counter.exe in DOS).

The program takes lines from the input, numbers each line and sends an amended line to the output.



(c) Use this command line and then compare the files names and names.num.

UNIX:
./do_file < names | ./counter | sort +19 > names.num

DOS:
do_file < names | counter | sort /+19 > names.num

The command line runs do_file which takes the input from the names file. The ouput of do_file is piped to the progam counter and the output of counter is piped to the sort program. The sort program sorts its input on column 19 and redirects its output to the names.num file.

Exercise 2.

The UNIX who command determines which users are logged in and displays output like this:

root     tty1     Aug 30 08:23
david    ttyp0    Aug 30 09:49 (drbeech)
john     ttyp1    Aug 29 23:30 (terra.tafe.tas.edu.au)

The last field eg: (terra.tafe.tas.edu.au) shows that the user is logged on from a remote host.

Write a program which takes the output of who and generates lines of output like this:

USER david   logged on from host drbeech on Aug 30 13:23
USER john    logged on from host terra.tafe.tas.edu.au on Aug 30 13:28
USER root    logged on locally on Aug 30 08:23
USER student logged on locally on Aug 30 13:28

The output should go to a file called who_where.txt and should be sorted in user name order.

You will need to use strings to do this exercise.

There is a sample answer for this exercise.

Return to top of page


First Next Previous Last Glossary About


Bruce Eckel "Thinking in C++", Prentice-Hall

Copyright © 1999 - 2001 David Beech