You shall see them on a beautiful quarto page, where a neat rivulet of text shall meander through a meadow of margin.
RICHARD BRINSLEY SHERIDAN, The School for Scandal
The layout of a program’s output is called the format of the output. In C++ you can control the format with commands that determine such details as the number of spaces between items and the number of digits after the decimal point. You already used three output formatting instructions when you learned the formula for outputting dollar amounts of money in the usual way (not in e-
notation) with two digits after the decimal point. Before outputting amounts of money, you inserted the following “magic formula” into your program:
cout.setf(ios::fixed);
cout.setf(ios::showpoint);
cout.precision(2);
Now that you’ve learned about object notation for streams, we can explain this magic formula and a few other formatting commands.
The first thing to note is that you can use these formatting commands on any output stream. If your program is sending output to a file that is connected to an output stream called outStream
, you can use these same commands to ensure that numbers with a decimal point will be written in the way we normally write amounts of money. Just insert the following in your program:
outStream.setf(ios::fixed);
outStream.setf(ios::showpoint);
outStream.precision(2);
To explain this magic formula, we will consider the instructions in reverse order.
Every output stream has a member function named precision
. When your program executes a call to precision
such as the previous one for the stream outStream
, then from that point on in your program, any number with a decimal point that is output to that stream will be written with a total of two significant figures, or with two digits after the decimal point, depending on when your compiler was written. The following is some possible output from a compiler that sets two significant digits:
23. 2.2e7 2.2 6.9e-1 0.00069
The following is some possible output from a compiler that sets two digits after the decimal point:
23.56 2.26e7 2.21 0.69 0.69e-4
In this book, we assume the compiler sets two digits after the decimal point.
A call to precision
applies only to the stream named in the call. If your program has another output stream named outStreamTwo
, then the call to outStream.precision
affects the output to the stream outStream
but has no effect on the stream outStreamTwo
. Of course, you can also call precision
with the stream outStreamTwo
; you can even specify a different number of digits for the numbers output to the stream outStreamTwo
, as in the following:
outStreamTwo.precision(3);
The other formatting instructions in our magic formula are a bit more complicated than the member function precision
. We now discuss these other instructions. The following are two calls to the member function setf
with the stream outStream
as the calling object:
outStream.setf(ios::fixed);
outStream.setf(ios::showpoint);
setf
is an abbreviation for set flags. A flag is an instruction to do something in one of two possible ways. If a flag is given as an argument to setf
, then the flag tells the computer to write output to that stream in some specific way. What it causes the stream to do depends on the flag.
In the previous example, there are two calls to the function setf
, and these two calls set the two flags ios::fixed
and ios::showpoint
. The flag ios::fixed
causes the stream to output numbers of type double
in what is called fixed-point notation, which is a fancy phrase for the way we normally write numbers. If the flag ios::fixed
is set (by a call to setf
), then all floating-point numbers (such as numbers of type double
) that are output to that stream will be written in ordinary everyday notation, rather than e-notation.
The flag ios::showpoint
tells the stream to always include a decimal point in floating-point numbers, such as numbers of type double
. So if the number to be output has a value of 2.0
, then it will be output as 2.0
and not simply as 2
; that is, the output will include the decimal point even if all the digits after the decimal point are 0
. Some common flags and the actions they cause are described in Display 6.5.
Formatting Flags for
setf
Flag |
Meaning |
Default |
---|---|---|
ios::fixed | If this flag is set, floating-point numbers are not written in e-notation. (Setting this flag automatically unsets the flag ios::scientific.) | Not set |
ios::scientific | If this flag is set, floating-point numbers are written in e-notation. (Setting this flag automatically unsets the flag ios::fixed.) If neither ios::fixed nor ios::scientific is set, then the system decides how to output each number. | Not set |
ios::showpoint | If this flag is set, a decimal point and trailing zeros are always shown for floating-point numbers. If it is not set, a number with all zeros after the decimal point might be output without the decimal point and following zeros. | Not set |
ios::showpos | If this flag is set, a plus sign is output before positive integer values. | Not set |
ios::right | If this flag is set and some field-width value is given with a call to the member function width, then the next item output will be at the right end of the space specified by width. In other words, any extra blanks are placed before the item output. (Setting this flag automatically unsets the flag ios::left.) | Set |
ios::left | If this flag is set and some field-width value is given with a call to the member function width, then the next item output will be at the left end of the space specified by width. In other words, any extra blanks are placed after the item output. (Setting this flag automatically unsets the flag ios::right.) | Not set |
Another useful flag is ios::showpos
. If this flag is set for a stream, then positive numbers output to that stream will be written with the plus sign in front of them. If you want a plus sign to appear before positive numbers, insert the following:
cout.setf(ios::showpos);
Minus signs appear before negative numbers without setting any flags.
One very commonly used formatting function is width
. For example, consider the following call to width
made by the stream cout
:
cout << "Start Now";
cout.width(4);
cout << 7 << endl;
This code causes the following line to appear on the screen:
Start Now 7
This output has exactly three spaces between the letter 'w'
and the number 7
. The width
function tells the stream how many spaces to use when giving an item as output. In this case the item (namely, the number 7
) occupies only one space, and width
said to use four spaces, so three of the spaces are blank. If the output requires more space than you specified in the argument to width
, then as much additional space as is needed will be used. The entire item is always output, no matter what argument you give to width
.
A call to width
applies only to the next item that is output. If you want to output 12 numbers, using four spaces to output each number, then you must call width
12 times. If this becomes a nuisance, you may prefer to use the manipulator setw
that is described in the next subsection.
Any flag that is set may be unset. To unset a flag, you use the function unsetf
. For example, the following will cause your program to stop including plus signs on positive integers that are output to the stream cout
:
cout.unsetf(ios::showpos);
A manipulator is a function that is called in a nontraditional way. In turn, the manipulator function calls a member function. Manipulators are placed after the insertion operator <<
, just as if the manipulator function call were an item to be output. Like traditional functions, manipulators may or may not have arguments. We have already seen one manipulator, endl
. In this subsection we will discuss two manipulators called setw
and setprecision
.
The manipulator setw
and the member function width
(which you have already seen) do exactly the same thing. You call the setw
manipulator by writing it after the insertion operator <<
, as if it were to be sent to the output stream, and this in turn calls the member function width
. For example, the following outputs the numbers 10
, 20
, and 30
, using the field widths specified:
cout << "Start" << setw(4) << 10
<< setw(4) << 20 << setw(6) << 30;
The preceding statement will produce the following output:
Start 10 20 30
(There are two spaces before the 10
, two spaces before the 20
, and four spaces before the 30
.)
The manipulator setprecision
does exactly the same thing as the member function precision
(which you have already seen). However, a call to setprecision
is written after the insertion operator <<
, in a manner similar to how you call the setw
manipulator. For example, the following outputs the numbers listed using the number of digits after the decimal point that are indicated by the call to setprecision
:
cout.setf(ios::fixed);
cout.setf(ios::showpoint);
cout << "$" << setprecision(2) << 10.3 << endl
<< "$" << 20.5 << endl;
The statement above will produce the following output:
$10.30
$20.50
When you set the number of digits after the decimal point using the manipulator setprecision
, then just as was the case with the member function precision
, the setting stays in effect until you reset it to some other number by another call to either setprecision
or precision
.
To use either of the manipulators setw
or setprecision
, you must include the following directive in your program:
#include <iomanip>
Your program should also include the following:
using namespace
std;
What output will be produced when the following lines are executed (assuming the lines are embedded in a complete and correct program with the proper include
directives)?
cout << "*";
cout.width(5);
cout << 123
<< "*" << 123 << "*" << endl;
cout << "*" << setw(5) << 123
<< "*" << 123 << "*" << endl;
What output will be produced when the following lines are executed (assuming the lines are embedded in a complete and correct program with the proper include
directives)?
cout << "*" << setw(5) << 123;
cout.setf(ios::left);
cout << "*" << setw(5) << 123;
cout.setf(ios::right);
cout << "*" << setw(5) << 123 << "*" << endl;
What output will be produced when the following lines are executed (assuming the lines are embedded in a complete and correct program with the proper include
directives)?
cout << "*" << setw(5) << 123 << "*"
<< 123 << "*" << endl;
cout.setf(ios::showpos);
cout << "*" << setw(5) << 123 << "*"
<< 123 << "*" << endl;
cout.unsetf(ios::showpos);
cout.setf(ios::left);
cout << "*" << setw(5) << 123 << "*"
<< setw(5) << 123 << "*" << endl;
What output will be sent to the file stuff.dat
when the following lines are executed (assuming the lines are embedded in a complete and correct program with the proper include
directives)?
ofstream fout; fout.open("stuff.dat"); fout << "*" << setw(5) << 123 << "*" << 123 << "*" << endl; fout.setf(ios::showpos); fout << "*" << setw(5) << 123 << "*" << 123 << "*" << endl; fout.unsetf(ios::showpos); fout.setf(ios::left); fout << "*" << setw(5) << 123 << "*" << setw(5) << 123 << "*" << endl;
What output will be produced when the following line is executed (assuming the line is embedded in a complete and correct program with the proper include
directives)?
cout << "*" << setw(3) << 12345 << "*" << endl;
In formatting output, the following flag constants are used with the stream
member function setf
. What effect does each have?
ios::fixed
ios::scientific
ios::showpoint
ios::showpos
ios::right
ios::left
Here is a code segment that reads input from infile.dat
and sends output to outfile.dat
. What changes are necessary to make the output go to the screen? (The input is still to come from infile.dat
.)
//Problem for Self Test. Copies three int numbers //between files.
#include <fstream>
int
main( ) {
using namespace
std; ifstream inStream; ofstream outStream; inStream.open("infile.dat"); outStream.open("outfile.dat");
int
first, second, third; inStream >> first >> second >> third; outStream << "The sum of the first 3" << endl << "numbers in infile.dat is " << endl << (first + second + third) << endl; inStream.close( ); outStream.close( );
return
0; }
A stream can be an argument to a function. The only restriction is that the function formal parameter must be call-by-reference. A stream parameter cannot be a call-by-value parameter. For example, the function makeNeat
in Display 6.6 has two stream parameters: one is of type ifstream
and is for a stream connected to an input file; another is of type ofstream
and is for a stream connected to an output file. We will discuss the other features of the program in Display 6.6 in the next two subsections.
rawdata.dat
(Not changed by program.)
10.37 −9.89897
2.313 −8.950 15.0
7.33333 92.8765
−1.237568432e2
|
|
---|---|
(After program is run.) | |
|
|
That’s all there is, there isn’t any more.
ETHEL BARRYMORE (1879–1959)
When you write a program that takes its input from a file, you will often want the program to read all the data in the file. For example, if the file contains numbers, you might want your program to calculate the average of all the numbers in the file. Since you might run the program with different data files at different times, the program cannot assume it knows how many numbers are in the file. You would like to write your program so that it keeps reading numbers from the file until there are no more numbers left to be read. If inStream
is a stream connected to the input file, then the algorithm for computing this average can be stated as follows:
double
next, sum = 0;
int
count = 0;
while
(There are still numbers to be read) { inStream >> next; sum = sum + next; count++; }
The average is
sum / count.
This algorithm is already almost all C++ code, but we still must express the following test in C++:
(There are still numbers to be read)
Even though it may not look correct at first, one way to express the aforementioned test is the following:
(inStream >> next)
This technique is generally the preferred way to test for the end of the file. It reads a value from the stream and if there is nothing left to read then the operation returns false. The previous algorithm can thus be rewritten as the following C++ code (plus one last line in pseudocode that is not the issue here):
doublenext, sum = 0;
int
count = 0;
while
(inStream >> next) { sum = sum + next; count++; }
The average is
sum / count.
Notice that the loop body is not identical to what it was in our pseudocode. Since inStream >> next
is now in the Boolean expression, it is no longer in the loop body.
This loop may look a bit peculiar, because inStream >> next
is both the way you input a number from the stream inStream
and the controlling Boolean expression for the while
loop. An expression involving the extraction operator >>
is simultaneously both an action and a Boolean condition.2 It is an instruction to take one input number from the input stream, and it is also a Boolean expression that is either satisfied or not. If there is another number to be input, then the number is read and the Boolean expression is satisfied, so the body of the loop is executed one more time. If there are no more numbers to be read in, then nothing is input and the Boolean expression is not satisfied, so the loop ends. In this example the type of the input variable next
was double
, but this method of checking for the end of the file works the same way for other data types, such as int
and char
.
We have tried to keep our using
directives local to a function definition. This is an admirable goal, but now we have a problem—functions whose parameter type is in a namespace. In our immediate examples we need the stream type names that are in the namespace std
. Thus, we need a using
directive (or something) outside of the function definition body so that C++ will understand the parameter type names, such as ifstream
. The easiest fix is to simply place one using
directive at the start of the file (after the include
directives). We have done this in Display 6.6.
Placing a single using
directive at the start of a file is the easiest solution to our problem, but many experts would not consider it the best solution, since it would not allow the use of two namespaces that have names in common, and that is the whole purpose of namespaces. At this point we are only using the namespace std
,3 so there is no problem. In Chapter 12, we will teach you another way around this problem with parameters and namespaces. This other approach will allow you to use any kinds of multiple namespaces.
Many programmers prefer to place using
directives at the start of the program file. For example, consider the following using
directive:
using namespace
std;
Many of the programs in this book do not place this using
directive at the start of the program file. Instead, this using
directive is placed at the start of each function definition that needs the namespace std
(immediately after the opening brace). An example of this is shown in Display 6.3. An even better example is shown in Display 5.11. All of the programs that have appeared so far in book, and almost all programs that follow, would behave exactly the same if there were just one using
directive for the namespace std
and that one using
directive were placed immediately after the include
directives, as in Display 6.6. For the namespace std
, the using
directive can safely be placed at the start of the file (in almost all cases). For some other namespaces, a single using
directive will not always suffice, but you will not see any of these cases for some time.
We advocate placing the using
directives inside function definitions (or inside some other small units of code) so that it does not interfere with any other possible using
directives. This trains you to use namespaces correctly in preparation for when you write more complicated code later in your programming career. In the meantime, we sometimes violate this rule ourselves when following the rule becomes too burdensome to the other issues we are discussing. If you are taking a course, do whatever your instructor requires. Otherwise, you have some latitude in where you place your using
directives.
The program in Display 6.6 takes its input from the file rawdata.dat
and writes its output, in a neat format, both to the screen and to the file neat.dat
. The program copies numbers from the file rawdata.dat
to the file neat.dat
, but it uses formatting instructions to write them in a neat way. The numbers are written one per line in a field of width 12, which means that each number is preceded by enough blanks so that the blanks plus the number occupy 12 spaces. The numbers are written in ordinary notation; that is, they are not written in e-
notation. Each number is written with five digits after the decimal point and with a plus or minus sign. The output to the screen is the same as the output to the file neat.dat
, except that the screen output has one extra line that announces that the program is ending. The program uses a function, named makeNeat
, that has formal parameters for the input-file stream and the output-file stream.
What output will be produced when the following lines are executed, assuming the file list.dat
contains the data shown (and assuming the lines are embedded in a complete and correct program with the proper include
directives)?
ifstream ins; ins.open("list.dat");
int
count = 0, next;
while
(ins >> next) { count++; cout << next << endl; } ins.close( ); cout << count;
The file list.dat
contains the following three numbers (and nothing more)
1 2
3
Write the definition for a void
function called toScreen
. The function toScreen
has one formal parameter called fileStream
, which is of type ifstream
. The precondition and postcondition for the function are as follows:
//Precondition: The stream fileStream has been connected
//to a file with a call to the member function open. The
//file contains a list of integers (and nothing else).
//Postcondition: The numbers in the file connected to
//fileStream have been written to the screen one per line.
//(This function does not close the file.)
(This exercise is for those who have studied the optional section entitled “File Names as Input.”) Suppose you are given the following string
variable declaration and input statement:
#include <iostream>
using namespace
std; // ...
char
name[21]; cout >> name;
Suppose this code segment is embedded in a correct program. What is the longest name that can be entered into the string
variable name
?