题目:用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)
要注意的是:使用这两个函数应该是在打开流之后和使用流之前。
下面给出我实现的代码,看了之后应该也很容易理解:
/* 用setvbuf来实现setbuf */
#include <stdio.h>
#include <stdlib.h> void pr_stdio(const char *, FILE *);
void my_setbuf(FILE *, char *); int main(void)
{
char buf[BUFSIZ];
char filename[BUFSIZ];
FILE *fp; printf("Please input a filename:");
scanf(" %s", filename); if ((fp = fopen(filename, "r")) == NULL) /* 打开文件 */
{
printf("fopen error");
exit();
} pr_stdio(filename, fp); /* 查看是什么缓冲,一般是全缓冲 */ if (fp->_IO_file_flags &_IO_UNBUFFERED ) /* 文件流是无缓冲的,调成有缓冲 */
my_setbuf(fp, buf);
else /* 文件流是有缓冲的,调成无缓冲 */
my_setbuf(fp, NULL); printf("After setbuf...\n");
pr_stdio(filename, fp); /* 关闭了缓冲 */ return ;
} void pr_stdio(const char *pathname, FILE *fp)
{
printf("stream = %s, ", pathname); if (fp->_IO_file_flags & _IO_UNBUFFERED) /* 无缓冲 */
printf("unbuffered\n");
else if (fp->_IO_file_flags & _IO_LINE_BUF) /* 行缓冲 */
printf("line buffered\n");
else /* 全缓冲 */
printf("fully buffered\n");
} void my_setbuf(FILE *fp, char *buf) /* setbuf函数,要么打开,要么关闭,是全缓冲还是行缓冲决定于fp */
{
int fd; fd = fileno(fp); /* 获取文件描述符 */ if (buf == NULL) /* 修改为无缓冲 */
{
setvbuf(fp, buf, _IONBF, BUFSIZ);
return;
} if (fd == || fd == || fd == ) /* 与终端设备相关,应设为行缓冲 */
setvbuf(fp, buf, _IOLBF, BUFSIZ);
else /* 设为全缓冲 */
setvbuf(fp, buf, _IOFBF, BUFSIZ); }
结果如下: