zoukankan      html  css  js  c++  java
  • APUE学习笔记——5.5~5.7数据流的打开与读写

    1.open

    1. #include <stdio.h>
    2. FILE *fopen(const char *restrict pathname,const char *restrict type)
    3. FILE *freopen(const char *restrict pathname,const char *restrict type,FILE *restrict fp);
    4. FILE *fdopen(int fd,const char *type);
    5. --All three return: file pointer if OK,NULLon error
        fopen:用于打开一个特定的文件
        freopen:在特定的流上打开特定的文件,主要用于实现重定向功能。如果流已经被打开,则先关闭它,如果流已经被含有定向设置,则清除它,重新进行设置。经常用在标准输入流、标准输出流、标准错误流的操作。(eg:标准输出重定向到一个文件)
        fdopen:使打开的文件描述符与标准I/O流向结合。这里的文件描述符可能来自open、dup、dup2、pipe、fcntl等。很多文件只能由网络通信或者创建管道获得的文件描述符,无法直接使用fopen函数。这些特殊的文件打开后就需要与标准I/O流向结合,因此需要fdopen函数。
        关于type的取值如Figure5.2所示

    example:

    关于freopen
    1. #include<stdio.h>
    2. int
    3. main()
    4. {
    5. /*redirect standard output to file test.out*/
    6. if(freopen("./test.out","w",stdout)==NULL)
    7. fprintf(stderr,"errorredirectingstdout ");
    8. /*this output will go to a file test.out*/
    9. printf("Hello World ");
    10. /*close the standard output stream*/
    11. fclose(stdout);
    12. return 0;
    13. }
    printf函数的输出   Hello World会被重定向到test.out中,而不是直接在终端显示。
    关于fdopen
    1. #include<stdio.h>
    2. int
    3. main()
    4. {
    5. FILE *fp = fdopen(0,"w+");
    6. fprintf(fp,"%s ", "Hello world!");
    7. fp =fdopen(1,"w+");
    8. fprintf(fp,"%s ","Hello world!");
    9. fclose(fp);
    10. }
    输出 
            Hello world!
            Hello world!
    首先将标准输入流与标准I/O流的"w+"结合,这样就可以用fprintf对标准输入流写入数据Hello world!
    然后将标准输出流与标准I/O流的"w+"结合,这样就可以用fprintf对标准输出流写入数据Hello world!(在此之前,标准输入流的数据Hello world会被先刷新输出。)   

    2.read and write

        非格式化的数据读写操作可以分为三种类型(这里的非格式化是针对scanf和printf系这样的格式化读写而言)
        ~一次一个字符
        ~一次一行字符
        ~直接I/O:
    Input function:
    1. #include <stdio.h>
    2. int getc(FILE *fp);
    3. int fgetc(FILE *fp);
    4. int getchar(void);
    5. All three return: next character if OK,EOFon end of file or error
            getchar()相当于fp为标准输入的getc,也就是getc()(stdin)
            getc和fgetc的区别在于fgetc()一定是一个函数,而getc()则一般被实现为一个宏,也就是说getc的定义可能是这样的:
    1. #define getc(_fp) _IO_getc (_fp)
            因为getc是一个宏,那么我们就不能使用带副作用的表达式作为它的参数,比如++i。设想如果我们使用++i作为参数,结果将如何。编译器会把函数中所有的_fp替换成++i,这样++i在函数中就可能被调用多次,也就是发生了多次的自加,结果显然不是我们需要的。
            宏的优点在于效率,函数调用需要花费时间。

        这三个函数在返回下一个字符时,都会将它从unsigned char 转化为 int。之所以制定为unsigned 是为了防止在高位为1时变成负数。

    输入判断
    1. #include <stdio.h>
    2. int ferror(FILE *fp);
    3. int feof(FILE *fp);
    4. Both return: nonzero(true) if condition is true, 0 (false) otherwise
    5. void clearerr(FILE *fp);
            一般来说,每个流都包含两个标志:
            •Anerror flag
            •Anend-of-file flag
            调用clearerr可以将他们清除
    1. #include <stdio.h>
    2. int ungetc(intc,FILE *fp);
    3. Returns:cif OK,EOFon error
            从流中读取数据后,ungetc可以将char再push back回去
            ungetc将一个字节退回输入流,如果该字节没有被读出来,则不能再将其它字节pushback到输入流中。

    Output function
        
    1. #include <stdio.h>
    2. int putc(intc,FILE *fp);
    3. int fputc(intc,FILE *fp);
    4. int putchar(intc);
    5. All three return:cif OK,EOFon error
    关键点与Input function类似。

    行缓冲 Line-at-a-Time I/O

    Input
    1. #include <stdio.h>
    2. char *fgets(char *restrict buf,int n,FILE *restrict fp);
    3. char *gets(char *buf);
    4. Both return:buf if OK,NULL on end of file or error
            fgets表示从流fp中读取n字节数据到buf中。buf中的最后一个字符为null。在读数据的时候,换行符也会被读入。因此,fgets读取的数据应该<=n-1.(包括换行符)。     也就是我们如果在输入流中输入Hello然后回车结束,且n不小于7,那么buf中的数据就是
    “Hello”+回车符+空字符。
            gets()不应该被使用。因为他没有指明buf的上限,因此可以无限读取。程序员需要确保buffer足够大,以便执行读操作是不会溢出。如果数据超过buffer的大小,那么就会有数据被覆盖,导致读取的数据出错。因此,gets()函数仅供娱乐。
            当输入的line比n-1大时,那么只有n-1个字符被读取,其它的字符等待其它fgets读:
    example:
    1. #include<stdio.h>
    2. #define BUFFSIZE 4096
    3. int
    4. main()
    5. {
    6. char buf[BUFFSIZE];
    7. fgets(buf,5,stdin);
    8. puts(buf);
    9. fgets(buf,10,stdin);
    10. puts(buf);
    11. return 0;
    12. }
    13. ~
    运行结果:

    windeal@ubuntu:~/Windeal/apue$ ./exe 
    Hello world!
    Hell
    o world!

    Output
    1. #include <stdio.h>
    2. int fputs(const char *restrict str,FILE *restrict fp);
    3. int puts(const char *str);
    4. Both return: non-negative value if OK,EOFon error
       fputs就是输出str中的字符。
        puts()虽然不会像gets那么不安全,但是一般也不使用,因为它会在字节流后加入换行符,给我们一些情况造成困扰。


  • 相关阅读:
    hdu6229 Wandering Robots 2017沈阳区域赛M题 思维加map
    hdu6223 Infinite Fraction Path 2017沈阳区域赛G题 bfs加剪枝(好题)
    hdu6438 Buy and Resell 买卖物品 ccpc网络赛 贪心
    hdu6441 Find Integer 求勾股数 费马大定理
    bzoj 1176 Mokia
    luogu 3415 祭坛
    bzoj 1010 玩具装箱
    bzoj 3312 No Change
    luogu 3383【模板】线性筛素数
    bzoj 1067 降雨量
  • 原文地址:https://www.cnblogs.com/Windeal/p/4284659.html
Copyright © 2011-2022 走看看