APUE第五章学习笔记

/*****************************************
包含头文件:  #include <stdio.h>
                #include <wchar.h>
函数原型:   int fwide(FILE *fp,int mode);
函数说明:   设置流的定向
注: 若mode为正值,则流试图被设置为宽定向,若mode是负值,则流试图被设置为字节定向,若mode为0,不试图设置流的定向
返回值:    若流是宽定向,返回正值,若流字节定向的,返回负值,若流是未定向的,返回0
*****************************************/

/*****************************************
包含头文件:  #include <stdio.h>
函数原型:   void setbuf(FILE * restrict fp,char *restrict buf);
函数说明:   可以使用setbuf打开或关闭缓冲机制
注: 为了带缓冲进行I/O,参数buf必须指向一个长度为BUFSIZ的缓冲区,通常在此之后,该流就是全缓冲的了,但是如果该流与一个终端设备相关,那么某些系统也可将其设置为行缓冲的,为了关闭缓冲,将buf设置为NULL
*****************************************/

/*****************************************
包含头文件:  #include <stdio.h>
函数原型:   int setvbuf(FILE *restrict fp,char restrict buf,int mode,size_t size);
函数说明:   设置流缓冲机制
使用setvbuf,我们可以精确地说明所需的缓冲类型,这是mode参数实现:
                _IOBUF           全缓冲
                _IOLBF            行缓冲
                _IONBF            不带缓冲
注:如果指定一个不带缓冲的流,则buf和size参数会被忽略,如果指定全缓冲或行缓冲,则buf和size可选地指定一个缓冲区及其长度,如果该流是带缓冲的,而buf是NULL,则标准I/O库自动的为该流分配适当长度(BUFSIZ)的缓冲区
返回值:    若成功,返回0,若失败,返回-1
 *****************************************/

/*****************************************
包含头文件:  #include <stdio.h>
函数原型:   int fflush(FILE *fp);
函数说明:   强制冲洗一个流
注:此函数是该流所有未写的数据都传入内核,作为一种特殊情形,若fp是NULL,此函数将导致所有输出流被冲洗
返回值:    若成功,返回0,若失败,返回-1
*****************************************/

/*****************************************
包含头文件:  #include <stdio.h>
函数原型:   FILE* fopen(const char *restrict pathname,const char *restrict type);
函数说明:   打开pathname指定的一个文件
type 取  r rb w wb a ab r+ r+b rb+ w+ w+b wb+
        a+ a+b ab+其中一种
返回值: 若成功,返回文件指针,若失败,返回NULL
*****************************************/

/*****************************************
包含头文件:  #include <stdio.h>
函数原型:   FILE *freopen(const char * restrict pathname,const char *restrict type,FILE *restrict fp);
函数说明:在一个指定的流上打开一个指定的文件,如若该流已经打开,则关闭该流,若流已经定向,则使用
freopen清除该定向,此函数一般用于指定的文件打开为一个预定义的流:标准输入,标准输出,标准错误
返回值:若成功,返回文件指针,若失败,返回NULL
*****************************************/

/*******************************************************
包含头文件:  #include <stdio.h>
函数原型:   FILE* fdopen(int fd,const char* type);
函数说明:取一个已有文件描述符,并使一个标准的I/O
流与该描述符相结合(此函数常用于创建管道和网络通信管道函数返回的描述符);
返回值:    若成功,返回文件指针,若失败,返回NULL
*****************************************/

/**********************************************************
包含头文件:  #include <stdio.h>
函数原型:   int fclose(FILE *fp);
函数说明: 关闭一个打开的流
返回值:若成功,返回0,若失败,返回EOF
************************************************************/

实例:5.1.c

#include <stdio.h>
#include <stdlib.h>
#include <wchar.h>

