apue第五章习题

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    

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均会冲洗缓冲区。

你可能感兴趣的:(apue学习笔记)