Stream Formatting with I/O Manipulators - dummies

By Stephen R. Davis

One of the difficulties with C++ in moving to stream objects for output is learning how to format the output. There are actually two ways to format-stream I/O.

The first technique that programmers normally learn is through direct method calls. For example, the following call sets the output stream in hexadecimal mode so that integers appear onscreen as hexadecimal values rather than as decimal values:

ios::fmtflags prev = cout.setf(ios::hex, ios::basefield);

Here the setf() method sets the format flags by first masking off the bits in the second argument and then setting the bits indicated by the first argument. The function returns the old value so that the calling function can restore the format flags before returning.

In practice, this function appears as follows:

#include <iostream>
using namespace std;
// displayHex - display a number in hex format
void displayHex(ostream& out, int n)
{
    ios::fmtflags prev = out.setf(ios::hex,
                                  ios::basefield);
    out << n;
    out.setf(prev);
}
int main()
{
    int n = 0x1234;
    cout << "n = " << n << endl;
    cout << "n in hex is ";
    displayHex(cout, n);
    cout << endl;
    return 0;
}

The program starts by setting the variable n to a hexadecimal value. It then displays the value to cout. It then calls the displayHex() function to display the value in hexadecimal format. The output from the program appears as follows:

n = 4660
n in hex is 1234

The value in decimal format is not recognizable but the hexadecimal display is clearly the value used to initialize n.

However, C++ provides a second way to control I/O format: I/O manipulators.

What is an I/O manipulator?

An I/O manipulator is an object that the programmer can insert into the output stream to invoke the format control functions. The following code snippet demonstrates the user of I/O manipulators. It performs the same function as the prior snippet, except this version uses an I/O manipulator to invoke the setf() function:

#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
    int n = 0x1234;
    cout << "n = " << n << endl
         << "n in hex is " << setbase(16) << n << endl;
    return 0;
}

Here main() first outputs n as a decimal value. It then uses the setbase(16) manipulator to change the display base from decimal (base 10) to hexadecimal (base 16) before displaying the value again. The output from this version is indistinguishable from the earlier version:

n = 4660
n in hex is 1234

The setbase(16) object appears just like a call to a function in the middle of the output stream. The fact that an object is being created is invisible to the user.

For hexadecimal, octal and decimal, C++ provides the shortcuts hex, oct and dec meaning that the code could take the following even shorter form:

cout << "n = " << n << endl
     << "n in hex is " << hex << n << endl;

What I/O manipulators does C++ offer?

Have a look at this table, which contains a list of I/O manipulators available to C++ 2011.

Common I/O Manipulators
I/O Manipulator Function
boolalpha
noboolalpha
Switches between textual and numeric display of a Boolean. When
boolalpha is set, true and false appear
onscreen as true and false. When it’s not set, they appear as 1 and ‘0’.
showbase
noshowbase
When showbase is set, octal values
are preceded by a 0 and hexadecimal
values are preceded by 0x or 0X.
showpoint
noshowpoint
A decimal point is always displayed when showpoint is set.
showpos
noshowpos
Displays a + sign in front of
positive values when showpos is set.
Displays nothing when noshowpos is
set.
skipws
noskipws
Skips leading white space on input.
uppercase
nouppercase
If uppercase is set, then use
uppercase for output formats, for example, 0X for hexadecimal output. If nouppercase is set, use lowercase, for example,
0x for hexadecimal output.
unitbuf
nounitbuf
If set, then output is not buffered but flushed after each
insert. If not set, output is buffered.
fixed
scientific
Set output of floating-point values to either fixed or
scientific notation.
ws This object eats white space from an input stream.
ends Inserts a null character () into an output
stream. Useful for null-terminating a string when using ostrstream.
flush Flushes any buffer characters to the output stream.
endl Inserts a newline character .
setiosflags(n)
resetiosflags(n)
Set or clear the ios flags en
masse.
setbase(n) Sets the base for integer input and output to 8, 10, 16 or 0.
See text for explanation of 0.
dec
oct
hex
Set the base to decimal, octal or hexadecimal.
Shorthand for setbase(10), setbase(8), and setbase(16), respectively.
setfill(c) Sets the character used to fill space when the number of
characters to display is less than the field width. The default
character is a space.
setprecision(n) Sets the number of digits to output when displaying a
floating-point number.
setw(n) Sets the minimum width of the next output field. The field is
expanded with setfill() characters as
necessary.
setfill(c) Sets the character used to fill space when the number of
characters to display is less than the field width. The default
character is a space.


