Skillversitas

I/O Manipulators in C++

I/O manipulators are special objects that modify the behavior of input/output streams, such as setting column width, numeric precision, numeric base, and other formats. Manipulators make output neater, more structured, and more professional. To use most manipulators, include the <iomanip> header.


Why Use Manipulators?

C++'s default output is often not enough for neat formatting needs. For example, if you want to display a table with aligned columns, or display numbers with a specific precision, I/O manipulators are the solution.


Code Example

#include <iostream>
#include <iomanip>
#include <string>
#include <vector>

using namespace std;

int main() {
    // setw — sets the field width
    cout << "=== setw (Field Width) ===" << endl;
    cout << "|" << setw(10) << "Name" << "|"
         << setw(10) << "Age" << "|"
         << setw(10) << "GPA" << "|" << endl;
    cout << "|" << setw(10) << "John" << "|"
         << setw(10) << 22 << "|"
         << setw(10) << 3.75 << "|" << endl;
    cout << "|" << setw(10) << "Alice" << "|"
         << setw(10) << 21 << "|"
         << setw(10) << 3.90 << "|" << endl;

    // setfill — sets the fill character
    cout << "\n=== setfill (Fill Character) ===" << endl;
    cout << setfill('0') << setw(10) << 42 << endl;
    cout << setfill('-') << setw(15) << "Hello" << endl;
    cout << setfill(' ');  // Back to space

    // setprecision — sets the decimal precision
    cout << "\n=== setprecision (Number Precision) ===" << endl;
    double pi = 3.14159265358979;
    cout << fixed << setprecision(2) << pi << endl;   // 3.14
    cout << fixed << setprecision(4) << pi << endl;   // 3.1416
    cout << fixed << setprecision(6) << pi << endl;   // 3.141593
    cout << defaultfloat;  // Back to the default

    // fixed and scientific
    cout << "\n=== fixed vs scientific ===" << endl;
    double number = 1234567.89;
    cout << "Default:  " << number << endl;
    cout << "Fixed:    " << fixed << number << endl;
    cout << "Scientific: " << scientific << number << endl;
    cout << defaultfloat;

    // boolalpha — displays bool as true/false
    cout << "\n=== boolalpha ===" << endl;
    bool a = true, b = false;
    cout << "Without boolalpha: " << a << " " << b << endl;
    cout << "With boolalpha: " << boolalpha << a << " " << b << endl;
    cout << noboolalpha;

    // Numeric base: dec, hex, oct
    cout << "\n=== Number Base ===" << endl;
    int value = 255;
    cout << "Decimal:    " << dec << value << endl;
    cout << "Hexadecimal: " << hex << value << endl;
    cout << "Octal:      " << oct << value << endl;
    cout << dec;  // Back to decimal

    // showpoint — always displays the decimal point
    cout << "\n=== showpoint ===" << endl;
    double whole = 100.0;
    cout << "Without showpoint: " << whole << endl;
    cout << "With showpoint: " << showpoint << whole << endl;
    cout << noshowpoint;

    // showpos — displays the + sign for positive numbers
    cout << "\n=== showpos ===" << endl;
    int positive = 42;
    int negative = -42;
    cout << "Without showpos: " << positive << " " << negative << endl;
    cout << "With showpos: " << showpos << positive << " " << negative << endl;
    cout << noshowpos;

    // left, right, internal
    cout << "\n=== Alignment ===" << endl;
    cout << left << setw(15) << "Left" << "|" << endl;
    cout << right << setw(15) << "Right" << "|" << endl;
    cout << internal << setw(15) << -42 << "|" << endl;
    cout << right;  // Default

    return 0;
}

Code Explanation

1. setw(n) — Set Width

Sets the width of the next output field. After one output, the width goes back to the default (0).

#include <iomanip>

cout << setw(20) << "Text" << endl;
// Output: "                 Text" (with space padding on the left)

// Fill with digits
cout << setw(10) << setfill('0') << 42 << endl;
// Output: "0000000042"

Characteristics of setw:
- Applies only to the next output (one-time use)
- Does not affect strings longer than the width
- Default: space as the fill character

2. setfill(c) — Set Fill Character

Sets the character used to fill empty space. The default is a space. It is persistent (stays active until changed).

cout << setfill('*');
cout << setw(10) << "Hello" << endl;
// Output: "*****Hello"

cout << setfill('-');
cout << setw(10) << 42 << endl;
// Output: "--------42"

cout << setfill(' ');  // Back to space

3. setprecision(n) — Set Precision

Sets the number of decimal digits displayed for floating point. Its behavior depends on whether fixed or scientific mode is active.

double pi = 3.14159265358979;

// Default (significant digits)
cout << setprecision(3) << pi << endl;   // 3.14
cout << setprecision(10) << pi << endl;  // 3.141592654

// With fixed (decimal places)
cout << fixed << setprecision(2) << pi << endl;  // 3.14
cout << fixed << setprecision(4) << pi << endl;  // 3.1416

// With scientific
cout << scientific << setprecision(2) << pi << endl;  // 3.14e+00

