Home / Articles / C++ Streams and Formatting Manipulators

C++ Streams and Formatting Manipulators

C++ streams provide extensive control over how values are formatted when written to an output stream. Formatting is controlled through flags stored in the stream, and can be changed programmatically or via convenient manipulator objects.

ios_base Formatting Flags

Every stream inherits from ios_base, which stores a set of formatting flags as a bitmask. The flags are accessed as static constants in ios_base (or equivalently, ios):

Number Base Flags (a group — only one active at a time)

Flag Effect
ios::dec Decimal (default)
ios::oct Octal
ios::hex Hexadecimal

Floating-Point Notation Flags

Flag Effect
ios::fixed Fixed-point notation (e.g., 3.14159)
ios::scientific Scientific notation (e.g., 3.14159e+00)

Adjustment Flags

Flag Effect
ios::left Left-align within field width
ios::right Right-align (default)
ios::internal Pad between sign and digits

Other Flags

Flag Effect
ios::boolalpha Print true/false instead of 1/0
ios::showbase Show 0x prefix for hex, 0 for octal
ios::showpoint Always show decimal point
ios::showpos Show + sign for positive numbers
ios::uppercase Use A-F for hex, E for scientific notation
ios::skipws Skip whitespace on input (default)
ios::unitbuf Flush after every output operation

setf() and unsetf()

setf(flag)

Sets one or more flags:

cout.setf(ios::hex);          // switch to hex output
cout.setf(ios::showbase);     // show 0x prefix
cout << 255 << "\n";          // prints: 0xff

setf(flag, mask) — Exclusive Group

For flags that are mutually exclusive (like the base flags), use the two-argument form with a mask to clear the group first:

cout.setf(ios::hex, ios::basefield);   // set hex, clear dec and oct
cout.setf(ios::fixed, ios::floatfield); // set fixed, clear scientific
cout.setf(ios::left, ios::adjustfield); // set left, clear right and internal

The masks ios::basefield, ios::floatfield, and ios::adjustfield represent the corresponding groups.

unsetf(flag)

Clears a flag:

cout.unsetf(ios::showbase);
cout.unsetf(ios::boolalpha);

flags() — Get and Set All Flags

Get the current flags as a bitmask:

ios_base::fmtflags saved = cout.flags();  // save current state

Restore saved flags:

cout.flags(saved);  // restore

Precision

Precision controls the number of significant digits (default mode) or decimal places (fixed/scientific mode):

cout.precision(4);
cout << 3.14159265 << "\n";   // default mode: "3.142"

cout.setf(ios::fixed, ios::floatfield);
cout.precision(2);
cout << 3.14159265 << "\n";   // fixed mode: "3.14"

cout.setf(ios::scientific, ios::floatfield);
cout.precision(3);
cout << 3.14159265 << "\n";   // scientific mode: "3.142e+00"

Get current precision:

int p = cout.precision();

Width and Fill

width()

Sets the minimum field width for the next output operation only (it resets to 0 after each use):

cout.width(10);
cout << 42 << "\n";   // "        42" (right-aligned in 10-char field)

fill()

Sets the fill character used to pad to the field width (default is space):

cout.fill('0');
cout.width(6);
cout << 42 << "\n";   // "000042"

cout.fill('*');
cout.setf(ios::left, ios::adjustfield);
cout.width(10);
cout << "hi" << "\n"; // "hi********"

Get current fill character:

char f = cout.fill();

Stream Manipulators

Manipulators are objects (or functions) that can be inserted directly into a stream expression using << or >>. They modify the stream's state inline, making code more readable.

Include <iomanip> for the parameterized manipulators.

Manipulators Without Arguments (<iostream>)

cout << boolalpha << true << "\n";    // "true"
cout << noboolalpha << true << "\n";  // "1"
cout << hex << 255 << "\n";           // "ff"
cout << oct << 255 << "\n";           // "377"
cout << dec << 255 << "\n";           // "255" (restore decimal)
cout << showbase << hex << 255 << "\n"; // "0xff"
cout << noshowbase << "\n";
cout << uppercase << hex << 255 << "\n"; // "0XFF"
cout << nouppercase << "\n";
cout << showpos << 42 << "\n";        // "+42"
cout << noshowpos << "\n";
cout << fixed << 3.14 << "\n";        // "3.140000"
cout << scientific << 3.14 << "\n";   // "3.140000e+00"
cout << left  << setw(10) << "hi" << "\n"; // "hi        "
cout << right << setw(10) << "hi" << "\n"; // "        hi"
cout << internal << showpos << setw(10) << 42 << "\n"; // "+       42"

Parameterized Manipulators (<iomanip>)

#include <iomanip>

cout << setw(10) << 42 << "\n";           // width 10
cout << setprecision(4) << 3.14159 << "\n"; // 4 significant digits
cout << setfill('0') << setw(6) << 42 << "\n"; // "000042"
cout << setbase(16) << 255 << "\n";       // hex output
cout << setiosflags(ios::showbase | ios::uppercase) << "\n";
cout << resetiosflags(ios::showbase) << "\n";

ws Manipulator

The ws input manipulator skips leading whitespace:

cin >> ws;  // skip whitespace
getline(cin, line);  // read from first non-whitespace

This is particularly useful after cin >> to discard a trailing newline before calling getline.

Saving and Restoring Stream State

Since flags persist until changed, it is good practice to save and restore state around temporary changes:

// Save state
ios_base::fmtflags saved_flags = cout.flags();
int saved_precision = cout.precision();
char saved_fill = cout.fill();

// Temporary formatting
cout << hex << showbase << setprecision(2);
cout << 255 << "\n";  // 0xff

// Restore state
cout.flags(saved_flags);
cout.precision(saved_precision);
cout.fill(saved_fill);

A cleaner RAII approach is to use a copy of the stream's state or a formatting guard class from your own toolkit.

Practical Example

#include <iostream>
#include <iomanip>
using namespace std;

void print_table(double values[], int n) {
    cout << left << setw(5) << "N"
         << right << setw(15) << "Value"
         << right << setw(15) << "Hex" << "\n";
    cout << string(35, '-') << "\n";

    for (int i = 0; i < n; i++) {
        cout << left  << setw(5) << i
             << right << setw(15) << fixed << setprecision(4) << values[i]
             << right << setw(15) << hex << showbase << (long)values[i]
             << dec << noshowbase << "\n";
    }
}

Mastering stream formatting gives you printf-level control with full type safety and the extensibility of the C++ object model.