原文地址:https://www.cnblogs.com/-lyric/p/5118666.html

http://c.biancheng.net/view/379.html

  1. gets——从标准输入接收一串字符,遇到'\n'时结束,但不接收'\n',把 '\n'留存输入缓冲区;把接收的一串字符存储在形式参数指针指向的空间,并在最后自动添加一个'\0'。
  2. getchar——从标准输入接收一个字符返回,多余的字符全部留在输入缓冲区,什么时候结束由程序员自己约定结束符,一般选择\n为结束符,当然也可以是任意其他字符。
  3. fgets——从文件或标准输入接收一串字符,遇到'\n'时结束,把'\n'也作为一个字符接收;把接收的一串字符存储在形式参数指针指向的空间,并在'\n'后再自动添加一个'\0'。
  4. scanf( )函数和gets( )函数都可用于输入字符串,但在功能上有区别。
  • gets可以接收空格。
  • scanf遇到空格、回车和Tab键都会认为输入结束,所有它不能接收空格

简单说:gets是接收一个不以'\n'结尾的字符串,getchar是接收任何一个字符(包括'\n'),fgets是接收一个以'\n'结尾的字符串。

fgets用法:

fgets(buf,sizeof(s),stdin):

fgets(buf, n, file) 函数功能:从 目标文件流 file 中读取 n-1 个字符,放入以 buf 起始地址的内存空间中。

说明:其关键在于在读出n-1个字符之前,如遇到了换行符或EOF,则插入字符串结束标志'\0',读出结束;如果读到n-1时还没遇到换行符或EOF,也会插入字符串结束标志'\0',读出结束。

  1. gets和fgets区别:

每当讨论 gets 函数时,大家不由自主地就会想起 1988 年的“互联网蠕虫”,它在 UNIX 操作系统的 finger 后台程序中使用一个 gets 调用作为它的攻击方式之一。很显然,对蠕虫病毒的实现来说, gets 函数的功劳不可小视。不仅如此,GCC 也不推荐使用gets和puts函数。
我们知道,对于 gets 函数,它的任务是从 stdin 流中读取字符串,直至接收到换行符或 EOF 时停止,并将读取的结果存放在 buffer 指针所指向的字符数组中。这里需要注意的是,换行符不作为读取串的内容,读取的换行符被转换为 null('\0') 值,并由此来结束字符串。即换行符会被丢弃,然后在末尾添加 null('\0') 字符。其函数的原型如下:

  1. char* gets(char* buffer);

如果读入成功,则返回与参数 buffer 相同的指针;如果读入过程中遇到 EOF 或发生错误,返回 NULL 指针。因此,在遇到返回值为 NULL 的情况,要用 ferror 或 feof 函数检查是发生错误还是遇到 EOF。

函数 gets 可以无限读取,不会判断上限,所以程序员应该确保 buffer 的空间足够大,以便在执行读操作时不发生溢出。也就是说,gets 函数并不检查缓冲区 buffer 的空间大小,事实上它也无法检查缓冲区的空间。

如果函数的调用者提供了一个指向堆栈的指针,并且 gets 函数读入的字符数量超过了缓冲区的空间(即发生溢出),gets 函数会将多出来的字符继续写入堆栈中,这样就覆盖了堆栈中原来的内容,破坏一个或多个不相关变量的值。如下面的示例代码所示:

  1. int main(void)
  2. {
  3. char buffer[11];
  4. gets(buffer);
  5. printf("输出: %s\n",buffer);
  6. return 0;
  7. }

示例代码的运行结果为:
aaa
输出: aaa

根据运行结果,当用户在键盘上输入的字符个数大于缓冲区 buffer 的最大界限时,gets 函数也不会对其进行任何检查,因此我们可以将恶意代码多出来的数据写入堆栈。由此可见,gets 函数是极其不安全的,可能成为病毒的入口,因为 gets 函数没有限制输入的字符串长度。所以我们应该使用 fgets 函数来替换 gets 函数,实际上这也是大多程序员所推荐的做法。

相对于 gets 函数,fgets 函数最大的改进就是能够读取指定大小的数据,从而避免 gets 函数从 stdin 接收字符串而不检查它所复制的缓冲区空间大小导致的缓存溢出问题。当然,fgets 函数主要是为文件 I/O 而设计的(注意,不能用 fgets 函数读取二进制文件,因为 fgets 函数会把二进制文件当成文本文件来处理,这势必会产生乱码等不必要的麻烦)。其中,fgets 函数的原型如下:

  1. char *fgets(char *buf, int bufsize, FILE *stream);

