printf打印

宏替换printf可以有如下形式:

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

#define FUN1(msg) printf(#msg"\n")
#define FUN2(param1,param2) printf("the %d\n",param1##param2)
#define FUN3(...) printf(__VA_ARGS__)
#define FUN4(format ,...) printf(format,##__VA_ARGS__)

int main()
{
printf("hello \n");
FUN1(hello\n);
FUN2(11, 22);
FUN3("testtttt %d ,%f , %c\n", 10, 100.23, 'a');
FUN4("the %d \n",100);
return 0;
}
运行结果
1
2
3
4
5
6
hello
hello

the 1122
testtttt 10 ,100.230000 , a
the 100

打印格式

原样输出字符串:

printf(“%s”, str);

输出指定长度的字符串, 超长时不截断, 不足时右对齐:

printf(“%Ns”, str); –N 为指定长度的10进制数值

输出指定长度的字符串, 超长时不截断, 不足时左对齐:

printf(“%-Ns”, str); –N 为指定长度的10进制数值

输出指定长度的字符串, 超长时截断, 不足时右对齐:

printf(“%N.Ms”, str); –N 为最终的字符串输出长度
–M 为从参数字符串中取出的子串长度

输出指定长度的字符串, 超长时截断, 不足时左对齐:

printf(“%-N.Ms”, str); –N 为最终的字符串输出长度
–M 为从参数字符串中取出的子串长度(M可以为*****)

自动调整字串长度

格式也适用sprintf

printf(“%N.*s”,len,str); N 为最终的字符串输出长度

示例:

1
printf("总宽度3位、保留2位小数:%3.*f\n", 2, 3.1415);

输出 总宽度3位、保留2位小数:3.14

部分 含义
%f ``基础格式符,表示要格式化一个浮点数(支持 float/double 类型)。
. 分隔符,用于区分 “最小宽度” 和 “小数精度”。
* 精度通配符(动态精度):表示小数部分的位数不由格式串直接写死,而是由后续的 precision 参数动态指定。
3 最小宽度:表示格式化后的字符串至少占 1 个字符的宽度(这个值几乎无实际约束,因为浮点数至少会有 1 位,比如 0)。

参数对应规则不变printf("%1.*f", precision, val) 中,* 依然对应第一个参数 precision(指定小数位数),f 对应第二个参数 val(要格式化的浮点数)。

1 的作用不变:和 sprintf 中一样,1 仅表示格式化后的字符串至少占 1 个字符宽度,几乎无实际约束(浮点数格式化结果最少也会有 1 位,比如 0)。

拓展用法:除了精度用 *,宽度也可以用 *(比如 %*.*f),示例如下:

1
2
3
// %*.*f:第一个*指定总宽度,第二个*指定小数精度
printf("总宽度8位、保留2位小数:%*.*f\n", 8, 2, 3.1415);
// 输出:总宽度8位、保留2位小数: 3.14(前面补空格凑够8位)

总结

  1. printf 完全支持 %1.*f 这种写法,格式化规则和 sprintf 完全一致;
  2. * 作为通配符,可动态指定精度(或宽度),参数顺序需严格对应格式串中的 * 位置;
  3. 两者核心区别仅在于输出目标(控制台 vs 字符缓冲区),格式化逻辑无差异。

用到的地方 时间显示到屏幕的时候,需要用到这些指定长度等。