10 -printf()函数

1 函数原型

printf():将格式化数据写入标准输出流stdout,函数原型如下:

int printf ( const char * format, ... );

cstdio库描述如下:

Print formatted data to stdout
1. Writes the C string pointed by format to the standard output (stdout). 
2. If format includes format specifiers (subsequences beginning with %), the additional arguments following format are formatted and inserted in the resulting string replacing their respective specifiers.

2 参数

printf()函数的参数分为两类:

  1. format:格式化字符串,用于指定后续可变数量的参数如何被格式化和插入到输出流中;
  2. …:可变数量的参数
    (1)可选的;
    (2)数量和类型应与格式化字符串中的格式说明符相匹配;
    (3)任意有效的C表达式。

cstdio库描述如下:

format
1. C string that contains the text to be written to stdout.
2. It can optionally contain embedded format specifiers that are replaced by the values specified in subsequent additional arguments and formatted as requested.

... (additional arguments)
1. Depending on the format string, the function may expect a sequence of additional arguments, each containing a value to be used to replace a format specifier in the format string (or a pointer to a storage location, for n).
2. There should be at least as many of these arguments as the number of values specified in the format specifiers. Additional arguments are ignored by the function.

2.1 格式化字符串

在printf()函数中:

  1. 格式化字符串是必不可少的;
  2. 格式化字符串由文本字符、转义序列和格式说明符三部分组成。

2.1.1 文本字符

在格式化字符串中,除了转义序列和格式说明符,剩余的部分都属于文本字符,文本字符按照原样显示在屏幕上。

2.1.2 转义序列

2.1.2.1 转义序列的定义
  1. 所谓转义,即转变字符的含义;
  2. 转义序列以反斜杠字符’'开头;
  3. 反斜杠’字符’告诉编译器以特殊的方式解释下一个字符。
2.1.2.2 常用的转义序列