该函数的第二个参数 bufsize 用来指示最大读入字符数。如果这个参数值为 n,那么 fgets 函数就会读取最多 n-1 个字符或者读完一个换行符为止,在这两者之中,最先满足的那个条件用于结束输入。

与 gets 函数不同的是,如果 fgets 函数读到换行符,就会把它存储到字符串中,而不是像 gets 函数那样丢弃它。即给定参数 n,fgets 函数只能读取 n-1 个字符(包括换行符)。如果有一行超过 n-1 个字符,那么 fgets 函数将返回一个不完整的行(只读取该行的前 n-1 个字符)。但是,缓冲区总是以 null('\0') 字符结尾,对 fgets 函数的下一次调用会继续读取该行。

也就是说,每次调用时,fgets 函数都会把缓冲区的最后一个字符设为 null('\0'),这意味着最后一个字符不能用来存放需要的数据。所以如果某一行含有 size 个字符(包括换行符),要想把这行读入缓冲区,要把参数 n 设为 size+1,即多留一个位置存储 null('\0')。

最后,它还需要第 3 个参数来说明读取哪个文件。如果是从键盘上读入数据,可以使用 stdin 作为该参数,如下面的代码所示:

  1. int main(void)
  2. {
  3. char buffer[11];
  4. fgets(buffer,11,stdin);
  5. printf("输出: %s\n",buffer);
  6. return 0;
  7. }

对于上面的示例代码,如果输入的字符串小于或等于 10 个字符,那么程序将完整地输出结果;如果输入的字符串大于 10 个字符,那么程序将截断输入的字符串,最后只输出前 10 个字符。示例代码运行结果为:

aaaaaaaaaaaaaaaa
输出: aaaaaaaaaa

除此之外,C99 还提供了 fgets 函数的宽字符版本 fgetws 函数,其函数的一般原型如下面的代码所示:

wchar_t *fgetws(wchar_t * restrict s, int n, FILE * restrict stream);

该函数的功能与 fgets 函数一样。

②一个问答题:

ASK

如果定义了两个字符数组a[10]  b[10]
然后连续用两个
fgets(a,11,stdin);
fgets(b,11,stdin);
然后用两个puts依次打印出两个字符数组的内容.
如果第一次输入的时候超过了10个字符(其中没有按回车键).
那么在第一次回车后会显示两个字符串的内容,第一次输入的多于10个的字符保存到了第二个字符数组中。
请问这是为什么?fgets不是行缓冲输入吗?
具体例子如下:
#include"stdio.h"
#include"string.h"
void main()
{
char str1[10];
char str2[10];
fgets(str1,11,stdin);
fgets(str2,11,stdin);---------------------------------------------fgets的用法,第一个参数为数组,第二个为数组的大小,第三个网上是这么说的//stdin是标准输入(也就是键盘输入),C标准库里面的一个全局变量
stdin也是FILE*类型的,因此在使用FILE*类型作为参数的地方,可以使用stdin//。。。。。。。
printf("%s\n%s\n",str1,str2);
printf("%c\n",str2[0]);
}

输入asdfasdfasdf123

回车后直接输出两组字符串
asdfasdfas
df123

ANSWER

字符串超长,fgets读了size-1个字符还没有读到'\n',就把已经读到的size-1个字符和一个'\0'字符存入字符数组,剩下的字符可以在下次调用fgets时继续读。
输入asdfasdfasdf123,第一次fgets只取走了前10个字符,余下的df123被下一次fgets取走了。
另外,还有两点:
1)包含的是系统头文件,建议用如下形式:
   #include <stdio.h>
   #include <string.h>
2)你这里fgets中size指定为11,而定义字符数组时,大小却为10,这样会溢出的。 你这里运行没问题是因为字符数组的数组名作参数时被自动转换为字符指针了。

