
关于scanf
LeonardoFoxscanf 的「按图索骥」原理
什么是scanf
scanf 是用来记录用户键盘输入的输入
在 scanf("格式字符串", &变量); 中,双引号里的内容就是给电脑下的“死命令”。
scanf有安全性问题
如果必须使用请在头部
#include <stdio.h>前加上#define _CRT_SECURE_NO_WARNINGS 1或者在项目名-右键-属性-C/C++-预处理器加上 _CRT_SECURE_NO_WARNINGS来屏蔽警告(C4996)
1. 核心结论:原样输入原则
除了以 % 开头的占位符(如 %d, %s),你在双引号里写的任何字符,用户在键盘上都必须原封不动地输入,否则匹配就会失败。
- 写了
aaa%d:用户必须输入aaa18,电脑才能把18存到变量去。 - 写了
%d, %d:用户必须在两个数字中间打一个英文逗号。 - 写了
年龄=%d:用户必须输入年龄=18。
结论:双引号里的非占位符就像是“通行证”,打错了或者漏打了,后面的数据电脑就拒收。
案例1
1 | #define _CRT_SECURE_NO_WARNINGS 1 |
2. 为什么 \n 会让程序“卡死”?
这是最特殊的规则。在 scanf 中,空格、回车(\n)、制表符(\t)统称为“空白符”。
逻辑陷阱:当你写
scanf("%d\n", &age);时,\n的意思是“跳过后面所有的空白字符”。死循环现象:你输入数字后敲回车,这个回车被
\n匹配掉了。但电脑不知道后面还有没有更多的空格或回车,它会一直等,直到你输入一个非空白字符(比如随便打个字母或数字)为止。感官体验:你觉得程序卡死了,其实它只是在等你输入一个“带头大哥”来结束空白符的等待。
案例2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
int num;
printf("请输入一个数字(注意:这个 scanf 后面带了 \\n): \n");
// 这里的 \n 会让程序进入“等不到头”的状态
scanf("%d\n", &num);
printf("终于运行到这一行了!你输入的数字是:%d\n", num);
return 0;
}在
scanf的逻辑里,它不觉得\n “循环”,它觉得这是一个“过滤过程”。1. 它是怎么“过滤”的?
当你写了
scanf("%d\n", &a);:- 第 1 步: 你输入数字
10。scanf拿走了它。 - 第 2 步: 你按下回车。
scanf里的\n发现了一个回车,它想:“这是个空白,我要继续往后找,直到看到不是空白的东西。” - 第 3 步: 你又按了 10 次回车,或者打了 100 个空格。
scanf依然想:“这些全是空白,我继续跳过。” - 第 4 步: 你终于打了一个字符
x或者数字5。 - 第 5 步:
scanf眼睛一亮:“终于看到一个‘正经’字符了!” - 第 6 步: 重点来了!它会把这个
x吐回到缓冲区(留给下一个scanf用),然后才觉得自己的任务完成了,程序才会继续往下走。
2. 笔记总结:怎样才能“叫醒”它?
你输入的内容 电脑的反应 能结束吗? 回车 (Enter) 认为是空白符,继续等 不能 空格 (Space) 认为是空白符,继续等 不能 制表符 (Tab) 认为是空白符,继续等 不能 字母 (a, b, c…) 发现非空白,完成匹配 可以 数字 (1, 2, 3…) 发现非空白,完成匹配 可以 符号 (!, @, #…) 发现非空白,完成匹配 可以 3. 给你的“避坑”结论
所以,并不是“输入什么都可以结束”,而是“输入任何不是空格/回车的东西”才能结束。
为什么这很危险?
因为你最后为了结束
scanf而多打的那个字符(比如那个x),并没有消失。它还留在电脑的缓存区里。如果你紧接着下面还有一个scanf要读字符,它会直接读到那个x,导致你的程序再次乱套。- 第 1 步: 你输入数字
3. 避坑指南总结表
| 写法 | 实际意义 | 推荐程度 |
|---|---|---|
scanf("%d", &a); |
只读数字,回车自动触发结束 | ⭐⭐⭐⭐⭐ (最标准) |
scanf("aaa%d", &a); |
必须先打 aaa 才能读数字 |
⭐ (除非特殊格式需求) |
scanf("%d\n", &a); |
读完数字后,必须再打个字符才能继续 | ❌ (千万别写,会卡住,导致内存溢出) |
scanf("%d ", &a); (%d后有空格) |
同上,空格也会导致需要额外输入 | ❌ (容易误触) |
4. 终极记忆口诀
printf 里面随你写,想怎么换行就换行。
scanf 里面要干净,除了百分号啥也别剩。
补充建议:
如果你想让用户知道该输什么,应该把提示文字写在 printf 里,而不是 scanf 里。
❌ 错误写法:
scanf("请输入年龄:%d", &age);(用户得照着打一遍“请输入年龄:”,累死了)✅ 正确写法:
1
2printf("请输入年龄:");
scanf("%d", &age);



