Chapter 5 Beginner 25 min min read Updated 2026-04-10

Input, Output, and Formatting

Practice Questions →

In This Chapter

What Is It?

What Is Input/Output in C++?

Input/Output (I/O) in C++ is handled through streams. A stream is an abstraction that represents a sequence of bytes flowing between your program and an external device (keyboard, screen, file). The <iostream> header provides four predefined stream objects:

StreamTypePurposeDefault Device
cinistreamStandard inputKeyboard
coutostreamStandard outputScreen (buffered)
cerrostreamStandard errorScreen (unbuffered)
clogostreamStandard logScreen (buffered)

The << operator (insertion) sends data to an output stream. The >> operator (extraction) reads data from an input stream. These operators can be chained: cout << "x = " << x << endl; chains three outputs in one statement.

Why Does It Matter?

Why Is I/O Knowledge Critical?

1. Competitive Programming

The difference between TLE (Time Limit Exceeded) and AC (Accepted) is often just I/O speed. Using endl instead of '\n' can make your program 10x slower when printing millions of lines. ios_base::sync_with_stdio(false) and cin.tie(NULL) are the first two lines of every competitive programmer's template.

2. The cin Buffer Problem

One of the most frustrating bugs beginners face is getline reading an empty string after cin >>. Understanding the input buffer -- that cin >> leaves the newline character in the buffer, which getline immediately reads -- prevents hours of confusion. This is asked in interviews.

3. Formatted Output

When problems require specific formatting (fixed decimal places, right-aligned columns, zero-padded numbers), you need <iomanip> manipulators. Interview coding rounds sometimes specify exact output formats. Without setprecision, fixed, and setw, matching the expected output is impossible.

4. Interview Topics

"Explain the difference between endl and '\n'" is a classic question. "What does cin.ignore() do?" and "Why use cerr instead of cout?" appear in systems programming interviews.

Detailed Explanation

Detailed Explanation

cout and cin Chaining

Both << and >> return a reference to the stream, enabling chaining. cout << a << " " << b; is equivalent to ((cout << a) << " ") << b;. Similarly, cin >> a >> b; reads two values separated by whitespace.

getline(cin, str)

cin >> reads until the first whitespace character (space, tab, newline) and leaves the delimiter in the buffer. To read an entire line including spaces, use getline(cin, str). It reads until the newline character, consumes the newline, and stores everything before it in str.

The cin Buffer Problem: cin.ignore() and cin.clear()

When you use cin >> n followed by getline(cin, str), the >> operator leaves the newline ('\n') in the input buffer. getline then reads that leftover newline immediately, producing an empty string. The fix is cin.ignore() between them, which discards the leftover newline.

cin.ignore(numeric_limits<streamsize>::max(), '\n') discards everything up to and including the next newline -- the most robust form.

cin.clear() resets the error state of cin. If the user enters a string when cin expects an int, cin enters a fail state and all subsequent reads fail silently. cin.clear() resets this state, and cin.ignore() clears the bad input from the buffer.

iomanip Formatting

The <iomanip> header provides manipulators for formatted output:

  • setw(n): Sets the minimum field width for the NEXT output only. If the output is shorter than n, it is padded (right-aligned by default).
  • setprecision(n): Sets the number of significant digits (or decimal places if used with fixed).
  • fixed: Switches to fixed-point notation. After fixed, setprecision(n) means n decimal places.
  • scientific: Switches to scientific notation (e.g., 3.14e+00).
  • left / right: Sets alignment for setw padding.
  • setfill(c): Sets the fill character for setw padding (default is space).
  • boolalpha: Prints bool as "true"/"false" instead of 1/0.

endl vs '\n'

endl does two things: inserts a newline AND flushes the output buffer. '\n' only inserts a newline. Flushing forces the buffered data to be written to the screen immediately. In competitive programming, flushing after every line is wasteful -- the buffer is flushed automatically when the program ends or when the buffer is full. Using '\n' instead of endl can be 5-10x faster when printing many lines.

cerr and clog

cerr is unbuffered -- output appears immediately without waiting for a flush. It is used for error messages and debug output because even if the program crashes, the error message will have been printed. clog is buffered, used for log messages. In competitive programming, cerr is useful for debug prints that are ignored by the judge (judges only check cout/stdout).

C-style I/O: printf and scanf

printf and scanf from C are available in C++ via <cstdio>. They use format specifiers: %d (int), %f (float/double), %c (char), %s (C-string), %lld (long long). printf is sometimes preferred for formatted output because the format string is more compact than chaining iomanip manipulators.

Fast I/O for Competitive Programming

The competitive programming I/O template:

ios_base::sync_with_stdio(false);
cin.tie(NULL);

