——字符串格式化)
目录1. std::format2. 格式说明符2.1 width2.2 [fill]align2.3 sign2.4 \#2.5 type2.6 precision2.7 0参考1. std::format直到C20之前字符串的格式化一般是通过printf()之类的C风格函数或是C的I/O流完成的1. C风格函数不推荐因为它们不是类型安全的并且无法扩展支持自定义类型因为字符串和参数是分开的所以可读性高且容易翻译成不同语言。例如printf(x has value %d and y has value %d.\n, x, y);2. C I/O流推荐(C20之前)因为类型安全且可扩展因为字符串和参数交织在一起所以可读性差且难以翻译成不同语言。例如std::cout x has value x and y has value y std::endl;C20引入了std::format()用来格式化字符串它定义在format中。它基本结合了C风格函数和C的I/O流的所有优点是一种类型安全且可扩展的机制。format()的第一个参数是待格式化的字符串后续参数是用于填充待格式化字符串中占位符的值。到目前为止使用format()时的占位符一般都是一对花括号{}。在这些花括号内可以是格式为[index][:specifier]的字符串。可以省略所有占位符中的index也可以为所有占位符指定从零开始的索引以指明应用于此占位符的第二个和后续参数。如果省略index则format()的第二个和后续参数传递的值将按给定顺序应用于所有占位符。specifier是一种格式化说明符用于更改值在输出中格式化的方式将在下一节详细说明。如果需要输出{or}字符则需要将其转义为{{or}}。以下对format()的调用省略了占位符中的显式索引auto s1 { std::format(Read {} bytes from {}\n, n, file1.txt) };可以按以下方式手动指定索引auto s1 { std::format(Read {0} bytes from {1}\n, n, file1.txt) };不允许混合使用手动和自动索引。下例使用了一个无效的字符串格式化auto s2 { std::format(Read {0} bytes from {}\n, n, file1.txt) };可以更改输出字符串中格式化值的顺序而不需要更改传递到format()的实参的实际顺序。如果要在软件中翻译字符串这是一个有用的功能。某些语言在句子中不同的顺序。例如前面的格式化字符串可以翻译成中文如下所示。在中文中句子中占位符的顺序是颠倒的但是由于格式化字符串中的占位符是有索引的format()函数的参数顺序保持不变(L前缀的用法后面介绍)。auto s3 { std::format(L从{1}中读取{0}个字节\n, n, Lfile1.txt) }:2. 格式说明符格式说明符用于控制值在输出中的格式前缀为冒号。格式说明符的一般形式如下所示(L与地区特定格式有关但是在我国好像没啥变化)。[[fill]align][sign][#][0][width][.precision][L][type]方括号里的所有说明符都是可选的。2.1 widthwidth指定待格式化的值所占字段的最小宽度例如5。width也可以是另一组花括号称为动态宽度。如果在花括号中指定了索引例如{3}则动态宽度的width取自给定索引对应的format()的实参。如果未指定索引例如{}则width取自format()的实参列表中的下一个参数。示例如下inti{42};std::coutstd::format(|{:5}|\n,i);// | 42|std::coutstd::format(|{:{}}|\n,i,8);// | 42|2.2 [fill]align[fill]align说明使用哪个字符作为填充字符然后是值在其字段中的对齐方式。对齐符号含义左对齐(非整数和非浮点数的默认对齐方式)右对齐(整数和浮点数的默认对齐方式)^居中对齐在待格式化字符前插入⌊ 宽度 − 待格式化字符串长度 2 ⌋ \lfloor\frac{宽度-待格式化字符串长度}{2}\rfloor⌊2宽度−待格式化字符串长度⌋个字符在待格式化字符串之后插入⌈ 宽度 − 待格式化字符串长度 2 ⌉ \lceil\frac{宽度-待格式化字符串长度}{2}\rceil⌈2宽度−待格式化字符串长度⌉fill字符会被插入输出中以确保输出中的字段达到说明符的[width]指定的最小宽度。如果未指定[width]则[fill]align无效。示例如下inti{42};std::coutstd::format(|{:7}|\n,i);// | 42|std::coutstd::format(|{:7}|\n,i);// |42 |std::coutstd::format(|{:_7}|\n,i);// |_____42|std::coutstd::format(|{:_^7}|\n,i);// |__42___|2.3 signsign符号含义-只显示负数的符号(默认方式)显示正数和负数的符号空格对负数使用负号对于正数使用空格示例如下inti{42};std::coutstd::format(|{:5}|\n,i);// |42 |std::coutstd::format(|{:5}|\n,i);// |42 |std::coutstd::format(|{: 5}|\n,i);// | 42 |std::coutstd::format(|{: 5}|\n,-i);// |-42 |2.4 ##启用所谓的备用格式规则。如果为整型启用并且还指定了十六进制、二进制或八进制数字格式则备用格式会在格式化数字前面插入0x、0X、0b、0B或0。如果为浮点类型启用则备用格式将始终输出十进制分隔符即使后面没有数字。具体示例见下面。2.5 typetype指定了给定值要被格式化的类型类型符号含义整型bBd(整型默认类型)oxX二进制二进制当指定#时使用0B而不是0b十进制八进制小写字母abcde的十六进制大写字母ABCDE的十六进制当指定#时使用0X而不是0x浮点型e,Ef,Fg(浮点型默认类型),Ga,A以小写e或大写E表示指数的科学表示法按照给定精度或6(如果未指定精度)格式化固定表示法按照给定精度或6(如果未指定精度)格式化以小写e或大写E表示指数的通用表示法按照给定精度或6(如果未指定精度)格式化带有小写字母(a)或大写字母(A)的十六进制表示法布尔型s(布尔型默认类型)bBcdoxX以文本形式输出true或false以整型输出1或0字符型c(字符型默认类型)bBdoxX输出字符副本整数表示字符串s(字符串默认类型)输出字符串副本指针p(指针默认类型)0x为前缀的十六进制表示法整型示例如下inti{42};std::coutstd::format(|{:10d}|\n,i);// | 42|std::coutstd::format(|{:10b}|\n,i);// | 101010|std::coutstd::format(|{:#10b}|\n,i);// | 0b101010|std::coutstd::format(|{:10o}|\n,i);// | 52|std::coutstd::format(|{:#10o}|\n,i);// | 052|std::coutstd::format(|{:10x}|\n,i);// | 2a|std::coutstd::format(|{:#10X}|\n,i);// | 0X2A|布尔型示例如下boolt{true};boolf{false};std::coutstd::format(|{:10s}|\n,t);// | true|std::coutstd::format(|{:10b}|\n,f);// | 0|std::coutstd::format(|{:10B}|\n,t);// | 1|std::coutstd::format(|{:10d}|\n,f);// | 0|std::coutstd::format(|{:10o}|\n,t);// | 1|std::coutstd::format(|{:10x}|\n,f);// | 0|std::coutstd::format(|{:10X}|\n,t);// | 1|字符型示例如下chara{c};std::coutstd::format(|{:10c}|\n,a);// |c |std::coutstd::format(|{:#10b}|\n,a);// | 0b1100011|std::coutstd::format(|{:#10B}|\n,a);// | 0B1100011|std::coutstd::format(|{:10d}|\n,a);// | 99|std::coutstd::format(|{:#10o}|\n,a);// | 0143|std::coutstd::format(|{:#10x}|\n,a);// | 0x63|std::coutstd::format(|{:#10X}|\n,a);// | 0X63|字符串的示例如下std::string s{ProCpp};std::coutstd::format(|{:_^10}|\n,s);// |__ProCpp__|2.6 precisionprecision只能用于浮点和字符串类型。它的格式为一个点后跟浮点类型要输出的小数点位数(e、f、a)或整个浮点类型包含的有效数字个数(g)或字符串要输出的字符数。就像width一样也可以是另一组花括号在这种情况下它被称为动态精度。precision取自format()的实参列表中的下一个实参或具有给定索引的实参。浮点型的示例如下doubled{3.1415/2.3};std::string s{Hello, World!};std::coutstd::format(|{:12.2g}|\n,d);// | 1.4|std::coutstd::format(|{:12.3e}|\n,d);// | 1.366e00|std::coutstd::format(|{:12.2a}|\n,d);// | 1.5ep0|intwidth{12};intprecision{3};std::coutstd::format(|{2:{0}.{1}f}|\n,width,precision,d);// | 1.366|2.7 00表示对于数值将0插入格式化结果中以达到[width]指定的最小宽度。这些0插在数值前面但在符号以及任何0x、0X、0b或0B前缀之后。如果指定了align则将忽略本选项。示例如下inti{42};doublef{3.1415/2.3};std::coutstd::format(|{:06d}|\n,i);// |000042|std::coutstd::format(|{:06d}|\n,i);// |00042|std::coutstd::format(|{:06X}|\n,i);// |00002A|std::coutstd::format(|{:#06X}|\n,i);// |0X002A|std::coutstd::format(|{:#06o}|\n,i);// |000052|std::coutstd::format(|{:012.3f}|\n,f);// |00000001.366|参考[比] 马克·格雷戈勒著 程序喵大人 惠惠 墨梵 译 C20高级编程(第五版)