c语言中gets 、getchar 、fgets 、scanf的用法相关推荐

  1. c语言putchar与getchar,C语言中的getchar和putchar详解

    首先给出<The_C_Programming_Language>这本书中的例子: #include int main() { int c; c = getchar(); while (c  ...

  2. putchar(c1)在C语言中表示,C语言中的getchar和putchar详解

    一.首先给出<The_C_Programming_Language>这本书中的例子: #include int main( ) { int c; c = getchar(); while ...

  3. c语言s_gets函数作用,C语言中gets_s(),gets(),fgets()函数的比较。

    先来讲讲大家最熟悉的gets()函数. 1.gets()函数不安全. 2.C11标准委员会已经将其废除,建议能不用尽量不用. 解释: gets()函数的作用:它读取整行输入,直至遇到换行符,然后丢弃换 ...

  4. C语言中gets_s(),gets(),fgets()函数的比较。

    先来讲讲大家最熟悉的gets()函数. 1.gets()函数不安全. 2.C11标准委员会已经将其废除,建议能不用尽量不用. 解释: gets()函数的作用:它读取整行输入,直至遇到换行符,然后丢弃换 ...

  5. c语言switch case缩进,C语言中的switchnbsp;casenbsp;语句的用法详解

    本文就几个实例来说明Switch case 语句的用法. 说是C语言中的Switch case,其实和html+javascript中的Switch case语法是基本一样的哦. 问题: 有这么一个C ...

  6. C语言中#define中的一些特殊用法

    转载自:http://blog.sina.com.cn/s/blog_4a4365030100edq7.html define是C语言中的预处理命令,它用于宏定义,可以提高源代码的可读性,为编程提供方 ...

  7. C语言中malloc函数及free函数用法(定义动态数组及释放)

    一.关于静态数组.动态数组 二.malloc()和free()的基本概念以及基本用法 1.函数定义 2.函数用法 3.关于函数使用注意事项 三.malloc()函数分配内存空间的由来 四.malloc ...

  8. perl语言中qq, qw等关键字的用法总结

    PERL 语言中的q,qw,qr,qx,qq......符号用法总结 在perl语言中,有两个特殊而常用的符号qq qw,分别解释如下: qq{foobar}的意思为意思为双引号字符串,可内插变量 相 ...

  9. c语言中gets与fgets,gets和fgets函数及其区别,C语言gets和fgets函数详解

    每当讨论 gets 函数时,大家不由自主地就会想起 1988 年的"互联网蠕虫",它在 UNIX 操作系统的 finger 后台程序中使用一个 gets 调用作为它的攻击方式之一. ...

  10. C语言中fgetc()、fgets()之间的区别

    在学习文件那一快关于读写文件中的字符让我折腾了一阵子,总是把这几个函数混淆,今天有时间就整理下,并分享下个人的心得,希望对大家有帮助. 1.fgetc() 和 fgets() 之间的区别 fgetc ...

最新文章

  1. 测试发现equals和hashCode与书上描述的不一样
  2. [实变函数]4.2 Egrov 定理
  3. wxWidgets:wxMediaEvent类用法
  4. python作业题目用户输入行数、输出倒的等腰三角形_智慧职教云课堂APPPython程序设计(常州工业职业技术学院)作业期末考试答案...
  5. Flink流处理练习
  6. 手动实现 NSTabViewController 的 Rect Transition 及 Propagate Title-b
  7. jquery 文档就绪
  8. 深度学习 检测异常_深度学习用于异常检测:全面调查
  9. Docker数据管理
  10. 海森(hessian)矩阵
  11. 调用Python的PyAutoGUI模块模拟登录QQ邮箱
  12. 【Zynq UltraScale+ MPSoC解密学习7】Zynq UltraScale+的PMU
  13. 为什么要分库分表?一个业务场景来理顺它!
  14. aix系统挂载nas
  15. Boll布林带突破策略
  16. python数学建模--时间序列模型--指数平滑
  17. 你离心想事成只差一个计划 | 进击
  18. mysql 连续七天不登录_使用MySQL窗口函数巧妙的解决用户连续登录天数等问题
  19. r语言 python 股票_R语言:抓取股票数据并存入数据库进行分析实例 MySQL
  20. 转载linux图形界面编程基本知识(X11, xorg, gdm/gnome)

热门文章

  1. 重装系统win11服务器未响应怎么修复操作
  2. static, const, static const 与 const static
  3. 如何在桥接模式下使用Eero保持路由器的高级功能
  4. HTML和web窗体的区别(转载)
  5. 云计算、社交网络和移动互联网
  6. linux arm fpu初始化,如何确定Linux主板是否使用硬件FPU?
  7. 安装win10出现“计算机意外的重新启动或遇到错误。Windows安装无法继续。若要安装Windows,请单击“确定”重新启动计算机,然后安装系统。”
  8. autocad2014点击保存闪退_AutoCAD2014闪退的具体原因和解决方法介绍
  9. python request.get
  10. getRequestURI()与getRequestURL()