C 语言笔记:scanf 函数
1. 基本用法
scanf 是 C 语言标准输入函数,用于从标准输入(通常是键盘)读取数据,并将读取的值存入指定变量。
#include <stdio.h>
int main(void)
{
int a;
scanf("%d", &a);
printf("%d\n", a);
return 0;
}
基本语法:
scanf("格式控制字符串", &变量1, &变量2, ...);
- 格式控制字符串:指定输入数据的类型和读取规则。
&变量:取变量的地址,使scanf能够修改变量的值。- 字符数组等特殊情况不一定需要
&,例如scanf("%s", str)。
2. 常用格式控制符
| 格式控制符 | 对应类型 | 说明 |
|---|---|---|
%d |
int |
读取十进制整数 |
%f |
float * |
读取 float 类型的数 |
%lf |
double * |
读取 double 类型的数 |
%c |
char * |
读取一个字符,包括空格、换行符 |
%s |
char * |
读取字符串,遇到空白字符停止 |
%ld |
long * |
读取 long 类型的整数 |
%lld |
long long * |
读取 long long 类型的整数 |
%u |
unsigned int * |
读取无符号整数 |
注意:scanf 中 %f 对应 float *,而 %lf 对应 double *;这与 printf 输出浮点数时的规则不同。
3. 一次读取多个变量
int a, b, c;
scanf("%d %d %d", &a, &b, &c);
输入:
10 20 30
结果:
a = 10b = 20c = 30
scanf 通常不要求输入必须位于同一行。它会按照格式依次读取数据,并自动跳过整数、浮点数等转换前的空白字符。
例如,以下输入也可以正确读取:
10
20
30
4. scanf 与空白字符
4.1 %d、%f 等会跳过前导空白
例如:
int n;
scanf("%d", &n);
输入:
123
仍然会读取到 123。
4.2 %c 不会自动跳过空白
这是最容易出错的地方。
int n;
char a, b, c;
scanf("%d%c%c%c", &n, &a, &b, &c);
输入:
3 A B C
读取过程:
%d读取整数3。- 第一个
%c读取空格。 - 第二个
%c读取字符A。 - 第三个
%c读取空格。
因此,a、b、c 分别是空格、A、空格。
解决方法一:在格式控制符之间添加空格。
scanf("%d %c %c %c", &n, &a, &b, &c);
格式字符串中的空白字符会匹配并跳过输入中的连续空白,包括空格、换行符和制表符。
解决方法二:在 %c 前添加空格。
scanf("%d %c%c%c", &n, &a, &b, &c);
这里的空格会跳过 3 后面的空白,但后面三个 %c 仍然会连续读取字符,不跳过字符之间的空格。因此,这种写法只适用于你确定字符之间没有空白的情况。
5. %s 与字符串读取
char word[20];
scanf("%19s", word);
%s读取连续的非空白字符。%s会自动在字符串末尾添加'\0'。word是字符数组,因此不需要写&word。%19s限制最多读取 19 个字符,为终止符预留一个位置。
例如,输入:
hello world
第一次读取后,word 保存 "hello",而不是整个 "hello world"。
如果需要读取包含空格的一整行,可以考虑使用 fgets。
6. scanf 的返回值
scanf 返回成功完成赋值的输入项数量。
例如:
int a, b, c;
int result = scanf("%d %d %d", &a, &b, &c);
如果成功读取三个整数,result 为 3。
如果只成功读取两个整数,result 为 2。
如果在任何赋值完成前遇到文件结束,可能返回 EOF。
常见用法:循环读取多组数据
int n, f1, a, b;
while (scanf("%d %d %d %d", &n, &f1, &a, &b) == 4)
{
// 处理一组数据
}
适用于题目没有给出测试组数、要求持续读取到输入结束的情况。
循环条件保证只有成功读取四个整数时才处理这一组数据。
7. 常见错误总结
| 错误 | 原因 | 解决方法 |
|---|---|---|
忘记写 & |
scanf 需要变量地址 |
基本类型变量通常写 &变量 |
%c 读到空格或换行 |
%c 不跳过空白 |
在 %c 前加空格 |
%s 读入字符串时发生越界 |
缓冲区空间不足 | 使用 %Ns 限制读取长度 |
| 忽略返回值 | 输入可能不完整或格式错误 | 检查返回值是否等于预期赋值数量 |
| 误以为按行读取 | scanf 通常按格式读取,而非按行读取 |
根据实际数据格式判断输入逻辑 |
scanf 读取失败后仍继续使用变量 |
变量可能未成功赋值 | 检查返回值后再使用数据 |