购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

2.13 使用std::format格式化文本

C++语言有两种格式化文本的方法:printf函数族和I/O流库。printf函数继承自C语言,单独提供了格式化文本和参数的功能。相比于printf函数,一般来说更推荐使用流库,因为它比较安全且可扩展,但是同时它相对来说速度会慢一点。C++20标准针对输出格式提出了一种新的格式化库替代方案,其形式与printf类似,且安全、可扩展,旨在补充现有的流库。在本节中,我们将学习如何使用新的函数,而不是printf函数或流库。

2.13.1 准备工作

新的格式化库在头文件<format>中,下面的示例必须要包含此头文件。

2.13.2 使用方式

std::format()函数的作用是根据所提供的格式化字符串格式化其参数。你可以这样使用它:

❍ 在格式化字符串中为每个参数提供空替换域,用{}表示:

❍ 在替换域内的参数列表中指定每个参数的基于0的索引,例如{0}、{1}等,其中参数的顺序并不重要,但索引必须有效:

❍ 使用冒号(:)后面替换域的格式说明符来控制文本的输出。对于基本类型和字符串类型,这是一个标准格式规范;对于时间(chrono)类型,这是一个chrono格式规范:

另外,你还可以使用迭代器std::format_to()或std::format_to_n()作为输出格式来写参数,如下所示:

❍ 使用std::format_n()和std::back_inserter()辅助函数写入缓冲区(如std::string或std::vector<char>):

❍ 使用std::formatted_size()来检索存储参数的格式化表示所需要的字符数:

❍ 可以使用std::format_to_n()来限制写入输出缓冲区的字符数,它类似于std::format_to(),但最多只能写入n个字符:

2.13.3 工作原理

函数std::format()有多个重载版本,可以将格式化字符串指定为字符串视图或宽字符串视图,同时让函数返回std::string或std::wstring。你还可以指定std::locale作为第一个参数,用于符合区域(locale)习惯的格式化。函数重载都是可变参数函数模板,这意味着你可以在格式后面指定任意数量的参数。

格式化字符串由普通字符、替换域和转义序列组成。如果转义序列是{{和}},输出的结果为{和},替换域用{}表示。它可以有选择性地包含一个非负数(表示要格式化的参数基于0的索引)和一个冒号(:),后跟一个格式说明符。如果格式说明符无效,将抛出std::format_error类型的异常。

类似地,像std::format()一样,std::format_to()有多个重载。不过,这两者之间的区别在于std::format_to()始终将输出缓冲区的迭代器作为第一个参数,并返回一个指向输出范围末尾的迭代器(而不是像std::format()那样的字符串)。另外,std::format_to_n()比std::format_to()多了一个参数,它的第二个参数是一个数字,表示能够写入缓冲区的最大字符数。

下面显示了这三个函数模板的最简单的重载函数的签名:

当提供格式化字符串时,可以提供参数标识符(基于0的索引)或忽略它们。然而,两者同时使用是不合理的:如果替换域中省略了索引,则将按照提供的顺序处理参数,并且替换域的数量不得大于提供的参数数量;如果提供了索引,则它们必须有效,这样格式化字符串才能有效。

当使用格式规范时:

❍ 对于基本类型和字符串类型,它被认为是标准格式规范。

❍ 对于时间类型,它被认为是chrono格式规范。

❍ 对于用户自定义类型,它由所需类型的std::formatter类来定义用户自定义规范。

标准格式规范基于Python中的格式规范,语法如下:

以下将简要介绍这些语法。

fill-and-align是可选的填充字符后跟一个对齐选项:

❍ <:用空格强制左对齐。

❍ >:用空格强制右对齐。

❍ ^:用空格强制中间对齐。为此,它将在左侧插入n/2个字符(空格),在右侧插入n/2个字符(空格):

sign、#和0仅在使用数字(整数或浮点数)时有效,该标志可以是:

❍ +:该符号必须同时用于负数和正数。

❍ -:该符号只能用于负数(这是隐式行为)。

❍ 空格:该符号必须用于负数,且前导空格必须用于非负数。

符号#则使用另一种形式,可以是下面情况中的一种:

❍ 对于整数类型,当指定二进制、八进制或十六进制表示时,替换形式将在输出中添加前缀0b、0或0x。

❍ 对于浮点类型,替换形式将导致格式化的值始终存在一个小数点字符,即使它后面没有数字。此外,当使用g或G时,不会删除结果末尾的零。

数字0指前面补0至指定的宽度,除非浮点类型的值为无穷大或NaN。当与对齐选项一起出现时,将忽略说明符0:

width表示最小域宽度,可以是正十进制数或嵌套替换域。precision字段表示浮点类型的精度,对于字符串类型,则表示将从字符串中使用多少字符,它用点(.)指定,后跟非负十进制数或嵌套的替换域。

符合区域习惯的格式化使用大写L指定,并使用符合区域习惯的形式,此选项仅适用于算术类型。

可选type决定了数据的输出方式,可用的字符串类型表示如表2.4所示。

表2.4

(续)

chrono格式规范有如下形式:

fill-and-align、width和precision字段的含义与前面描述的标准格式规范中的含义相同。当表示类型为浮点类型时,precision仅对std::chrono::duration类型有效,在其他情况下会抛出std::format_error异常。

chrono-spec可以为空,在这种情况下,格式化的参数像是被流化到std::stringstream对象,然后复制其结果。另外,它也可以由一系列转换说明符和普通字符组成。表2.5列出了其中的一些格式说明符。

表2.5

有关chrono库格式说明符的完整列表,请访问https://en.cppreference.com/w/cpp/chrono/system_clock/formatter。

2.13.4 延伸阅读

❍ 阅读2.14节,以了解如何为用户自定义类型创建自定义格式说明符。

❍ 阅读2.1节,以了解如何在数值类型和字符串类型之间转换。 Dr6UwVRnhj30I4vk1yTSa9yoHWVLk78zeSInl1Uf2S+As2i83FBJ4uWofGOiDe2H

点击中间区域
呼出菜单
上一章
目录
下一章
×

打开