C++学习笔记----Strings与String View(12)-- 格式化转义字符与字符串、范围(Range)

1、格式化转义字符与字符串

        怎么把转义字符或转义字符串输出来,不让它转义,原样输出来,你可能觉得奇怪,这是要干什么?这个确实有用的,比如在程序调试的时候,我想把某一段含有转义字符或者转义字符串的内容输出出来。用法也是比较简单的,就是使用?类型说明符,其实在上一篇文章中也提到了,只是没有进行解释,下面我们看一下常用的转义字符吧:

转义字符列表
字符转义输出
水平制表符\t
换行\n
回车\r
反斜杆\\
双引号\"
单引号\'

还有一点,要单独的“两边要用',要单独的'两边要用",这个也比较好理解吧,看示例:

import std;
using namespace std;
int main()
{
	println("|{:?}|", "Hello\tWorld!\n");
	println("|{:?}|", "\"");
	println("|{:?}|", '\'');
	println("|{:?}|", '"');
	println("|{:?}|", "'");
	return 0;
}

结果如下:

|"Hello\tWorld!\n"|
|"\""|
|'\''|
|'"'|
|"'"|

2、格式化范围Range

        在C++中,std::vector,array,pair会保存多个数据,在标准库容器中,还会有这样的容器,我们要直接将这样的元素输出出来,这就是本节要讨论的话题,可能会比较复杂,要集中一下思想,否则可能会跟不上。像vector,array这样的范围Range,缺省输出是有[]符号的,其元素是由,分隔的,原样输出,这比较好理解,当然了,对于元素类型为字符串的,如果字符串中包含转义字符,缺省是会进行转义的。

        范围Range格式化的说明符如下:

[[fill]align][width][n][range-type][:range-underlying-spec]

        所有[]中的内容都可以省略,前面几节我们也介绍了格式化字符串的一些内容,这里面的一些说明符与前面介绍的大同小异,本次就简单地一带而过了。fill指定了填充符,align指定了对齐方式,width指定了输出的宽度,如果指定了n,那么输出中就省略掉了范围Range两边的[],range-type解释如下:

  • m:只针对于带两个元素的pair与tuple有效,缺省是由,分隔括号包围的,如果指定了m,就不用括号了,分隔符也变成了:
  • s:将范围Range格式化为字符串(不与n或者range-underlying-spec同时使用)
  • ?s:将范围Range格式化为转义字符串(不与n或者range-underlying-spec同时使用)

        range-underlying-spec是范围Range元素的可省略的格式说明符。范围Range说明符支持多层嵌套,如果范围Range的元素又是一个范围Range(例如Vector的元素也是Vector),那么range-underlying-spec也是另一个范围Range的格式化说明符,以此类推。

        还是通过示例来学习吧,可能更容易理解一些:

        先看一个元素为数字的Vector:

vector values { 11, 22, 33 };
println("{}", values); // [11, 22, 33]
println("{:n}", values); // 11, 22, 33

        默认输出就是以[]包围的以,分隔的三个元素的vector,与定义完全一致,:n就是把包围的[]去掉,再继续往下看,如果你只是想把[]替换为其他的符号,那就要与:n结合使用,看示例:

println("{{{:n}}}", values); // {11, 22, 33}

        该示例就是将[]替换为{}的代码,其中:n去掉了[],替换成{},由于{}与指示符冲突,所以要用{{与}}来代替。再看如下的例子:

println("{:*^16}", values); // **[11, 22, 33]**
println("{:*^16n}", values); // ***11, 22, 33***

        *为填充符,^为居中对齐符,16为宽度;第二行有n,就将[]去除掉了,继续学习:

println("{::*^6}", values); // [**11**, **22**, **33**]

        由于多加了一个:,那就是对各个元素进行格式化了,将各个元素以*为填充符,宽度为6,居中,再继续:

println("{:n:*^6}", values); // **11**, **22**, **33**

        外层加上n,也就把[]去除掉了,go on,这次我们把元素换成字符串:

vector strings { "Hello"s, "World!\t2023"s };
println("{}", strings); // ["Hello", "World!\t2023"]
println("{:}", strings); // ["Hello", "World!\t2023"]
println("{::}", strings); // [Hello, World! 2023]
println("{:n:}", strings); // Hello, World! 2023

        第一行、第二行都是默认输出,第三行对vector的字符串元素进行转义输出,由于第二个字符串中有\t,被转义成了一个制表符的正常输出,第四行外围加了n,就将[]去除掉了。

        再举一个元素为字符的例子:

vector chars { 'W', 'o', 'r', 'l', 'd', '\t', '!' };
println("{}", chars); // ['W', 'o', 'r', 'l', 'd', '\t', '!']
println("{::#x}", chars); // [0x57, 0x6f, 0x72, 0x6c, 0x64, 0x9, 0x21]
println("{:s}", chars); // World !
println("{:?s}", chars); // "World\t!"

        第一行正常输出,第二行对各个元素以0x开头转换成16进制进行输出,第三行将字符组合成字符串进行转义输出,第四行在第三行的基础上不转义。

        再看一个有两个元素的pair的例子:

pair p { 11, 22 };
println("{}", p); // (11, 22)
println("{:n}", p); // 11, 22
println("{:m}", p); // 11: 22

        第一行正常输出,第二行将两边的()去掉,第三行在第二行的基础上将,替换成:进行分隔。

        最后再看一个嵌套vector的例子:

vector<vector<int>> vv { {11, 22}, {33, 44, 55} };
println("{}", vv); // [[11, 22], [33, 44, 55]]
println("{:n}", vv); // [11, 22], [33, 44, 55]
println("{:n:n}", vv); // 11, 22, 33, 44, 55
println("{:n:n:*^4}", vv); // *11*, *22*, *33*, *44*, *55*

        第一行正常输出,第二行将最外围的[]去掉,第三行将外围及里面的[]都去掉,第四行在第三行的基础上对元素的子元素进行格式化,以*填充,宽度为4,居中。

  • 17
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值