int main(int argc,char* argv[])
{
    if (argc != 2)
    {
    printf("add <pathname>\n");
    exit(0);
    }

    FILE *fp;
    if ((fp = fopen(argv[1],"r")) == NULL)
    {
    printf("fopen error\n");
    exit(0);
    }

    // 设置全缓冲
    int ret1;
    if ((ret1 = fwide(fp,5)) <= 0)
    {
    printf("fwide error\n");
    exit(0);
    }
    printf("ret1 is %d\n",ret1);
    //get ret-value

    int ret2;
    ret2 = fwide(fp,0);
    printf("ret2 is %d\n",ret2);
}

这里写图片描述

/*****************************************************
包含头文件:  #include <stdio.h>
函数原型:   int getc(FILE *fp);
            int fgetc(FILE *fp);
            int getchar(void)
函数说明: 一次读一个字符
getchar(void)相当于getc(stdin),getc通常被实现为宏,fgetc一定是个函数,所以getc通常速度较快,fgetc可作为函数参数。
注:getc参数不应该为具有副作用的表达式
********************************************************/
/*********************************************************
包含头文件:  #include <stdio.h>
函数原型:   int ferror(FILE *fp);
            int feof(FILE *fp);
函数说明:   ferror:判断流是否出错
            feof: 判断流是否到达文件尾端
返回值:    若条件为真,返回非0,否则,返回0
************************************************************/
/*********************************************************
包含头文件:  #include <stdio.h>
函数原型:   void clearerr(FILE *fp);
函数说明:   清除文件出错和文件结束标志
********************************************************/
/********************************************************
包含头文件:  #include <stdio.h>
函数原型:   int ungetc(int c,FILE *fp);
函数说明:从流中读取数据后,调用ungetc将字符再压送回流中。
注:回送的字符不必是上一次读的字符,不能回送EOF,但是当达到文件尾端时仍可以回送一个字符
(一次成功的ungetc调用会清除该流的文件结束标志)
返回值:若成功,返回c,若出错,返回EOF
*********************************************************/
/******************************************************
包含头文件:  #include <stdio.h>
函数原型:   int putc(int c,FILE *fp);nt 
            int fputc(int c,FILE *fp);
            int putchar(int c);
函数说明:   putchar(int c)相当于putc(int c,stdout)
            putc(int c,FILE *fp)通常为宏调用,fputc
必须为函数
*****************************************************/
/***************************************************
包含头文件:  #include <stdio.h>
函数原型:   char* fgets(char *restrict buf,int n,FILE *restrict fp);
            char* gets(char* buf);
函数说明:   每次输入一行
注:  对于fgets,必须指定缓冲的长度n,函数一直读到下一个换行符为止,但是不超过n-1个字符,读入的字符被送入缓冲区
gets不推荐使用
返回值: 若成功,返回buf,若达到文件尾端或出错,则返回NULL
**************************************************/

/***************************************************
包含头文件:  #include <stdio.h>
函数原型:   int fputs(const char *restrict str,FILE *restrict fp);
            int puts(const char *str);
函数说明:   每次输出一行
注:函数fputs将一个以null字节终止的字符串写到指定的流,尾端的终止符null不写出
返回值:    若成功,返回非负值,若出错,返回EOF
***************************************************/

实例:5.2.c

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int c;
    while ((c = getc(stdin)) != EOF)
    {
    if (putc(c,stdout) == EOF)
    {
        printf("putc error\n");
        exit(0);
    }
    }

    if (ferror(stdin))
    printf("输入错误\n");

    if (feof(stdin))
    printf("输入完毕\n");
    exit(0);
}

运行:

这里写图片描述

5.3.c

#include <stdio.h>
#include <stdlib.h>
#define MAXLINE 4096
int main()
{
    char buf[MAXLINE];

    while (fgets(buf,MAXLINE,stdin) != NULL)
    {
    if (fputs(buf,stdout) == EOF)
    {
        printf("fputs error\n");
        exit(0);
    }
    }

    if (ferror(stdin))
    printf("输入错误\n");

    if (feof(stdin))
    printf("输入完毕\n");
    exit(0);
}

运行:

这里写图片描述

