C_格式化输入输出

C_格式化输入/输出

输入/输出模型

由于硬件设备速度:CPU>>内存>>IO设备

为了平衡内存和 IO 设备之间的速度差异,会在内存中设置缓冲区(buffer),其中就有标准输入缓冲区 (stdin) 和标准输出缓冲区 (stdout)等。

printf函数

printf 函数的作用:显示格式串中的内容,并用后面表达式的值替换格式串中的转换说明

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

格式串中包含普通字符和转换说明。其中,普通字符会原样显示,转换说明则会替换为后面表达式的值。如:

1
2
3
4
5
6
7
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函数可以将其它类型的数据转换成字符数据,并输出到stdout缓冲区中。

转换说明

转换说明可以对输出格式进行精确的控制。

转换说明的格式为: %m.pX%-m.pX ,其中 mp 都是整数常量,而 X 是字母。mp 都是可选的;如果省略 p,则小数点也要省略。如:

1
%10.2f, %10f, %.2f, %f

最小字段宽度 (minimum field width) m 指定了要显示的最少字符数量。

如果显示值所需的字符数少于 m,会在值前面添加额外的空格(右对齐)。例如,转换说明%4d 将以 •123 的形式显示 123 (代表空格)。

如果显示值所需的字符数多于m,会自动扩展为所需的大小,不会丢失数字。因此, %4d 将以 12345 的形式显示12345m前面的负号会导致值左对齐%-4d 将以 123• 的形式显示123

精度 (precision) p 的含义依赖于转换说明符 X 的选择。常用的转换说明符有以下几个:

  • %d: 表示十进制整数。p 表示待显示数字的最小个数 (必要时在数字前面补 0);如果省略 p,则默认为1。
  • %f: 表示“定点十进制”形式的浮点数。p 表示小数点后数字的个数 (默认为 6)。如果 p 为 0,则不显示小数点。
  • %c: 用于字符
  • %s: 用于字符串
  • %p: 指针的地址
  • %m: 报告上一个错误的描述。
  • %n: 存储前面参数输出字符的数量。
  • %hh: 用于 char 类型。
  • %Lf: 用于 long double 类型,以长双精度浮点数格式输出。
  • %o: 用于八进制整数
  • %u: 用于无符号十进制整数
  • %i: 有符号十进制、八进制、或十六进制整数(根据输入的前缀)
  • %x%X: 用于无符号十六进制整数,%x表示小写字母,%X表示大写字母
  • %a%A: 浮点数的十六进制浮点表示法,%a表示小写字母,%A表示大写字母。
  • %e%E: 用于以指数形式表示的浮点数,%e表示小写字母,%E表示大写字母
  • %g%G: 用于浮点数,根据值的大小自动选择 %f%e%g表示小写字母,%G表示大写字母
  • %ll%j%z%t: 用于 long longintmax_tsize_tptrdiff_t 类型的整数,分别表示长长整数、最大整数类型、大小类型、指针差异类型。
1
2
3
4
5
6
7
8
int main(void) 
{
int i = 40;
float x = 839.21f;
printf("|%d|%5d|%-5d|%5.3d|\n", i, i, i, i);
printf("|%f|%10f|%10.2f|%-10.2f|\n", x, x, x, x);
   return 0;
}

scanf函数

scanf 函数的作用:根据格式串读取 stdin 中的字符,并将字符转换成指定类型的数据后,写到后面表达式所指定的位置。

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

在绝大多数情况下, scanf 函数的格式串中只包含转换说明:

1
2
3
int i, j;
float x, y;
scanf("%d%d%f%f", &i, &j, &x, &y);

值得注意的是,通常会在后面变量的前面加 & 符号(取地址运算符),但并不是必须的。

scanf函数的工作原理

scanf 函数本质上是一个”模式匹配”函数,试图把 stdin 中的字符与格式串匹配。

scanf 函数会从左到右依次匹配格式串中的每一项。如果匹配数据项成功,那么scanf 函数会继续处理格式串的剩余部分;如果匹配不成功, scanf 函数将不再处理格式串的剩余部分,而会立刻返回。

scanf 函数的格式串中的每一项都表示一个匹配规则,其中:

  • %d : 忽略前置的空白字符 (包括空格符、水平和垂直制表符、换页符和换行符),然后匹配十进制的整数。

  • %f : 忽略前置的空白字符,然后匹配浮点数。

注意:当**scanf函数**遇到一个不属于当前项的字符时,它不会读取该字符。在下一次读取输入时,才会读取该字符。如果scanf输入后没有清理缓冲区,下次读写很可能错误

1
scanf("%d%d%f%f", &i, &j, &x, &y);

scanf 可以从 stdin 缓冲区中读取字符数据,然后转换成其它类型的数据,并写到后面表达式所指定的位置。

格式串中的普通字符

scanf 函数的格式串中也可以包含普通字符,普通字符也用来表示匹配规则。

  • 空白字符:匹配 0 个或多个空白字符。

  • 其它字符:精确匹配(是什么字符就匹配什么字符)。

    1
    2
    3
    假设格式串是: "%d/%d"
    输入1: •5/•96
    输入2: •5•/•96

不要混淆printf函数和scanf函数

虽然 scanf 函数调用和 printf 函数调用看起来很相似,但这两个函数之间有很大的差异!

一个常见的错误是:调用 printf 函数时,在变量的前面加 &

1
printf("%d,%d\n", &i, &j); /*** 错误的!!!***/

scanf 函数在寻找数据项时,通常会跳过前面的空白字符。所以除了转换说明,格式串通常不包含其它字符。

另一个常见的错误就是:认为 scanf 函数的格式串应该类似于 printf 函数的格式串。

1
2
scanf("%d,%d", &i, &j);
输入:10 20 /*** 错误的!!!,需要加,号***/