购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

3.1 printf 函数

printf 函数被设计用来显示 格式串 (format string)的内容,并且在该串中的指定位置插入可能的值。调用 printf 函数时必须提供格式串,格式串后面的参数是需要在显示时插入到该串中的值:

printf(格式串, 表达式1, 表达式2, ...);

显示的值可以是常量、变量或者更加复杂的表达式。

格式串包含普通字符和 转换说明 (conversion specification),其中转换说明以字符 % 开头。转换说明是用来表示打印过程中待填充的值的占位符。跟随在字符 % 后边的信息指定了把数值从内部形式(二进制) 转换 成打印形式(字符)的方法,这就是“转换说明”这一术语的由来。例如,转换说明 %d 指定 printf 函数把 int 型值从二进制形式转换成十进制数字组成的字符串,转换说明 %f float 型值也进行类似的转换。

格式串中的普通字符完全按照它们在字符串中出现的那样显示出来,而转换说明则要用待显示的值来替换。思考下面的例子:

int i, j;
float x, y;

i = 10;
j = 20;
x = 43.2892f;
y = 5527.0f;

printf("i = %d, j = %d, x = %f, y = %f\n", i, j, x, y);

这个 printf 函数调用会产生如下输出:

i = 10, j = 20, x = 43.289200, y = 5527.000000

格式串中的普通字符被简单复制给输出行,而变量 i j x y 的值则依次替换了4个转换说明。

C语言编译器不会检测格式串中转换说明的数量是否和输出项的数量相匹配。下面这个 printf 函数调用所拥有的转换说明的数量就多于要显示的值的数量:

    printf("%d %d\n", i);   /*** WRONG ***/
  

printf 函数将正确显示变量 i 的值,接着显示另一个(无意义的)整数值。函数调用带有太少的转换说明也会出现类似的问题:

    printf("%d\n", i, j);   /*** WRONG ***/
  

在这种情况下, printf 函数会显示变量 i 的值,但是不显示变量 j 的值。

此外,C语言编译器也不检测转换说明是否适合要显示项的数据类型。如果程序员使用不正确的转换说明,程序将简单地产生无意义的输出。思考下面的 printf 函数调用,其中 int 型变量 i float 型变量 x 的顺序放置错误:

    printf("%f %d\n", i, x);   /*** WRONG ***/
  

因为 printf 函数必须服从于格式串,所以它将如实地显示出一个 float 型值,接着是一个 int 型值。可惜这两个值都是无意义的。

3.1.1 转换说明

转换说明给程序员提供了大量对输出格式的控制方法。另外,转换说明可能很复杂且难以阅读。事实上,在本节中想要完整详尽地介绍转换说明是不可能的,这里只是简要地介绍一些较为重要的性能。

在第2章中我们已经看到,转换说明可以包含格式化信息。具体来说,我们可以用 %.1f 来显示小数点后带一位数字的 float 型值。更一般地,转换说明可以用 % m.pX 格式或 % - m.pX 格式,这里的 m p 都是整型常量,而 X 是字母。 m p 都是可选的。如果省略 p m p 之间的小数点也要去掉。在转换说明 %10.2f 中, m 10 p 2 ,而 X f 。在转换说明 %10f 中, m 10 p (连同小数点一起)省去了;而在转换说明 %.2f 中, p 2 m 省去了。

最小栏宽 (minimum field width) m 指定了要显示的最少字符数量。如果要显示的数值所需的字符数少于 m ,那么值在字段内是右对齐的。(换句话说,在值前面放置额外的空格。)例如,转换说明 %4d 将以 ·123 的形式显示数123(本章用符号 · 表示空格字符)。如果要显示的值所需的字符数多于 m ,那么栏宽会自动扩展为所需的尺寸。因此,转换说明 %4d 将以 12345 的形式显示数12345,而不会丢失数字。在 m 前放上一个负号会导致左对齐;转换说明 %-4d 将以 123· 的形式显示123。

精度 (precision) p 的含义很难描述,因为它依赖于 转换指定符 (conversion specifier) X 的选择。 X 表明在显示数值前需要对其进行哪种转换。对数值来说最常用的转换指定符有以下几个。

编写程序时无法预知数的大小或者数值变化范围很大的情况下,说明符 g 对于数的显示是特别有用的。在用于显示大小适中的数时,说明符 g 采用定点十进制形式。但是,在显示非常大或非常小的数时,说明符 g 会转换成指数形式以便减少所需的字符数。

除了 %d %e %f %g 以外,还有许多其他的说明符[整型说明符(➤7.1节)、浮点型说明符(➤7.2节)、字符说明符(➤7.3节)和字符串说明符(➤13.3节)]。我们将在后续章节中陆续进行介绍。转换指定符的全部列表以及转换指定符其他性能的完整解释见22.3节。

程序 用 printf 函数格式化数

下面的程序举例说明了用 printf 函数以各种格式显示整数和浮点数的方法。

tprintf.c

/* Prints int and float values in various formats */

#include <stdio.h>

int main(void)
{
  int i;
  float x;

  i = 40;
  x = 839.21f;

  printf("|%d|%5d|%-5d|%5.3d|\n", i, i, i, i);
  printf("|%10.3f|%10.3e|%-10g|\n", x, x, x);

  return 0;
}

在显示时, printf 函数格式串中的字符 | 只是用来帮助显示每个数所占用的空格数量。不同于 % \ ,字符 | printf 函数而言没有任何特殊意义。此程序的输出如下:

︱40︱   40︱40   ︱  040︱
︱    839.210︱ 8.392e+02︱839.21   ︱

下面仔细看一下上述程序中使用的转换说明。

3.1.2 转义序列

格式串中常用的代码 \n 被称为 转义序列 (escape sequence)。转义序列(➤7.3节)使字符串包含一些特殊字符而不会使编译器引发问题,这些字符包括非打印的(控制)字符和对编译器有特殊含义的字符(如 " )。后面会提供完整的转义序列表,现在先看一组示例。

当这些转义序列出现在 printf 函数的格式串中时,它们表示在显示中执行的操作。在大多数机器上,输出 \a 会产生一声鸣响,输出 \b 会使光标从当前位置回退一个位置,输出 \n 会使光标跳到下一行的起始位置, 输出 \t 会把光标移动到下一个制表符的位置。

字符串可以包含任意数量的转义序列。思考下面的 printf 函数示例,其中的格式串包含了6个转义序列:

printf("Item\tUnit\tPurchase\n\tPrice\tDate\n");

执行上述语句显示出一条两行的标题:

Item    Unit    Purchase
        Price   Date

另一个常用的转义序列是 \" ,它表示字符 " 。因为字符 " 标记字符串的开始和结束,所以它不能出现在没有使用上述转义序列的字符串内。下面是一个示例:

printf("\"Hello!\"");

这条语句产生如下输出:

"Hello!"

附带提一下,不能在字符串中只放置单独一个字符 \ ,编译器将认为它是一个转义序列的开始。为了显示单独一个字符 \ ,需要在字符串中放置两个字符 \ 9/D5A+M5Mwu93AJdVQ2qOTS8MOXwIYUuB1Gxt8UjP0uXT/BjURfNWrPA98dREJjC

printf("\\");   /* prints one \ character */
点击中间区域
呼出菜单
上一章
目录
下一章
×