在 C++ 中,scanf()是一个来自 C 标准库 的输入函数,定义在 <cstdio>(或旧式的 <stdio.h>)头文件中。它用于从标准输入(通常是键盘)按照指定的格式读取数据,并存储到变量中。
一、基本语法
int scanf(const char* format, ...);- 返回值:成功读取并赋值的参数个数;如果发生错误或遇到文件结束(EOF),则返回 EOF(通常是 -1)。
- format:格式化字符串,指定了要读取的数据类型和格式。
- ...:可变参数,表示要接收输入数据的变量的地址(通常使用 &取地址符)。
二、常见用法示例
示例 1:读取一个整数
#include <cstdio>int main() { int num; printf("请输入一个整数: "); scanf("%d", &num); // 注意取地址符 & printf("你输入的整数是: %d\n", num); return 0;}示例 2:读取多个不同类型的值
#include <cstdio>int main() { int age; float height; char name[50]; printf("请输入你的姓名、年龄和身高(用空格分隔): "); scanf("%s %d %f", name, &age, &height); printf("姓名: %s\n", name); printf("年龄: %d\n", age); printf("身高: %.2f\n", height); return 0;}⚠️ 注意:
- 对于字符串(如 char name[50]),不需要加 &,因为数组名本身就代表地址。
- 使用 %s时,遇到空白字符(空格、制表符、换行)就会停止读取,所以不适合读取包含空格的字符串。
三、常用的格式说明符(Format Specifiers)
说明符 | 对应类型 | 说明 |
%d | int | 读取十进制整数 |
%i | int | 同 %d,可识别不同进制 |
%u | unsigned int | 无符号十进制整数 |
%f | float | 单精度浮点数 |
%lf | double | 双精度浮点数(注意!) |
%c | char | 读取单个字符 |
%s | char[] | 读取字符串(到空白停止) |
%x | int | 十六进制整数 |
%o | int | 八进制整数 |
⚠️ 对于 double类型,必须使用 %lf,而在 printf中则统一使用 %f(C++ 中 printf也接受 %lf,但标准只要求 %f)。
四、与 C++ 更推荐的输入方式对比
虽然 scanf()在 C++ 中仍然可用,但 C++ 更推荐使用 cin(来自 <iostream>),因为它更安全、更易用,且类型安全。
对比示例:
使用 cin读取输入:
#include <iostream>using namespace std;int main() { int age; float height; string name; // 需要 #include <string> cout << "请输入你的姓名、年龄和身高: "; cin >> name >> age >> height; cout << "姓名: " << name << endl; cout << "年龄: " << age << endl; cout << "身高: " << height << endl; return 0;}优点:
- 不需要手动管理格式字符串;
- 不需要取地址符 &(除了需要引用传递的特殊情况);
- 更加类型安全,不容易出错。
五、注意事项
- 缓冲区问题:
- scanf()不会处理输入缓冲区中的换行符,可能导致后续输入异常。比如在输入数字后跟字符串时容易出错。
- 解决方法:可以用 getchar()清除多余的回车,或者更推荐使用 cin/getline()。
- 安全性:
- scanf()对输入长度没有自动检查,容易导致缓冲区溢出(尤其是 %s读取字符串时)。
- 更安全的替代品是 fgets()或者使用 C++ 的 std::string和 getline()。
- 格式匹配:
- 用户输入必须严格符合格式字符串的要求,否则可能导致读取失败或程序行为异常。
六、总结
特性 | scanf() | cin(C++方式) |
来源 | C 标准库 <cstdio> | C++ 标准库 <iostream> |
类型安全 | ❌ 不安全 | ✅ 类型安全 |
易用性 | 需手动控制格式和地址 | 更直观,自动类型推导 |
缓冲区安全 | ❌ 容易溢出(特别是 %s) | ✅ 更安全,尤其搭配 string |
推荐程度 | 一般用于 C 或特定场景 | ✅ C++ 开发首选 |
七、如果你一定要用scanf(),推荐这样做:
- 对于字符串,使用 %Ns(如 %49s)限制最大输入长度,防止溢出。
- 混合输入时注意清除输入缓冲区。
- 能用 C++ 的 cin/ getline()时优先使用它们。
如你有具体使用场景或遇到问题,欢迎继续提问,我可以给出更针对性的代码示例!
