C语言 不安全的gets()

本文将探究不安全的 gets() 和它的替代品。

一、问题

在 C 语言中,gets() 常被用于读入字符串。它有着能够读取一行字符(包括空格),且简单易用的特点。但它可能因为输入过多而出现越界问题。函数仅仅知道数组位置,而不知道数组的大小,如果输入的字符串过长,会导致缓冲区溢出,即多余的字符放置在数组之外。如果这些多余的字符只是占用了尚未使用的内存,则不会立即出现问题。但如果它们占据了已被使用的内存,并对其进行了擦写,则可能导致出现重大错误。

gets() 对此没有任何解决方法。

C99 标准承认了此函数的问题并建议不要使用该函数, C11 正式从标准中废除了该函数。

二、解决办法

1.scanf

scanf 也可以读取字符串,虽然和 gets() 一样,都可能因为输入过多而出现越界问题。但它可以通过增加修饰符,限定输入量的方法解决,例如:

1
scanf("%(len-1)s", str);

2.fgets()

用于从文件中读取字符串,也可用于从键盘中读取字符(stdin),用法如下:

1
fgets(数组, len, stdin);
  • 读取 len-1 个字符

  • 将会保留换行符,添加’\0’

    例如:

    1
    2
    输入:  a 、 b 、 c 、 回车
    存储: 'a''b''c''\n''\0'
  • 不会清空缓存区,可以继续读入

3.gets_s()

gets_s() 是 C11 新增的可选函数,编译器不一定支持

从标准输入中读取字符串,用法如下:

1
gets_s(数组, len);
  • 读取 len-1 个字符

  • 将会舍弃换行符,添加’\0’

  • 会自动清空缓存区

三、总结

函数 用法 是否安全 清空缓存区 特点
gets() gets(数组) 不安全 全部读入 整行读入,丢弃换行符,添加’\0’
scanf scanf(“%(len-1)s”, 数组) 安全 读入一个单词,添加’\0’
fgets() fgets(数组, len, 文件) 安全 整行读入,保留换行符,添加’\0’,可以从文件读入
gets_s() gets_s(数组, len) 安全 整行读入,丢弃换行符,添加’\0’

参考