Previous Table of Contents Next


Chapter 4
Input, Output, and C++

In Chapter 2, I introduced input/output techniques to help you write simple programs. But there’s a good deal more to C++ input and output.

C++ is object-oriented, and it provides an object-oriented approach to input and output through stream objects, which are supported by the C++ standard library and header files. Stream objects are not supported in C. If you have a C background, stream objects may be the first C++ extension you use regularly. On the other hand, introducing these objects into your programs is entirely optional.

Not all input and output involves the keyboard and screen. Just as important, particularly in serious programs, is the process of reading and writing to data files. This chapter examines different file reading and writing techniques.

Going with the Flow: Introduction to Streams

In this chapter, you’re going to see the term stream a good deal. It is often used in systems programming generally. What is a stream?

Speaking literally, a stream is a flow of water. In computer programming, a stream is a flow of data. One of the chief characteristics of a stream is that it is a one-directional flow. Although you might argue that this isn’t absolutely true (even a small stream can have whirlpools and back-flows), it’s true enough to hang a metaphor on. An input/output stream is a sequence of bytes continually flowing in one direction or another, either input or output.

Another characteristic of a stream is that it is nearly inexhaustible. Streams sometimes run dry, but you don’t expect this to happen often. An output stream, in particular, will always accept another byte (except under rare error conditions such as a full disk).

The two most commonly used streams in programming are standard input and standard output, and they do not run dry. You can always ask standard input to provide another ASCII character from the keyboard, and you can always print another character on the screen (see Figure 4.1).


Figure 4.1.  Input and output streams.

Files are also considered streams. When you perform file input or output, you can always put or get the next byte. “The next byte” is always valid, except under error conditions. An example of something that holds data but is not a stream is an array or data structure. An array, for example, always has a specific size and cannot grow as an output file can.

To some extent, the concept of streams is a fiction created by computer scientists. An area of random access memory (RAM), for example, can be treated as a large array, or it can be used as virtual disk memory, which in turn can support streams. It’s the same hardware in either case. As with many other concepts in programming, what makes something a stream is how it is treated. In the final analysis, a stream is a context in which the idea of “the next byte” makes sense.

A stream is either an input or an output stream. The following statements are true, barring error conditions such as end-of-file or disk full:

  With an input stream, you can always read the next byte.
  With an output stream, you can always write another byte.

The ability to read or write the next byte implies the ability to read or write any number of bytes. Writing a two-byte field, for example, is the same as writing one byte and then writing another byte. Of course, the bytes must be read and written in a consistent order.

Stream Operators (<< and >>): A First Look

Stream operators (<< and >>) provide an alternative to using printf, scanf, and the other functions defined in STDIO.H. The stream operators provide two advantages: you don’t have to use format specifiers if you are happy with the default formats, and it’s possible to extend the operators so that they work with your own classes. (The next chapter introduces the subject of classes.) For information on how to extend the operators, see the topics “istream Class” and “ostream Class” in Part III.

This chapter presents several input/output techniques: printf and scant stream operators, and line-based input. You should not mix these techniques in the same program. You can pick any kind of input technique and any kind of output technique (for example, mixing printf with line-based input), but don’t switch between two different kinds of input. The C++ standard library uses different I/O buffers for each technique, so mixing them causes unpredictable results.

Here is a simple program that gets two floating-point numbers and then prints their sum:

#include <iostream.h>

void main() {
   double a, b;

   cout << “Enter the first number: ”;
   cin >> a;
   cout <<  “Enter the second number: ”;
   cin >> b;
   cout << “The total is ”;
   cout << a + b;
}

This program behaves the same way as the following program, which uses printf and scanf:

#include <stdio.h>

void main () {

   double a, b;

   printf(“Enter the first number: ”);
   scanf(“%If”, &a);
   printf(“Enter the second number: ”);
   scanf(“%If”, &b);
   printf(“The total is %s”, a + b);
}

Note the following important points about the version that uses the stream operators, cin, and cout.

  The file IOSTREAM.H, rather than STDIO.H, is included.
  No format specifiers are needed. C++ uses the type of the object (a and b in the example) to determine how to perform the data transfer. In this respect, the stream operators are like the Basic PRINT statement and are a little easier to use than printf and scanf.
  The address operator (&) isn’t used to get input, as it is in scanf. (Here, input streams act more like Basic by using reference arguments, which you’ll learn more about in Chapter 6.)
  Data flows toward standard output (cout), which usually represents the display screen:
      cout << “Enter the first number: ”;
  Data flows from standard input (cin), which usually represents the keyboard:
      cin >> a;


Previous Table of Contents Next