/******************************************************
包含头文件:  #include <stdio.h>
函数原型:   size_t fread(void *restrict ptr,size_t size,
size_t nobj,FILE *fp);
函数说明: 读对象
返回值:    读的对象数
********************************************************/
/********************************************************
包含头文件:  #include <stdio.h>
函数原型: int fwrite(const void *restrict ptr,size_t size,size_t nobj,FILE *restrict fp);
函数说明:   写对象
返回值:    写的对象数
******************************************************/

实例:

5.4.c

#include <stdio.h>
#include <stdlib.h>

struct Person
{
    char* name;
    int age;
};

int main(int argc,char* argv[])
{
    if (argc != 2)
    {
    printf("add <pathname>\n");
    exit(0);
    }

    FILE *fp;

    if ((fp = fopen(argv[1],"r+b")) == NULL)
    {
    printf("fopen error\n");
    exit(0);
    }

    printf("writing\n");

    struct Person p;
    p.name = "Marco";
    p.age = 19;

    if (fwrite(&p,sizeof(struct Person),1,fp) != 1)
    {
    printf("fwrite error\n");
    exit(0);
     }
    //设置eof
    getc(fp);

    if (feof(fp))
    printf("write over\n");
    clearerr(fp);
    fseek(fp,0,SEEK_SET);

    printf("reading\n");
    struct Person m;

    if (fread(&m,sizeof(struct Person),1,fp) != 1)
    {
    printf("fread error\n");
    exit(0);
    }
    //设置eof

    getc(fp);
    if (feof(fp))
    printf("read error\n");
    fclose(fp);
    printf("name is %s\n",m.name);
    printf("age is %d\n",m.age);
    exit(0);
}

运行:

这里写图片描述

/*******************************************************
包含头文件:  #include <stdio.h>
函数原型: long ftell(FILE *fp);
            off_t ftello(FILE *fp);
            int fgetpos(FILE *restrict fp,fpos_t *restrict pos);
函数说明: 确定流的位置
返回值:    若成功ftell 返回当前文件位置,若出错,返回-1L
        若成功,ftello返回当前文件位置,若出错,返回
(off_t) – 1
        fgetpos,若成功,返回0,若出错返回非0
***************************************************/

/********************************************************
包含头文件:  #include <stdio.h>
函数说明:   int     fseek(FILE *fp,long offset,int whence);
            int fseeko(FILE *fp,off_t offset,int whence);
            int fsetpos(FILE *fp,const fpos_t *pos);
函数说明: 设置当前文件位置
返回值:    fseek:若成功,返回0,若出错,返回-1
        fseeko:若成功,返回0,若出错,返回-1
        fsetpos: 若成功,返回0,若出错,返回非0
**********************************************************/
/*********************************************************
包含头文件:  #include <stdio.h>
函数原型:   int fileno(FILE *fp);
函数说明:   获得一个流的文件描述符
返回值:    返回与该流相关的文件描述符
*******************************************************/
/****************************************************
包含头文件:  #include <sdtio.h>
函数原型:   char* tmpnam(char *ptr);
            FILE* tmpfile(void);
函数说明: 创建临时文件
tmpnam:若ptr是NULL,则产生的路径名存放在一个静态区,指向该静态区的指针作为函数值返回,该静态区可能回重写,所以我们应当保存路径名的副本,而不是指针的副本,若ptr不是NULL,则长度至少是L_tmpnam个字符的数组
tmpfile:创建一个临时二进制文件(类型wb+),在关闭和程序结束时自动删除该文件
******************************************************/

tmpnam已弃用
5.5.c

#include <stdio.h>
#include <stdlib.h>

#define MAXLINE 4096

int main()
{
    FILE *fp;
    if ((fp = tmpfile()) == NULL)
    {
    printf("tmpfile error\n");
    exit(0);
    }
    fputs("I'm tmpfile\n",fp);

    rewind(fp);
    char line[MAXLINE];
    if (fgets(line,sizeof(line),fp) == NULL)
    {
    printf("fgets error\n");
    exit(0);
    }

    fputs(line,stdout);
    exit(0);
}

