道阻且长,行则将至。埋头苦干,不鸣则已,一鸣惊人!

1 printf 函数简介

  printf() 和 scanf() 函数,是输入输出函数,或者叫做 I/O 函数。

  两个函数,虽然一个是输出,一个是输入函数,但是他们的工作原理几乎相同。两个函数都使用格式字符串和参数列表。

  请求 printf() 函数打印数据的指令要与待打印数据的类型相匹配。

  参考网址:
    菜鸟教程:C 输入 & 输出
    菜鸟教程:C库函数 - printf()

2 转换说明及其打印的输出结果

  参考《C Primer Plus》把常用的转换说明总结记录如下:

序号 转换说明 输出
1 %a 浮点数、十六进制数和 p 计数法(C99/C11)
2 %A 浮点数、十六进制数和 p 计数法(C99/C11)
3 %c 单个字符
4 %d 有符号十进制整数
5 %e 浮点数,e 计数法
6 %E 浮点数,e 计数法
7 %f 浮点数,十进制计数法
8 %g 根据值的不同,自动选择 %f 或 %e。%e 格式用于指数小于 -4 或者大于或等于精度时
9 %G 根据值的不同,自动选择 %f 或 %E。%E 格式用于指数小于 -4 或者大于或等于精度时
10 %i 有符号十进制整数(与 %d 相同)
11 %o 无符号八进制整数
12 %p 指针
13 %s 字符串
14 %u 无符号十进制整数
15 %x 无符号十六进制整数,使用十六进制数 0f
16 %X 无符号十六进制整数,使用十六进制数 0F
17 %% 打印一个百分号

  警告:格式字符串中的转换说明一定要与后面的每个项相匹配,若忘记这个基本要求会导致严重的后果。

3 转换说明修饰符

  在 % 和转换字符之间插入修饰符可修饰基本的转换说明。参考《C Primer Plus》把常用的修饰符用表格记录部分常用内容如下:

修饰符 含义
标记 有5种标记符号(-、+、空格、#和0)详细内容见下一份表格,可以不使用标记或使用多个标记。
示例:"%-10d"
数字 最小字段宽度
如果该字段不能容纳待打印的数字或字符串,系统会使用更宽的字段(系统会根据实际字段显示,而不会去掉不显示)
示例:"%4d"
.数字 精度
对于 %e、%E 和 %f 转换,表示小数点右边数字的位数
对于 %g 和 %G 转换,表示有效数字最大位数
对于 %s 转换,表示待打印字符的最大数量
对于整形转换,表示待打印数字的最小位数
如有必要,使用前导 0 来达到这个位数
只是用 . 表示其后跟随一个 0,所以 %.f 和 %.0f 相同
示例:"%5.2f"打印一个浮点数,字段宽度为5字符,其中小数点后有两位数字
t 和整型转换说明一起使用,表示 ptrdiff_t 类型的值。ptrdiff_t 是两个指针差值的类型(C99)
示例:"%td"、"%12ti"
z 和整型转换说明一起使用,表示 size_t 类型的值。size_t 是 sizeof 返回的类型(C99)
  • 针对类型可移植性,需做如下特别说明
     sizeof 运算符以字节为单位返回类型或值的大小。但是在不同的系统中,使用printf()函数显示sizeof表达式,可能有不同的用法。这意味着,如果移植到不同的系统,还需要再查找适合当前系统的用法。这样就很麻烦,在C中提供了可移植性更好的类型。
     1. size_t 定义成系统使用 sizeof 返回的类型,这个被称为底层类型。其次 printf 中使用 z 修饰符表示打印相应的类型。
     2. C还定义了 ptrdiff_t 类型和 t 修饰符来标识系统使用的两个地址差值的底层有符号整数类型。

  • 针对浮点类型,float 参数的转换
     对于浮点类型,有用于 double 和 long double 类型的转换说明,却没有 float 类型的。这是因为在标准 C 中,表达式或参数中的 float 类型值会被自动转换成 double 类型。

4 printf 中的标记

  根据书本记录,总结标记内容如下:

标记 含义
- 待打印项左对齐。即,从字段的左侧开始打印该项
示例:"%-20s"
+ 有符号值若为正,则在值前面显示加号;若为负,则在值前面显示减号
空格 有符号值若为正,则在值前面显示前导空格(不显示任何符号);若为负,则在值前面显示减号
+标记覆盖一个空格
示例:"% 6.2f"
# 把结果转换为另一种形式。如果是 %o 格式,则以 0 开始;如果是 %x 或 %X 格式,则以 0x 或 0X 开始;
对于所有的浮点格式,# 保证了即使后面没有任何数字,也打印一个小数点字符。对于 %g 和 %G 格式,# 防止结果后面的 0 被删除
示例:"%#o"、"%#8.0f"、"+#10.3e"
0 对于数值格式,用前导 0 代替空格填充字段宽度。对于整数格式,如果出现 - 标记或指定精度,则忽略该标记
示例:"%010d"和"%0.83f"
5 转换说明的意义

  转换说明把以二进制格式存储在计算机中的值转换成一系列字符(字符串)便于显示。

转换(conversion)可能会是我们误认为原始值被替换成转换后的值。实际上,转换说明是翻译说明,%d 的意思是:把给定的值翻译成十进制整数文本并打印出来。

5.1 举例说明

  参数传递机制因实现而异,下边举例说明:

float n1 = 3.0;
double n2 = 3.0;
long n3 = 2000000000;
long n4 = 1234567890;

printf("%ld %ld %ld %ld\n", n1, n2, n3, n4)

  观察上述代码,进行如下分析:

  • 分析上边的打印函数,n1 n2 是浮点类型,在打印的时候,float 会被转换为 double 类型,因此n1 n2 分别占8个字节;但是 long 类型的 n3 n4 分别占4个字节。
  • 再来看我们的打印函数,使用的是%ld,也就是 long 类型的,这样按照顺序依次取,会先取 n1 的前半部分,然后第二次取 4 个字节,会取 n1 的后半部分,接下来的 4 个字节会是 n2 的前半部分,然后是 n2 的后半部分;到此打印就完了。因此对于 n3 n4,虽然用对了转换说明,但是printf还是读错了字节。

5.2 Printf 的返回值

printf 函数也有返回值,返回打印字符的个数。如果输出有错误,printf()则返回一个负值。

printf() 的打印输出是附带功能,通常很少用到。在写入文件时很常用。

5.3 打印较长的字符串

  在实际操作中,经常会遇到打印一些较长字符串的问题,这个时候该怎么办呢?参考书本,有如下几种解法:

  • 方法一: 使用多个 printf() 语句。
printf("Here's one way to print a ");
printf("long string.\n");

  产生如下输出:

Here's one way to print a long string.
  • 方法二: 用反斜杠(\)和 Enter(或 Return)键组合来断行。这会使得光标移动至下一行,而且字符串中不会包含换行符。其效果是在下一行继续输出。但是,下一行代码必须和程序清单中的代码一样从左边开始(貌似我现在在编译器中使用时,都是回车默认的缩进,而且好多也不是在这一行最左边)。
printf("Here's another way to print a \
long strint.\n");

  产生如下输出:

Here's another way to print a long strint.
  • 方法三: ANSI C引入的字符串连接。在两个用双括号括起来的字符串之间用空白隔开,C编译器会把多个字符串看作是一个字符串。
6 总结
  1. 实际使用过程中,熟能生巧,勤加练习;
  2. 不需要刻意去记住这些东西,但是需要了解,需要知道有这些东西可以用!????