5.1 用setvbuf实现setbuf
void setbuf(FILE *stream, char *buf);
int setvbuf(FILE *stream, char *buf, int mode, size_t size);
当buf为NULL,则为无缓冲,否则为全缓冲。
void my_setbuf(FILE *restrict fp, char *restrict buf)
{
setvbuf(fp, buf, buf? _IOFBF: _IONBF, BUFSIZ);
}
5.2 图5-5中的程序利用每次一行I/O(fgets和fputs函数)复制文件。若将程序中的MAXLINE改为4,当复制的行超过该最大值时会出现什么情况。对此进行解释。
fgets函数读入数据,直到行结束或缓冲区满(当然会留出一个字节存放终止null字节)。同样fputs只负责将缓冲区的内容输出直到遇到null字节,而并不考虑缓冲区是否包含换行符。所以,如果MAXLINE设得很小,这两个函数仍正常工作,只不过缓冲区较大时,函数被执行的次数要多于MAXLINE值设置得较大的时候。
5.3 printf返回0值表示什么
没有输出字符,即printf(“”);
5.4 下面的代码在已写机器上运行正确,而在另一些机器运行时出错,解释问题所在。
#include <stdio.h>
int
main(void)
{
char c;
while ((c = getchar()) != EOF)
putchar(c);
}
这是一个比较常见的错误。getc以及getchar的返回值是int 类型,而不是char类型。由于EOF经常定义为-1,那么如果系统使用的是有符号的字符类型,程序还可以正常工作。但如果使用的是无符号字符类型,那么返回的EOF被保存到字符c后将不再是-1,所以,程序会陷入死循环。
5.5 对标准I/O流如何使用fsync函数?
使用方法,先调用fflush后调用fsync(保证文件系统与缓冲区内容的一致性)。fsync所使用的参数由fileno函数获得。如果不调用fflush,所有的数据仍然在内存缓冲区中,此时调用fsync将没有任何效果。
示例代码:
#include "apue.h"
int fsync_streamaa(FILE *);
int main(void)
{
FILE *fp;
if ((fp = fopen("txt.txt", "w+")) == NULL)
{
perror("fopen error!");
exit(-1);
}
fprintf(fp, "As I lay dying");
fsync_streamaa(fp);
_Exit(0);
}
int fsync_streamaa(FILE *fp)
{
fflush(fp);
return (fsync(fileno(fp)));
}
使用自定义的fsync_streamaa函数之后,可以在fopen的文件中看到写入的内容,而将fflush注释掉时,fopen的文件无内容。
PS:exit与_Exit区别:exit直接使进程停止运行,清除其使用的内存空间,并清除其在内核的各种数据结构;exit 函数则在这些基础上做了一些小动作,在执行退出之前还加了若干道工序。exit() 函数与 _Exit() 函数的最大区别在于exit()函数在调用exit 系统调用前要检查文件的打开情况,把文件缓冲区中的内容写回文件。也就是“清理I/O缓冲”
5.6 在图1-7和图1-10程序中,打印的提示信息没有包含换行符,程序也没有调用fflush函数,请解释输出提示信息的原因是什么?
标准输入和标准输出均为行缓冲方式,fgets每次调用stdin均会冲洗缓冲区。