Appendix D / Command Line Compiling and Linking
785
Appendix D
Command Line Compiling and Linking
Appendix E
Dealing with Older Compilers
These two appendices are at www.cs.colorado.edu/~main/online_appendix.pdf to allow for better
updates.
Appendix F
Input and Output in C++
This appendix is primarily for students with a background in C programming, but with little or no
C++ programming experience. In this appendix we provide details of the C++ approach to reading
from standard input, writing to standard output, and reading/writing files. Throughout the appendix,
we assume that your programs have a using directive using namespace std; for the standard
namespace (otherwise you must write longer names such as std::cout rather than just cout).
Writing to Standard Output
The insertion 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>. 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>). For
example:
cout << '\n';
cout << endl;
786
Appendix F / Input and Output in C++
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>. 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;
uses setw from iomanip
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
Appendix F / Input and Output in C++
787
side of the field width. (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> and may be used with any output stream. The arguments,
such as ios::left, are also defined in the header file <iostream>.
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 fixedpoint 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 10. For example, the large number
1.8 × 1016 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 cout << setprecision(12); , which uses setprecision from <iomanip>.)
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 automatic 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 automatic
788
Appendix F / Input and Output in C++
notation 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>. 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 or a C++ String
You may use the extraction operator to read a null-terminated string. For example:
char message[100];
cin >> message;
Appendix F / Input and Output in C++
789
In this case, the extraction operator skips any initial whitespace and reads characters into message
until more whitespace 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 whitespace and 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.
C++ strings (from the <string> header file) can be read in the same manner as null-terminated
strings, but there is also a getline function that will read an entire line into a string variable. For
example:
string message;
// Reads one input line into message, including whitespace. The end-of-line is read, but not
// added to the end of the message string:
getline(cin, message);
Failed 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 illegal data is encountered, the
input stream is marked as failed. Once the input stream has failed, 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 has
failed. A failed 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;
The failure can occur for many reasons, but the most common failure is encountering the wrong
type of data in the input stream. If an incorrect data type is the cause of the problem, you may reset
the input stream and try to read the data again using a variable of a different type. The member
function to reset a failed input stream is clear( ). For example, cin.clear( ) will reset the console input, allowing you to try to read the data again.
Three More Functions: get, ignore, and peek
Many other input functions are part of <iostream>. 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);
790
Appendix F / Input and Output in C++
Notice that get is called as a member function of the cin object. How does cin.get(c); differ
from cin >> c; ? The answer is that get always reads the next character without skipping
whitespace; on the other hand, the >> operator skips whitespace 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 whitespace. As another
example, this code will read and discard characters until the input stream fails, 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
fails or a nonwhitespace character is reached. The function makes use of a boolean function, called
isspace, to determine whether a character is whitespace:
void eat_white( )
// Postcondition: Characters have been read from standard input until the input stream
// becomes bad, or a nonwhitespace character is reached.
// Library facilities used: cctype (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>). 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
Appendix F / Input and Output in C++
791
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 earlier):
int sum = 0;
int next;
// The sum of all the numbers that we read
// The next number that we read
eat_white( ); // Skip any whitespace 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, a member function cin.eof( ) will return true.
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 should include both
<iostream> and <fstream>, 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:
Opening an Output File:
Opening an Input File:
#include <iostream>
#include <fstream>
#include <iostream>
#include <fstream>
ofstream outfile;
ifstream infile;
outfile.open("results");
infile.open("data");
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
792
Appendix F / Input and Output in C++
as failed. You may use the name of a stream as a boolean expression to test whether the stream is
bad. A failed 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 cassert), as shown here:
Check for Failure of an Output File:
Check for Failure of an Input File:
#include <iostream>
#include <fstream>
#include <cassert>
#include <iostream>
#include <fstream>
#include <cassert>
ofstream outfile;
ifstream infile;
outfile.open("results");
assert(outfile);
infile.open("data");
assert(infile);
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 an Output File:
Closing an Input File:
#include <iostream>
#include <fstream>
#include <cassert>
#include <iostream>
#include <fstream>
#include <cassert>
ofstream outfile;
ifstream infile;
outfile.open("results");
assert(outfile);
infile.open("data");
assert(infile);
...Statements that use outfile...
...Statements that use infile...
outfile.close( );
infile.close( );
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.
0
You can add this document to your study collection(s)
Sign in Available only to authorized usersYou can add this document to your saved list
Sign in Available only to authorized users(For complaints, use another form )