C++ IO and Formatting
- Description: A note on C++ I/O streams, formatting manipulators,
std::bindwith placeholders, and modern formatting (std::format,std::print) - My Notion Note ID: K2A-B1-20
- Created: 2018-12-27
- Updated: 2026-02-28
- License: Reuse is very welcome. Please credit Yu Zhang and link back to the original on yuzhang.io
Table of Contents
- 1.
std::ios_base::openmode - 2. Stream Formatting:
std::setwandstd::setfill - 3.
std::bindandstd::placeholders - 4.
std::formatandstd::print(C++20/23)
1. std::ios_base::openmode
- File-open flags, combinable:
| Flag | Meaning |
|---|---|
std::ios_base::in |
Open for reading |
std::ios_base::out |
Open for writing |
std::ios_base::app |
Seek to end of stream before each write (append) |
std::ios_base::ate |
Seek to end of stream immediately after opening |
std::ios_base::trunc |
Discard existing contents when opening |
std::ios_base::binary |
Open in binary mode (no text translation) |
#include <fstream>
// Open for reading and writing in binary mode
std::fstream file("data.bin",
std::ios_base::in | std::ios_base::out | std::ios_base::binary);
// Open for appending (does not truncate existing content)
std::ofstream log("app.log", std::ios_base::app);
// Open for writing, truncating existing content (default for ofstream)
std::ofstream out("output.txt", std::ios_base::out | std::ios_base::trunc);
2. Stream Formatting: std::setw and std::setfill
<iomanip>— manipulators for output formatting.setw= minimum field width;setfill= padding character.
#include <iostream>
#include <iomanip>
int main() {
int value = 42;
// Pad with zeros to a width of 9 characters
std::cout << std::setw(9) << std::setfill('0') << value << std::endl;
// Output: 000000042
// Right-align with spaces (default)
std::cout << std::setw(9) << std::setfill(' ') << value << std::endl;
// Output: 42
// Left-align
std::cout << std::left << std::setw(9) << std::setfill('.') << value << std::endl;
// Output: 42.......
return 0;
}
- Note:
setwresets after each insertion.setfillpersists until changed.
Other common <iomanip> manipulators:
setprecision(n)— digits for FP output. Combine withfixed/scientific.hex,oct,dec— integer base for in/out.boolalpha/noboolalpha— print booleans astrue/falsevs1/0.showbase— prefix0x/0on hex / octal.
3. std::bind and std::placeholders
std::bind— new callable by fixing some args of an existing callable; rest are placeholders for future args.
3.1 std::placeholders
- Placeholders
_1,_2,_3, ... mark positions for future args._1= first arg passed to bound fn. Numbering starts at_1.
3.2 std::bind
- Produces a forwarding call wrapper. Calling it invokes original with bound args substituted.
#include <functional>
#include <iostream>
int sum(int a, int b) {
return a + b;
}
int main() {
using namespace std::placeholders;
// Bind the second argument to 3; _1 is the first argument passed to add_3
auto add_3 = std::bind(sum, _1, 3);
std::cout << add_3(4) << std::endl; // sum(4, 3) = 7
// Swap argument order
auto swapped = std::bind(sum, _2, _1);
std::cout << swapped(10, 20) << std::endl; // sum(20, 10) = 30
return 0;
}
3.3 Modern Alternative: Lambdas
- Lambdas usually clearer + more flexible than
bind:
// Equivalent to std::bind(sum, _1, 3)
auto add_3 = [](int x) { return sum(x, 3); };
Why prefer lambdas:
- Easier to read.
- Predictable with overloads (no ambiguity in overload resolution).
- Better optimization — compiler inlines through them;
bindoften type-erased. - Support generic captures (
[](auto x) { ... }) and capture-by-move ([p = std::move(ptr)] { ... }) —bindcannot.
4. std::format and std::print (C++20/23)
std::format(C++20,<format>) +std::print(C++23,<print>) — modern alternatives to<<andprintf.
#include <format>
#include <print> // C++23
std::string s = std::format("Hello, {}!", "world"); // "Hello, world!"
std::print("count = {}\n", 42); // C++23: print to stdout
std::println("widget at ({}, {})", 1, 2); // adds a newline
std::format_to(buf, "pid {}", pid); // write to an iterator
printf |
<< (iostream) |
std::format |
|
|---|---|---|---|
| Type-safe | No (format-string mismatch is runtime UB) | Yes | Yes |
| Custom types | Manual | Overload << |
Specialize std::formatter<T> |
| Speed | Fast | Slow | Fast |
| Positional args | No | No | Yes ({0}, {1}) |
| Compile-time format check | No | N/A | Yes (C++20) |
| Locale-independent | Yes | Mixed | Yes (default) |
- Full format specifier coverage, custom formatters, conversions → C++ Strings and Text § 5.