题目:用setvbuf实现setbuf。
这两个函数都是改变流的缓冲模式的。函数原型如下:
#include <stdio.h>
void setbuf(FILE *fp, char *buf);
void setvbuf(FILE *fp, char *buf, int mode, size_t size);
毫无疑问,setvbuf是setbuf的升级版。下面我们再看看这两个函数是怎么工作的:
setbuf只能决定打开或者关闭缓冲(设buf为NULL则关闭),而是行缓冲还是全缓冲则决定与fp是否与终端设备相关。
setvbuf则更加详细,可以自由选择缓冲类型而缓冲区的大小(图上合适长度的系统缓冲区则就是本身就有定义的BUFSIZ)
要注意的是:使用这两个函数应该是在打开流之后和使用流之前。
下面给出我实现的代码,看了之后应该也很容易理解:
1 /* 用setvbuf来实现setbuf */ 2 #include <stdio.h> 3 #include <stdlib.h> 4 5 void pr_stdio(const char *, FILE *); 6 void my_setbuf(FILE *, char *); 7 8 int main(void) 9 { 10 char buf[BUFSIZ]; 11 char filename[BUFSIZ]; 12 FILE *fp; 13 14 printf("Please input a filename:"); 15 scanf(" %s", filename); 16 17 if ((fp = fopen(filename, "r")) == NULL) /* 打开文件 */ 18 { 19 printf("fopen error"); 20 exit(1); 21 } 22 23 pr_stdio(filename, fp); /* 查看是什么缓冲,一般是全缓冲 */ 24 25 if (fp->_IO_file_flags &_IO_UNBUFFERED ) /* 文件流是无缓冲的,调成有缓冲 */ 26 my_setbuf(fp, buf); 27 else /* 文件流是有缓冲的,调成无缓冲 */ 28 my_setbuf(fp, NULL); 29 30 printf("After setbuf... "); 31 pr_stdio(filename, fp); /* 关闭了缓冲 */ 32 33 return 0; 34 } 35 36 void pr_stdio(const char *pathname, FILE *fp) 37 { 38 printf("stream = %s, ", pathname); 39 40 if (fp->_IO_file_flags & _IO_UNBUFFERED) /* 无缓冲 */ 41 printf("unbuffered "); 42 else if (fp->_IO_file_flags & _IO_LINE_BUF) /* 行缓冲 */ 43 printf("line buffered "); 44 else /* 全缓冲 */ 45 printf("fully buffered "); 46 } 47 48 void my_setbuf(FILE *fp, char *buf) /* setbuf函数,要么打开,要么关闭,是全缓冲还是行缓冲决定于fp */ 49 { 50 int fd; 51 52 fd = fileno(fp); /* 获取文件描述符 */ 53 54 if (buf == NULL) /* 修改为无缓冲 */ 55 { 56 setvbuf(fp, buf, _IONBF, BUFSIZ); 57 return; 58 } 59 60 if (fd == 0 || fd == 1 || fd == 2) /* 与终端设备相关,应设为行缓冲 */ 61 setvbuf(fp, buf, _IOLBF, BUFSIZ); 62 else /* 设为全缓冲 */ 63 setvbuf(fp, buf, _IOFBF, BUFSIZ); 64 65 }
结果如下: