C++学习笔记----Strings与String View(11)-- 格式化说明符

        上几篇文章中对于输出函数中的格式化字符串(format_string),索引(index)等格式化输出内容进行了详细的讲解,从这一篇开始,我们进入到一个更丰富且重要的内容:格式化说明符:[:specifier]。

        格式化说明符可以更精确地将输出内容进行格式化,以:开头,其格式是这样的:

[[fill]align][sign][#][0][width][.precision][L][type]

        我们比较清楚的是,在C/C++语言中,[]表示可以省略,如果不省略的话,其含义又是什么样的呢,让我们一个一个地来学习吧:

1 width宽度

        width宽度指定了输出值的最小宽度,也可以用{}包住,说明是一个动态的宽度,给我们的编程带来很大的灵活性,如果将index也变成变量的话,可能就有一点复杂了,用文字描述,远没有结合程序实例更容易理解掌握,那我们就来看一个例子吧:

import std;
using namespace std;
int main()
{
	int i{ 42 };
	println("|{:5}|", i);		// |   42|
	println("|{:{}}|", i, 7);	// |     42|
	println("|{1:{0}}|", 7, i);	// |     42|
	return 0;
}

运行结果:

|   42|
|     42|
|     42|

与代码注释中一致,符合预期,我们就通过这个示例详细介绍一下width宽度的用法,||使我们更清晰地看出其输出宽度,第一个println()输出值为42,其宽度为5,最简单的那一种;第二个println(),输出值是i,为42,在外围的那对{},里面的在:后面的那对{}使用index为1的参数,其值为7,表示宽度为7,由此可以看出,如果没有标注的话,index对应的顺序是以{为准的,其输出结果与解释一致吧;从第二个println()自然而然地就能够想到,我要改变一下顺序呢,把后面的调到前面呢,第三个println()就给出了示例,不用系统默认的index,显示指出就可以了,将外围的{}调整为index为1,:后面的{},即宽度值,使用index为0,即格式化后第一个参数,就可以达到目的了。我觉得,通过实例,根据代码去理解学习width宽度值的用法,应该还是比较好懂的吧。

2 [fill]align填充对齐

        align对齐是指靠左、靠右、居中,与WORD排版中的意思一致,靠左默认是针对于非数字的,靠右默认是针对于数字的;[fill]是指对于输出的空白部分的填充符,默认是空格。当然了,前提是指定了width宽度,如果没有指定宽度,这两个都不起作用。

        当指定对齐方式为居中时,而需要填充的宽度为奇数时,后面多一个。

        还有一个有趣的情况,就是输出填充符是我们的目的,我们就可以用““作为输出值,而在格式化字符串中的width及[fill]中给出相应的值,就可以达到我们的目的。

        请看示例:

import std;
using namespace std;
int main()
{
	int i{ 42 };
	println("|{:7}|", i);		// |     42|
	println("|{:<7}|", i);		// |42     |
	println("|{:_<7}|", i);		// |_____42|
	println("|{:_^7}|", i);		// |__42___|
	println("|{:=>16}|", "");	//|================|
	return 0;
}

看结果:

|     42|
|42     |
|42_____|
|__42___|
|================|

该结果验证了以下对于[fill]align填充对齐方式的说明,这个比上一个width宽度的使用我觉得更易于理解一些,你怎么认为呢?

3 sign符号

        sign符号这个比较好理解,就是正负号的显示方式,列表如下:

  • - 为缺省值,值为负数时显示-,为正数时不显示
  • +值为负数时显示-,为正数时显示+
  • 空格 值为负数时显示-,为正数时显示空格,这个与缺省值-在正数时显示的区别是,这个是要用空格进行占位的,而-为正数时则什么也不显示。

        还是看示例吧,更好理解一些,也可以加深印象:

import std;
using namespace std;
int main()
{
	int i{ 42 };
	println("|{:<5}|", i);		// |42   |
	println("|{:<+5}|", i);		// |+42  |
	println("|{:< 5}|", i);		// | 42  |
	println("|{:< 5}|", -i);	// |-42  |
	return 0;
}

结果:

|42   |
|+42  |
| 42  |
|-42  |

这个比较容易理解,就直接过了,进入下一项。

4 #与type

        #对于数字类型,像16进制、二进制、8进制、会在数字之前插入0x或者0X、0b或者0B、0等,对于浮点类型,会输出数字分隔符,不管后面有没有数字。

        type为类型说明符,有以下几种类型,分别加以说明:

  1. 整型:b:二进制、B:二进制(如果指定#的话,用0B而不是0b)、d:十进制、o:八进制、x:十六进制(用a、b、c、d、e、f)、X:十六进制(用大写的A、B、C、D、E、F,如果指定#的话,用0X而不是0x)、如果没有指定类型的话,对于整型数默认为d:十进制
  2. 浮点类型:前面的文章已经讨论过,std::chars_format::scientific, fixed, general,以及hex,e,E:表示指数,后面跟给定精度的数字,默认为6;f,F:给定精度的固定表示,默认为6;g,G:小数点前至少有一位数字的最简洁的表达方式、a,A:十六进制中的abcdef或者ABCDEF;如果没有指定的话,就使用g,对于此处如果不好理解的话,请参见https://mp.csdn.net/mp_blog/creation/editor/140945993
  3. 布尔型:s:输出true或者false,b, B, c, d, o, x, X:输出0或者1,默认为s。
  4. 字符型:c:正常字符输出、?:转义字符输出,以后会详细讨论、b, B, d, o, x, X:整型数字输出;默认为c。
  5. 字符串型:s:正常字符串输出、?:转义字符串输出,以后会详细讨论,如果类型没有指定,默认为s:正常字符串输出。
  6. 指针型:p:以0x开头的十六进制,如果type类型没有指定的话,p就是用于指针类型,记住一点,只有void*的指针类型可以格式化输出,其他类型一定要转成void*的类型,例如:static_cast<void*>(myPointer)

先展示一下整型及字符串类型的例子,其他的,到使用的时候再展示吧:

import std;
using namespace std;
int main()
{
	int i{ 42 };
	println("|{:10d}|", i);		
	println("|{:10b}|", i);		
	println("|{:#10b}|", i);		
	println("|{:10X}|", i);	
	println("|{:#10X}|", i);

	string s{ "ProCpp" };
	println("|{:_^10}|", s);

	return 0;
}

看一下结果:

|        42|
|    101010|
|  0b101010|
|        2A|
|      0X2A|
|__ProCpp__|

不多做解释了,这些都是一些死知识,理解后掌握就行了,不复杂。

5precision精度

        precision精度只针对于浮点型及字符串型,格式就是小数点.后指定一个数字,对于浮点型来说,就是指定了浮点型数的位数;对于字符串型来说,就是字符串的长度。浮点型数的位数包括小数点前后的数字,但对于以f或者F表示的浮点数,指的小数点后的位数,这一点需要特别注意。

        与width宽度一样,precision精度也可以使用格式化字符串后面的变量来指定,这样的话,就给程序的灵活性带来了很大的方便,精度可以使用紧挨着格式化字符串后面的变量,也可以使用index指定的格式化字符串后面的任意要输出的变量,看示例吧:

import std;
using namespace std;
int main()
{
	double d{ 3.1415 / 2.3 };
	println("|{:12g}|", d);
	println("|{:12.2}|", d);
	println("|{:12e}|", d);

	int width{ 12 };
	int precision{ 3 };
	println("|{2:{0}.{1}f}|", width, precision, d);
	println("|{2:{0}.{1}}|", width, precision, d);

	return 0;
}

看结果:

|     1.36587|
|         1.4|
|1.365870e+00|
|       1.366|
|        1.37|

6 0符号

        0符号比较简单,就是对于数值型的数据来说,插入0,达到指定的width宽度,0插入的位置是在数值型的数据之前,但在+、-符号、0x、0X、0b、0B等之后。当然了,如果指定了对齐方式,该符号无效,看示例:

import std;
using namespace std;
int main()
{
	int i{ 42 };
	println("|{:06d}|", i);
	println("|{:+06d}|", i);
	println("|{:06X}|", i);
	println("|{:#06X}|", i);
	println("|{:^06d}|", i);
	return 0;
}

看结果:

|000042|
|+00042|
|00002A|
|0X002A|
|  42  |

7 L符号

        L符号是本地化符号,只是针对于整型数、浮点型数、布尔型的有效,当使用L符号的时候,其输出就是当地的习惯表达;该参数只针对std::format()有效,而对于print()、println()无效。

举一个例子,设置不同的locale,看一下不同:

import std;
using namespace std;
int main()
{
	float f{ 1.2f };
	cout << format(std::locale{ "nl" }, "|{:Lg}|\n", f);
	cout << format(std::locale{ "zh" }, "|{:Lg}|\n", f);
	return 0;
}

看结果:

|1,2|
|1.2|

看,还是有与中国不同的表达方式吧,当然,我们要尊重。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值