这里写图片描述

/********************************************************
包含头文件:  #include <stdio.h>
函数原型:   char* mkdtemp(char* template);
函数说明:   创建一个目录,该目录拥有唯一的一个名字
返回值:    若成功,返回指向目录名的指针,若出错,返回NULL
***************************************************/

/************************************************
包含头文件:  #include <stdio.h>
函数原型:   int mkstemp(char *template);
函数说明:创建一个拥有唯一名字的文件
返回值:    若成功,返回文件描述符,若出错返回-1
************************************************/
注:template要留XXXXXX(6个X)作占位符

实例:5.6.c

#include <stdio.h>
#include <stdlib.h>

int main()
{
    char filename[] = "/home/marco/tmpfieXXXXXX";

    int fd;
    printf("making file\n");

    if ((fd = mkstemp(filename)) < 0)
    {
    printf("mkstemp error\n");
    exit(0);
    }

    printf("make over\n");
    printf("file name is %s\n",filename);

    printf("making dir\n");
    char dirname[] = "/home/marco/tmpdirXXXXXX";
    char *get;
    if ((get =  mkdtemp(dirname)) == NULL)
    {
    printf("mkdtemp error\n");
    exit(0);
    }

    printf("make over\n");
    printf("dirname is %s\n",get);
    exit(0);
}

运行:

这里写图片描述

/*********************************************************
包含头文件:  #include <stdio.h>
函数原型:   FILE *fmemopen(void *restrict buf,size_t size,const char *restrict type);
函数说明:   创建内存流
注:内存流不适合存储二进制数据(二进制数据在尾端之前可能就有NULL字节)
******************************************************/
/****************************************************
包含头文件:  #include <stdio.h>
函数原型:   FILE *open_memstream(char **bufp,size_t *sizep);
包含头文件:  #include <wchar.h>
函数原型:   FILE *open_wmemstream(char **bufp,size_t *sizep);
函数说明:open_memstream:创建一个面向字节的流
    open_wmemstream: 创建一个面向宽字节的流
这两个函数与fmemopen函数的不同之处在于:
1.创建的流只能写打开
2.不能指定自己的缓冲区,但可以分别通过bufp和sizep参数访问缓冲区地址和大小
3.关闭流需要自行释放缓冲区
4.对流添加字节会增加缓冲区大小
返回值:    若成功,返回流指针,若出错,返回NULL
*******************************************************/

注: 任何时候需要增加流缓冲区中数据量以及调用fclose fflush,fseek,fseeko以及fsetpos时都会在当前位置写入一个null字节
实例:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define BSZ 48

int main()
{
    FILE *fp;
    char buf[BSZ];

    memset(buf,'a',BSZ - 2);
    buf[BSZ - 2] = '\0';
    buf[BSZ - 1] = 'X';

    if ((fp = fmemopen(buf,BSZ,"w+")) == NULL)
    {
    printf("fmemopen error\n");
    exit(0);
    }

    fprintf(fp,"hello, world");
    printf("before fflush: %s\n",buf);

    fflush(fp);
    printf("after fflush %s\n",buf);
    printf("len of string in buf = %ld\n",(long)(strlen(buf)));

    memset(buf,'b',BSZ - 2);
    buf[BSZ - 2] = '\0';
    buf[BSZ - 1] = 'X';

    fprintf(fp,"hello, world");
    fseek(fp,0,SEEK_SET);
    printf("after fseek: %s\n",buf);
    printf("len of string in buf = %ld\n",(long)strlen(buf));

    memset(buf,'c',BSZ - 2);
    buf[BSZ - 2] = '\0';
    buf[BSZ - 1] = 'X';
    fprintf(fp,"hello, world");
    fclose(fp);
    printf("after fclose: %s\n",buf);
    printf("len of string in buf = %ld\n",(long)strlen(buf));
    return 0;
}

这里写图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值