核心要点
scanf 函数的返回值是一个 整数,它表示 成功匹配并赋值的输入项的个数。

这个返回值非常重要,因为它可以帮助你判断用户输入的数据是否符合你的预期,从而编写出更健壮、更安全的程序。
返回值的几种情况
scanf 的返回值主要有以下三种情况:
成功匹配并赋值
当 scanf 成功从标准输入(通常是键盘)读取到数据,并且这些数据与格式字符串中的格式说明符(如 %d, %f, %s)匹配,并将数据成功赋值给对应的变量时,它会返回一个正整数。
这个正整数的值就是 成功赋值的变量的个数。

示例代码:
#include <stdio.h>
int main() {
int a, b;
printf("请输入两个整数,用空格隔开: ");
// scanf 尝试读取两个整数
int result = scanf("%d %d", &a, &b);
// 打印 scanf 的返回值
printf("scanf 的返回值是: %d\n", result);
if (result == 2) {
printf("成功读取两个整数: a = %d, b = %d\n", a, b);
}
return 0;
}
运行情况:
请输入两个整数,用空格隔开: 10 20
scanf 的返回值是: 2
成功读取两个整数: a = 10, b = 20
在这个例子中,用户输入了两个整数,scanf 成功将它们分别赋值给了 a 和 b,因此返回值为 2。
输入不匹配(失败)
当 scanf 遇到了一个与当前格式说明符不匹配的输入时,它会 立即停止 读取,并返回到目前为止 已经成功赋值的变量的个数。

示例代码:
#include <stdio.h>
int main() {
int a, b;
printf("请输入两个整数,用空格隔开: ");
int result = scanf("%d %d", &a, &b);
printf("scanf 的返回值是: %d\n", result);
if (result == 2) {
printf("成功读取两个整数: a = %d, b = %d\n", a, b);
} else if (result == 1) {
printf("只成功读取了第一个整数: a = %d\n", a);
printf("第二个输入的不是有效的整数,\n");
} else if (result == 0) {
printf("第一个输入就不是有效的整数,\n");
}
return 0;
}
运行情况 1 (第二个输入不匹配):
请输入两个整数,用空格隔开: 10 abc
scanf 的返回值是: 1
只成功读取了第一个整数: a = 10
第二个输入的不是有效的整数。
scanf 成功读取了 10 并赋值给 a(返回值部分 +1),但在尝试读取第二个整数时,遇到了 abc,这不匹配 %d,所以它停止了,最终返回值为 1。
运行情况 2 (第一个输入就不匹配):
请输入两个整数,用空格隔开: abc 20
scanf 的返回值是: 0
第一个输入就不是有效的整数。
scanf 一开始就期望一个整数,但遇到了 abc,完全不匹配,所以它没有给任何变量赋值,立即停止并返回 0。
遇到文件结束符 (EOF)
当 scanf 读取到文件结束符(End-Of-File)时,它会返回 EOF。
EOF 是一个在 <stdio.h> 中定义的宏,通常它的值是 -1。
在交互式程序(从键盘输入)中,你可以通过在 Windows/Linux 命令行中按下 Ctrl+D(在 Windows 的某些终端中是 Ctrl+Z)来发送 EOF 信号。
示例代码:
#include <stdio.h>
int main() {
int number;
printf("请输入整数,按 Ctrl+D (Linux/macOS) 或 Ctrl+Z (Windows) 结束:\n");
// 循环读取,直到遇到 EOF
while (scanf("%d", &number) != EOF) {
printf("你输入的数字是: %d\n", number);
}
printf("\nscanf 遇到了 EOF,程序结束,\n");
return 0;
}
运行情况:
请输入整数,按 Ctrl+D (Linux/macOS) 或 Ctrl+Z (Windows) 结束:
10
你输入的数字是: 10
20
你输入的数字是: 20
^D // 用户按下 Ctrl+D
scanf 遇到了 EOF,程序结束。
在这个循环中,scanf 会一直读取整数,直到它收到一个 EOF 信号。scanf 的返回值变为 EOF(即 -1),循环条件 != EOF 不再满足,循环终止。
最佳实践:使用 scanf 返回值进行输入验证
这是 scanf 返回值最重要的用途。永远不要假设用户的输入是正确的,使用返回值可以防止程序因错误的输入而崩溃或产生不可预期的行为。
一个健壮的整数输入示例:
#include <stdio.h>
#include <stdlib.h> // 用于 exit()
int main() {
int age;
printf("请输入你的年龄: ");
// 循环直到用户输入一个有效的整数
while (1) {
int result = scanf("%d", &age);
if (result == 1) {
// 成功读取一个整数
if (age > 0 && age < 150) { // 可以添加更合理的范围检查
printf("你的年龄是: %d\n", age);
break; // 输入正确,退出循环
} else {
printf("输入的年龄不合理,请重新输入: ");
}
} else if (result == 0) {
// 输入的不是整数,需要清除输入缓冲区中的错误数据
printf("输入无效,请输入一个整数: ");
// 清除输入缓冲区,防止死循环
while (getchar() != '\n'); // 读取并丢弃所有字符,直到遇到换行符
} else if (result == EOF) {
printf("输入被用户终止,\n");
exit(1); // 退出程序
}
}
return 0;
}
代码解析:
while(1)创建一个无限循环,直到我们得到有效输入才break。if (result == 1):说明scanf成功读取了一个整数,但我们还需要检查这个整数是否在合理的范围内(0 < age < 150),如果合理,就break退出循环。else if (result == 0):说明用户输入的不是整数。age变量的值是未定义的,并且错误的输入("abc")还留在输入缓冲区中,如果不处理,下一次scanf会再次读到这个 "abc",导致result再次为0,形成无限循环。while (getchar() != '\n');这行代码至关重要,它从输入缓冲区中一个一个地读取字符,并丢弃它们,直到遇到换行符\n,这样就清除了缓冲区中的无效数据,为下一次scanf的调用做好了准备。
else if (result == EOF):处理用户手动终止输入的情况。
| 情况 | scanf 返回值 |
描述 |
|---|---|---|
| 成功匹配并赋值 | 正整数 (n) | 成功为 n 个变量赋值。 |
| 输入不匹配 | 0 | 第一个输入项就不匹配格式说明符。 |
| 部分匹配 | 0 < n < 格式项总数 | 前 n 个变量赋值成功,第 n+1 个输入项不匹配。 |
| 遇到文件结束符 (EOF) | EOF (通常是 -1) |
输入流已结束,无法继续读取。 |
| 发生读取错误 (从已关闭的文件读取) | EOF (通常是 -1) |
与遇到 EOF 类似,表示读取操作失败。 |
记住这个黄金法则:
始终检查
scanf的返回值,并用它来验证用户输入,以确保程序的健壮性和安全性。