internal
left
right
Set the placement of fill characters. If the fill character
were ‘*’ (for example), then:
internal
$**123.00
left **$123.00
right $123.00**
get_money()
put_money()
Read or display a monetary value, using the local rules as set
by locale. (This is not implemented in the current version of
gcc.)
get_time()
put_time()
Read or display a time or date, using the local rules as set by
locale. (This is not implemented in the current version of
gcc.)

Most of the manipulators are straightforward. A few require some explanation, however. For example, regarding the setbase() manipulator, not all values of base are supported. In fact, C++ supports only decimal, octal, and hexadecimal I/O — which is okay, as that’s pretty much all that’s required. You can, however, set the base to 0 — in fact, 0 is the default value.

Setting the base to 0 is the same as setting it to decimal for output. For input, however, setting the base to 0 means “extract the base from the number itself”. The rules for doing so are as follows:

  • *If a number begins with 0x or 0X, it is assumed to be hexadecimal.

  • *If a number begins with just 0, then it is assumed to be octal.

  • *Otherwise the number is assumed to be decimal.

The following simple program demonstrates these rules:

#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
    int n1, n2, n3;
    cin >> setbase(0) >> n1 >> n2 >> n3;
    cout << showbase << setbase(16)
         << "n1 = " << n1 << ", n2 = " << n2
         << ", n3 = "<< n3 << endl;
    return 0;
}

The first line sets the base for the cin object to 0 and then extracts three integers. The second line displays these three integers in hexadecimal format. The showbase manipulator causes the leading 0x to be displayed for hexadecimal values. The following shows an example execution of this program, where the three numbers in bold are values that I input from the keyboard:

10 010 0x10
n1 = 0xa, n2 = 0x8, n3 = 0x10

You can see that the first number was interpreted as 10 in base 10, which is 0xA in hexadecimal. The second number was interpreted as 10 in base 8, which is 8 in hexadecimal. The third and final number was interpreted as 10 in hexadecimal.

Another manipulator that deserves special mention is the setw(), short for “set width”. This sets the minimum display width of the next field displayed. The following simple program shows how setw()interacts with padding and the fill character:

#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
    int width;
    int value;
    cout << "Enter the width:";
    cin >> width;
    cout << setfill('*');
    for(;;)
    {
        cout << "Enter a value:";
        cin >> value;
        if (value == 0)
        {
            break;
        }
        cout << "Left, Right and Internal:n"
             << left     << setw(width) << value << ", "
             << right    << setw(width) << value << ", "
             << internal << setw(width) << value << endl;
    }
    return 0;
}

This program sets the fill character to * (the default is space). It then reads the width to be used for all numbers from the keyboard before entering a loop that reads and displays values. Within this loop, the program first displays the number with left-hand fill, then with right-hand fill, and finally with internal fill.

The following is a sample run of the program with the input bolded:

Enter the width:5
Enter a value:100000
Left, Right and Internal:
100000, 100000, 100000
Enter a value:100
Left, Right and Internal:
100**, **100, **100
Enter a value:-100
Left, Right and Internal:
-100*, *-100, -*100
Enter a value:0

Here 5 is entered as the width of the field. However, the first value entered, 100,000, requires more than 5 columns to display so none of the display fields had any effect. The set width only sets the minimum width to display.

The next value entered, 100, requires only three columns to display, so the program displayed the value first with two * characters on the right, then on the left, and again on the left.

The next value entered, –100, demonstrates the difference between right fill and internal fill. Right fill put the fill character on the left of the value, including the minus sign. Internal fill put the fill character between the value and the minus sign. This also works for a plus sign when plus is forced on with the showpos manipulator and between the number and the currency sign (when currency is supported by the compiler).

The manipulators don’t add any capability that isn’t already present. After all, each of these manipulators ends up calling a public method on the stream object. However, they do provide a convenient means of formatting I/O.