在这里插入图片描述
根据用途,转移序列注意分为以下几类:

  1. 表示特殊意义的字符,如单引号(\')、双引号(\")和反斜杠(\\);
  2. 表示ASCII的字符,如\ddd和\xhh;
  3. 控制输出格式的字符,如(\r)、(\n)、(\t)、(\v)和(\f)。

特别提醒:任何转移序列都只表示一个字符,一个字符,一个字符,重要的事情说三遍。

2.1.2.3 转义序列示例

示例代码如下所示:

int main()
{
   //
   printf("%c\n", '\'');
   printf("%c\n", '\\');
   printf("\"hello world\"\n");
   printf("C:\\test\\test_0718\\test.c\n");
   printf("%zu\n", strlen("c:\test\628\test.c"));
   //
   return 0;
}

代码运行结果如下图所示:

在这里插入图片描述

代码及运行结果分析如下:

  1. 对于第5个printf()语句, \t (水平制表符) 是1个字符,\62是1个字符(注意8不属于8进制)。

2.1.3 格式说明符

格式说明符以百分号字符’%'开头,格式如下:

%[标志][最小宽度][.精度][类型长度]类型

cstdio库描述如下:

1. A format specifier follows this prototype : %[flags][width][.precision][length]specifier
2. Where the specifier character at the end is the most significant component, since it defines the type and the interpretation of its corresponding argument.
2.1.3.1 类型

类型字段是格式说明符中必不可少的部分,用于指定printf()函数如何格式化对应的参数,常用的类型如下图所示:

在这里插入图片描述

特别说明:在C语言中,当函数(如printf)的参数是可变参数时,它们的类型可能会根据某些规则进行提升或转换

2.1.3.1.1 整形

%d期望的参数类型是int,%u/%x/%X期望的参数类型是unsigned int;但是,可变参数类型可以是任意整数类型,示例代码如下所示:

int main()
{
   //
   char ch = -1;
   //
   printf("%d\n", ch);
   printf("%u\n", ch);
   printf("%x\n", ch);
   printf("%X\n", ch);
   //
   return 0;
}

代码运行结果如下图所示:

在这里插入图片描述

代码及运行结果分析如下:

  1. ch是char类型,存储在内存中占1个字节,值为11111111,传递给printf()函数后,首先提升为int型,值为11111111_11111111_11111111_11111111,最高位是符号位,1表示负数;当以%u/%x/%X形式输出时,再由int型转换为unsigned int型,最高位不再是符号位。
2.1.3.1.2 浮点型

%f/%e/%E/%g/%G期望的参数类型是double;但是,可变参数类型可以是float型或double,示例代码如下所示:

int main() {
   //
   double doubleNum_s = 1.23;

   printf("使用%%f打印1.23 : %f\n", doubleNum_s);
   printf("使用%%e打印1.23 : %e\n", doubleNum_s);
   printf("使用%%E打印1.23 : %E\n", doubleNum_s);
   printf("使用%%g打印1.23 : %g\n", doubleNum_s);
   printf("使用%%G打印1.23 : %G\n", doubleNum_s);
   //
   printf("\n");
   //
   double doubleNum_l = 1.2345678;

   printf("使用%%f打印1.2345678 : %f\n", doubleNum_l);
   printf("使用%%e打印1.2345678 : %e\n", doubleNum_l);
   printf("使用%%E打印1.2345678 : %E\n", doubleNum_l);
   printf("使用%%g打印1.2345678 : %g\n", doubleNum_l);
   printf("使用%%G打印1.2345678 : %G\n", doubleNum_l);
   //
   return 0;
}

代码运行结果如下图所示:

在这里插入图片描述

特别说明

  1. 浮点型常量默认是双精度浮点型;
  2. 打印浮点数时:
    (1)对于%f、%e和%E,默认打印6位小数,不足6位时补0,超过6位时四舍五入到6位;
    (2)对于%g和%G,默认最多打印6位有效数字(注意是最多),不足6位时不补0(不显示无意义的0),超过6位时四舍五入到6位。
2.1.3.1.3 字符和字符串

%c期望的参数类型是int型,参考2.1.3.2小节cstdio库关于%c的描述,示例代码如下所示:

int main()
{
   //
   char ch = 'c';
   char str[] = "printf() test string.";
   //
   printf("%c\n", ch);
   printf("%s\n", str);
   //
   return 0;
}

代码运行结果如下图所示:

在这里插入图片描述

2.1.3.1.5 指针

当以%p形式打印指针指向的内存地址时:

  1. 对于x86架构,地址为32位;
  2. 对于x64架构,地址位64位。

示例代码如下所示:

int main()
{
   //
   int a = 0;
   //
   printf("%p\n", &a);
   //
   return 0;
}

VS2019>>Debug>>x86下,代码运行结果如下图所示:

在这里插入图片描述

VS2019>>Debug>>x64下,代码运行结果如下图所示:

在这里插入图片描述

2.1.3.2 类型长度

类型长度字段在格式说明符中是可选的,cstdio库描述如下:

1. The length sub-specifier modifies the length of the data type. 
2. This is a chart showing the types used to interpret the corresponding arguments with and without length specifier (if a different type is used, the proper type promotion or conversion is performed, if allowed).
3. Note regarding the c specifier: it takes an int as argument, but performs the proper conversion to a char value before formatting it for output.

常用的类型长度字段如下图所示:
在这里插入图片描述

注意:strlen()函数的返回值为size_t,需要以%zu格式输出。

2.1.3.3 精度

精度字段在格式说明符中是可选的,cstdio库描述如下:

.number
1. For integer specifiers (d, i, u, x, X): precision specifies the minimum number of digits to be written. If the value to be written is shorter than this number, the result is padded with leading zeros. The value is not truncated even if the result is longer. A precision of 0 means that no character is written for the value 0.
2. For e, E and f specifiers: this is the number of digits to be printed after the decimal point (by default, this is 6).
3. For g and G specifiers: This is the maximum number of significant digits to be printed.
4. For s: this is the maximum number of characters to be printed. By default all characters are printed until the ending null character is encountered.
5. If the period is specified without an explicit value for precision, 0 is assumed.

.*
1. The precision is not specified in the format string, but as an additional integer value argument preceding the argument that has to be formatted.
2.1.3.3.1 整数说明符

对于整数说明符(d, i, u, x, X),精度字段不常用,一般使用最小宽度字段+标志字段。

2.1.3.3.2 浮点数说明符
  1. 对于f、e和E说明符,精度指定了小数点后要打印的位数;默认情况下,打印6位小数,通过指定精度可以改变小数的打印位数:
    (1)如果格式化后的参数包含的小数位数小于指定精度,则在小数部分后面补0至指定精度;
    (2)如果格式化后的参数包含的小数位数大于指定精度,则将小数部分四舍五入到指定精度。
  2. 对于g和G说明符,精度指定了要打印的最大有效数字位数;默认情况下,最多打印6位有效数字,通过指定精度可以改变有效数字的打印位数:
    (1)如果格式化后的参数包含的有效数字位数小于指定精度,则直接输出不补0;
    (2)如果格式化后的参数包含的有效数字位数大于指定精度,则四舍五入到指定精度。

示例代码如下所示:

int main() {
   //
   double doubleNum_s = 3.4;

   printf("使用%%f + 精度3 打印3.4 : %.3f\n", doubleNum_s);
   printf("使用%%e + 精度3 打印3.4 : %.3e\n", doubleNum_s);
   printf("使用%%g + 精度3 打印3.4 : %.3g\n", doubleNum_s);
   //
   printf("\n");
   //
   double doubleNum_l = 3.456789;

   printf("使用%%f + 精度3 打印3.456789 : %.3f\n", doubleNum_l);
   printf("使用%%e + 精度3 打印3.456789 : %.3e\n", doubleNum_l);
   printf("使用%%g + 精度3 打印3.456789 : %.3g\n", doubleNum_l);
   //
   return 0;
}

代码运行结果如下图所示:

在这里插入图片描述

2.1.3.3.3 字符串说明符

对于字符串说明符%s,精度指定了最多要打印的字符数:

  1. 如果字符串的长度小于指定的精度,则完整打印字符串;
  2. 如果字符串的长度大于指定的精度,则只打印前N个字符(N是精度值),并省略剩余的字符。
2.1.3.4 最小宽度

最小宽度字段在格式说明符中是可选的:

  1. 如果格式化后的参数包含的字符数大于指定的最小宽度,则按实际输出;
  2. 如果格式化后的参数包含的字符数小于指定的最小宽度,则左侧填充空格直至达到指定宽度(右对齐)。

cstdio库描述如下:

number
1. Minimum number of characters to be printed. If the value to be printed is shorter than this number, the result is padded with blank spaces. The value is not truncated even if the result is larger.

*
1. The width is not specified in the format string, but as an additional integer value argument preceding the argument that has to be formatted.

示例代码如下所示:

int main() {
   //
   int intValue_s = 123;
   int intValue_l = 123456789;

   double doubleValue_s = 1.23;
   double doubleValue_l = 12345.6789;

   char* str_s = "Hello";
   char* str_l = "Hello World";
   // 使用%d和width  
   printf("使用%%d + width  8 打印123         : |%8d|\n", intValue_s);
   printf("使用%%d + width  8 打印123456789   : |%8d|\n", intValue_l);
   printf("\n");
   // 使用%f和width
   printf("使用%%f + width 10 打印1.23        : |%10f|\n", doubleValue_s);
   printf("使用%%f + width 10 打印12345.6789  : |%10f|\n", doubleValue_l);
   printf("\n");
   // 使用%e和width
   printf("使用%%e + width 10 打印1.23        : |%10.2e|\n", doubleValue_s);
   printf("使用%%e + width 10 打印12345.6789  : |%10e|\n", doubleValue_l);
   printf("\n");
   // 使用%g和width
   printf("使用%%s + width 10 打印Hello       : |%10s|\n", str_s);
   printf("使用%%s + width 10 打印Hello World : |%10s|\n", str_l);
   //
   return 0;
}

代码运行结果如下图所示:

在这里插入图片描述

2.1.3.5 标志

标志字段在格式说明符中是可选的,用于调整输出的格式:

  1. 减号-
    (1)与最小宽度字段一起使用,默认情况下,输出是右对齐的;
    (2)使用 - 标志可以使输出左对齐。
  2. 加号+
    (1)对于数值类型(如整数、浮点数等),默认情况下,如果数值是非负的,则不会显示符号;
    (2)使用 + 标志时,即使数值是非负的,也会在其前面显示 + 符号。
  3. 空格
    (1)与 + 标志类似,如果数值是非负的,则在数值前添加一个空格,使得正数和负数在视觉上对齐。
  4. 井号#
    (1)对于%x 或 %X,在输出前添加 0x 或 0X;
    (2)对于%f、%e、%E、%g和%G,要求小数点总是被打印,即使它后面没有数字(当精度字段指定为0时,默认小数点是不打印的)。
  5. 数字0
    (1)与最小宽度字段一起使用,默认情况下,输出使用空格进行填充;
    (2)使用 0 标志,可以使输出使用0进行填充。

cstdio库描述如下:

-
1. Left-justify within the given field width。
2. Right justification is the default (see width sub-specifier).

+
1. Forces to preceed the result with a plus or minus sign (+ or -) even for positive numbers.
2. By default, only negative numbers are preceded with a - sign.

(space)
1. If no sign is going to be written, a blank space is inserted before the value.

#
1. Used with x or X specifiers the value is preceeded with 0x or 0X respectively for values different than zero.
2. Used with f, e, E, g or G it forces the written output to contain a decimal point even if no more digits follow. By default, if no digits follow, no decimal point is written.

0
1. Left-pads the number with zeroes (0) instead of spaces when padding is specified (see width sub-specifier).

示例代码如下所示:

int main()
{
   //
   int a = 123;

   printf("使用右对齐打印123     :|%10d|\n", a);
   printf("使用左对齐打印123     :|%-10d|\n", a);
   printf("使用标志0打印123      :|%010d|\n", a);
   printf("\n");
   printf("使用标志#打印123      : %#x\n", a);
   printf("使用标志#打印123      : %#X\n", a);
   printf("\n");
   //
   double b1 = 1.23;
   double b2 = -1.23;

   printf("使用标志+打印 1.23    :%+f\n", b1);
   printf("使用标志+打印-1.23    :%+f\n", b2);
   printf("\n");
   printf("使用标志空格打印 1.23 :% f\n", b1);
   printf("使用标志空格打印-1.23 :% f\n", b2);
   printf("\n");
   //
   double b3 = 123.456;
   printf("使用精度0打印123.456  : %.0f\n", b3);
   printf("使用标志#打印123.456  : %#.0f\n", b3);
   //
   return 0;
}

代码运行结果如下图所示:

在这里插入图片描述

3 返回值

printf()函数的返回值类型为int型:

  1. 写入成功,返回输出的总字符数;
  2. 写入失败,返回一个负数。

cstdio库描述如下:

1. On success, the total number of characters written is returned.
2. If a writing error occurs, the error indicator (ferror) is set and a negative number is returned.

示例代码如下所示:

int main()
{
   //
   int ret_val = 0;
   //
   ret_val = printf("Hello World!\n");
   printf("The printf return value = %d\n", ret_val);
   //
   return 0;
}

代码运行结果如下图所示:

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值