在 C 语言中,并没有一个叫做 keyboard 的特定函数或关键字,我们通常使用 标准输入流 来获取来自键盘的输入,这个标准输入流在 C 语言中用 stdin 表示。

(图片来源网络,侵删)
获取键盘输入主要通过以下几个函数,它们都定义在头文件 <stdio.h> 中:
scanf(): 最常用、最灵活的格式化输入函数。getchar(): 用于读取单个字符。gets()/fgets(): 用于读取一行字符串。(注意:gets()已被废弃,不推荐使用)getche()/getch(): 非标准函数,用于读取字符且不回显(常用于游戏开发等场景)。
下面我们逐一详细介绍。
scanf() - 格式化输入
scanf() 是最通用的输入函数,它可以根据你指定的格式(如 %d 代表整数,%s 代表字符串)从 stdin 读取数据。
基本语法
int scanf(const char *format, ...);
format: 一个格式化字符串,告诉scanf()你期望输入什么类型的数据。- 可变参数列表,你需要提供与
format中每个格式说明符相对应的变量地址。
常用格式说明符
| 说明符 | 数据类型 | 示例 |
|---|---|---|
%d 或 %i |
十进制整数 | int age; scanf("%d", &age); |
%f |
单精度浮点数 | float price; scanf("%f", &price); |
%lf |
双精度浮点数 | double pi; scanf("%lf", &pi); |
%c |
单个字符 | char grade; scanf("%c", &grade); |
%s |
字符串(直到遇到空格) | char name[50]; scanf("%s", name); |
%[^\n] |
读取一行(直到遇到换行符) | char line[100]; scanf("%[^\n]", line); |
示例代码
#include <stdio.h>
int main() {
int age;
double height;
char name[50];
printf("请输入您的年龄: ");
scanf("%d", &age); // 注意 &age,需要传入地址
printf("请输入您的身高 (米): ");
scanf("%lf", &height); // 注意是 %lf
// 清除输入缓冲区中的换行符,否则会被下面的 %s 读取
while (getchar() != '\n');
printf("请输入您的姓名: ");
scanf("%s", name); // 注意 name,数组名本身就是地址,不需要 &
printf("\n--- 您的信息 ---\n");
printf("姓名: %s\n", name);
printf("年龄: %d\n", age);
printf("身高: %.2f\n", height); // %.2f 保留两位小数
return 0;
}
运行示例:

(图片来源网络,侵删)
请输入您的年龄: 25
请输入您的身高 (米): 1.78
请输入您的姓名: 张三
--- 您的信息 ---
姓名: 张三
年龄: 25
身高: 1.78
scanf() 的注意事项:
- 地址 (
&): 对于普通变量(如int,char,float),你必须使用取地址符&来传递变量的地址,对于数组(如char name[50]),数组名name已经代表其首地址,所以不需要&。 - 缓冲区问题:
scanf在读取数据时,会留在输入缓冲区中,你用scanf("%d", &age)读取一个整数后,按下的回车符\n会留在缓冲区,如果下一个scanf是%s或%c,它会直接读取这个\n,导致你无法输入预期的内容,上面的代码while (getchar() != '\n');就是为了解决这个问题,它会清空缓冲区直到遇到换行符。 - 空格问题:
scanf("%s", name)遇到空格、Tab或回车就会停止读取,所以它不能读取包含空格的字符串(如 "Zhang San")。
getchar() - 读取单个字符
getchar() 函数从标准输入流中读取一个字符,并返回它的 ASCII 码值,如果到达文件末尾(EOF),则返回 EOF。
基本语法
int getchar(void);
示例代码
#include <stdio.h>
int main() {
char ch;
printf("请按一个键,然后按回车: ");
ch = getchar(); // 等待用户输入一个字符
printf("你按下的键是: ");
putchar(ch); // putchar() 用于输出一个字符
printf("\n");
return 0;
}
gets() 和 fgets() - 读取一行字符串
gets() (已废弃,不推荐使用)
gets() 会读取用户输入的一整行,直到遇到换行符 \n,然后将 \n 替换为字符串结束符 \0。
为什么不推荐使用? 因为它无法指定读取的最大字符数,这会导致缓冲区溢出,如果用户输入的字符超过了数组的大小,程序就会崩溃或产生安全漏洞。

(图片来源网络,侵删)
fgets() (推荐使用)
fgets() 是 gets() 的安全替代品,它允许你指定最大读取的字符数。
基本语法
char *fgets(char *str, int n, FILE *stream);
str: 存储读取内容的字符数组。n: 最多读取n-1个字符,因为第n个位置会留给字符串结束符\0。stream: 从哪个流读取,通常是stdin(标准输入,即键盘)。
示例代码
#include <stdio.h>
int main() {
char name[50];
printf("请输入您的全名: ");
// 最多读取 49 个字符,留 1 个给 '\0'
fgets(name, sizeof(name), stdin);
// fgets 会保留输入时的换行符 \n,我们可以手动去掉它
for (int i = 0; name[i] != '\0'; i++) {
if (name[i] == '\n') {
name[i] = '\0';
break;
}
}
printf("你好, %s!\n", name);
return 0;
}
运行示例:
请输入您的全名: 张三
你好, 张三!
getche() 和 getch() - 无回显输入
这两个函数不是 C 标准库的一部分,而是 Windows 平台下的扩展(在 conio.h 头文件中定义),它们在 Linux/macOS 上通常不可用。
getche(): 读取一个字符,并在屏幕上回显(即你按什么键,屏幕上就显示什么)。getch(): 读取一个字符,不在屏幕上回显。
它们常用于需要隐藏输入的场景,比如输入密码。
示例代码 (仅适用于 Windows)
// 注意:此代码只能在 Windows 上编译运行
#include <stdio.h>
#include <conio.h> // 包含 conio.h
int main() {
char password[20];
int i = 0;
printf("请输入密码: ");
// 使用循环逐个读取字符,直到按下回车
while ((password[i] = getch()) != '\r') { // \r 是回车符
if (password[i] == '\b') { // 处理退格键
if (i > 0) {
i--;
printf("\b \b"); // 光标回退,打印空格,再回退
}
} else {
printf("*"); // 打印星号代替实际字符
i++;
}
}
password[i] = '\0'; // 字符串结束
printf("\n\n你的密码是: %s\n", password);
return 0;
}
总结与选择
| 函数 | 用途 | 特点 | 推荐度 |
|---|---|---|---|
scanf() |
读取格式化数据(整数、浮点数、字符串) | 灵活强大,但容易出错(缓冲区问题) | ⭐⭐⭐⭐ (需谨慎使用) |
getchar() |
读取单个字符 | 简单,但无法直接读取整行 | ⭐⭐⭐ |
fgets() |
读取一行字符串 | 安全,可防止缓冲区溢出 | ⭐⭐⭐⭐⭐ (读取行的首选) |
gets() |
读取一行字符串 | 不安全,极易导致缓冲区溢出 | ⭐ (已废弃,绝对不要用) |
getch()/getche() |
无回显/有回显地读取字符 | 非标准,仅限 Windows,常用于密码输入 | ⭐⭐ (特定场景下使用) |
给初学者的建议:
- 如果只是想读取一个数字或一个单词,用
scanf()。 - 如果想读取一行包含空格的文本(比如姓名、地址),一定要用
fgets()。 - 如果想逐个字符处理输入,用
getchar()。 - 永远不要使用
gets()。
