20 topics
/
← Back to Quick Reference
Topic 04

Input / Output

Streams · Formatting · cin · File I/O · sstream · std::format

C++17 · Advanced Reference

The iostream Model

01

Streams as abstractions

A stream is a sequence of bytes flowing in one direction. C++ wraps every I/O source and destination — terminal, file, string, network socket — behind the same interface: operator<< to write, operator>> to read. Switch targets by swapping the stream object; your formatting code stays the same.

Standard streams

  1. 1.std::cin — standard input. Connected to keyboard; reads whitespace-delimited tokens.
  2. 2.std::cout — standard output. Buffered for performance; flushed on endl or program exit.
  3. 3.std::cerr — standard error. Unbuffered — writes appear immediately even if cout is redirected.
  4. 4.std::clog — buffered error log. Same destination as cerr but batched for efficiency.

Stream state flags

  1. 1.goodbit — no errors; stream is ready for I/O.
  2. 2.eofbit — end-of-file reached. Further reads will fail.
  3. 3.failbit — logical error (e.g., reading letters into an int).
  4. 4.badbit — unrecoverable hardware/system error.

Check with if (stream) or stream.good(). Reset with stream.clear().

// The four standard stream objects (always available via <iostream>)
std::cin      // standard input  — connected to keyboard by default
std::cout     // standard output — connected to terminal by default
std::cerr     // standard error  — unbuffered, flushes immediately
std::clog     // standard error  — buffered (faster for logging)

// Chaining — operator<< / >> return the stream, so you can chain:
std::cout << "x=" << x << ", y=" << y << "\n";
std::cin  >> a >> b >> c;    // reads whitespace-separated tokens

// endl vs \n
std::cout << "line\n";      // fast — writes newline only
std::cout << "line" << std::endl;  // slow — writes newline + flushes buffer

// cerr for errors (always reaches the terminal even if cout is redirected)
std::cerr << "Error: file not found\n";

Output Formatting (iomanip)

02
#include <iomanip>   // all manipulators live here

double pi = 3.14159265358979;
int n = 255;

// ── Floating-point ──────────────────────────────────────────
std::cout << std::fixed      << std::setprecision(2) << pi; // 3.14
std::cout << std::scientific << std::setprecision(3) << pi; // 3.142e+00
std::cout << std::defaultfloat;  // reset to default notation

// ── Integer bases ───────────────────────────────────────────
std::cout << std::dec << n;   // 255  (decimal, default)
std::cout << std::hex << n;   // ff
std::cout << std::oct << n;   // 377
std::cout << std::uppercase << std::hex << n;  // FF
std::cout << std::showbase  << std::hex << n;  // 0xff

// ── Width & fill ────────────────────────────────────────────
std::cout << std::setw(8) << 42;          //       42  (right-aligned)
std::cout << std::left << std::setw(8) << 42;   // 42      (left-aligned)
std::cout << std::setfill('0') << std::setw(5) << 42;  // 00042

// Note: setw() resets after ONE output — must repeat each time
// setfill(), setprecision(), bases — persist until changed
setprecision(n)Number of significant digits (default) or decimal places (fixed/scientific).
fixedAlways show decimal point with exactly setprecision() decimal places.
scientificExponential notation: 3.14e+00.
setw(n)Minimum field width for next output ONLY — does not persist.
setfill(c)Fill character used when output is shorter than setw(). Default is space. Persists.
left / rightAlignment within the field set by setw(). Persists until changed.
setw() resets after one use. All other manipulators (fixed, setprecision, setfill, bases) persist until you explicitly change them.

cin & Input Handling

03
int x;
std::cin >> x;               // reads one int, skips leading whitespace

std::string word;
std::cin >> word;            // reads one whitespace-delimited token

std::string line;
std::getline(std::cin, line); // reads entire line including spaces

// ── Mixing >> and getline — classic pitfall ──────────────────
int age;
std::cin >> age;             // reads number, leaves '\n' in buffer
std::cin.ignore();           // discard the leftover newline
std::getline(std::cin, line); // now reads correctly

// ── Reading until EOF ────────────────────────────────────────
int val;
while (std::cin >> val) {    // loop exits on EOF or bad input
  sum += val;
}

