Output Formatting


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.

Field width

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.

Alignment

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.

Integer base

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

Floating-Point Output

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