Formatting program output is an essential part of any serious application. Surprisingly, most C++ textbooks don't give a full treatment of output formatting. The purpose of this section is to describe the full range of formatting abilities available in C++.
Formatting in the standard C++ libraries is done through the use of manipulators, special variables or objects that are placed on the output stream. Most of the standard manipulators are found in <iostream>
. Like cin
and cout
, the standard C++ manipulators are not keywords in the language, but it is often convenient to think of them as a permanent part of the language.
The standard C++ output manipulators are:
endl
places a new line character on the output stream. This is identical to placing '\n'
on the output stream.
#include<iostream>
using std::cout;
using std::endl;
int main()
{
cout << "Hello world 1" << endl;
cout << "Hello world 2\n";
return 0;
}
produces
Hello world 1 Hello world 2
flush
Flushes the output buffer to its final destination.
Some explanation is in order here. For efficiency reasons, most output is not sent directly to the output device at the time a program uses a cout
statement. Rather it is collected in an output buffer in the system memory. Periodically, the collected contents of the buffer are flushed to the output device in one large block. This is much faster than sending the output one character at a time. This flushing happens automatically when the buffer contents get too large.
The output buffer is also flushed before an input statement is executed. This is because the output may be a prompt, and a prompt should appear on the screen in full before any input is accepted.
The output buffer is also flushed by the endl
manipulator.
The output buffer is also flushed when the stream is closed at the end of the program.
In short, the output buffer and its flushing mechanism is largely transparent to the user. The flush
manipulator is rarely needed.
One exception to this is in using printing statements for debugging. When a program crashes, the output buffer may or may not make it to the output device when the program terminates. Consequently, if print statements are used to locate where the crash occurs, misleading results may be obtained. Using the flush
operator after every output will help prevent this problem (but is not guaranteed to work every time).
A better solution to this problem is to use the output stream cerr
for error output. This stream is also defined in <iostream>
and is an output stream of type ostream
. It works just like cout
except that all output is automatically flushed.
A very useful thing to do in a program is output numbers and strings in fields of fixed width. This is crucial for reports.
setw()
Adjusts the field width for the item about to be printed.
Important Point
The setw()
manipulator only affects the next value to be printed.
The setw()
manipulator takes an integer argument which is the minimum field width for the value to be printed.
Important Point
All manipulators that take arguments are defined in the header file <iomanip>
. This header file must be included to use such manipulators.
#include <iostream>
#include <iomanip>
using std::cout;
using std::endl;
using std::setw;
int main()
{
// A test of setw()
cout << "*" << -17 << "*" << endl;
cout << "*" << setw(6) << -17 << "*" << endl << endl;
cout << "*" << "Hi there!" << "*" << endl;
cout << "*" << setw(20) << "Hi there!" << "*" << endl;
cout << "*" << setw(3) << "Hi there!" << "*" << endl;
return 0;
}
produces
*-17* * -17* *Hi there!* * Hi there!* *Hi there!*
Note that the values are right-aligned in their fields. This can be changed. Note also what happens if the value is too big to fit in the field.
Important Point
The argument given to setw()
is a minimum width. If the value needs more space, the output routines will use as much as is needed.
This field overflow strategy is different than that used in other programming languages. Some languages will fill a small field with *'s or #'s. Others will truncate the value. The philosophy for the C++ standard output is that it's better to have a correct value formatted poorly than to have a nicely formatted error.
Important Point
The default field width is 0.
Values can be aligned in their fields. There are three manipulators for adjusting the alignment: left
, right
, and internal
.
Important Point
The default alignment is right-aligned.
Important Point
All manipulators except setw()
are persistent. Their effect continues until explicitly changed.
left
Left-align all values in their fields.
right
Right-align all values in their fields. This is the default alignment value.
#include <iostream>
#include <iomanip>
using std::cout;
using std::endl;
using std::setw;
using std::left;
using std::right;
int main()
{
cout << "*" << -17 << "*" << endl;
cout << "*" << setw(6) << -17 << "*" << endl;
cout << left;
cout << "*" << setw(6) << -17 << "*" << endl << endl;
cout << "*" << "Hi there!" << "*" << endl;
cout << "*" << setw(20) << "Hi there!" << "*" << endl;
cout << right;
cout << "*" << setw(20) << "Hi there!" << "*" << endl;
return 0;
}
produces
*-17* * -17* *-17 * *Hi there!* *Hi there! * * Hi there!*
internal
Internally aligns numeric values in their fields. Internal alignment separates the sign of a number from its digits. The sign is left-aligned and the digits are right-aligned. This is a useful format in accounting and business programs, but is rarely used in other applications.
#include <iostream>
#include <iomanip>
using std::cout;
using std::endl;
using std::setw;
using std::internal;
int main()
{
cout << setw(9) << -3.25 << endl;
cout << internal << setw(9) << -3.25 << endl;
return 0;
}
produces
-3.25 - 3.25
setfill
Sets the specified character as the stream's fill character. The fill character is the character used by output insertion functions to fill spaces when padding results to the field width.Important Point
The default fill character is a space.
#include <iostream>
#include <iomanip>
using std::cout;
using std::endl;
using std::setw;
using std::internal;
int main()
{
cout << setw(9) << -3.25 << endl;
cout << setfill('0');
cout << internal << setw(9) << -3.25 << endl;
cout << setfill(' ');
cout << internal << setw(9) << -3.25 << endl;
return 0;
}
produces
-3.25 -00003.25 - 3.25
boolalpha and noboolalpha
Boolean values (variables of type bool
) are normally printed as 0 for false and 1 for true. It is sometimes nice to print out these values as words. The boolalpha
manipulator will print out true and false values as true
and false
respectively. The nobooolalpha
manipulator will return the printed values to 1 and 0.
#include <iostream>
using std::cout;
using std::endl;
using std::boolalpha;
using std::noboolalpha;
int main()
{
bool bt = true, bf = false;
cout << "bt: " << bt << " bf: " << bf << endl;
cout << boolalpha;
cout << "bt: " << bt << " bf: " << bf << endl;
cout << noboolalpha;
cout << "bt: " << bt << " bf: " << bf << endl;
return 0;
}
produces
bt: 1 bf: 0 bt: true bf: false bt: 1 bf: 0
A point for advanced users: In a Unix environment changing the default session language will automatically change the alpha values for true and false so that boolalpha
will use the proper words for that language.
showpos and noshowpos
This manipulator determines how positive numbers are printed. A negative number is traditionally printed with a minus sign in front. The lack of a minus sign means a positive value. However some accounting and scientific applications traditionally place a plus sign in front of positive numbers just to emphasize the fact that the number is positive. Using the showpos
manipulator makes this happen automatically. The noshowpos
manipulator returns the output state to placing nothing in front of positive values.
#include <iostream>
using std::cout;
using std::endl;
using std::showpos;
using std::noshowpos;
int main()
{
int pos_int = 4, neg_int = -2, zero_int = 0;
float pos_f = 3.5, neg_f = -31.2, zero_f = 0.0;
cout << "pos_int: " << pos_int << " neg_int: " << neg_int;
cout << " zero_int: " << zero_int << endl;
cout << "pos_f: " << pos_f << " neg_f: " << neg_f;
cout << " zero_f: " << zero_f << endl << endl;
cout << showpos;
cout << "pos_int: " << pos_int << " neg_int: " << neg_int;
cout << " zero_int: " << zero_int << endl;
cout << "pos_f: " << pos_f << " neg_f: " << neg_f;
cout << " zero_f: " << zero_f << endl << endl;
return 0;
}
produces
pos_int: 4 neg_int: -2 zero_int: 0 pos_f: 3.5 neg_f: -31.2 zero_f: 0 pos_int: +4 neg_int: -2 zero_int: +0 pos_f: +3.5 neg_f: -31.2 zero_f: +0
Note that zero is considered to be a positive number in this case.
dec, oct, and hex
Computer science applications occasionally use number systems other than base 10. The most frequently used number systems (after decimal) are octal (base 8) and hexadecimal (base 16). Octal number systems use the digits 0 through 7. Hexadecimal systems use the digits 0 through 9 and add the digits A through F to represent in one digit the values ten through fifteen.
The manipulators dec
, oct
, and hex
change the base that is used to print out integer values.
Important Point
The base used for output formatting is completely independent from how a value is stored in machine memory. During output, the bit patterns in memory are converted to character sequences that are meaningful to human beings.
#include <iostream>
using std::cout;
using std::endl;
using std::dec;
using std::oct;
using std::hex;
int main()
{
// These sequences of characters are treated as decimal numbers by
// the compiler and converted to the machine internal format.
long int pos_value = 12345678;
long int neg_value = -87654321;
float value = 2.71828;
cout << "The decimal value 12345678 is printed out as" << endl;
cout << "decimal: " << pos_value << endl;
cout << "octal: " << oct << pos_value << endl;
cout << "hexadecimal: " << hex << pos_value << endl << endl;
cout << "The decimal value -87654321 is printed out as" << endl;
cout << "decimal: " << dec << neg_value << endl;
cout << "octal: " << oct << neg_value << endl;
cout << "hexadecimal: " << hex << neg_value << endl << endl;
cout << "The decimal value 2.71828 is printed out as" << endl;
cout << "decimal: " << dec << value << endl;
cout << "octal: " << oct << value << endl;
cout << "hexadecimal: " << hex << value << endl << endl;
return 0;
}
produces
The decimal value 12345678 is printed out as decimal: 12345678 octal: 57060516 hexadecimal: bc614e The decimal value -87654321 is printed out as decimal: -87654321 octal: 37261500117 hexadecimal: fac6804f The decimal value 2.71828 is printed out as decimal: 2.71828 octal: 2.71828 hexadecimal: 2.71828
Note that negative integers are not printed as such in octal or hexadecimal. Rather, the internal bit patterns are interpreted as always being positive values.
Also note that floating-point values are always printed out in decimal format.
showbase and noshowbase
When a program is printing out integers in decimal, octal, and hex, it can become difficult to determine at a glance what the real value of a number is. For example, a program outputs the string of characters "1234". Does this represent a decimal 1234, an octal 1234 or a hexadecimal 1234? All are legal, but have very different internal values.
By tradition in C++, any printed integer value that is immediately preceded by a zero is considered to be an octal value. Any printed integer that is immediately preceded by a "0x" is considered to be a hexadecimal value. For example the output 1234 is likely a decimal value. The output 01234 is considered to be octal and 0x1234 is considered to be hexadecimal.
By default, these prefixes are not added. The programmer can add them or the showbase
manipulator can be used. This manipulator simply provides an appropriate prefix to octal and hexadecimal values. The noshowbase
manipulator turns off this behavior.
#include <iostream>
using std::cout;
using std::endl;
using std::dec;
using std::oct;
using std::hex;
using std::showbase;
using std::noshowbase;
int main()
{
long int value = 12345678;
cout << "The decimal value 12345678 is printed out with showbase as" << endl;
cout << showbase;
cout << "decimal: " << value << endl;
cout << "octal: " << oct << value << endl;
cout << "hexadecimal: " << hex << value << endl << endl;
cout << "The decimal value 12345678 is printed out without showbase as" << endl;
cout << noshowbase;
cout << "decimal: " << dec << value << endl;
cout << "octal: " << oct << value << endl;
cout << "hexadecimal: " << hex << value << endl << endl;
return 0;
}
produces
The decimal value 12345678 is printed out with showbase as decimal: 12345678 octal: 057060516 hexadecimal: 0xbc614e The decimal value 12345678 is printed out without showbase as decimal: 12345678 octal: 57060516 hexadecimal: bc614e
uppercase and nouppercase
Numeric output consists largely of numeric digits. But there are a few places where alphabetic characters make their appearance. These include the 0x
prefix for hexadecimal numbers, the hexadecimal digits a
through f
, and the e
that is used in scientific notation for large floating point numbers (6.02e+23
). In some applications, it is important that these letters appear as uppercase letters instead of lowercase. The uppercase
manipulator enables this behavior. The nouppercase
manipulator turns all of these characters back to lower case.
#include <iostream>
using std::cout;
using std::endl;
using std::dec;
using std::oct;
using std::hex;
using std::showbase;
using std::noshowbase;
using std::uppercase;
using std::nouppercase;
int main()
{
long int value = 12345678;
float value_f = 6020000000.0;
cout << "Some values without the uppercase manipulator" << endl;
cout << showbase << hex;
cout << "hexadecimal: " << value << endl;
cout << "exponential: " << value_f << endl << endl;
cout << uppercase;
cout << "Some values with the uppercase manipulator" << endl;
cout << "hexadecimal: " << value << endl;
cout << "exponential: " << value_f << endl << endl;
return 0;
}
produces
Some values without the uppercase manipulator hexadecimal: 0xbc614e exponential: 6.02e+09 Some values with the uppercase manipulator hexadecimal: 0XBC614E exponential: 6.02E+09
There are 3 floating-point formats: general, fixed, and scientific. Fixed format always has a number, decimal point, and fraction part, no matter how big the number gets, i.e., not scientific notation. 6.02e+17 would be displayed as 602000000000000000 instead of 6.02e+17.
Scientific format always displays a number in scientific notation. The value of one-fourth would not be displayed as 0.25, but as 2.5e-01 instead.
General format is a mix of fixed and scientific formats. If the number is small enough, fixed format is used. If the number gets too large, the output switches over to scientific format. General format is the default format for floating-point values.
fixed and scientific
The manipulator fixed
will set up the output stream for displaying floating-point values in fixed format.
The scientific
manipulator forces all floating point values to be displayed in scientific notation.
Unfortunately, there is no manipulator to place the output stream back into general format. The author of these notes considers this to be a design flaw in the standard C++ libraries. There is a way to place the output stream back into general format, but it's not pretty and requires more explanation than is appropriate here. In short, here's the magic incantation
cout.unsetf(ios::fixed | ios::scientific);
In order to use this statement, you need a using declaration for the ios class.
#include <iostream>
using std::cout;
using std::endl;
using std::scientific;
using std::fixed;
using std::ios;
int main()
{
float small = 3.1415926535897932384626;
float large = 6.0234567e17;
float whole = 2.000000000;
cout << "Some values in general format" << endl;
cout << "small: " << small << endl;
cout << "large: " << large << endl;
cout << "whole: " << whole << endl << endl;
cout << scientific;
cout << "The values in scientific format" << endl;
cout << "small: " << small << endl;
cout << "large: " << large << endl;
cout << "whole: " << whole << endl << endl;
cout << fixed;
cout << "The same values in fixed format" << endl;
cout << "small: " << small << endl;
cout << "large: " << large << endl;
cout << "whole: " << whole << endl << endl;
// Doesn't work -- doesn't exist
// cout << general;
cout.unsetf(ios::fixed | ios::scientific);
cout << "Back to general format" << endl;
cout << "small: " << small << endl;
cout << "large: " << large << endl;
cout << "whole: " << whole << endl << endl;
return 0;
}
produces
Some values in general format small: 3.14159 large: 6.02346e+17 whole: 2 The values in scientific format small: 3.141593e+00 large: 6.023457e+17 whole: 2.000000e+00 The same values in fixed format small: 3.141593 large: 602345661202956288.000000 whole: 2.000000 Back to general format small: 3.14159 large: 6.02346e+17 whole: 2
setprecision()
An important point about floating-point output is the precision, which is roughly speaking the number of digits displayed for the number. The exact definition of the precision depends on which output format is currently being used.
In general format, the precision is the maximum number of digits displayed. This includes digits before and after the decimal point, but does not include the decimal point itself. Digits in a scientific exponent are not included.
In fixed and scientific formats, the precision is the number of digits after the decimal point.
Important Point
The default output precision is 6.
The setprecision
manipulator allows you to set the precision used for printing out floating-point values. The manipulator takes an integer argument. The header file <iomanip>
must be included to use this manipulator.
showpoint and noshowpoint
There is one aspect of printing numbers in general format that is either very nice or very annoying depending on your point of view. When printing out floating-point values, only as many decimal places as needed (up to the precision) are used to print out the values. In other words, trailing zeros are not printed. This is nice and compact, but impossible to get decimal points to line up in tables.
The showpoint
manipulator forces trailing zeros to be printed, even though they are not needed. By default this option is off. As can be seen from previous examples, this manipulator is not needed in fixed or scientific format, only in general format.
#include <iostream>
using std::cout;
using std::endl;
using std::showpoint;
int main()
{
float lots = 3.1415926535;
float little1 = 2.25;
float little2 = 1.5;
float whole = 4.00000;
cout << "Some values with noshowpoint (the default)" << endl << endl;
cout << "lots: " << lots << endl;
cout << "little1: " << little1 << endl;
cout << "little2: " << little2 << endl;
cout << "whole: " << whole << endl;
cout << endl << endl;
cout << "The same values with showpoint" << endl << endl;
cout << showpoint;
cout << "lots: " << lots << endl;
cout << "little1: " << little1 << endl;
cout << "little2: " << little2 << endl;
cout << "whole: " << whole << endl;
return 0;
}
produces
Some values with noshowpoint (the default) lots: 3.14159 little1: 2.25 little2: 1.5 whole: 4 The same values with showpoint lots: 3.14159 little1: 2.25000 little2: 1.50000 whole: 4.00000