printf 日常使用指南

Posted zhzht19861011

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了printf 日常使用指南相关的知识,希望对你有一定的参考价值。

格式化适用场景

  • 调试输出
  • LCD显示内容

格式化函数的一般格式

格式化输出函数printffprintfsprintfsnprintf在格式化处理部分是相同的,本文以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|
    

精度说明

可选

精度说明小数点 . 后跟一个 * 或者是一个十进制整数

  • 最小字段宽度类似,如果精度说明.* ,一个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、l、L

可选

  • h 表示转换参数的类型为 short intunsigned short int ,只对 d、i、o、x、X 转换类型有效;
  • l 表示转换参数的类型为 long intunsigned 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标准库》

以上是关于printf 日常使用指南的主要内容,如果未能解决你的问题,请参考以下文章

printf 日常使用指南

C++中printf() 使用方法?

初学c语言用和不用中间参量进行两个数交换

c语言里怎么使用printf?

printf与scanf格式

printf函数怎么使用?