C/C++——gets函数族比较

时间:2024-03-11 12:18:15

声明:本文系原创,转载请注明出处。

 


1. 函数原型

1)gets()函数

char * gets ( char * str );

说明:

从 stdin 读入 str 所指向的字符数组,直到发现换行符或出现文件尾。在读入数组的最后一个字符后立即写入空字符。换行符被舍弃,但不会存储于缓冲区中。

注意:

gets() 函数不进行边界检查,从而此函数对缓冲区溢出攻击极度脆弱。无法安全使用它(除非程序运行的环境限定能出现在 stdin 上的内容)。因此gets() 函数在 C99 的第三次勘误中被弃用,而在 C11 标准发布时被移除。推荐的替代品是 fgets() 和 gets_s() 。

绝对不要用 gets() 。

 

2)fgets()函数

char *fgets( char          *str, int count, FILE          *stream );   //(C99 前)
char *fgets( char *restrict str, int count, FILE *restrict stream );   //(C99 起)

说明:

从给定文件流读取最多 count 1 个字符并将它们存储于 str 所指向的字符数组。若文件尾出现或发现换行符则终止分析,后一情况下 str 将包含一个换行符。若无错误发生,则紧随写入到 str 的最后一个字符后写入空字符。

若 count 小于 1 则行为未定义。

 注意:

POSIX 附带要求,若 fgets 遇到异于文件尾条件的失败则设置 errno 。

尽管标准规定在 count==1 的情况有歧义,通常实现不读入字符,存储零于 str[0] ,并报告成功(返回 str )。

 

3)gets_s()函数

char *gets_s( char *str, rsize_t n );

说明:

从 stdin 读取字符直到发现换行符或出现文件尾。至多写入 n-1 个字符到 str 所指向的数组,并始终写入空终止字符(除非 str 是空指针)。若发现换行符,则忽略它并且不将它计入写入缓冲区的字符数。

gets_s()函数在运行时检测下列错误,并调用当前安装的制约处理函数:

    • n 为零
    • n 大于 RSIZE_MAX
    • str 是空指针
    • 在存储 n-1 个字符到缓冲区后没有遇到换行符或文件尾。

在上述异常的任何情况下,gets_s 首先结束读取并忽略来自 stdin 的字符,直到换行符、文件尾条件,或在调用制约处理前的读取错误。

注意:

同所有边界检查函数, gets_s 仅若实现定义了 __STDC_LIB_EXT1__ ,且用户在包含 <stdio.h> 前定义 __STDC_WANT_LIB_EXT1__ 为整数常量 1 才保证可用。

(在我的系统上,gets_s函数不可用,因此推荐总是使用fgets()函数来读取字符串)

 

 


2. fgets()与gets()比较

1)gets()函数示例:

#include <stdio.h>

int main(){
    char str[20];
    printf("input:\n");
    gets(str);
    char ch = getchar();
    printf("\noutput:\n");
    printf("str = %s,getchar() = %c\n",str,ch);
    return 0;
}

输出如下:

 

2)fgets函数示例:

#include <stdio.h>

int main(){
    char str[20];
    printf("input:\n");
    fgets(str,20,stdin);
    char ch = getchar();
    printf("\noutput:\n");
    printf("str = %s,getchar() = %c\n",str,ch);
    return 0;
}

输出如下:

 

3)fgets()和gets()的区别:

  1. fgets()函数的第2个参数指明了读入字符的最大数量。如果该参数的值是n,那么fgets()将读入n-1个字符,或者读到遇到第一个换行符为止;而gets()函数不进行边界检查。
  2. 如果fgets()读到一个换行符,会把它存储在字符串中(即以 "\n\0" 结尾)。这点与gets()不同,gets()会丢弃换行符(即以 \'\0\' 结尾)。
  3. fgets()读入的空字符串存储表示为"\n\0" ,gets()读入的空字符串为"\0" 。
  4. fgets()函数的第三个参数指明要读入的文件。如果读入从键盘输入的数据,则以stdin(标准输入)作为参数,该标识定义在stdio.h中。
  5. 因为fgets()函数把换行符放在字符串的末尾(假设输入行不溢出),通常要与fputs()函数(与puts()类似)配对使用,除非该函数不在字符串末尾添加换行符。fputs()函数的第2个参数指明它要写入的文件,如果要显示在计算机显示器上,应使用stdout(标准输出)作为该参数。 

 

 


参考资料:

  1. https://zh.cppreference.com/w/c/io/gets
  2. https://zh.cppreference.com/w/c/io/fgets
  3. https://www.cnblogs.com/aexin/p/3908003.html
  4. https://blog.csdn.net/hgj125073/article/details/8282883
  5. https://blog.csdn.net/libing403/article/details/73012280