应用编程#printf格式化输出简介

printf是一套家族函数,是C语言标准库函数,定义于头文件stdio.h,其定义如下所示:

1
2
3
4
5
6
7
#include <stdio.h>

int printf(const char *format, ...);
int fprintf(FILE *stream, const char *format, ...);
int dprintf(int fd, const char *format, ...);
int sprintf(char *str, const char *format, ...);
int snprintf(char *str, size_t size, const char *format, ...);

printf的format参数是格式控制字符串,它包含两种字段:一是普通字符串,打印时原样输出;二是控制字段,打印时使用可变变量…指定的参数数据,来替换对应的控制字段。两种字段相结合,形成结果字符串,然后printf将结果字符串打印到标准输出。

格式化字符串

printf的控制字段,通用格式定义如下,其中[]中的部分是可选项:

%[flags][width][.precision][length]specifier
即:
%[标志][最小宽度][.精度][类型长度]说明符

specifier

specifier亦即说明符,为必选项,其规范如下:

specifier对应数据类型说明例子
d/iint有符号十进制整数,i是老式写法392
uunsigned int无符号十进制整数7235
ounsigned int无符号八进制整数,无前导0610
xunsigned int无符号十六进制整数,小写,无前导0x后者0X7fa
Xunsigned int无符号十六进制整数,大写,无前导0x后者0X7FA
f/lfdouble十进制浮点数,默认精度为6(lf在C99开始加入标准,意思和f相同)392.65
edouble科学计数法表示的数,小写,默认浮点数精度为63.9265e+2
Edouble科学计数法表示的数,大写,默认浮点数精度为63.9265E+2
gdouble根据数值不同自动选择%f或%e,%e格式在指数小于-4或指数大于等于精度时用使用392.65
Gdouble根据数值不同自动选择%f或%E,%E格式在指数小于-4或指数大于等于精度时用使用392.65
adouble十六进制浮点数,小写-0xc.90fep-2
Adouble十六进制浮点数,大写-0XC.90FEP-2
cchar字符,可以按照ASCII码的数字转换为对应的字符a
schar *字符串,输出字符串中的字符以'\0'结尾或者打印由精度指定的字符数sample
pvoid *十六进制形式输出指针b8000000
nint *到此字符之前为止,一共输出的字符个数,不输出文本
%不转换参数不进行转换,输出字符‘%’(百分号)本身

flags

flags亦即标志,为可选项,其规范如下:

flags字符名称说明
-减号在给定的字段宽度内左对齐,右边填充空格(默认右对齐)
+加号强制在结果之前显示加号或减号(+或-),默认情况下,只有负数前面会显示 - 号
(space)空格输出值为正时加上空格,为负时加上负号
#井号根据specifier加前缀:o、x、X 时,加前缀0、0x、0Xe、E、f、g、G 时,一定使用小数点g、G 时,尾部的0保留
0数字零对于所有的数字格式,使用前导零填充字段宽度(如果出现了减号标志或者指定了精度,则忽略该标志)

width

width亦即最小宽度,为可选项,用于控制当前字段的显示宽度,其规范如下:

width字符名称说明
digit(n)数字字段显示宽度的最小值

如果输出的字段长度小于该数,结果会用前导空格填充;

如果输出的字段长度大于该数,结果使用更宽的字段,不会截断输出。

*星号宽度在format字符串中的规定位置未指定,使用星号表示附加参数,指示下一个参数是width

示例程序:

1
2
3
4
5
6
7
8
9
10
11
12
13
#include<stdio.h>

int main(int argc, char ** argv)
{
printf("WIDTH-CASE1:%*s\n", 10, "123456789");
printf("WIDTH-CASE2:%*s\n", 5, "123456789");
printf("WIDTH-CASE3:%9d\n", 123);
printf("WIDTH-CASE4:%2d\n", 123);
printf("WIDTH-CASE5:%*d\n", 9, 123);
printf("WIDTH-CASE6:%*d\n", 2, 123);

return 0;
}

示例程序执行结果输出如下:

.precision

.precision亦即精度,为可选项,用于指定输出精度,其规范如下:

.precision字符名称说明
.digit(n)点+数字对d/i/o/u/x/X:指定要打印的数字的最小位数。

如果写入的值短于该数,结果用前导数0来填充;

如果写入的数长于该数,结果不会截断;

如果为0,表示不写入任何字符。

对e/E/f:要在小数点后输出的小数位数;

对g/G:要输出的最大有效位数;

对s:要输出的最大字符数。

如果字符串实际长度大于该精度,则按该精度显示字符串,亦即截断;

如果小于,按原字符串实际长度输出。

对c:没有任何影响;

当未指定任何精度时,默认为 1。如果指定时只使用点而不带有一个显式值,则标识其后跟随一个 0。

.*点+星号精度在 format 字符串中规定位置未指定,使用点+星号标识附加参数,指示下一个参数是精度

示例程序:

1
2
3
4
5
6
7
8
#include<stdio.h>

int main(int argc, char ** argv)
{
printf("%.*s\n", 5, "123456789");

return 0;
}

length

length亦即类型长度,用于控制待输出数据的数据类型长度,其规范如下:

lengthd/iu/o/x/Xf/F/e/E/g/G/a/Acspn
intunsigned intdoubleintchar *void *int *
hhsigned charunsigned charsigned char*
hshort intunsigned short intshort int*
llong intunsigned long intwint_twchar_t*long int*
lllong long intunsigned long long intlong long int*
jintmax_tuintmax_tintmax_t*
zsize_tsize_tsize_t*
tptrdiff_tptrdiff_tptrdiff_t*
Llong double

备注:intmax_t/uintmax_t,表示在某系统中最大宽度整数类型。在64位系统中,如此定义:

1
2
typedef long long intmax_t;
typedef unsigned long long uintmax_t;

参考资料