- theMightyDevil's blog
在 C 编写中的常见问题
- 2024-9-18 12:36:14 @
关于 gets 函数
gets
由于具有缓冲区溢出的安全性问题(具体是输入的字符串长度超过传入的字符数组长度),自 C11 标准开始已被移除[1],需要使用 fgets
或者 gets_s
代替。以下是解决方案
使用 fgets
fgets
用于从文件流中读取字符串,其原型如下[2]:
char* fgets(char* restrict str, int count, FILE* restrict stream);
其中 str
为第一个参数,表示目标字符数组;count
为第二个参数,表示字符数组的长度(读取到该长度时读取将会终止);stream
为要读取的文件流,若要从控制台(标准输入流)读取则应当使用 stdin
。
使用 fgets
代替 gets
读取一行字符串至字符数组 str
示例:
gets
:
gets(str);
fgets
:
fgets(str, sizeof(str), stdin);
相关参数可以根据实际情况调整。
使用 gets_s
gets_s
起源于 Microsoft Secure-enhanced CRT,于 C11 正式加入[1:1]。要在除 MSVC 以外的平台上启用必须在代码的开头加入
#define __STDC_WANT_LIB_EXT1__ 1
其原型如下[1:2]:
char* gets_s(char* str, rsize_t n);
其中 str
为第一个参数,表示目标字符数组;count
为第二个参数,表示字符数组的长度(读取到该长度时读取将会终止)。相比 fgets
少了文件流参数。
使用 fgets
代替 gets
读取一行字符串至字符数组 str
示例:
gets
:
gets(str);
gets_s
:
gets_s(str, sizeof(str));
相关参数可以根据实际情况调整。
关于 scanf
scanf
在输入字符串等时与 gets
同样由于具有缓冲区溢出的安全性问题,在 Microsoft Visual C++ 平台上会被要求使用 scanf_s
代替,以下是解决方案
仍然使用 scanf
在代码第一行加入
#define _CRT_SECURE_NO_WARNINGS
即可在 Microsoft Visual C++ 平台上忽略安全性问题并继续
切换到 scanf_s
scanfs_s
亦起源于 Microsoft Secure-enhanced CRT,于 C11 正式加入[3]。要在除 Microsoft Visual C++ 以外的平台上启用必须在代码的开头加入
#define __STDC_WANT_LIB_EXT1__ 1
在使用时若要读取字符或字符串,则需要在相应参数后应附带缓冲区大小。