4. fixed and scientific

double number = 1234567.89;

cout << defaultfloat << number << endl;   // 1.23457e+06 (default)
cout << fixed << number << endl;          // 1234567.890000
cout << scientific << number << endl;     // 1.234568e+06

5. boolalpha and noboolalpha

bool active = true;
bool inactive = false;

cout << boolalpha;
cout << active << endl;    // "true"
cout << inactive << endl; // "false"

cout << noboolalpha;
cout << active << endl;    // "1"
cout << inactive << endl; // "0"

6. dec, hex, oct — Numeric Base

int num = 255;

cout << dec << num << endl;    // 255
cout << hex << num << endl;    // ff
cout << oct << num << endl;    // 377
cout << dec;  // Back to decimal

// Display the 0x prefix for hex
cout << showbase << hex << num << endl;  // 0xff
cout << noshowbase << dec;

7. showpoint and noshowpoint

double bulat = 100.0;

cout << noshowpoint << bulat << endl;  // 100
cout << showpoint << bulat << endl;    // 100.000

8. showpos and noshowpos

int positif = 42;
int negatif = -42;

cout << noshowpos;
cout << positif << " " << negatif << endl;  // 42 -42

cout << showpos;
cout << positif << " " << negatif << endl;  // +42 -42

9. left, right, internal

// left — left-aligned (padding on the right)
cout << left << setw(15) << "Name" << "|" << endl;
// Output: "Name           |"

// right — right-aligned (padding on the left) [DEFAULT]
cout << right << setw(15) << "Name" << "|" << endl;
// Output: "           Name|"

// internal — sign on the left, digits on the right
cout << internal << setw(15) << -42 << "|" << endl;
// Output: "-            42|"

Complete List of Manipulators

Manipulators Without Parameters

Manipulator Header Function
endl <iostream> Newline + flush buffer
ends <iostream> Null character (\0)
flush <iostream> Flush buffer
dec <iostream> Decimal base
hex <iostream> Hexadecimal base
oct <iostream> Octal base
fixed <iostream> Fixed-point floating-point notation
scientific <iostream> Scientific floating-point notation
defaultfloat <iostream> Default floating-point format
boolalpha <iostream> Display bool as true/false
noboolalpha <iostream> Display bool as 1/0
showbase <iostream> Display the base prefix (0, 0x)
noshowbase <iostream> Hide the base prefix
showpoint <iostream> Display the decimal point
noshowpoint <iostream> Hide the decimal point
showpos <iostream> Display the + sign
noshowpos <iostream> Hide the + sign
skipws <iostream> Skip whitespace (default)
noskipws <iostream> Do not skip whitespace
unitbuf <iostream> Flush after every operation
nounitbuf <iostream> Default buffering
left <iomanip> Left-aligned
right <iomanip> Right-aligned
internal <iomanip> Internal alignment

Manipulators With Parameters

Manipulator Header Function
setw(n) <iomanip> Set field width
setfill(c) <iomanip> Set fill character
setprecision(n) <iomanip> Set decimal precision
setbase(b) <iomanip> Set base (8, 10, 16)

Everyday Use Cases

Student Data Table With Formatting

#include <iostream>
#include <iomanip>
#include <string>
#include <vector>

using namespace std;

struct Student {
    string name;
    string studentId;
    double gpa;
    int semester;
};

int main() {
    vector<Student> list = {
        {"John Smith", "2024001", 3.85, 4},
        {"Alice Williams", "2024002", 3.92, 3},
        {"Carl Johnson", "2024003", 3.67, 5},
        {"Dana Lewis", "2024004", 3.95, 4},
        {"Eric Foster", "2024005", 3.78, 6}
    };

    // Table header
    cout << setfill('=');
    cout << setw(60) << "" << endl;
    cout << setfill(' ');

    cout << left
         << setw(5)  << "No"
         << setw(20) << "Name"
         << setw(12) << "StudentID"
         << setw(10) << "Semester"
         << setw(10) << "GPA" << endl;

    cout << setfill('-');
    cout << setw(60) << "" << endl;
    cout << setfill(' ');

    // Data
    int no = 1;
    for (const auto& s : list) {
        cout << left
             << setw(5)  << no
             << setw(20) << s.name
             << setw(12) << s.studentId
             << setw(10) << s.semester
             << fixed << setprecision(2) << setw(10) << s.gpa
             << defaultfloat << endl;
        no++;
    }

    // Footer
    cout << setfill('-');
    cout << setw(60) << "" << endl;
    cout << setfill(' ');

    // Average GPA
    double totalGpa = 0;
    for (const auto& s : list) {
        totalGpa += s.gpa;
    }
    double average = totalGpa / list.size();

    cout << left << setw(37) << "Average GPA:"
         << fixed << setprecision(2) << average << endl;
    cout << defaultfloat;

    cout << setfill('=');
    cout << setw(60) << "" << endl;

    return 0;
}

Price Formatting in Rupiah

#include <iostream>
#include <iomanip>
#include <string>
#include <vector>

