知识点

C格式化输入

定义

scanf按格式串解析标准输入,并通过指针把转换结果写入对象。例如scanf("%d", &n) 将整数写入int n。格式说明与指针所指向的类型必须匹配,否则行为未定义。

性质

%d需要int *,%f需要float *,%lf需要double *。字符数组作为实参时通常转换为首元素指针,例如char word[16] 可传word。用 %15s最多读取15个字符,并为结尾的 \0留出空间;不限制宽度可能导致数组越界。

大多数转换会跳过前导空白;%c、%[ 和 %n是例外。格式串中的空白会匹配任意多个输入空白,因此 " %c" 会先跳过空白再读取一个字符。%s在空白处停止;需要读取一整行时可使用fgets。

返回值是成功赋值的项数。例如scanf("%d %d", &a, &b) 在输入12 abc时返回1。在第一次成功转换或匹配失败之前发生输入失败,返回EOF。应按期望的赋值数检查返回值。

例子

%c读到上一行留下的换行

char-input.c
#include <stdio.h>
int main(void) {
int n;
char ch;
scanf("%d", &n); /* 输入42后按回车,换行留在缓冲区 */
scanf("%c", &ch); /* 读到的是 '\n' */
printf("n=%d ch=[%c]\n", n, ch);
scanf(" %c", &ch); /* 格式串开头的空格跳过空白 */
printf("ch=[%c]\n", ch);
return 0;
}

第一次printf会打印出一个空行,因为ch是换行符;在 %c前加一个空格后,才能读到缓冲区里真正等待的那个字符。

用返回值判断读取是否成功

scanf-return.c
#include <stdio.h>
int main(void) {
int n;
if (scanf("%d", &n) != 1) {
printf("没有读到整数\n");
return 1;
}
printf("n = %d\n", n);
return 0;
}

输入abc时scanf返回0,输入42时返回1,输入为空(文件结束)时返回EOF。若只判断 != 0,返回EOF时也会被误当成读取成功。

探索

读取字符时前导空白会怎样处理?

比较 %c与前有空白的格式串。

正在准备演示…

题集

练习

  1. 输入为12 abc时,执行scanf("%d %d", &a, &b) 的返回值是 。

    参考解答

    只有第一个整数转换成功,第二个转换遇到abc失败,函数返回成功赋值的项数1。

  2. 要把输入读进double变量d,正确的写法是:

    选择答案
    参考解答

    double在scanf中要用 %lf,并且必须传地址 &d;%f需要float *;传入不匹配的指针类型或漏写 & 都会导致未定义行为。