说明
文本格式化库提供 printf 函数族的安全且可扩展的替用品。有意使之补充既存的 C++ I/O 流库并复用其基础设施,例如对用户定义类型重载的流插入运算符。
头文件
#include <format>
函数定义
template<class... Args>
std::string format(std::string_view fmt, const Args&... args);
template<class... Args>
std::wstring format(std::wstring_view fmt, const Args&... args);
template<class... Args>
std::string format(const std::locale& loc, std::string_view fmt, const Args&... args);
template<class... Args>
std::wstring format(const std::locale& loc, std::wstring_view fmt, const Args&... args);
按照格式字符串 fmt 格式化 args ,并返回作为 string 的结果。 loc 若存在,则用于本地环境特定的格式化。
参数说明
fmt - 表示格式字符串的字符串视图。
格式字符串由以下内容组成:
- 通常字符(除了 { 与 } ),它们被不加修改地复制到输出
- 转义序列 {{ 与 }} ,它们在输出中被分别替换成 { 与 }
- 替换域
每个替换域拥有下列格式:
- 引入的 { 字符
- (可选) arg-id ,一个非负数
- (可选) 冒号( : )后随格式说明
- 终止的 } 字符
arg-id 指定用于格式化其值的 args 中的参数的下标;若省略 arg-id ,则按顺序使用参数。格式字符串中的 arg-id 必须全部存在或全部被省略。混合手动和自动指定下标是错误。
格式说明由对应参数特化的 std::formatter 定义。
- 对于基本类型和标准字符串类型,格式说明为标准格式说明
- 对于标准日期和时间类型,格式说明为 chrono 格式说明
- 对于用户定义类型,格式说明由用户定义的 std::formatter 特化决定
args… - 要格式化的参数
loc - 用于本地环境特定格式化的 std::locale
返回值
保有格式化结果的 string 对象。
异常
若 fmt 对于提供的参数不是合法的格式字符串则抛出 std::format_error 。并且会传播任何格式化器所抛的异常。
注意,提供多于格式字符串所要求的参数不是错误:
std::format("{} {}!", "Hello", "world", "something"); // OK :产生 "Hello world!"
填充与对齐
基本格式:
填充与对齐(可选) 符号(可选) #(可选) 0(可选) 宽度(可选) 精度(可选) L(可选) 类型(可选)
填充与对齐 是一个可选的填充字符(可为任何 { 或 } 外的的字符),后随对齐选项 < 、 > 、 ^ 之一。对齐选项的意义如下:
- < :强制域在可用空间内左对齐。这在使用非整数非浮点显示类型时为默认。
- > :强制域在可用空间内右对齐。这在使用整数或浮点显示类型时为默认。
- ^ :强制域在可用空间中央,通过在值的前面插入n/2向下取整个字符,后面插入n/2向上取整个字符,其中 n 是待插入的总字符数。
char c = 120;
auto s0 = std::format("{:6}", 42); // s0 的值为 " 42"
auto s1 = std::format("{:6}", 'x'); // s1 的值为 "x "
auto s2 = std::format("{:*<6}", 'x'); // s2 的值为 "x*****"
auto s3 = std::format("{:*>6}", 'x'); // s3 的值为 "*****x"
auto s4 = std::format("{:*^6}", 'x'); // s4 的值为 "**x***"
auto s5 = std::format("{:6d}", c); // s5 的值为 " 120"
auto s6 = std::format("{:6}", true); // s6 的值为 "true "
符号、 # 与 0
符号 选项能为下列之一:
- + :指示符号应该一同用于非负数和负数。在非负数的输出值前插入 + 号。
- - :指示符号应该仅用于负数(这是默认行为)。
- 空格:指示应对非负数使用前导空格,而对负数使用负号。
负零被当作负数。符号 选项应用于浮点无穷大和 NaN 。
double inf = std::numeric_limits<double>::infinity();
double nan = std::numeric_limits<double>::quiet_NaN();
auto s0 = std::format("{0:},{0:+},{0:-},{0: }", 1); // s0 的值为 "1,+1,1, 1"
auto s1 = std::format("{0:},{0:+},{0:-},{0: }", -1); // s1 的值为 "-1,-1,-1,-1"
auto s2 = std::format("{0:},{0:+},{0:-},{0: }", inf); // s2 的值为 "inf,+inf,inf, inf"
auto s3 = std::format("{0:},{0:+},{0:-},{0: }", nan); // s3 的值为 "nan,+nan,nan, nan"
formatter - 自定义的类型扩展
formatter 的被启用特化对给定类型定义格式化规则。被启用特化必须满足格式化器 (Formatter) 要求。特别是,它们定义成员函数或函数模板 parse 与 format 。
#include <format>
#include <iostream>
// 类型 T 的包装
template<class T>
struct Box {
T value;
};
// 能用被包装值的格式说明格式化包装 Box<T>
template<class T, class CharT>
struct std::formatter<Box<T>, CharT> : std::formatter<T, CharT> {
// 从基类继承 parse()
// 通过以被包装值调用基类实现定义 format()
template<class FormatContext>
auto format(Box<T> t, FormatContext& fc) {
return std::formatter<T, CharT>::format(t.value, fc);
}
};
int main() {
Box<int> v = { 42 };
std::cout << std::format("{:#x}", v);
}
输出:
0x2a
参考:https://zh.cppreference.com/w/cpp/utility/format