赞
踩
格式化输出函数printf
、fprintf
、sprintf
和snprintf
在格式化处理部分是相同的,本文以printf
为例,说明此类函数的用法。
printf
函数的调用格式为:
printf(“<格式化字符串>”, <参量表>);
比如:
printf("The Value %d.\n", 500); //输出数字
这句代码产生如下输出:
The value 500.
在上面提到的 printf
函数调用格式 printf("<格式化字符串>", <参量表>);
中,我们忽略其中的 <参量表>,只关注 <格式化字符串>。
"<格式化字符串>"应该是一个字符序列,形如:
“普通字符(%除外) %<转换参数> …”
在形如 “普通字符(% 除外) %<转换参数> ...”
的格式化字符串中,普通字符(%除外)原封不动的被复制到输出流,以%
开头的转换说明用于指示转换数据类型、精度等,转换说明的格式为:
% <标志字符> <最小字段宽度> <精度说明> <h、l、L> <转换类型字符>
在转换说明中,<标志字符> <最小字段宽度> <精度说明> <h、l、L> <转换类型字符>
统称为转换参数,一共有5种转换参数。除 <转换类型字符>
外,其它4种都可以忽略不用。我们再看一下上文的例子:
printf("The Value %d.\n", 500); //输出数字
%d
是一个转换说明,它只有一个转换参数:d
。转换参数 d
属于 5 种转换参数中的转换类型字符。这个是我们接触最早也最多的转换参数。
我们一步一步的忽略 printf
函数的次要内容,只关心其中的转换说明,这一过程可以用一张图来表示:
下面详细描述5种转换参数。
允许0个或多个标志字符,如果标志字符多于1个,它们的顺序任意。标志字符有:
-
:左对齐字段宽度中的值。没有这个标志字符,则是右对齐。比较代码:
int value = 500;
printf("The value |%-8d|\n", value); //左对齐
printf("The value |%8d|\n", value); //右对齐
代码输出:
The value |500 |
The value | 500|
+
:有符号数转换总是显示符号:正号(+)
或负号(-)
。如果没有这个标志字符,只有负值才会显示符号。比较代码:
printf("The value %d\n", 500); //正数无 '+'
printf("The value %d\n", -500); //负数无 '+'
printf("The value %+d\n", 500); //正数有 '+'
代码输出:
The value 500
The value -500
The value +500
空格
:有符号数转换的结果中第一个字符不是符号(比如默认情况下转换正数是不显示正号(+)
的),则在结果前加一个空格。如果同时出现 空格
和 +
标志字符,则忽略 空格
标志。
这个标志可以实现有符号数的数字域对齐,在LCD显示数据时很有用,比较代码:
printf("The value % d\n", 500); //有'空格'标志
printf("The value % d\n", -500); //有'空格'标志
printf("The value %+ d\n", 500); //同时有'空格'和'+'标志
代码输出:
The value 500
The value -500
The value +500
#
:对于 o、x、X
转换类型,在非零结果前添加前缀,比如十六进制前缀 0x
,比较代码:
printf("The value %o\n", 0500); //八进制,无'#'标志
printf("The value %#o\n", 0500); //八进制,有'#'标志
printf("The value %#o\n", 0); //八进制,有'#'标志
printf("The value %x\n", 0x500); //十六进制,无'#'标志
printf("The value %#x\n", 0x500); //十六进制,有'#'标志
printf("The value %#x\n", 0); //十六进制,有'#'标志
代码输出:
The value 500
The value 0500
The value 0
The value 500
The value 0x500
The value 0
浮点数
对于 e、E、f、g、G
转换类型,即使小数点后面没有数,结果也要包含一个小数点。比较代码(这里会用到精度说明参数,可以在理解了精度说明参数后再看这个例子):
printf("The value %.0f\n", 500.1234); //精度指定为0
printf("The value %#.0f\n", 500.1234); //精度指定为0,有'#'标志
代码输出:
The value 500
The value 500.
0
:使用 0
填充,没有这个标志字符,则使用 空格
填充,如果和左对齐标志(-
)同时出现,则忽略0填充标志(0
)。比较代码:
int value = 500;
printf("The value |%8d|\n", value); //空格填充,右对齐
printf("The value |%08d|\n", value); // 0填充,右对齐
printf("The value |%-8d|\n", value); //空格填充,左对齐
printf("The value |%-08d|\n", value); //左对齐标志('-')和0填充标志('0')同时出现,忽略0填充标志
代码输出:
The value | 500|
The value |00000500|
The value |500 |
The value |500 |
可选。
最小字段宽度是一个 *
或者是一个十进制整数
。如果转换结果比最小字段宽度小,则转换结果会被填充。
左对齐标志举例 printf("The value |%8d|\n", value);
,其中 %8d
中的十进制整数 8
就是最小字段宽度,比较代码:
printf("The value |%8d|\n", 500); //空格填充,右对齐
printf("The value |%08d|\n", 500); // 0填充,右对齐
printf("The value |%8d|\n", 1234567890); //空格填充,右对齐,数值大于最小字段宽度
printf("The value |%08d|\n", 1234567890); // 0填充,右对齐,数值大于最小字段宽度
代码输出:
The value | 500|
The value |00000500|
The value |1234567890|
The value |1234567890|
如果最小字段宽度是一个 *
,一个int
型参数提供最小字段宽度。比较代码:
printf("The value |%*d|\n", 8, 500); //空格填充,右对齐,使用'*'
printf("The value |%0*d|\n", 8, 500); // 0填充,右对齐,使用'*'
printf("The value |%8d|\n", 500); //空格填充,右对齐
printf("The value |%08d|\n", 500); // 0填充,右对齐
代码输出:
The value | 500|
The value |00000500|
The value | 500|
The value |00000500|
浮点数最小字段宽度包含小数点,比较代码
printf("电流:%5.1fmA \n", 145.82);
printf("电流:%5.1fmA \n", 0.1);
代码输出:
电流:145.8mA
电流: 0.1mA
可选。
精度说明是小数点 .
后跟一个 *
或者是一个十进制整数
。
与最小字段宽度类似,如果精度说明是 .*
,一个int
型参数提供精度。
对于 d、i、o、x、X
转换类型,精度说明指定了转换中出现数字的最少个数。比较代码:
printf("The value |%8d|\n", 500); //空格填充,右对齐
printf("The value |%.8d|\n", 500); //使用精度说明,对空格填充有影响
printf("The value |%.8d|\n", 1234567890); //使用精度说明,数值大于指定精度
代码输出:
The value | 500|
The value |00000500|
The value |1234567890|
对于 e、E、f
转换类型,精度说明指定了转换的小数点右边的个数。比较代码:
printf("The value %f\n", 500.1234); //不使用精度说明
printf("The value %.2f\n", 500.1234); //使用精度说明
printf("The value %e\n", 500.1234); //不使用精度说明
printf("The value %.2e\n", 500.1234); //使用精度说明
代码输出:
The value 500.123400
The value 500.12
The value 5.001234e+02
The value 5.00e+02
对于 s
转换类型,精度说明指定了转换中要从字符串写入的最大字符数。比较代码:
char *string = "123456789";
printf("The value %s\n", string); //不使用精度说明
printf("The value %.2s\n", string); //使用精度说明
代码输出:
The value 123456789
The value 12
CmBacktrace
源码在输出最后字符串时使用了这个特性(%.*s
),在格式化时可以避免处理字符串结尾符。如代码所示:
cmb_println("查看更多函数调用栈信息,请运行:addr2line -e %s%s -a -f %.*s",
fw_name,
CMB_ELF_FILE_EXTENSION_NAME,
cur_depth * (8 + 1), call_stack_info);
CmBacktrace (Cortex Microcontroller Backtrace)是一款针对 ARM Cortex-M 系列 MCU 的错误代码自动追踪、定位,错误原因自动分析的开源库。
可选。
h
表示转换参数的类型为 short int
或 unsigned short int
,只对 d、i、o、x、X
转换类型有效;l
表示转换参数的类型为 long int
或 unsigned long int
,只对 d、i、o、x、X
转换类型有效;L
表示转换参数的类型为 long double
,只对e、E、f、g、G
转换类型有效。d、i
:将 int
参数转换为有符号十进制数;
o
:将 unsigned int
参数转换为无符号八进制数;
u
:将 unsigned int
参数转换为无符号十进制数;
x、X
:将 unsigned int
参数转换为无符号十六进制数;
f
:将 double
参数转换为十进制数,形式为 [-]ddd.ddd
,默认精度为6位;
e、E
:将 double
参数转换为十进制数,形式为 [-]d.ddde±dd
,默认精度为6位;
c
:将 int
参数转换为 unsigned char
类型,并输出结果;
s
:参数应该是指向字符型数组的指针,如果指定了精度说明,则最多转换精度说明指定的字符,否则,数组应包含一个字符串结尾符。
p
:参数是一个指向 void
类型的指针;
n
:参数是一个指向整形变量的指针,这个整形变量记录到目前为止通过调用 printf
所转换的字符总数。不转换参数。
int num1, num2;
printf("The value %n%s%n\n", &num1, string, &num2);
printf("num1 = %d\n", num1);
printf("num2 = %d\n", num2);
代码输出:
The value 123456789
num1 = 10
num2 = 19
%
:转换一个 %
号。
用一张图来表示以上内容:
参考:《C标准库》
读后有收获,资助博主养娃 - 千金难买知识,但可以买好多奶粉 (〃‘▽’〃)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。