ios_base::sync_with_stdio(false) disconnects C++ streams from C streams, removing synchronization overhead. cin.tie(NULL) unties cin from cout, so cout is not flushed before every cin read. After these two lines, do NOT mix C I/O (printf/scanf) with C++ I/O (cout/cin).

Code Examples

cout and cin Chaining
#include <iostream>
using namespace std;

int main() {
    // Output chaining
    int a = 10, b = 20;
    cout << "a = " << a << ", b = " << b << endl;

    // Input chaining
    int x, y, z;
    cout << "Enter three numbers: ";
    cin >> x >> y >> z;
    cout << "Sum: " << x + y + z << endl;

    // Multiple types in one chain
    string name;
    int age;
    cout << "Enter name and age: ";
    cin >> name >> age;
    cout << name << " is " << age << " years old." << endl;

    return 0;
}
The << and >> operators return the stream object, enabling chaining. cin >> x >> y >> z reads three whitespace-separated values. Note that cin >> name reads only the first word (stops at whitespace).
a = 10, b = 20 Enter three numbers: 3 5 7 Sum: 15 Enter name and age: Priya 21 Priya is 21 years old.
getline and the cin Buffer Problem
#include <iostream>
#include <string>
using namespace std;

int main() {
    int rollNo;
    string fullName;

    cout << "Enter roll number: ";
    cin >> rollNo;

    // WRONG: getline reads the leftover '\n' from cin >>
    // getline(cin, fullName);  // fullName would be empty!

    // FIX: ignore the leftover newline
    cin.ignore();  // Discard the '\n' left by cin >>

    cout << "Enter full name: ";
    getline(cin, fullName);

    cout << "Roll: " << rollNo << endl;
    cout << "Name: " << fullName << endl;

    // Reading multiple lines
    string line1, line2;
    cout << "Enter address (2 lines):" << endl;
    getline(cin, line1);
    getline(cin, line2);
    cout << "Line 1: " << line1 << endl;
    cout << "Line 2: " << line2 << endl;

    return 0;
}
After cin >> rollNo, the newline from pressing Enter remains in the buffer. Without cin.ignore(), getline immediately reads that newline and stores an empty string. cin.ignore() discards one character (the leftover newline). Always use cin.ignore() when switching from >> to getline.
Enter roll number: 101 Enter full name: Rahul Sharma Roll: 101 Name: Rahul Sharma Enter address (2 lines): 42 MG Road New Delhi 110001 Line 1: 42 MG Road Line 2: New Delhi 110001
iomanip: setw, setprecision, fixed, setfill
#include <iostream>
#include <iomanip>
using namespace std;

int main() {
    // setprecision without fixed: total significant digits
    double pi = 3.141592653589793;
    cout << "Default: " << pi << endl;
    cout << "setprecision(3): " << setprecision(3) << pi << endl;
    cout << "setprecision(10): " << setprecision(10) << pi << endl;

    // fixed + setprecision: decimal places
    cout << fixed;
    cout << "fixed + setprecision(2): " << setprecision(2) << pi << endl;
    cout << "fixed + setprecision(6): " << setprecision(6) << pi << endl;

    // Reset to default
    cout << defaultfloat;

    // setw and alignment
    cout << "\n--- Table ---" << endl;
    cout << left << setw(15) << "Name" << right << setw(10) << "Marks" << endl;
    cout << left << setw(15) << "Ananya" << right << setw(10) << 95 << endl;
    cout << left << setw(15) << "Vikram" << right << setw(10) << 87 << endl;
    cout << left << setw(15) << "Deepa" << right << setw(10) << 92 << endl;

    // setfill for zero-padding
    cout << "\n--- Zero Padding ---" << endl;
    for (int i = 1; i <= 5; i++) {
        cout << "Item " << setfill('0') << setw(3) << i << endl;
    }

    return 0;
}
Without fixed, setprecision(n) controls total significant digits. With fixed, it controls decimal places. setw sets the minimum width for the next output only (it resets after each use). left/right control alignment within the setw field. setfill('0') uses zeros for padding instead of spaces.
Default: 3.14159 setprecision(3): 3.14 setprecision(10): 3.141592654 fixed + setprecision(2): 3.14 fixed + setprecision(6): 3.141593 --- Table --- Name Marks Ananya 95 Vikram 87 Deepa 92 --- Zero Padding --- Item 001 Item 002 Item 003 Item 004 Item 005
endl vs '\n' Performance
#include <iostream>
#include <chrono>
using namespace std;

