本知识点对应谭浩强《C程序设计(第五版)》第3章3.4.4节"用scanf函数输入数据"的综合复习,是C语言用户交互功能的核心基础。scanf与printf是一对功能互补的标准输入输出函数,掌握scanf的正确用法是编写健壮交互程序的前提。
1. scanf函数的核心功能
scanf函数的本质:将用户从键盘输入的字符序列,按照指定格式转换为对应类型的数据,并存入指定变量的内存地址中。
它与printf函数功能完全对应:
-
printf:将变量的内容从内存输出到显示器
-
scanf:将用户输入的数据从键盘存入内存变量
2. scanf的两种基本用法
2.1 用法一:仅包含输入控制符(推荐)
格式字符串中只包含输入控制符,这是最常用、最不易出错的用法。
语法:
scanf("输入控制符", &变量名);
示例:
#include <stdio.h>
int main() {
int i;
char ch;
float f;
scanf("%d", &i); // 输入整数
scanf("%c", &ch); // 输入单个字符
scanf("%f", &f); // 输入单精度浮点数
return 0;
}
2.2 用法二:包含非输入控制符(不推荐)
格式字符串中同时包含输入控制符和非输入控制符。
核心规则 :非输入控制符必须被用户原样输入,否则会导致输入失败。
示例:
#include <stdio.h>
int main() {
int i;
scanf("m%d", &i); // 非输入控制符'm'必须被原样输入
printf("i = %d\n", i);
return 0;
}
输入要求 :用户必须输入m123才能正确赋值,直接输入123会失败。
强烈不推荐的原因:
-
增加用户输入难度,容易出错
-
降低程序健壮性,任何格式偏差都会导致输入失败
-
替代方案:使用printf函数输出提示信息,明确告知用户输入格式
3. 输入控制符的核心作用
3.1 为什么必须使用输入控制符?
关键事实 :从键盘输入的所有内容,本质上都是字符,而不是数字。
例如,用户输入123时,操作系统接收到的是三个独立的字符:'1'(ASCII 49)、'2'(ASCII 50)、'3'(ASCII 51)。
输入控制符的作用就是:告诉scanf如何将这些字符转换为对应类型的数据。
| 输入控制符 | 转换规则 |
|---|---|
%d |
将数字字符序列转换为十进制整数 |
%c |
直接读取单个字符,不进行转换 |
%f |
将数字字符序列转换为单精度浮点数 |
3.2 常用输入控制符
scanf的输入控制符与printf的输出控制符完全一致:
| 输入控制符 | 含义 | 适用数据类型 |
|---|---|---|
%d |
输入十进制有符号整数 | int |
%ld |
输入十进制有符号长整数 | long int |
%c |
输入单个字符 | char |
%f |
输入单精度浮点数 | float |
%lf |
输入双精度浮点数 | double |
3.3 取地址符&的必要性
-
所有输入参数必须是变量的地址,即变量名前必须加取地址符
& -
scanf需要知道变量的内存地址,才能将转换后的数据存入正确的位置
-
忘记加
&是初学者最常见的严重错误,会导致程序崩溃或产生不可预知的结果
4. scanf的输入解析逻辑
scanf函数按照以下严格规则解析用户输入:
-
从输入缓冲区中逐个读取字符
-
跳过前导空白字符(空格、制表符、回车符)
-
读取符合输入控制符要求的字符,直到遇到不符合要求的字符为止
-
将读取到的字符序列转换为对应类型的数据
-
将转换后的数据存入指定变量
-
未读取的字符(包括非法字符)会留在输入缓冲区中
-
下一次调用scanf时,会从上次停止的位置继续读取
4.1 示例解析
#include <stdio.h>
int main() {
int i, j;
printf("请输入第一个整数:");
scanf("%d", &i); // 假设用户输入:89m
printf("请输入第二个整数:");
scanf("%d", &j); // 这行代码会直接失败
printf("i = %d, j = %d\n", i, j);
return 0;
}
执行过程:
-
用户输入
89m并按下回车键 -
第一个
scanf读取字符'8'和'9',转换为整数89存入变量i -
遇到非法字符
'm',停止解析,'m'被留在输入缓冲区中 -
第二个
scanf从输入缓冲区中读取到'm',无法转换为整数,直接失败 -
变量
j被赋予随机垃圾值
结论:一个地方的输入错误会导致后续所有scanf语句失败,这是初学者最容易遇到的陷阱之一。
5. 多变量输入的最佳实践
5.1 推荐用法:使用默认空白分隔符
多个输入控制符之间不添加任何非输入控制符,使用默认的空白字符(空格、回车、制表符)作为分隔符。
示例:
#include <stdio.h>
int main() {
int i, j;
printf("请输入两个整数,用空格分隔:");
scanf("%d%d", &i, &j); // 两个%d之间没有任何字符
printf("i = %d, j = %d\n", i, j);
return 0;
}
合法输入方式:
-
12 34(空格分隔) -
12\n34(回车分隔) -
12\t34(制表符分隔)
5.2 不推荐用法:使用逗号等非输入控制符
scanf("%d,%d", &i, &j); // 不推荐
用户必须严格输入12,34才能正确赋值,输入12 34会导致第二个变量赋值失败。
5.3 绝对禁止:在格式字符串末尾添加\n
scanf("%d\n", &i); // 严重错误
会导致程序卡住,用户必须输入任意字符并再次按下回车键才能继续执行。
6. 编程规范与常见问题
-
使用scanf前必须加printf提示信息:明确告知用户输入格式和要求
-
尽量避免使用非输入控制符:所有格式提示都通过printf输出
-
每个变量前必须单独添加取地址符
& -
非法输入处理:可以通过循环清除输入缓冲区中的垃圾字符,解决输入错误的连锁反应问题。该功能依赖while循环,将在第5章流程控制中详细讲解。
7. 要点总结
-
核心功能:将键盘输入的字符转换为指定格式的数据,存入变量中
-
两种用法:仅含输入控制符(推荐)和包含非输入控制符(不推荐)
-
控制符作用:必须使用输入控制符,因为键盘输入的本质是字符,需要转换为对应类型的数据
-
取地址符 :所有输入参数必须是变量的地址,变量名前必须加
& -
解析逻辑:遇到非法字符会停止解析,未读取的字符会留在输入缓冲区中,影响后续输入
-
多变量输入:推荐使用默认空白分隔符,不要使用逗号等非输入控制符
-
绝对禁止 :不要在scanf格式字符串末尾添加
\n -
编程规范:使用scanf前必须用printf输出提示信息,提高程序的用户体验