getchar() - 逐个字符读取
getchar() 的功能非常单一:从标准输入(通常是键盘)中读取一个字符。

(图片来源网络,侵删)
函数原型
int getchar(void);
- 返回值类型是
int,而不是char,这是一个非常重要的细节。- 成功时,返回读取到的字符(这个字符会被提升为
int类型)。 - 如果到达文件末尾(End-of-File, EOF),或者发生读取错误,则返回
EOF。EOF通常是一个宏定义,值为-1,使用int类型可以确保EOF这个特殊值能够被正确返回。
- 成功时,返回读取到的字符(这个字符会被提升为
使用示例
示例 1:读取单个字符
#include <stdio.h>
int main() {
int c; // 必须是 int 类型,而不是 char
printf("请输入一个字符: ");
c = getchar(); // 等待用户输入一个字符并按回车
printf("你输入的字符是: ");
putchar(c); // 使用 putchar 输出字符
printf("\n");
return 0;
}
运行过程:
- 程序运行,打印 "请输入一个字符: "。
- 你在键盘上输入
A,然后按回车。 getchar()读取到字符'A',c的值变为65('A'的 ASCII 码)。- 程序打印 "你输入的字符是: A"。
示例 2:读取一行字符(直到遇到换行符 \n)
#include <stdio.h>
int main() {
int c;
printf("请输入一行文本,按回车结束: \n");
// 循环读取字符,直到遇到换行符 '\n'
while ((c = getchar()) != '\n') {
putchar(c);
}
printf("\n程序结束,\n");
return 0;
}
运行过程:

(图片来源网络,侵删)
- 程序提示输入。
- 你输入
Hello World并按回车。 getchar()会一个一个地读取:'H','e','l','l','o', ,'W','o','r','l','d'。- 当读取到回车符时,
getchar()得到的是换行符'\n',循环条件c != '\n'不再满足,循环结束。 - 程序打印出你输入的内容,然后打印 "程序结束。"。
getchar() 的特点
- 功能:只读取单个字符。
- 输入缓冲区:它会从输入缓冲区中取出一个字符,如果缓冲区为空,它会等待用户输入。
- 回车符的处理:当你在键盘上按回车时,回车符
'\n'也会被作为一个字符存入输入缓冲区,getchar()也能读取到它。 - 主要用途:
- 逐个字符处理输入(过滤掉空格、统计行数等)。
- 读取单个字符的响应(
y/n选择)。 - 清空输入缓冲区(
while(getchar() != '\n');)。
scanf() - 格式化读取
scanf() 是一个功能强大的格式化输入函数,它可以根据你指定的格式,从标准输入中读取数据,并转换成对应类型的变量。
函数原型
int scanf(const char *format, ...);
- 返回值:成功读取并赋值的参数个数,如果读取失败(例如输入类型不匹配),则返回
0,如果遇到文件结尾(EOF),则返回EOF。
常用格式说明符
| 格式说明符 | 含义 | 示例 |
|---|---|---|
%d |
读取一个十进制整数 | int a; scanf("%d", &a); |
%f |
读取一个 float 类型的浮点数 |
float f; scanf("%f", &f); |
%lf |
读取一个 double 类型的浮点数 |
double d; scanf("%lf", &d); |
%c |
读取一个字符 | char c; scanf("%c", &c); |
%s |
读取一个字符串(直到遇到空白字符) | char str[20]; scanf("%s", str); |
%c |
注意:%c 会读取任何字符,包括空格和制表符,而 %s 遇到空格、制表符、换行符就会停止。 |
使用示例
示例 1:读取整数和浮点数
#include <stdio.h>
int main() {
int age;
double height;
printf("请输入你的年龄和身高( 25 1.75): ");
// 返回值 2 表示成功读取了 2 个变量
int result = scanf("%d %lf", &age, &height);
if (result == 2) {
printf("年龄: %d, 身高: %.2f\n", age, height);
} else {
printf("输入格式错误!\n");
}
return 0;
}
运行过程:
- 程序提示输入。
- 你输入
30 1.82并按回车。 scanf成功读取30到age,82到height,result的值为2。- 程序打印 "年龄: 30, 身高: 1.82"。
示例 2:读取字符和字符串

(图片来源网络,侵删)
#include <stdio.h>
#include <string.h> // 用于 strlen
int main() {
char first_initial;
char last_name[50];
printf("请输入你的姓的首字母和姓( S Smith): ");
// 注意 &first_initial,但 last_name 数组名本身就是地址
scanf(" %c %s", &first_initial, last_name);
printf("姓的首字母: %c\n", first_initial);
printf("姓: %s\n", last_name);
printf("姓的长度: %zu\n", strlen(last_name));
return 0;
}
运行过程:
- 程序提示输入。
- 你输入
J Doe并按回车。 scanf读取到'J'赋给first_initial,然后读取到"Doe"赋给last_name,注意,"Doe"之后的空格或换行符会留在缓冲区中。
scanf() 的特点和常见陷阱
-
必须传递变量的地址:
scanf需要知道要把读到的数据存到哪里去,所以除了%s(数组名本身就是地址)之外,其他所有变量前都必须加&(取地址符),这是初学者最容易犯的错误。- 错误:
scanf("%d", num); - 正确:
int num; scanf("%d", &num);
- 错误:
-
输入缓冲区的“幽灵”:这是
scanf最令人头疼的问题。- 场景:当你用
scanf("%d", &a);读取一个整数后,你按下了回车,回车符'\n'会留在输入缓冲区中,如果下一个scanf是scanf("%c", &c);,它会立刻读取到这个残留的'\n',而不会等待你输入新字符。 - 解决方案:
- 在
%c前加一个空格:scanf(" %c", &c);,格式字符串中的空格会告诉scanf跳过所有的空白字符(包括空格、制表符、换行符),直到找到一个非空白字符。 - 清空缓冲区:在混合使用
scanf和getchar时,如果遇到问题,可以用while(getchar() != '\n');来清空缓冲区。
- 在
- 场景:当你用
-
输入与格式不匹配:
scanf期望一个数字,但你却输入了字母,scanf会读取失败,并且错误的输入会留在缓冲区中,导致后续的scanf也全部失败,程序可能进入死循环。- 示例:
int a; printf("请输入一个数字: "); if (scanf("%d", &a) != 1) { printf("输入的不是有效数字!\n"); // 必须清空缓冲区,否则下一次循环还会失败 while(getchar() != '\n'); // 清空缓冲区 }
- 示例:
getchar() vs scanf() 核心区别总结
| 特性 | getchar() |
scanf() |
|---|---|---|
| 功能 | 只读取一个字符 | 按指定格式读取多种类型的数据 |
| 参数 | 无需参数 | 需要格式字符串和变量的地址 |
| 返回值 | 读取到的字符(int类型),或 EOF |
成功赋值的变量个数,或 EOF |
| 灵活性 | 低,功能单一 | 高,非常灵活强大 |
| 输入缓冲区 | 读取缓冲区中的单个字符,包括空格、换行符 | 根据格式说明符来读取和跳过字符 |
| 主要用途 | 逐个字符处理、清空缓冲区、读取单字符响应 | 读取结构化数据(如数字、字符串) |
| 易用性 | 简单,不易出错 | 复杂,容易因缓冲区问题和地址问题而出错 |
何时使用哪个?
-
使用
getchar()的情况:- 你需要逐个字符地处理输入流(实现一个简单的行编辑器)。
- 你只需要读取一个按键(如
y/n确认)。 - 你需要清空
scanf或其他输入函数留下的“垃圾”在输入缓冲区中。
-
使用
scanf()的情况:- 你需要读取明确类型的数据,如整数、浮点数。
- 你需要读取一个单词(以空格分隔的字符串)。
- 输入的数据格式是固定的、结构化的。
一个混合使用的经典陷阱示例
#include <stdio.h>
int main() {
int age;
char name[50];
printf("请输入你的年龄: ");
scanf("%d", &age); // 读取年龄
printf("请输入你的名字: ");
scanf("%s", name); // 读取名字
printf("年龄: %d, 名字: %s\n", age, name);
return 0;
}
如果用户这样输入:
25
Zhang San
会发生什么?
scanf("%d", &age);读取了25。- 回车符
'\n'留在了输入缓冲区。 scanf("%s", name);开始读取,它遇到'\n',认为这是一个分隔符,于是它停止读取,并将空字符串 赋给了name。- 程序输出:
年龄: 25, 名字:(名字为空)。
如何修复?
在读取名字的 scanf 前加一个空格,或者用 getchar 清空缓冲区。
修复方法 1 (推荐):
printf("请输入你的名字: ");
scanf(" %s", name); // 注意 %c 前的空格
这个空格会消耗掉前面留下的换行符,让 scanf 正确等待用户输入 "Zhang San"。
修复方法 2:
printf("请输入你的名字: ");
while(getchar() != '\n'); // 清空缓冲区
scanf("%s", name);
希望这个详细的解释能帮助你彻底理解 getchar() 和 scanf() 的用法和区别!
