首页 > 代码库 > 关于fputs和fgets的几个细节

关于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输出的时候并不是根据字符的最后一个‘\0‘来确38      * 定的,而是在这个程序内有个计数器,来计量一共输入了多少个字符,然后再来输出的。39      */40 41     return 0;42 }

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

  

  就比如上面的那个程序!字符数组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的部分,从目标内存中读取字符串,并且忽略掉字符串尾部的‘\0‘。

  

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

  

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

  

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

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

  

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

关于fputs和fgets的几个细节