关于fputs和fgets的几个细节

  C语言中两个标准IO fputs和fgets都是针对行来进行数据的读取的!这里关于这两个IO函数我有几个小细节想在这里和大家分享一下,希望能够对大家产生帮助!

  首先贴上这两个函数的函数声明,下面以这两个函数声明为基础进行讨论:

  

  

  我用于调试的代码如下:

 1 /* 本程序的输入为nihaoa,然后通过gdb调试来查看fputs的缓冲区内的内容
 2  */
 3 #include<stdio.h>
 4 #include<string.h>
 5 #include<stdlib.h>
 6 #include<errno.h>
 7 
 8 #define MAXLINE 4
 9 
10 int main(int argc,char *argv[])
11 {
12     char buffer[MAXLINE];
13     memset(buffer,1,MAXLINE);
14     char buffer_o[BUFSIZ];
15     memset(buffer_o,1,BUFSIZ);
16 
17     setbuf(stdout,buffer_o);
18 
19     while(NULL != fgets(buffer,MAXLINE,stdin))
20     {
21     if(EOF == fputs(buffer,stdout))
22     {
23         printf("[fputs]: %s",strerror(errno));
24         exit(EXIT_FAILURE);
25     }
26     }
27 
28     if(ferror(stdin))    //检查上面循环停止是否是因为出错
29     {
30     printf("[fgets]: %s",strerror(errno));
31     exit(EXIT_FAILURE);
32     }
33 
34     buffer_o[6] = 'k';    
35     buffer_o[7] = 'j';
36     /*  这里我把fputs的缓冲区的内容调整了一下,最后一个换行字符变成了k,换行字符的后一个变成了j,但是fputs输
37      * 出的时候还是输出了到k的内容,后面那个j并没有输出。所以fputs输出的时候并不是根据字符的最后一个''来确
38      * 定的,而是在这个程序内有个计数器,来计量一共输入了多少个字符,然后再来输出的。
39      */
40 
41     return 0;
42 }

  首先说第一个问题,fgets每回从其缓冲区内读的数据的长度为SIZE-1个字节,然后它会自动在字符串末尾添加一个''符号!而fgets将字符串存入其缓冲区的时候,会自动忽略末尾的''符号!如下图所示:

  

  就比如上面的那个程序!字符数组buffer用来充当这个程序的缓冲区!而那个buffer_o我通过setbuf函数来让它变成了标准输出的缓冲区!为了便于区分,我把这两个数组的数据初始化全部设置为1.

  举个例子,比如我在上面那个程序的19行和21行设置两个个断点!然后运行查看buffer的内存!

  首先是第19行的,此时buffer的内存全部都是1:

  

        然后运行一句,我输入的数据是nihaoa<CR>,由于buffer的内容不够大,所有它只会读size-1也就是3个字节的内容,最后一个字节填充为0,如下图所示:

  

  上面这个就说明了关于fgets的内容,它只从它的缓冲区中读取size-1个字节,然后在字符串的尾部加上一个0;

  接下来我们接着调试,继续来向下运行一步,其结果如下图所示:

  

  这里这个buffer_o是stdout的缓冲区,此时它里面只有3个字节的内容,这正好说明了关于fputs的部分,从目标内存中读取字符串,并且忽略掉字符串尾部的''。

  

  接着我们再来说第二个问题,那就是fputs程序内部应该有一个计数器,用来统计stdout的缓冲区中一共有多少个字符,fputs输出的时候就是根据这个计数器来输出!我们还是以上面那段代码为例,这回我们在34行和40行设置一个断点。再来看buffer_o这片内存中的内容!如下图所示:

  

  这回我的输入还是nihaoa<CR>,这回stdout的缓冲区中放的内容就是nihaoa<CR>的ASCII码了!然后我把那个回车和回车的下一个的ASCII码改一下,如下图所示:

  

  回车字符变成了k,它的下一个变成了j。然后我们再来查看输出的结果!

  由于gdb自动添加了一个换行符,所以我就以普通方式运行查看了!如下图所示:

  

  最后的输入是nihaoak,并没有多,这里就说明fgets的输出是根据它的那个计数器来的!

原文地址:https://www.cnblogs.com/bwangel23/p/4169004.html