♂ 一句话理解 scanf
「按照你的‘抓捕模板’(格式字符串),从输入流中精准捕获数据,存入指定变量!」
函数原型
#include <stdio.h>
int scanf(const char *format, ...); // "..." 表示可变参数(必须是变量地址)
入口参数
参数 | 类型 | 比喻解释 |
format | const char* | 「抓捕模板」(含占位符的格式字符串) |
...(可变参数) | 指针类型 | 存放捕获数据的「容器地址」(变量地址) |
返回参数
返回值 | 含义 |
int | 成功捕获的数据项数 |
EOF | 输入结束或错误(如文件结束) |
核心功能图解
输入流:"25 3.14 Hello"
scanf("%d%f%s", &age, &price, name);
→ age=25, price=3.14, name="Hello"
代码实例:数据抓捕实战
场景1:基础捕获(键盘输入)
#include <stdio.h>
int main() {
int age;
float height;
char name[20];
printf("请输入年龄 身高 姓名(如:25 1.75 Alice): ");
// 按顺序捕获数据(注意&符号)
int captured = scanf("%d %f %s", &age, &height, name);
if (captured == 3) {
printf("抓捕成功:%d岁,%.2f米,%s\n", age, height, name);
} else {
printf(" 数据不匹配!只捕获了%d项\n", captured);
}
return 0;
}
场景2:格式化捕获(处理复杂输入)
#include <stdio.h>
int main() {
int year, month, day;
// 输入要求格式:YYYY-MM-DD
printf("请输入日期(格式:YYYY-MM-DD): ");
if (scanf("%d-%d-%d", &year, &month, &day) == 3) {
printf("日期:%04d年%02d月%02d日\n", year, month, day);
} else {
printf(" 格式错误!\n");
}
return 0;
}
魔法失控(常见错误)
1.忘记地址符&
int num;
scanf("%d", num); // 缺少& → 程序崩溃!
2.缓冲区溢出(字符串未限制长度)
char city[10];
scanf("%s", city); // 输入超过9字符 → 内存越界!
// 安全写法:scanf("%9s", city); // 限制最多读取9字符
3.输入残留导致后续读取失败
int a, b;
scanf("%d", &a); // 输入"123\n"
scanf("%d", &b); // 残留的换行符导致直接跳过输入
安全魔法升级(错误处理模板)
#include <stdio.h>
int main() {
int num;
printf("请输入数字:");
while (1) {
int result = scanf("%d", &num);
if (result == 1) {
break; // 捕获成功
} else if (result == EOF) {
printf("输入结束\n");
return 1;
} else {
printf(" 输入的不是数字!请重新输入:");
// 清空错误输入
while (getchar() != '\n'); // 读取并丢弃残留字符
}
}
printf("你输入的是:%d\n", num);
return 0;
}
技术细节剖析
1.占位符与变量的对应关系
占位符 | 变量类型 | 示例 |
%d | int* | int x; scanf("%d", &x); |
%f | float* | float f; scanf("%f", &f); |
%lf | double* | double d; scanf("%lf", &d); |
%s | char[](数组首地址) | char s[10]; scanf("%9s", s); |
%c | char* | char c; scanf(" %c", &c);(注意空格) |
2.空格的神秘力量
- 格式字符串中的空格会跳过任意数量的空白字符(空格、制表符、换行符):
scanf("%d %f", &a, &b); // 输入"25\n3.14"也能正确捕获
3.%c 的特殊性
char c;
scanf(" %c", &c); // 添加空格跳过之前的换行符
魔法咒语速查表(常用占位符)
占位符 | 用途 | 注意事项 |
%d | 十进制整数 | 必须对应 int* |
%u | 无符号整数 | 对应 unsigned int* |
%f | float类型浮点数 | 对应 float* |
%lf | double类型浮点数 | 对应 double* |
%s | 字符串(无空格) | 必须预留空间+限制长度 |
%[] | 自定义字符集合 | 如 %[a-z] 只读取小写字母 |
%% | 匹配百分号字符 | 如 scanf("%d%%", &num) |
总结
- 核心功能:按指定格式从输入流捕获数据
- 必用场景:控制台输入、文件数据解析、格式化输入验证
- 安全准则:
- 永远检查返回值!
- 字符串必须限制长度(如 %10s)
- 优先用 fgets + sscanf 组合处理复杂输入
- 类比记忆:就像特工用解码器破解密文,scanf 是程序员从输入流中精准提取数据的「数据破译器」