作者:解学武

C语言gets()被删除了,改用fgets()!

在《C语言的五套标准:C89、C99、C11、C17和C23》一节里提到,作为上世纪 70 年代的产物,C语言历经了多个版本的迭代,增加很多新语法的同时,也剔除了当下认为不再适用的语法,这其中就包括 gets() 函数。

gets() 算得上是 C 语言里“元老级”的输入函数,C语言诞生的时候就有它了。在 C99 标准中,gets() 被标记为“不推荐使用(deprecated)”的函数,甚至在后来的 C11 标准里被正式移除了。

注意,虽然 gets() 函数在 C11 标准中被移除了,但很多 C语言编译器(或者 IDE)仍旧保留着 gets() 函数。

接下来,我将带领读者了解 gets() 被移除的原因,以及 gets() 函数的替代方案。

gets()被移除的原因

gets() 函数从最初的“不推荐使用”到最后被移除,原因其实很简单,就是它不安全!

当 gets() 函数从键盘读取字符时,会一直读,直至遇到换行符'\n'为止,丝毫不关心已经读取到的字符数量。存在的安全隐患是,一旦存储字符串的空间不足,那么字符串里的一部分就会“溢出”到指定空间的外面,非法抢占一块内存空间。如果被抢占的空间里存放着程序运行所需要的重要数据,由于这部分数据被溢出的字符覆盖了,会导致程序运行过程不可控,又或者运行崩溃。

举个简单的例子:
#include <stdio.h>

int main() {
    char buffer[10];  // 定义一个长度为10的字符数组。
    printf("请输入一些字符: ");
    gets(buffer);  // 使用gets函数读取输入
    printf("你输入的内容是: %s\n", buffer);
    return 0;
}
上面代码中,buffer 数组最多存储 10 个字符。如果用户输入的字符数量超过 10 个(比如 "https://xiexuewu.github.io/c/"),gets() 函数依然会将所有字符一股脑塞进 buffer 数组,那么超出长度的字符会覆盖掉 buffer 数组后面内存空间中存放的数据,很可能导致程序运行不可控。

对于这种异常情况,一些 C语言编译器(IDE)会给出警告信息。比如在 VS2022 运行上面的实例,运行结果为:

请输入一些字符: https://xiexuewu.github.io/c/
你输入的内容是: https://xiexuewu.github.io/c/

同时 VS 会提示程序运行异常,如下图所示:

图 VS提示运行异常
图:VS 提示程序执行异常

用fgets()函数替代gets()函数

C14 标准将 gets() 函数彻底移除了,如果想在程序中读取一行字符,除了用 scanf() 函数以外,还可以考虑 fgets() 函数,且更推荐使用后者。

fgets() 函数的使用也非常简单,这里直接将上文实例中的 gets() 改用 fgets() 函数:
#include <stdio.h>

int main() {
    char buffer[10];  // 定义一个长度为10的字符数组。
    printf("请输入一些字符: ");
    fgets(buffer, 10, stdin);  // 使用gets函数读取输入
    printf("你输入的内容是: %s\n", buffer);
    return 0;
}
仔细观察第 6 行中的 fgets() 函数,fgets() 的括号里有三份数据,依次是:
  • buffer:和 gets() 函数一样,要指定一块存储字符串的空间;
  • 10:指定最多读取的字符个数;
  • stdin:指定从哪里读取字符,当它的值设为 stdin 时,表示从键盘读取字符。关于 FILE,会在《C语言文件操作》一章中讲解。

和 gets() 对比不难发现,使用 fgets() 函数时需要指定最多读取的字符个数,这样就有效的避免了“gets()函数无限制读取字符”的安全隐患。

再次运行程序,结果为:

请输入一些字符: https://xiexuewu.github.io/c/
你输入的内容是: https://x

可以看到,fgets() 函数只读取了 9 个字符,最后的位置用来存储‘\0’

总结

从 C99 标准开始,就不再推荐使用 gets() 函数了,当程序中需要读取一行字符时,可以用 fgets() 函数代替 gets() 函数。

值得一提的是,尽管新的 C 语言标准已经移除了 gets() 函数,但很多 C 语言编译器(IDE)仍然保留着 gets() 函数,程序里使用 gets() 函数,大概率也能成功运行!

声明:当前文章为本站“玩转C语言和数据结构”官方原创,由国家机构和地方版权局所签发的权威证书所保护。

添加微信咨询 加站长微信免费领
C语言学习小册
加站长微信免费领C语言学习小册
微信ID:xiexuewu333