This appendix is primarily for students with a background in C programming, but with little or no C++ programming. In the appendix we provide details of the C++ approach to reading from standard input, writing to standard output, and reading/writing files.

Writing to Standard Output

The i nsertion operator (written << ) is used to write a value to an output stream such as the standard output device (usually the monitor screen). For example, if i is an integer variable, then the following statement writes its value to the standard output:

cout << i;

In this statement, cout stands for the "console output," and is defined as part of the header file iostream.h . You may write several items at once by chaining together a sequence of insertion operators. For example, if i , j , and k are integer variables, then the following statement first writes i , then j , and finally k to the standard output:

cout << i << j << k;

Writing the End of a Line

There are two ways to write the end of a line to an output stream. You may simply write the newline character '\n' , or you may write the special object called endl (which is part of iostream.h ). For example:

cout << '\n';

cout << endl;

What's the difference between these two statements? The main difference deals with the fact that output is often written to a special place called a buffer, rather than to the actual output device. When the buffer becomes full, the output is "flushed" from the buffer to the actual output device. Such buffering can cause problems if a program crashes before the buffer is flushed. The buffer may contain some output that never shows up on the output device. To avoid this problem, whenever you write the endl object, the output buffer is automatically flushed. However, simply writing the newline character does not automatically flush the output buffer.

Setting the Field Width of an Output Item

The field width of an output item is the preferred number of output characters to be used when the item is printed. For example, if you print the number 123 with a field width of eight, the result will be five blank spaces followed by the digits 123 for a total of eight characters. If the output item won't fit in the specified field width, then more characters may be used. For example, if you print the number 123 with a field width of only two, then the entire number 123 is still printed (even though this requires three characters rather than just two). If you define the field width to be zero, the item will be printed using the minimum possible number of characters.

How do you define the field width for an output item? One method is to use a special "manipulator" named setw , which is part of iomanip.h . The setw manipulator is called like a function, with one argument that is the desired field width. This manipulator is placed in the output statement just before the item to be printed. For example, to print the number 123 with a field width of eight, you may write the statement:

cout << setw(8) << 123;

The setw function may be used with the standard output device ( cout ), or with other output devices that you will use later. Keep in mind that setw affects the field width of only the next item to be printed.

Justification of the Output and Showing Plus Signs on Positive Numbers

When output occurs with a wide field width, each output item is padded with spaces to bring the total number of characters up to the required field width. For example, when the number 123 is printed with a field width of eight, the complete output will consist of five spaces followed by the three digits of 123 . If you don't specify otherwise, the item is printed on the far right of the field width, with any padding spaces before the item. You can control the placement of the item by calling the setf function to set the "control flags" of an output device such as cout . This function is called with the syntax shown in these three examples:

cout.setf(ios::right;    ios::adjustfield); // Item appears on right side of field

cout.setf(ios::left;     ios::adjustfield); // Item appears on left side of field

cout.setf(ios::internal; ios:: adjustfield); // "Internal" spaces (described below)

Once the justification is set with the setf function, it remains in effect for all subsequent outputs until it is reset to some other value. The ios::internal setting causes numbers to be printed with the + or - sign as the first output character, but the remainder of the number appears on the right side of the field width. (In order to force a number to be printed with a + sign, you will have to call cout.setf(ios::showpos) ; When you no longer want the + signs to print, you may call cout.unsetf(ios::showpos) .)

By the way, you can see that setf and unsetf are both member functions of the cout output stream. They are defined in iostream.h and may be used with any output stream. The arguments, such as ios::left , are also defined in the header file iostream.h .

Format of Float and Double Numbers

The format for printing float and double numbers is also controlled by the setf functions. Here are three examples:

cout.setf(ios:: fixed,      ios::floatfield);

cout.setf(ios::scientific, ios::floatfield);

cout.setf(0,               ios::floatfield);

Fixed-point notation

The first example, using ios::fixed , causes numbers to be printed in fixed-point notation, which is the common way of writing numbers with a decimal point. For example, the number 19 will be printed as 19.25 .

Scientific notation

