Using Insertion Operators and Controlling Format

This section shows how to control format and how to create insertion operators for your own classes. The insertion (<<) operator, which is preprogrammed for all standard C++ data types, sends bytes to an output stream object. Insertion operators work with predefined “manipulators,” which are elements that change the default format of integer arguments.

Output Width

To align output, you specify the output width for each item by placing the setw manipulator in the stream or by calling the width member function. This example right aligns the values in a column at least 10 characters wide:

#include <iostream.h>

void main()
{
   double values[] = { 1.23, 35.36, 653.7, 4358.24 };
   for( int i = 0; i < 4; i++ )
   {
      cout.width(10);
      cout << values[i] << '\n';
   }
}

The output looks like this:

      1.23
     35.36
     653.7
   4358.24

Leading blanks are added to any value fewer than 10 characters wide.

To pad a field, use the fill member function, which sets the value of the padding character for fields that have a specified width. The default is a blank. To pad the column of numbers with asterisks, modify the previous for loop as follows:

for( int i = 0; i < 4; i++ )
{
   cout.width( 10 );
   cout.fill( '*' );
   cout << values[i] << endl
}

The endl manipulator replaces the newline character ('\n'). The output looks like this:

******1.23
*****35.36
*****653.7
***4358.24

To specify widths for data elements in the same line, use the setw manipulator:

#include <iostream.h>
#include <iomanip.h>

void main()
{
   double values[] = { 1.23, 35.36, 653.7, 4358.24 };
   char *names[] = { "Zoot", "Jimmy", "Al", "Stan" };
   for( int i = 0; i < 4; i++ )
      cout << setw( 6 )  << names[i]
           << setw( 10 ) << values[i] << endl;
}

The width member function is declared in IOSTREAM.H. If you use setw or any other manipulator with arguments, you must include IOMANIP.H. In the output, strings are printed in a field of width 6 and integers in a field of width 10:

 Zoot       1.23
Jimmy      35.36
   Al      653.7
 Stan    4358.24

Neither setw nor width truncates values. If formatted output exceeds the width, the entire value prints, subject to the stream’s precision setting. Both setw and width affect the following field only. Field width reverts to its default behavior (the necessary width) after one field has been printed. However, the other stream format options remain in effect until changed.

Alignment

Output streams default to right-aligned text. To left align the names in the previous example and right align the numbers, replace the for loop as follows:

for ( int i = 0; i < 4; i++ )
   cout << setiosflags( ios::left )
        << setw( 6 )  << names[i]
        << resetiosflags( ios::left )
        << setw( 10 ) << values[i] << endl;

The output looks like this:

Zoot        1.23
Jimmy      35.36
Al         653.7
Stan     4358.24

The left-align flag is set by using the setiosflags manipulator with the ios::left enumerator. This enumerator is defined in the ios class, so its reference must include the ios:: prefix. The resetiosflags manipulator turns off the left-align flag. Unlike width and setw, the effect of setiosflags and resetiosflags is permanent.

Precision

The default value for floating-point precision is six. For example, the number 3466.9768 prints as 3466.98. To change the way this value prints, use the setprecision manipulator. The manipulator has two flags, ios::fixed and ios::scientific. If ios::fixed is set, the number prints as 3466.976800. If ios::scientific is set, it prints as 3.4669773+003.

To display the floating-point numbers shown in Alignment with one significant digit, replace the for loop as follows:

for ( int i = 0; i < 4; i++ )
   cout << setiosflags( ios::left )
        << setw( 6 )  
        << names[i]
        << resetiosflags( ios::left )
        << setw( 10 ) 
        << setprecision( 1 )
        << values[i] 
        << endl;

The program prints this list:

Zoot          1
Jimmy     4e+001
Al        7e+002
Stan      4e+003

To eliminate scientific notation, insert this statement before the for loop:

cout << setiosflags( ios::fixed );

With fixed notation, the program prints with one digit after the decimal point.

Zoot         1.2
Jimmy       35.4
Al         653.7
Stan      4358.2

If you change the ios::fixed flag to ios::scientific, the program prints this:

Zoot    1.2e+000
Jimmy   3.5e+001
Al      6.5e+002
Stan    4.4e+003

Again, the program prints one digit after the decimal point. If either ios::fixed or ios::scientific is set, the precision value determines the number of digits after the decimal point. If neither flag is set, the precision value determines the total number of significant digits. The resetiosflags manipulator clears these flags.

Radix

The dec, oct, and hex manipulators set the default radix for input and output. For example, if you insert the hex manipulator into the output stream, the object correctly translates the internal data representation of integers into a hexadecimal output format. The numbers are displayed with digits a through f in lowercase if the ios::uppercase flag is clear (the default); otherwise, they are displayed in uppercase. The default radix is dec (decimal).