int main() {
    const int N = 100000;

    // Timing with endl
    auto start1 = chrono::high_resolution_clock::now();
    for (int i = 0; i < N; i++) {
        cout << i << endl;  // Flushes every iteration
    }
    auto end1 = chrono::high_resolution_clock::now();

    // Timing with '\n'
    auto start2 = chrono::high_resolution_clock::now();
    for (int i = 0; i < N; i++) {
        cout << i << '\n';  // No flush
    }
    auto end2 = chrono::high_resolution_clock::now();

    auto ms1 = chrono::duration_cast<chrono::milliseconds>(end1 - start1).count();
    auto ms2 = chrono::duration_cast<chrono::milliseconds>(end2 - start2).count();

    cerr << "endl: " << ms1 << " ms" << endl;
    cerr << "'\\n': " << ms2 << " ms" << endl;

    return 0;
}
endl flushes the buffer after every write. With 100,000 iterations, this means 100,000 flushes vs zero flushes with '\n'. The difference is dramatic -- typically 5-10x slower. Note we print timing to cerr to keep it separate from the numbered output. In competitive programming, always use '\n'.
(100000 numbers printed) endl: ~350 ms '\n': ~50 ms
cerr, clog, and Debug Output
#include <iostream>
using namespace std;

int main() {
    // cout: standard output (buffered)
    cout << "This goes to stdout" << endl;

    // cerr: standard error (unbuffered) -- appears immediately
    cerr << "Error: something went wrong!" << endl;

    // clog: standard log (buffered)
    clog << "Log: program started" << endl;

    // In competitive programming, use cerr for debugging
    // The judge only checks stdout (cout)
    int arr[] = {3, 1, 4, 1, 5};
    int n = 5;
    cerr << "DEBUG: array = ";
    for (int i = 0; i < n; i++) cerr << arr[i] << " ";
    cerr << endl;

    // Your actual answer
    int sum = 0;
    for (int i = 0; i < n; i++) sum += arr[i];
    cout << sum << endl;  // Only this is checked by the judge

    return 0;
}
cerr is unbuffered -- output appears immediately even if the program crashes. In competitive programming, debug prints to cerr are not checked by the judge (which only compares stdout). This means you can leave debug output in your submission without getting Wrong Answer.
This goes to stdout Error: something went wrong! Log: program started DEBUG: array = 3 1 4 1 5 14
Fast I/O Template for Competitive Programming
#include <iostream>
using namespace std;

int main() {
    // Fast I/O: must be the first two lines
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    // After these lines, do NOT use printf/scanf
    // Do NOT use endl -- use '\n'

    int t;
    cin >> t;
    while (t--) {
        int n;
        cin >> n;
        long long sum = 0;
        for (int i = 0; i < n; i++) {
            int x;
            cin >> x;
            sum += x;
        }
        cout << sum << '\n';
    }

    return 0;
}
ios_base::sync_with_stdio(false) disconnects C++ I/O from C I/O, removing synchronization overhead. cin.tie(NULL) prevents cout from being flushed before every cin operation. Together, these make cin/cout as fast as scanf/printf. After using these, never mix C and C++ I/O in the same program.
(Processes t test cases, each with n numbers, printing their sum)
printf and scanf (C-style I/O)
#include <cstdio>
using namespace std;

int main() {
    // printf with format specifiers
    int age = 20;
    double gpa = 8.75;
    char grade = 'A';

    printf("Age: %d\n", age);
    printf("GPA: %.2f\n", gpa);    // 2 decimal places
    printf("Grade: %c\n", grade);

    // Formatted table with printf
    printf("\n%-15s %5s %10s\n", "Name", "Roll", "Marks");
    printf("%-15s %5d %10.1f\n", "Arjun", 101, 92.5);
    printf("%-15s %5d %10.1f\n", "Kavitha", 102, 88.0);
    printf("%-15s %5d %10.1f\n", "Ravi", 103, 95.3);

    // scanf for input
    int x;
    printf("\nEnter a number: ");
    scanf("%d", &x);  // Note the & (address-of operator)
    printf("You entered: %d\n", x);

    // Zero-padding with printf
    for (int i = 1; i <= 5; i++) {
        printf("Item %03d\n", i);  // 3-digit zero-padded
    }

    return 0;
}
printf uses format specifiers: %d (int), %.2f (double with 2 decimal places), %c (char), %s (C-string). %-15s means left-aligned in 15 chars. %03d means zero-padded to 3 digits. scanf requires the address of the variable (&x). printf formatting is more concise than cout + iomanip for tabular output.
Age: 20 GPA: 8.75 Grade: A Name Roll Marks Arjun 101 92.5 Kavitha 102 88.0 Ravi 103 95.3 Enter a number: 42 You entered: 42 Item 001 Item 002 Item 003 Item 004 Item 005