The second example, using ios::scientific , causes numbers to be printed in scientific notation consisting of a number times some power of ten. For example, the large number 1.8  10 16 will be printed as 1.8e16 . The letter e indicates the exponent.

Automatic notation

The third form, using the number 0 as the argument, causes C++ to select the format that it thinks is best for a number (either fixed-point or scientific notation).

If you don't specify one of the three formats, then C++ uses the automatic format. Once a format is set, it remains in place for all subsequent outputs.

Precision of Float and Double Numbers

Output streams have a precision function with one integer argument to determine how many digits are printed for each number. For example, this statement sets the precision to 12:

cout.precision(12);

(An alternative is , using setprecision from iomanip.h .) With a precision of 12, the fixed-point and scientific notations will both have 12 digits of accuracy after the decimal point. The automatic notation will have a total of 12 significant digits. Once you set the precision, it stays in effect for all subsequent outputs.

When the fixed-point notation is used, trailing zeros and the decimal point are not always printed. For example, the double number 123.0 will be printed as 123 (with no decimal point). With a precision of 12, the number 19 will be printed with no trailing zeros, resulting in 19.25 (rather than 19.250000000000 ). You may force the decimal point and trailing zeros for fixed-point numbers with the function call cout.setf(ios::showpoint) . You may revert to the usual method of fixed-point numbers with the function call cout.unsetf(ios::showpoint) . As usual, these functions may be used with any output stream (not just with cout ).

Reading from Standard Input

The extraction operator (written >> ) is used to read a value from an input stream such as the standard input device (usually the keyboard). For example, if i is an integer variable, then the following statement reads an integer value from the standard input, and stores the result in i :

cin >> i;

In this statement, cin stands for the "console input," and is defined as part of the header file iostream.h . You may read several items at once by chaining together a sequence of extraction operators. For example, if i , j , and k are integer variables, then the following statement first reads i , then j , and finally k from the standard input:

cin >> i >> j >> k;

There are several details that you should be aware of regarding the extraction operator:

  1. If the standard input device is a keyboard, then usually nothing is read until the user presses the return key. This gives the user a chance to use the backspace key to correct mistakes before pressing the return key.
  2. When the extraction operator reads a data value, it starts by skipping any "white space" that occurs in the input. This white space consists of any blanks, tabs, and newline characters. Skipping the white space occurs even if you are reading a character value, which means that the extraction operator cannot be used to read a character if the value that you want to read might be a blank or other white space.
  3. The extraction operator reads the input until the end of the input value is reached. The end of the value occurs by reaching any character that is not part of the input value. This "ending character" is called the delimiter, and the delimiter is not actually read. For example, suppose that i is an integer variable, c is a character variable, and we execute the statement:

      cin >> i >> c;

The program's user might type the following input (followed by the return key):

       42xyz

With this input, the number 42 will be assigned to i , and the character 'x' is assigned to c . The characters 'y' and 'z' remain in the input, perhaps to be read at a later time.

Reading a Null-Terminated String

You may use the extraction operator to read a null-terminated string. For example:

char message[100];

cin >> message;

In this case, the extraction operator skips any initial white space and reads characters into message until more white space is encountered. For example, suppose that the program's user types the following input line (followed by the return key):

The quick brown fox jumps over the lazy dog.

The statement cin >> message will skip any initial white space, read the characters The --ending when the blank is encountered after the e. The blank itself is not read. The three characters that were read are placed in message , with a null terminator after the third character. There is no checking to ensure that the array is large enough to hold the characters that were read.

Bad Input

Sometimes a user provides illegal data for an input operation. For example, the program might be reading an integer, but the user types the word quick. Whenever bad data is encountered, the input stream is marked as bad input. Once the input stream is bad, any subsequent attempts to read from the input stream will have no effect! Nothing is read, no variable values are assigned.

You may use the name of an input stream as a boolean expression to test whether the stream is bad. A bad stream results in a false expression; a device that is still good results in a true expression. For example:

if (cin)

    cout << "Input is still good." << endl;

else

    cout << "Input is bad." << endl;

Three More Functions: get , ignore , and peek

Many other input functions are part of iostream.h . We'll describe three of the most useful functions. The first function, called get , has several forms, including a form that simply reads the next input character. For example, suppose that c is a character variable. The following statement reads the next character from the standard input, and assigns the read value to c :

