第 7 讲:数据类型(四):格式化输出
格式化输出(Formatted Output)是为了保证数据显示和呈现有序和控制显示规范的一种模式。在我们之前的输出内容里,我们完全不必需要显示任何额外的东西,因为本身显示出来就已经达到了目的。
那么,如果我们要显示一个表格的话,单纯的字符串就没办法控制得那么好了。下面我们来介绍这种控制输出格式的语法规则和用法。
Part 1 填充(Padding)
填充分两种:空格填充和非空格填充,所以分两部分介绍。
1-1 空格填充
我们在之前显示一个数字的时候,我们通过 Console.WriteLine
方法来显示。而如果要把数值嵌入到字符串的指定位置的时候,我们用的是一个叫做占位符的东西,写成一个大括号,里面是编号。
那么,如果我们要控制显示的数据的前后空格个数,怎么办呢?举个例子。假设我要输出表格,表格假设为两列,而第一列放数字信息,且这一列的宽度占据 8 个数字字符的位置:
比如说这样。为了保证显示的空格后面补充 7 个空格(使得数字一共占 8 个字符位置),我们可以这么写:
填充空格(Space Padding)的东西。
我们推广一下占位符的语法。我们在占位符的编号后添加逗号,然后增加一个整数,用来表示这个位置显示的数据,左侧或右侧补充一定数量的空格来保证整体数字的显示。
举个例子,我们使用语法 {0,8}
表示,这个占位符的编号是 0(即第一个替换数据),且它在输出的时候占据 8 个字符的位置;如果数据不够长(比如前文表格里的那个数字,只有一位数),那么就会在左侧补充空格。
如果逗号后面这个数字为负数的话,就表示在右侧补充空格来保证数据占多少个字符的位置。比如说:
这两个数据的显示结果分别是

总结一下:
正整数表示在左边补充空格达到指定宽度;
负整数表示在右边补充空格达到指定宽度。
当然,这个占位符同样可以适用于浮点数类型数据。只是,浮点数的小数点、整数部分、小数部分全部都算在格式排版的范围内。比如 3.5 是由整数部分 3、小数点和小数部分 5 构成的。整数部分占一个字符、小数点占一个字符、小数部分占一个字符,所以 3.5 是算三个字符位置。因此,如果对小数使用这个占位符补充空格的话,一定要注意字符的宽度的补充空格数量。
顺带一提,如果数据超出指定宽度的范围的话,那么这个指定的宽度就没有意义了。比如说一个浮点数 123.456 一共占据 7 个字符的位置,但是用
{0,6}
作为占位符的话,输出宽度显然是不够的,所以这个占位符里的指定宽度 6 是无效的。所以这样一来,占位符就等价于{0}
。
1-2 非空格填充
当然,空格可以用来填充,但是我们有时候也可以用别的符号来作为填充对象,但占位符的填充行为只能是使用空格,因此占位符只能做空格的填充。如果要别的符号,我们这里要用别的办法了。
C# 里有一个方法叫做 string.PadLeft
或者 string.PadRight
。这两个方法专门用来填充指定的内容(不一定是空格)。
我们使用 .PadLeft
或 .PadRight
.PadRight(8, ' ')
,这个 8 和前面占位符里的指定宽度(-8)是一个逻辑(指定宽度里是可以写负整数的,但是这里用 PadRight
的时候,因为 PadLeft
是左侧补充字符,PadRight
在右侧补充字符,所以用 PadRight
就会自动在右侧补充字符,因此不需要负号);而逗号后面的这个 ' '
是空格字符,这表示补充的时候用空格来补充。所以,上面这种写法完全和前面占位符写法 {0,-8}
是等价的。
但是,你也可以用别的填充字符。比如说:
此时我们用的 PadLeft
就表示在左侧补充。逗号后面写的是 '0'
00000001
。这是一个相当方便的填充方式。
唯一一点需要注意的是,这里用的 .PadLeft
和 .PadRight
,小数点左侧都必须是字符串(变量也好,字面量也好,但不能是别的东西)。
Part 2 说明符(Specifier)
前文的排版填充空格或非空格的内容其实不太难,但是语法严谨导致很多时候初学它们会很容易记不住它们。没有关系,这毕竟不是考试,所以不要担心用不来。只要你记不住,还可以回来翻文档,也可以网上查资料。
下面这个内容,是用来转换呈现数据模型的。在 C# 里,除了我们可以显示整数、小数以外,它还提供了显示货币、百分比等等模型。显然货币并不是一种数据类型,但用来把一个数值作为呈现对象的话,就需要这样的说明符号来表达出我到底希望它显示成啥样。
比如说,我想把 123
这个数字显示成货币表达式,而因为货币并不是数据类型,因此我们没有办法通过变量赋值和字面量的方式来把 123 给到一个“货币类型”的变量上去。因此,这里只能靠呈现来完成任务。
我们使用冒号 :
,和一个字母 C
(或小写字母 c
¥123.00
。
货币显示的话,不同国家使用这个方法产生的结果是有偏差的。比如在中国,这段输出就是显示人民币的结果;而其它国家可能是别的货币符号,比如说英镑(
£
)、美元($
)等等。电脑会自动抉择符号选取,因此非常方便。
说明符有如下的一些(不全,用不上的就不介绍了):

其中,只有 D
和 X
只支持整数,其它的则整数、小数均可。所谓的“只支持整数”,其实就是说,占位符替换的变量(或字面量)必须得是一个整数。不论它是短整数、长整数、甚至无符号整数等等,它们起码用来表示整数,所以它们都属于整数类型。但是,浮点数就不行。如果尝试把浮点数用类似 {0:D}
的语法的话,就会直接在运行程序的时候看到严重的错误信息提示。
另外,D
后是可以跟上一个正整数的,这样就可以保证显示的数据的左侧补充一定数量的字符 0。之前我们用 PadLeft
D8
,就表示用整数形式显示,且填充 0 到数字之前以保证显示宽度为 8 个字符。
当然,别的说明符后也可以加数字,比如货币类型后加数字表示显示到小数位后多少位;不过这里用不上其它的,就不用多说了:说多了反而记不住。
Part 3 混用说明符和宽度指定
如果我们既想要指定宽度,又想要指定说明符的话,我们就需要都写上。因此,C# 的语法是这样的:
比如这个例子里,{0,-28:C2}
就是在说,这里显示的数据是第一个代替数值 amount1
,占 28 个字符宽度(不够长度就在右边填充空格);C2
表示显示货币表达式,且显示两位小数;同理后面的 {1,14:C2}
是一样的用法。
Part 4 显示数字的通配符
除了使用说明符 D
(或小写 d
)来显示数字,我们还可以使用通配符表达式来显示一个数字。这里说的数字既包含整数又包含浮点数。
如果前面的这些格式并不能满足你自定义显示一种数据模型的话,那么这一节的内容会比较灵活。
我们使用数字 0 来表示一个显示的数位(如果这个位置上没有数字,则故意显示一个字符 0 占位)。比如说
显然 12 不够三个数位的,所以 {0:000}
里的 000
保证显示三个数位,最高位用 0 填充,即显示结果是 012。
这个用法前面已经有一样的了。所以这里就得看你用
PadLeft
方便一些,还是D3
方便一些,还是这个000
PadLeft
需要接的是字符串而不是整数,稍微麻烦一点。
其它还有逗号(三位一组分隔符)、逗点组合(缩小 1000 倍数据)、井号(数字)、百分号(百分比数据)等等通配符,但这里就不说明了。