Skip to content

Wiki

std::format / std::print

About 8 min read

Existing English translations were reused. 6 current source blocks remain in Simplified Chinese, without triggering paid translation.

1.What problem does this section solve?

C++ Outputting formatted strings in C has always been rather troublesome:

  • printf:Fast but type-unsafe; formatting string errors can cause crashes.
  • std::cout:Type-safe but verbose to write, and formatting control is inconvenient.
  • std::stringstream:Feature-complete but very verbose.

C++20/23 introduced std::format (formatted strings) and std::print (direct output), combining Python-style conciseness with C++'s type safety + high performance.

2.What is this feature?

  • std::format(C++20): Similar to Python's f"{name}: {score}", returns the formatted std::string.
  • std::print(C++23): Similar to Python's print(), directly outputs the formatted result to stdout.

Built on the {fmt} library, it delivers extremely high performance—approaching or even exceeding that of printf.

3.C++ Standard Edition

  • std::format:C++20
  • std::print:C++23

4.编译器和系统环境

下面的代码在 Linux 和 Windows 中使用同一份写法。先按 现代C++ 的编译约定 检查标准版本和工具链支持。

只有 std::format 的例程使用 C++20;出现 <print> 的例程需要 C++23 和支持它的标准库。入门模板默认 C++20,所以复制 std::println 例程后,还要把对应 target 的编译特性提升为 cxx_std_23。Windows 终端显示中文时,源文件与终端也应使用一致的 UTF-8 设置。

5.Required header files

#include <format>    // for std::format (C++20)
#include <print>     // for std::print, std::println (C++23)

6.Basic syntax

// std::format:返回 string
std::string s = std::format("Hello, {}!", name);
std::string s2 = std::format("{0} + {1} = {2}", a, b, a + b);

// std::print:直接输出(不自动换行)
std::print("x = {}, y = {}", x, y);

// std::println:输出并换行
std::println("Hello, {}!", name);

// 指定输出目标:stdout / stderr 是 FILE*
std::println(stdout, "normal message");
std::println(stderr, "error message");

// 格式控制
std::format("{:.2f}", 3.14159);     // "3.14" —— 保留 2 位小数
std::format("{:>10}", 42);          // "        42" —— 右对齐,宽度 10
std::format("{:<10}", 42);          // "42        " —— 左对齐
std::format("{:^10}", 42);          // "    42    " —— 居中
std::format("{:#x}", 255);          // "0xff" —— 十六进制带前缀
std::format("{:04d}", 7);           // "0007" —— 前导零填充

7.Output Mode Comparison

Method Performance Type safety Conciseness Version introduced
printf Fast ❌ ✅ C
std::cout Slow ✅ ❌ C++98
std::format Very fast ✅ ✅ C++20
std::print Very fast ✅ ✅ C++23

8.Where does std::print output to?

C++ In the standard library, there are std::print / std::println commonly used in two types of notation:

Usage Output target
std::println("x = {}", x) By default, output goes to standard output, i.e. stdout
std::println(stdout, "x = {}", x) Explicitly output to stdout
std::println(stderr, "error = {}", code) Output to standard error stderr

Here, stdout and stderr are in the C standard library's FILE*, and you need to include <cstdio>.

Note: the standard C++23 'sstd::println first parameter is not std::cout.std::cout is C++ 's std::ostream object, which belongs to <iostream>. You may have seen a similar {fmt} syntax in the fmt::print(std::cout, "...") library or certain extensions, but that is not the same interface as the standard library std::println.

9.Example code

9.1.Example 1: Basic usage of std::format

#include <iostream>
#include <format>
#include <string>

int main()
{
    std::string name = "Alice";
    int age = 25;
    double score = 92.5;

    // 基本占位符
    std::string s1 = std::format("Name: {}, Age: {}, Score: {}", name, age, score);
    std::cout << s1 << "\n";

    // 指定顺序
    std::string s2 = std::format("{1} is {0} years old", age, name);
    std::cout << s2 << "\n";

    // 保留 2 位小数
    std::string s3 = std::format("Score: {:.2f}", score);
    std::cout << s3 << "\n";

    return 0;
}

Running result:

Name: Alice, Age: 25, Score: 92.5
Alice is 25 years old
Score: 92.50

9.2.Example 2: Based on Example 1, format control and alignment

