fgets比gets更安全,已成为替代选择。1. gets因不进行边界检查,易导致缓冲区溢出,已被c标准移除;2. fgets通过指定最大读取字符数(size-1),有效防止溢出;3. fgets会保留换行符,需手动去除;4. fgets返回buffer指针,失败或eof时返回null,可用于判断读取状态。

fgets和
gets都是 C 语言中用于从标准输入读取字符串的函数,但它们之间存在显著的区别,主要体现在安全性上。
gets函数由于不进行边界检查,容易导致缓冲区溢出,因此已被弃用。
fgets函数则提供了一定的安全性,允许指定读取的最大字符数,从而避免缓冲区溢出。

解决方案

fgets函数从指定的流(通常是标准输入
stdin)读取字符串,直到读取到换行符(
\n),文件结束符(
EOF),或者读取了
size - 1个字符为止。读取到的字符串会包含换行符,并在字符串末尾添加一个空字符
\0。
gets函数则直接从标准输入读取字符串,直到遇到换行符为止,并将换行符替换为空字符
\0。
立即学习“C语言免费学习笔记(深入)”;

由于
gets不进行边界检查,如果输入的字符串长度超过了目标缓冲区的长度,就会发生缓冲区溢出,可能导致程序崩溃或者被恶意利用。
fgets通过指定最大读取字符数,可以有效地防止缓冲区溢出。
fgets 如何避免缓冲区溢出?
fgets函数接受一个
size参数,用于指定读取的最大字符数。它最多读取
size - 1个字符,并在字符串末尾添加一个空字符
\0。这样,即使输入字符串的长度超过了
size - 1,
fgets也只会读取前
size - 1个字符,从而避免了缓冲区溢出。
例如:
#includeint main() { char buffer[10]; printf("请输入字符串:"); fgets(buffer, sizeof(buffer), stdin); printf("你输入的字符串是:%s", buffer); return 0; }
在这个例子中,
fgets函数最多读取 9 个字符,加上一个空字符
\0,总共 10 个字符,正好是
buffer的大小。如果输入的字符串超过 9 个字符,
fgets会截断字符串,保证不会发生缓冲区溢出。
为什么 gets 被弃用,fgets 成为推荐选择?
gets函数最大的问题在于其不安全性。由于它不进行边界检查,如果输入的字符串长度超过了目标缓冲区的长度,就会发生缓冲区溢出。这使得
gets函数成为黑客攻击的目标,他们可以利用缓冲区溢出漏洞来执行恶意代码。
为了解决这个问题,C 标准委员会在 C99 标准中建议不要使用
gets函数,并在 C11 标准中将其完全移除。
fgets函数由于其安全性,成为替代
gets函数的推荐选择。
fgets 的返回值是什么?如何判断读取是否成功?
fgets函数的返回值是指向
buffer的指针,如果读取成功。如果发生错误或者到达文件结束符(
EOF),则返回
NULL。
可以通过检查
fgets的返回值来判断读取是否成功。如果返回值为
NULL,则表示读取失败,需要进行错误处理。
#includeint main() { char buffer[10]; printf("请输入字符串:"); if (fgets(buffer, sizeof(buffer), stdin) == NULL) { printf("读取失败!\n"); return 1; } printf("你输入的字符串是:%s", buffer); return 0; }
如何去除 fgets 读取的字符串中的换行符?
fgets函数会将换行符
\n也读取到字符串中。如果不需要换行符,可以使用以下方法将其去除:
#include#include int main() { char buffer[10]; printf("请输入字符串:"); fgets(buffer, sizeof(buffer), stdin); // 查找换行符并替换为空字符 size_t len = strlen(buffer); if (len > 0 && buffer[len - 1] == '\n') { buffer[len - 1] = '\0'; } printf("你输入的字符串是:%s", buffer); return 0; }
这段代码首先使用
strlen函数获取字符串的长度,然后判断最后一个字符是否为换行符。如果是,则将其替换为空字符
\0。
总而言之,
fgets是一个比
gets更安全、更可靠的函数,应该优先使用
fgets来从标准输入读取字符串。理解
fgets的工作原理和使用方法,可以有效地避免缓冲区溢出,提高程序的安全性。