// ── Error recovery ───────────────────────────────────────────
if (std::cin.fail()) {
  std::cin.clear();            // reset error flags
  std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
cin >> xSkips whitespace, reads one token. Stops at next whitespace.
getline(cin, s)Reads until newline (consuming it). Includes spaces in the result.
cin.ignore()Discards one character from the buffer — use after >> to clear the leftover newline before getline.
cin.fail()True if last operation failed (bad type, EOF). Must clear() before next read.
cin.clear()Resets all error flags. Pair with ignore() to discard bad input.
Always validate input. If cin >> x fails (wrong type), the stream enters a fail state and all subsequent reads silently do nothing until you call clear().

File I/O (fstream)

04
#include <fstream>

// ── Writing to a file ────────────────────────────────────────
std::ofstream out("data.txt");          // opens for writing (truncates)
std::ofstream app("log.txt", std::ios::app);  // append mode

if (!out) { std::cerr << "Cannot open file\n"; }

out << "Hello, file!\n";
out << std::fixed << std::setprecision(2) << 3.14;
out.close();   // optional — destructor closes automatically

// ── Reading from a file ──────────────────────────────────────
std::ifstream in("data.txt");

std::string line;
while (std::getline(in, line)) {        // line-by-line
  std::cout << line << "\n";
}

int val;
while (in >> val) { /* token-by-token */ }

// ── Read/write (fstream) ─────────────────────────────────────
std::fstream file("data.bin", std::ios::in | std::ios::out | std::ios::binary);

// File open modes (combine with |)
// ios::in      read     ios::out   write    ios::app   append
// ios::trunc   truncate ios::binary binary mode
ifstreamRead-only file stream. Fails silently if file doesn't exist — always check!
ofstreamWrite-only. Creates file if missing; truncates existing file by default.
fstreamRead+write. Must specify open mode flags explicitly.
ios::appAppend mode — seek to end before each write. File is not truncated.
ios::binaryBinary mode — disables newline translation on Windows.
RAII closes for you. File streams close automatically when they go out of scope. Explicit .close() is only needed when you want to reopen or check for write errors before the destructor runs.

String Streams (sstream)

05
In-memory I/O — format or parse strings
#include <sstream>

// ── ostringstream — build a string with << ───────────────────
std::ostringstream oss;
oss << "User: " << name << ", Score: " << std::setw(4) << score;
std::string result = oss.str();

// ── istringstream — parse a string with >> ───────────────────
std::string data = "10 3.14 hello";
std::istringstream iss(data);
int i; double d; std::string s;
iss >> i >> d >> s;     // i=10, d=3.14, s="hello"

// ── stringstream — read and write ───────────────────────────
std::stringstream ss;
ss << 42;
int n;
ss >> n;    // round-trip: int → string → int

// ── Common patterns ──────────────────────────────────────────
// String → number (prefer stoi/stod for simple cases)
int val = std::stoi("123");
double x = std::stod("3.14");

// Number → string (prefer to_string for simple cases)
std::string s2 = std::to_string(255);   // "255"
ostringstreamBuild a formatted string with <<. Call .str() to get the result.
istringstreamParse a string with >>. Great for splitting space-delimited data.
stringstreamBoth directions. Useful for type-safe number↔string conversion.

Performance & std::format

06
// ── Decouple C and C++ I/O (huge speedup in competitive programming)
std::ios::sync_with_stdio(false);  // disable C/C++ stream sync
std::cin.tie(nullptr);             // untie cin from cout

// ⚠ After these calls: do NOT mix printf/scanf with cin/cout

// ── Use \n instead of endl
// endl = \n + flush — flushing is expensive on every line
// \n   = just a newline character — buffered, fast

// ── printf / scanf — still fastest for simple formatted I/O
#include <cstdio>
printf("x = %d, pi = %.4f\n", x, 3.14159);
scanf("%d", &x);

// Format specifiers
// %d  int      %ld  long      %lld  long long
// %f  float    %lf  double    %s    char*
// %c  char     %x   hex       %05d  zero-padded width 5

// ── C++20: std::format (like Python's f-strings)
#include <format>
std::string s = std::format("x = {}, pi = {:.4f}", x, 3.14159);
std::cout << std::format("{:>8} | {:<12} | {:06.2f}\n", id, name, score);
sync_with_stdio(false)Decouples C and C++ I/O buffers. ~3-5× faster cin/cout. Do this once at the start of main().
cin.tie(nullptr)Stops cout from auto-flushing before each cin read. Faster when mixing input and output.
printf / scanfStill the fastest for simple formatted I/O. No type safety — format string must match args.
std::format (C++20)Type-safe, Python-style formatting. Compile-time format string checking. Prefer over printf when available.
Competitive programming fast I/O: put ios::sync_with_stdio(false) and cin.tie(nullptr) at the top of main() and use \n instead of endl — often the difference between TLE and AC.