#include <iostream>
#include <format>

int main()
{
    // 右对齐,宽度 10
    std::cout << std::format("[{:>10}]\n", 42);

    // 左对齐,宽度 10
    std::cout << std::format("[{:<10}]\n", 42);

    // 居中,宽度 10
    std::cout << std::format("[{:^10}]\n", 42);

    // 前导零
    std::cout << std::format("{:05d}\n", 7);

    // 十六进制
    std::cout << std::format("hex = {:#x}, oct = {:#o}\n", 255, 255);

    // 打印一个简单的表格
    std::cout << std::format("{:<10} {:>5} {:>7}\n", "Name", "Age", "Score");
    std::cout << std::format("{:<10} {:>5} {:>7.1f}\n", "Alice", 25, 92.5);
    std::cout << std::format("{:<10} {:>5} {:>7.1f}\n", "Bob", 22, 88.0);
    std::cout << std::format("{:<10} {:>5} {:>7.1f}\n", "Charlie", 24, 78.5);

    return 0;
}

Running result:

[        42]
[42        ]
[    42    ]
00007
hex = 0xff, oct = 0377
Name         Age   Score
Alice         25    92.5
Bob           22    88.0
Charlie       24    78.5

9.3.Example 3: std::print direct output (C++23)

#include <cstdio>
#include <print>
#include <string>

int main()
{
    std::string name = "World";
    int value = 42;

    // 直接输出,不换行
    std::print("Hello, ");
    std::print("{}", name);
    std::print("!\n");

    // 输出到 stdout 并换行
    std::println("The answer is {}", value);

    // 第一个参数也可以显式写 stdout
    std::println(stdout, "stdout: {}", name);

    // 带格式输出
    std::println("pi = {:.3f}", 3.1415926);

    // 输出到 stderr
    std::println(stderr, "Error: something went wrong!");

    return 0;
}

Running result:

Hello, World!
The answer is 42
stdout: World
pi = 3.142
Error: something went wrong!

10.Operation result

See the "run results" for each example above.

11.Key syntax explanation in the example

示例 讲了什么 新出现的语法 为什么这样写 注意事项
示例 1 format 基本用法 std::format("...", arg1, arg2)、{} 占位符 Python 风格 + C++ 类型安全 参数个数要和 {} 个数匹配
示例 2 格式控制和表格 {:>10}、{:.2f}、{:#x} 内置格式说明符比 printf 更丰富 格式控制符在 {} 内,: 后面
示例 3 print/println 直接输出 std::println()、std::print()、stdout、stderr 不需要 std::cout,直接格式化输出 标准接口接收的是 FILE*,不是 std::cout

12.Common Errors

错误 1:格式说明符 : 前忘了写索引

std::format("{.2f}", 3.14);       // ❌ 缺少 : 前的占位符

Correct approach:std::format("{:.2f}", 3.14); or std::format("{}", 3.14);

Error 2: Parameter count mismatch

std::format("{}, {}", 1);  // ❌ 有 2 个占位符,只有 1 个参数

Compilation error (this is where format is safer than printf).

错误 3:用 format 输出的字符串中包含 { 或 }

std::format("Set = {1, 2, 3}");  // ❌ {1, 2, 3} 会被误解为格式说明

Correct approach: use {{ to denote the literal { , and }} to denote the literal }:

std::format("Set = {{1, 2, 3}}");  // 输出:Set = {1, 2, 3}

13.Usage Recommendations

  1. C++20 uses std::format to replace stringstream and sprintf: concise code, type safety, and high performance.
  2. C++23 uses std::print/std::println to simplify formatted output: by default it outputs to stdout, and you can also pass stderr.
  3. The format specifiers are very similar to Python: if you are familiar with Python's formatting syntax, you'll get up to speed quickly.
  4. If your compiler does not yet support C++20/23, you can use the {fmt} library (https://github.com/fmtlib/fmt),它是标准化的基础。

14.Summary

  • std::format("{} + {} = {}", a, b, c) Return the formatted string.
  • std::print("...") / std::println("...") Directly output to stdout.
  • std::println(stderr, "...") Can output to standard error.
  • Type safety + powerful formatting + high performance: combines the speed of printf with the safety of cout.
  • Format control:{:.2f} decimal places,{:>10} alignment,{:#x} base,{:04d} zero padding.