《unix环境高级编程》--- 标志I/O库

用getc和putc将标准输入复制到标准输出

#include "apue.h"

int main(void)
{
    int c;

    /*
       int getc(FILE *fp);
       一个读一个字符, 可实现为宏
    */
    while((c = getc(stdin)) != EOF)
    {
        /*
           int putc(int c, FILE *fp);
           一个写一个字符, 可实现为宏
        */
        if(putc(c, stdout) == EOF)
            err_sys("output error");
    }

    /*
          int ferror(FILE *fp);
      用以区分是出错还是到达文件尾端
    */
    if(ferror(stdin))
        err_sys("input error");

    exit(0);
}

这里写图片描述

用fgets和fputs将标准输入复制到标准输出

#include "apue.h"

int main(void)
{
    char buf[MAXLINE];

    /*
       char *fgets(char *restrict buf, int n, FILE *restrict fp);
       直到读到下一个换行符为止,但不超过n-1个字符
       缓冲区以null字符结尾
    */
    while(fgets(buf, MAXLINE, stdin) != NULL)
    {
        /*
          int fputs(const char *restrict str, FILE *restrict fp);
          将一个以null符终止的字符串写到指定的流,尾端的终止符null不写出
        */
        if(fputs(buf, stdout) == EOF)
            err_sys("output error");
    }

    if(ferror(stdin))
        err_sys("input error");

    /* 冲洗任何未写的数据 */
    exit(0);
}

这里写图片描述

使用标准I/O无需考虑缓冲及最佳I/O长度的选择。使用fgets时需要考虑最大行长

对各个标准I/O流打印缓冲状态信息
为三个标准流以及一个与普通文件相关联的流打印有关缓冲的状态信息
在打印缓冲状态信息前,先对每个流执行I/O操作,第一个I/O操作通常为该流分配缓冲

#include "apue.h"

void pr_stdio(const char *, FILE *);

int main(void)
{
    FILE *fp;
    fputs("enter any character\n", stdout);
    if(getchar() == EOF)
        err_sys("getchar error");
    fputs("one line to standard error\n", stderr);

    pr_stdio("stdin", stdin);
    pr_stdio("stdout", stdout);
    pr_stdio("stderr", stderr);

    if((fp = fopen("/etc/motd", "r")) == NULL)
        err_sys("fopen error");
    if(getc(fp) == EOF)
        err_sys("getc error");
    pr_stdio("/etc/motd", fp);
    exit(0);
}

void pr_stdio(const char *name, FILE *fp)
{
    printf("stream = %s, ", name);

    /* The following is nonportable */
    if(fp->_IO_file_flags & _IO_UNBUFFERED)
        printf("unbuffered");
    else if(fp->_IO_file_flags & _IO_LINE_BUF)
        printf("line buffered");
    else 
        printf("fully buffered");
    printf(", buffer size = %d\n", fp->_IO_buf_end - fp->_IO_buf_base);
}

这里写图片描述

tmpnam和tmpfile函数实例

#include "apue.h"

int main(void)
{
    char name[L_tmpnam], line[MAXLINE];
    FILE *fp;

    /*
       char * tmpnam(char *ptr);
       创建临时文件
       产生一个与现有文件名不同的一个有效路径名字符串。
       每次调用时,都产生一个不同的路径名,最多调用次数时TMP_MAX
       若ptr是NULL,则所产生的路径名存放在一个静态区中,
       指向该静态区的指针作为函数值返回。下次再调用时,重写该静态区
       返回:路径名
    */
    printf("%s\n", tmpnam(NULL));  /* first temp name */


    tmpnam(name);  /* second temp name */
    printf("%s\n", name); 

    /*
       FILE *tmpfile(void)
       创建临时二进制文件
       在关闭该文件或进程结束时将自动删除这种文件
       返回:文件指针
    */
    if((fp = tmpfile()) == NULL)  /* create temp file */
        err_sys("tmpfile error");

    fputs("one line of output\n", fp);  /* write to temp file */
    rewind(fp);
    if(fgets(line, sizeof(line), fp) == NULL)
        err_sys("fgets error");
    fputs(line, stdout);  /* print the line we wrote */

    exit(0);
}

这里写图片描述

可先调用tmpnam产生一个唯一的路径名,然后用该路径名创建一个文件,并立即unlink它

#include "apue.h"

int main(int argc, char *argv[])
{
    if(argc != 3)
        err_quit("usage: a.out <directory> <prefix>");

    /*
       char *tempnam(const char *directory, const char *prefix);
       为所产生的路径名指定目录和前缀
       prefix最所包含5个字符
       依次选用以下作为目录:
       1、如定义了环境变量TMPDIR,则用其作为目录
       2、如directory为非NULL,则用其作为目录
       3、<stdio.h>中的字符串P_tmpdir作为目录
       4、将本地目录(通常是/tmp)作为目录
    */
    printf("%s\n", tempnam(argv[1][0] != ' ' ? argv[1] : NULL,
            argv[2][0] != ' ' ? argv[2] : NULL));

    exit(0);
}

这里写图片描述

标准I/O库的不足之处是效率不高,当使用每一行函数fget和fputs是,通常需要复制两次数据:
一次是在内核和标准I/O缓冲之间(当调用read和write时)
第二次时在标准I/O缓冲区和用户程序的行缓冲区之间

猜你喜欢

转载自blog.csdn.net/u012319493/article/details/80369160