using namespace std;

struct Product {
    string name;
    int price;
    int stock;
};

string formatCurrency(int amount) {
    string result;
    string str = to_string(amount);
    int calculate = 0;

    for (int i = str.length() - 1; i >= 0; i--) {
        result = str[i] + result;
        calculate++;
        if (calculate % 3 == 0 && i != 0) {
            result = "." + result;
        }
    }

    return "  + result;
}

int main() {
    vector<Product> list = {
        {"Laptop ASUS ROG", 18500000, 15},
        {"Mouse Logitech G502", 650000, 50},
        {"Keyboard Mechanical", 1200000, 30},
        {"Monitor LG 27 inch", 4500000, 20},
        {"Headset SteelSeries", 1500000, 25}
    };

    cout << setfill('=');
    cout << setw(72) << "" << endl;
    cout << setfill(' ');

    cout << left
         << setw(5)  << "No"
         << setw(25) << "Name Product"
         << right
         << setw(15) << "Price"
         << setw(10) << "Stock"
         << setw(15) << "Total" << endl;

    cout << setfill('-');
    cout << setw(72) << "" << endl;
    cout << setfill(' ');

    int no = 1;
    long long total_grade = 0;

    for (const auto& p : list) {
        long long total = (long long)p.price * p.stock;
        total_grade += total;

        cout << left
             << setw(5)  << no
             << setw(25) << p.name
             << right
             << setw(15) << formatCurrency(p.price)
             << setw(10) << p.stock
             << setw(15) << formatCurrency(total) << endl;
        no++;
    }

    cout << setfill('-');
    cout << setw(72) << "" << endl;
    cout << setfill(' ');

    cout << left << setw(45) << "Total Grade Inventaris:"
         << right << setw(27) << formatCurrency(total_grade) << endl;

    cout << setfill('=');
    cout << setw(72) << "" << endl;

    return 0;
}

Financial Report Formatting With Various Bases

#include <iostream>
#include <iomanip>

using namespace std;

int main() {
    int grade = 255;

    cout << "=== Number Base Conversion ===" << endl;
    cout << "Decimal:      " << dec << setw(15) << right << grade << endl;
    cout << "Hexadecimal: " << hex << setw(15) << right << showbase << grade << endl;
    cout << "Octal:        " << oct << setw(15) << right << grade << endl;
    cout << noshowbase << dec;

    cout << "\n=== Format Floating Point ===" << endl;
    double pi = 3.14159265358979;
    double distance = 149600000.0;
    double mass = 0.0000000000012;

    cout << fixed;
    cout << "Pi (2 desimal):    " << setprecision(2) << setw(20) << pi << endl;
    cout << "Pi (10 desimal):   " << setprecision(10) << setw(20) << pi << endl;

    cout << defaultfloat;
    cout << "Distance (fixed):     " << fixed << setw(20) << distance << endl;
    cout << "Distance (scientific):" << scientific << setw(20) << distance << endl;

    cout << "Massa (scientific):" << scientific << setprecision(2) << setw(20) << mass << endl;
    cout << defaultfloat;

    cout << "\n=== Boolean and Positive ===" << endl;
    bool x = true;
    cout << boolalpha << "Status: " << x << endl;
    cout << noboolalpha << "Status: " << x << endl;

    cout << showpos;
    cout << "Positif: " << 42 << endl;
    cout << "Negatif: " << -42 << endl;
    cout << noshowpos;

    return 0;
}

Good Formatting Tips

  1. Always reset manipulators after using them — especially setfill, left/right, fixed/scientific
  2. Use setw to create tables with neat columns
  3. Use fixed + setprecision to display currency or consistent decimal values
  4. Use hex/oct for debugging or displaying memory addresses
  5. Use boolalpha for human-readable boolean output
  6. Use showpos when displaying value changes (positive/negative)
// A good reset pattern
cout << fixed << setprecision(2) << grade;
cout << defaultfloat;  // Reset float format
cout << right;         // Reset alignment
cout << setfill(' ');  // Reset fill character
cout << noshowpos;     // Reset showpos

Custom Manipulators

You can create your own manipulators:

#include <iostream>
#include <iomanip>
#include <string>

using namespace std;

// Custom manipulator: underlines text
ostream& underline(ostream& os) {
    return os << "\033[4m";  // ANSI escape code
}

// Custom manipulator: resets the format
ostream& resetFormat(ostream& os) {
    return os << "\033[0m";
}

int main() {
    cout << underline << "Underlined Text" << resetFormat << endl;
    cout << "Normal Text" << endl;

    return 0;
}

Conclusion

I/O manipulators enable neat, structured output formatting in C++. setw() sets the field width, setfill() sets the fill character, setprecision() sets the decimal precision, and manipulators such as fixed/scientific/boolalpha/hex/oct set the display format. The <iomanip> header is required for parameterized manipulators such as setw, setfill, and setprecision. Use manipulators to create tables, currency formatting, financial reports, and other professional output. Always remember to reset manipulators after using them so they do not affect subsequent output.