cin. get(c);

Notice that get is called as a member function of the cin object. How does differ from ? The answer is that get always reads the next character without skipping white space; on the other hand, the >> operator skips white space before reading the next character.

Another member function, called ignore , allows you to read and discard the next input character. With cin , the function is called as shown here:

cin. ignore( ); // Read the next character from cin, and discard this character.

 

Another member function, called peek , allows you to look at the next available character without actually reading it. For example, the following code checks to see whether the next character is the letter 'X' :

if (cin. peek( ) == 'X')

    cout << "I am about to read an X from the standard input." << endl;

The peek function always returns the next input character without skipping white space. As another example, this code will read and discard characters until the input stream becomes bad, or a newline character is reached:

while (cin  &&  (cin.peek( ) != '\n'))

    cin.ignore( );

Here is one more example of a function that reads and discards characters until the input stream becomes bad or a non-white space character is reached. The function makes use of a boolean function, called isspace , to determine whether a character is white space:

void eat_white( )

// Postcondition: Characters have been read from standard input until the input stream

// becomes bad, or a non-white space character is reached.

//  Library facilities used: ctype.h (provides isspace)

{

     while (cin  &&  isspace(cin.peek( )))

        cin.ignore( );

}

Detecting the End of a File

It is possible for the standard input to be connected to a file of characters. In this case, a program must be able to detect when the end of the input file has been reached. When the last actual character of the file has been read, the peek function returns a special constant named EOF (which is part of iostream.h ). For example:

if (cin.peek( ) == EOF)

    cout << "There is nothing more to read." << endl;

One warning: The peek function does not return the EOF constant until all characters of the file have been read--including any blanks or newline characters that may appear after the last piece of actual data. For example, suppose that the standard input is a file of integers. We want to read and add up all these integers until the end of file is reached. The correct way to process the input file is shown here (using the eat_white function, written above):

int sum = 0;  // The sum of all the numbers that we read

int next;     // The next number that we read

 

eat_white( ); // Skip any white space at the front of the file.

while (cin  &&  (cin.peek( ) != EOF))

{

    cin >> next;

    eat_white( );

    sum += next;

}

 

cout << "The total of all numbers is: " << sum << endl;

The special EOF character at the end of a file can be read by the usual get function. After this character is read, the input stream is marked as bad.

Writing or Reading a Text File

So far, we have shown output and input using the standard streams cout and cin . A program can also create its own streams, connecting these streams to files. Such a program must include both iostream.h and fstream.h , and proceed as follows:

Opening a file

For writing, a program should declare a variable of type ofstream . For reading, a program should declare a variable of type ifstream . Once the variable is declared, it can be connected to an actual file with the open member function, as shown here:

 

The argument to the open function is the name of the file that you wish to write. In our output example, this argument is the constant string "results" , so we will be writing a file named results . Our input example is reading text from a file named data . The argument to the open function may also be a string variable, or any other string expression.

Checking for failure

Sometimes, when you open a file, the open operation fails. For example, opening a file for writing can fail if the computer's disk is already full. Opening a file for input will fail if the specified file cannot be found. If the open operation fails, then the stream will be marked as "bad." You may use the name of a stream as a boolean expression to test whether the stream is bad. A bad stream results in a false expression; a device that is still good results in a true expression. Thus, after opening a file, you should check for possible failure. A simple approach uses the assert function (from assert.h ), as shown here:

Using the ofstream or ifstream

Once an ofstream is open, you may use it in the same way that you have used cout . For example, using outfile (opened as shown above), you may write:

outfile << "This sentence will be written to the file." << endl;

Once an ifstream is open, you may use it in the same way that you have used cin . For example, suppose that infile (opened above) contains lines of digits. You can read the next integer in the input file, storing the result in an integer variable i , as shown here:

infile >> i;

Closing a file

When you are done writing or reading a file, you should activate the close member function of the ofstream or ifstream . This function has no arguments, as shown here:

Closing a file releases any resources that the file implementation uses. If output buffering is used, then closing an output file also flushes the output buffer.