Common Mistakes

getline Reads Empty String After cin >>

#include <iostream>
#include <string>
using namespace std;
int main() {
    int n;
    string name;
    cout << "Enter number: ";
    cin >> n;
    cout << "Enter name: ";
    getline(cin, name);  // Reads empty string!
    cout << "Name: '" << name << "'" << endl;
    return 0;
}
name is empty. getline reads the leftover '\n' from cin >> n immediately.
#include <iostream>
#include <string>
using namespace std;
int main() {
    int n;
    string name;
    cout << "Enter number: ";
    cin >> n;
    cin.ignore();  // Discard the leftover '\n'
    cout << "Enter name: ";
    getline(cin, name);
    cout << "Name: '" << name << "'" << endl;
    return 0;
}
After cin >> n, the newline character from pressing Enter remains in the buffer. getline reads until the next newline -- which is immediately available -- producing an empty string. cin.ignore() discards that leftover newline. This is the most common beginner I/O bug in C++.

Using endl in Competitive Programming (Performance)

#include <iostream>
using namespace std;
int main() {
    int n = 1000000;
    for (int i = 0; i < n; i++) {
        cout << i << endl;  // Flushes 1 million times!
    }
    return 0;
}
Time Limit Exceeded. endl flushes the buffer every iteration, making output 5-10x slower.
#include <iostream>
using namespace std;
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    int n = 1000000;
    for (int i = 0; i < n; i++) {
        cout << i << '\n';  // No flush, much faster
    }
    return 0;
}
endl inserts a newline AND flushes the buffer. '\n' only inserts a newline. In competitive programming, use '\n' and add fast I/O at the top. The buffer flushes automatically when the program ends.

Mixing C and C++ I/O After sync_with_stdio(false)

#include <iostream>
#include <cstdio>
using namespace std;
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout << "Hello from cout" << '\n';
    printf("Hello from printf\n");  // Undefined behavior!
    return 0;
}
Output may be interleaved or out of order. After disabling sync, mixing cout and printf is undefined.
#include <iostream>
using namespace std;
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout << "Hello from cout" << '\n';
    cout << "Hello again from cout" << '\n';
    // Use ONLY cout/cin after sync_with_stdio(false)
    return 0;
}
ios_base::sync_with_stdio(false) disconnects C++ streams from C streams. After this, using printf/scanf alongside cout/cin causes undefined behavior -- output may appear in wrong order or get lost.

setw Only Affects the Next Output

#include <iostream>
#include <iomanip>
using namespace std;
int main() {
    cout << setw(10);
    cout << 42 << 99 << endl;  // Only 42 is padded!
    return 0;
}
Output is ' 4299' not ' 42 99'. setw only affects the very next output.
#include <iostream>
#include <iomanip>
using namespace std;
int main() {
    cout << setw(10) << 42 << setw(10) << 99 << endl;
    return 0;
}
setw is consumed by the next output operation and then resets. You must write setw before EVERY value you want padded. Other manipulators like setprecision, fixed, left, and setfill are persistent -- they stay in effect until changed.

Summary

  • C++ I/O uses streams: cin (input), cout (output), cerr (error, unbuffered), clog (log, buffered). Include <iostream> for all four.
  • cin >> reads until whitespace. getline(cin, str) reads the entire line including spaces. Always use cin.ignore() when switching from >> to getline.
  • The cin buffer problem: cin >> leaves '\n' in the buffer. getline reads that '\n' immediately, producing an empty string. Fix with cin.ignore().
  • cin.clear() resets the error state after bad input. cin.ignore() discards characters from the buffer. Use both together to recover from invalid input.
  • endl inserts a newline AND flushes the buffer. '\n' only inserts a newline. Use '\n' in competitive programming for 5-10x faster output.
  • iomanip manipulators: setw(n) sets minimum width (next output only), setprecision(n) sets precision, fixed switches to decimal places, setfill(c) changes padding character.
  • setw resets after each use. setprecision, fixed, left, right, and setfill are persistent (stay in effect until changed).
  • cerr is unbuffered and writes to stderr. In competitive programming, use cerr for debug output -- judges only check stdout (cout).
  • printf/scanf from C are available via <cstdio>. printf uses format specifiers (%d, %f, %s, %c). printf is more compact for formatted tables.
  • Fast I/O template: ios_base::sync_with_stdio(false) + cin.tie(NULL). After this, do NOT mix C I/O (printf/scanf) with C++ I/O (cout/cin).

Ready to Practice?

Test your understanding with 50+ practice questions on this topic.

Go to Practice Questions

Want to learn C++ with a live mentor?

Explore our C++ Masterclass