C语言输入函数对比解析
目录
- C语言输入函数全家福(和它们的秘密)
- fgets
- gets
- scanf
- getchar
- fscanf
- 函数对比表
- 灵魂总结
哈哈,看来你正在和C语言的输入函数们玩“大家来找茬”!放心,我会用最接地气的方式给你讲明白,保证比看《甄嬛传》还精彩。咱们先上结论:fgets
是输入函数界的防弹衣,其他函数可能是皇帝的新装。下面进入正片环节——
C语言输入函数全家福(和它们的秘密)
fgets
fgets
:安全感爆棚的暖男
char *fgets(char *str, int n, FILE *stream);
功能:从文件流(比如键盘stdin
)读取一行,直到换行符或读到n-1
个字符。
优点:
- 自带防溢出护盾:
n
参数强制你声明缓冲区大小,比如char buffer[10]; fgets(buffer, 10, stdin);
最多读9个字符,留1个给\0
。 - 会贴心保留换行符(比如输入"Hello\n",
buffer
里存的是"Hello\n\0"
)。
缺点:
- 像个强迫症患者,如果输入太长,剩下的字符会赖在输入缓冲区里等你下次处理。
- 换行符可能让你想手动
strcspn(buffer, "\n")
把它干掉。
这里插入一个函数介绍
strcspn 函数功能
strcspn
是 C 标准库中的一个字符串处理函数,用于计算字符串中从起始位置开始,直到遇到指定字符集合中的任意一个字符为止的长度。该函数返回的是从字符串开头到第一个匹配字符之间的字符数。
函数原型
size_t strcspn(const char *str, const char *reject);
参数说明
str
:要扫描的字符串。reject
:包含需要匹配的字符集合的字符串。
返回值
返回str
中从开头到第一个出现在reject
中的字符之间的字符数。如果str
中没有任何字符出现在reject
中,则返回str
的长度。
示例代码
#include <stdio.h>
#include <string.h>int main() {const char *str = "Hello, World!";const char *reject = " ,!";size_t len = strcspn(str, reject);printf("Length until first match: %zu\n", len); // 输出: 5return 0;
}
解释
在示例中,strcspn
函数会扫描字符串"Hello, World!"
,直到遇到reject
中的字符,
或!
。由于,
是第一个匹配的字符,函数返回5
,即"Hello"
的长度。
应用场景
strcspn
常用于字符串解析,例如在解析命令行参数或处理用户输入时,可以用来查找特定字符或分隔符的位置。
gets
gets
:已被赐死的危险前任
char *gets(char *str); // C11标准中已移除!
功能:读取一行输入,直到换行符(不保留换行符,换成\0
)。
致命缺点:
- 缓冲区溢出之王:完全不检查输入长度,比如
char buffer[5]; gets(buffer);
,如果你输入"ABCDEFG",直接内存崩溃,黑客最爱。
教训:像过期的泡面——别碰!
scanf
scanf
:傲娇的格式控
int scanf(const char *format, ...);
- 功能:按格式读取输入(比如
%d
,%s
)。 - 坑点集锦:
%s
的暴走模式:scanf("%s", buffer);
遇到空格就罢工,且不检查长度。输入"Hello World"只会读"Hello",剩下的留在缓冲区,还可能溢出。- 输入残留问题:如果
scanf("%d", &num);
之后用fgets
,会吃到之前残留的换行符,导致fgets
秒退。
- 保命技巧:
- 用宽度限制:
scanf("%9s", buffer);
(最多读9字符)。 - 清空缓冲区:
while ((c = getchar()) != '\n' && c != EOF);
(但写起来像跳大神)。
- 用宽度限制:
getchar
getchar
:专注单身的极简主义者
int getchar(void);
- 功能:一次读一个字符。
- 使用场景:
- 手动组装字符串:比如实现低配版
fgets
。 - 清理输入缓冲区的工具人。
- 手动组装字符串:比如实现低配版
- 示例:
int c; while ((c = getchar()) != '\n' && c != EOF) { /* 吞掉所有字符 */ }
fscanf
fscanf
:文件界的scanf
int fscanf(FILE *stream, const char *format, ...);
- 功能:从文件流按格式读取(比如读取文件中的数字)。
- 注意:和
scanf
一样有格式匹配的傲娇属性,但至少不会随便炸内存。
函数对比表
函数 | 安全性 | 换行符处理 | 防溢出 | 适用场景 | 危险指数 |
---|---|---|---|---|---|
fgets | ⭐⭐⭐⭐ | 保留并存储 | ✅ | 读取整行输入 | 安全 |
gets | 💀 | 替换为\0 | ❌ | 已淘汰,禁止使用 | 核弹级 |
scanf | ⭐⭐ | 不处理(残留) | ❌ | 格式化输入(需谨慎) | 地雷 |
getchar | ⭐⭐⭐⭐ | 逐字符处理 | ✅ | 单字符输入或清理缓冲区 | 安全 |
fscanf | ⭐⭐ | 同scanf | ❌ | 从文件读取格式化数据 | 地雷 |
灵魂总结
- 选
fgets
的理由:它像你的老妈,总是担心你吃不饱(缓冲区溢出),所以严格限制你的饭量。 scanf
的悲剧:程序员A:“为什么我的程序崩溃了?” 程序员B:“因为你用了scanf("%s", buffer)
,而用户输入了《战争与和平》全文。”getchar
的哲学:生活就像getchar()
,一次只处理一个字符,急不得。
终极建议:除非你在写一次性脚本,否则对用户输入保持“被害妄想症”,用fgets
+sscanf
组合技(先安全读入整行,再解析),保你平安夜夜好眠!
(程序员深夜画面:盯着屏幕怒吼——“为什么这个fgets
后面有个换行符?!” —— 所以记住,buffer[strcspn(buffer, "\n")] = '\0';
是你的解药)