Skip to content
C++

std::cout, std::cin, and std::format

Input and output in C++ are handled through streams — objects that represent a flowing sequence of data. std::cout (character output) sends data to the terminal. std::cin (character input) reads data from the keyboard. The << operator sends data into a stream; >> extracts data from a stream. The stream abstraction is powerful because the same << operator works for files, strings, and the network — you learn it once and reuse the pattern everywhere.

Output with std::cout

The << operator is left-to-right associative, so you can chain multiple insertions in one statement. Each argument is converted to text and sent to the terminal. "\n" moves to the next line; std::endl does the same but also flushes the buffer (forces any buffered output to appear now). Prefer "\n" in loops for performance.

#include <iostream>

int age = 25;
double gpa = 3.7;
std::string name = "Alice";

// Chained output:
std::cout << "Name: " << name << ", Age: " << age << "\n";
// Output: Name: Alice, Age: 25

// endl vs \n:
std::cout << "Line one" << std::endl;  // flushes buffer
std::cout << "Line two" << "\n";       // faster, no flush

// Numbers are formatted automatically:
std::cout << gpa << "\n";             // 3.7

Output formatting: width, precision, and alignment can be controlled with IO manipulators from <iomanip>. However, the modern approach is std::format (C++20), covered below.

#include <iomanip>

double pi = 3.14159265;
std::cout << std::fixed << std::setprecision(2) << pi;  // 3.14
std::cout << std::setw(10) << "hello";   // right-aligned in 10 chars

Input with std::cin

The >> extraction operator reads from the input stream into a variable. For numbers, it skips whitespace and reads until a non-numeric character. For strings, it reads one whitespace-delimited word. To read an entire line including spaces, use std::getline(std::cin, str).

#include <iostream>
#include <string>

int age;
std::cout << "Enter your age: ";
std::cin >> age;

double price;
std::cout << "Enter price: ";
std::cin >> price;

// Read multiple values in one statement:
int x, y;
std::cin >> x >> y;   // reads two integers separated by whitespace

// Read a full line (including spaces):
std::cin.ignore();    // discard leftover newline from previous >> read
std::string line;
std::getline(std::cin, line);

Input validation: if the user types something that doesn't match the expected type, std::cin enters a fail state. All subsequent reads produce zero/empty without waiting. Always check std::cin.fail() or test the stream directly when robustness matters.

int n;
std::cin >> n;
if (!std::cin) {   // or: if (std::cin.fail())
    std::cout << "Invalid input\n";
    std::cin.clear();           // clear the error flag
    std::cin.ignore(1000, '\n'); // discard bad input up to newline
}

Formatted strings with std::format (C++20)

C++20 introduced std::format — a type-safe, Python/Rust-style string formatting function. It uses curly-brace placeholders ({}) that are filled with the provided arguments, producing a formatted std::string. It is cleaner than printf (type-safe) and more convenient than chained << operators for complex formatting.

#include <format>   // C++20

std::string s = std::format("Hello, {}! You are {} years old.", "Alice", 25);
// s = "Hello, Alice! You are 25 years old."

// Directly to cout with std::print (C++23) or format + cout:
std::cout << std::format("Pi ≈ {:.4f}\n", 3.14159);   // Pi ≈ 3.1416

// Format specifiers:
std::cout << std::format("{:>10}",   "right");  // right-aligned in 10 chars
std::cout << std::format("{:<10}",   "left");   // left-aligned
std::cout << std::format("{:^10}",   "center"); // centered
std::cout << std::format("{:08d}",   42);       // "00000042"
std::cout << std::format("{:.2f}",   3.14159);  // "3.14"
std::cout << std::format("{:+}",     42);       // "+42" (always show sign)

If your compiler does not yet support std::format (requires GCC 13+, Clang 14+, MSVC 19.29+), the fmt library (fmtlib) provides the same API as a third-party dependency, and was the reference implementation for the standard.

std::cerr and std::clog

Beyond std::cout, the standard library provides two other output streams. std::cerr writes to standard error (stderr) and is always unbuffered — use it for error messages that must appear immediately. std::clog is buffered standard error — use it for diagnostic logging.

// Errors to stderr — separate from normal output:
if (!file.is_open()) {
    std::cerr << "Error: could not open file\n";
    return 1;
}

// Redirect stdout to a file while keeping errors on the terminal:
// $ ./myprogram > output.txt    — cerr still appears on terminal

Key rules to remember

Prefer "\n" over std::endl in performance-sensitive output

endl flushes the output buffer every time. \n just appends a newline. Flushing on every line is expensive inside loops.

Use std::getline for reading a full line; plain >> stops at the first space

After a >> read, a newline remains in the buffer. Call std::cin.ignore() before std::getline to discard it.

Check std::cin after reading to detect invalid input

If the user types letters when you expect an integer, cin enters a fail state. Call cin.clear() and cin.ignore() to recover.

Use std::format (C++20) for complex formatted output

It is type-safe (unlike printf), cleaner than chained <<, and supports all the common format specifiers (width, precision, alignment, sign).

Send error messages to std::cerr, not std::cout

Users can redirect stdout to a file with > while keeping stderr visible on the terminal. Mixing errors into stdout makes both unusable.

Sign in to track progress