zoukankan      html  css  js  c++  java
  • 20191317王鹏宇第九章学习笔记

    第九章:I/O库函数

    知识点归纳总结

    本章讨论了I/O库函数,解释了什么是I/O库函数以及系统调用的用法。详细解释了几个经典I/O库函数例如:fread,fwrite,fclose,而且还介绍了这几个函数与read,write,close之间的关系。介绍了I/O库函数的不同模式,包括字符模式,行模式,结构化记录模式和格式化I/O操作。解释了文件流缓冲方案,并通过示例说明了不同方案的效果。


    其中让我最有收获的几个部分如下:

    • I/O库函数与系统调用
    • I/O库函数算法
    • I/O库模式

    文件操作种类:参考网站

    fopen():文件打开操作
    头文件:stdio.h
    函数定义:FILE *fopen(char *pname, char *mode)
    函数说明:pname是文件名,mode是打开文件的方式


    fclose():文件关闭
    函数定义:int fclose(FILE *fp);
    函数说明:fp是一个以打开的文件的文件指针
    返回值:
    正常返回:0
    异常返回:EOF,表示文件在关闭时发生错误


    fgetc():读取一个字符
    函数定义:int fgetc(FILE *fp)
    函数说明:从fp中读取一个字符,作为返回值返回
    返回值:
    正常返回:返回读取字符的代码
    异常返回:返回EOF。例如:要从“写打开”的文件中读取一个字符时,会发生错误而返回一个EOF


    fputc():写一个字符到文件中
    函数定义:int fputc(int ch, FILE*fp)
    函数说明:ch是一个整型变量,要写到文件的字符
    fp:文件指针,要写入的文件
    返回值:
    正常返回:要写入的字符的代码
    异常返回:返回EOF


    fgets():从文件中读取一个字符串
    函数定义:char *fgets(char *str, int n, FILE *fp)
    函数说明:由fp指出的文件中读取n-1个字符,并把他们存放到有str指出的字符数组中区,最后加上一个由字符串结束符''
    参数说明:str:接受字符串的内存地址,可以是数组别名,也可以是指针
    n:指出要读取的字符的个数
    fp:这个是文件指针,指出要从中读取字符的文件
    返回值:
    正常返回:字符串的内存首地址,即str的值
    异常返回:返回一个NULL值,此时应当用feof()或ferror()函数来判别是读取到了文件尾,还是发生了错误。


    fputs():写入字符串到文件中去
    函数定义:把由str之处的字符串写入到fp所指的文件中去
    函数说明:
    str:之处要写入到文件中去的字符串,不包括最后的''
    fp:这个是文件指针,之处字符串要写入到的文件指针
    返回值:
    正常返回:写入到的文件的字符个数,即字符串的长度
    非正常返回:返回一个NULL值,此时应当用feof()或ferror()函数来判别是读取到了文件尾,还是发生了错误。

    问题:二进制文件和文本文件如何转换?
    参考网站

    使用vim修改:vim -b 文件名
    :%!xxd ——转化成16进制
    然后进行修改二进制
    :%!xxd -r——转回去
    :wq

    实践内容:数据结构如何读写

    参考网站
    代码:

    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #define MAX 100
    //定义一个结构体
    typedef struct Student
    {
         int stu_id;       //学号
         char name[100];     //姓名
    }Stu;
    
    int main(int argc, char const *argv[]) 
    {
        // 声明函数
        void Write();
        void Read();
        // 函数调用
        Write();
        Read();
        return 0;
    }
    // 数据写入文件 
    void Write()
    {
        // 定义一个文件指针
        FILE *fp ;
        // 初始化一个结构体数组
        Stu stuw[2] = {
            {20180001, "xiaoming" },
            {20180002, "小明"}
        };
        // 打开文件,没有文件自动创建
        fp = fopen("student.dat","wb"); // wb:表示以二进制写入
        // 写入数据
        fwrite( (char*)stuw,sizeof(Stu),2,fp); //2:表示将数组中两个元素写入文件
        // 关闭文件
        fclose(fp);
    }
    // 文件数据读取
    void Read()
    {
        // 定义一个文件指针
        FILE *fp ;
        // 定义一个buf结构体,用于得到文件内容
        struct stat buf;
        // 定义一个文件行数记录变量
        int rows;
        // 定义一个Student结构体
        Stu stur[MAX];
        // 求文件中的行数(记录个数)
        stat("student.dat",&buf);
        rows = buf.st_size/sizeof(Stu);
        // 打开文件
        fp = fopen("student.dat","rb");
        // 读取数据到数组中
        fread((char *)stur,sizeof(Stu),rows,fp);
        // 关闭文件
        fclose(fp);
        // 遍历数组,打印数据信息
        for(int i=0;i<rows;i++)
            printf("%d	%s
    ",stur[i].stu_id,stur[i].name);
    }
    

    实践截图:


    实践内容:教材练习9.1

    教材示例代码9.1:

    #include <fcntl.h>
    int main(int argc, char *argv[])
    {
        int fd;
        int i,n;
        char buf[4096];
        if(argc < 2 ) 
            exit(1);
        fd = open(argv[1],O_RDONLY);
        if (fd < 0) 
        {
           exit(2);
        }
        while (n = read(fd,buf,4096))
        {
            for (i=0; i<n;i++)
                write(1,&buf[i],1);
        }
    }
    

    这里我就不得不说一下了,这个代码有错,在运行的时候,如果完全按照这个代码,系统会报错:

    warning: implicit declaration of function ‘exit’ [-Wimplicit-function-declaration]
    warning: implicit declaration of function ‘read’ [-Wimplicit-function-declaration]

    我查询了一下发现,这是头文件缺失的问题,需要再加一个头文件:#include unistd.h才能成功编译,而且需要把exit替换为return,因为exit报错同样也是因为缺少头文件。当然也有可能是我编译有问题,在编译的时候并没有自动补全缺失的库。

    问题:

    在示例9.1的系统调用程序中,通过一个系统调用来写每个字符是非常低效的。用一个write()系统调用来替换for循环。


    代码:

    #include <fcntl.h>
    #include <unistd.h>
    int main(int argc, char *argv[])
    {
        int fd;
        int i,n;
        char buf[4096];
        if(argc < 2 ) 
            return 1;
        fd = open(/Desktop/WPY_TEST/j.txt,O_RDONLY);
        if (fd < 0) 
        {
            return 2;
        }
        while (n = read(fd,buf,4096))
        {
            write(1,&buf[i],4096);
        }
    }
    

    这里直接利用之前的while循环,将write()函数的参数更改一下就可以了


    实践内容:教材练习9.2

    问题:

    编写一个C程序,将文本文件中的大写字母转换为小写字母


    代码:

    #include <ctype.h>
    //C 标准库的 ctype.h 头文件提供了一些函数,可用于测试和映射字符。
    #include <stdio.h>
    #include <stdlib.h>
    #define INPUT_FILE "tmp1.txt"   //同一文件夹下的输入文件
    #define OUTPUT_FILE "tmp2.txt"  //同一文件夹下的输出文件
    int main(void)
    {
        char c;
        FILE *finput, *foutput;     //定义文件类型的指针变量
        finput = fopen(INPUT_FILE, "r");        //以只读的方式打开“tmp1”文件
        foutput = fopen(OUTPUT_FILE, "w");      //以只写的方式打开输出文件,如果没有则新建输出文件
        while ((c = fgetc(finput)) != EOF) //如果输入文件不为空
        {
            if (isupper(c) || islower(c))    //isupper 该函数检查所传的字符是否是大写字母  islower该函数检查是否为小写字母
            {    
               fputc(tolower(c), foutput);      //将得到的结果转成小写字母并写入输出文件 
            }
        }
        return 0;
    }
    

    输入文件tmp1截图:

    代码运行截图:

    输出文件tmp2截图:

    实践内容:教材练习9.3

    问题:

    编写一个C程序,计算文本文件的行数。


    代码:

    #include <stdio.h>
    #include <stdlib.h>
    #define INPUT_FILE "tmp3.txt"   //同一文件夹下的输入文件
    int main()
    {
        int count = 0;
        char c;
        FILE *fp;
        if((fp=fopen(INPUT_FILE,"r"))==NULL)    //如果文件不存在
        {
            printf("Can not open this file.
    ");    //打印错误信息
    	exit(0);
        }
        while (!feof(fp)) //如果输入文件不为空
        {
            c = getc(fp);  //遍历文件字符
    	if(c =='
    ')    //如果检测到换行符
            {
    	    count++;    //计算行数
            }
        }
        printf("the row of the file is %d
    ",count+1);
        return 0;
    }
    

    tmp3文件内容:

    A panda looks like a little bear.
    It has black and white fur.
    It lives only in China, so it is called the national treasure of China and protected by the law.
    We all see panda on TV or in the zoo.
    They look stupid and walk slowly, but they are lovely and everyone likes them.
    A panda is lucky animal. We Chinese like it, and people of the world like it, too.
    Now there are China’s pandas in many other countries, such as Japan and the USA.
    A panda isn’t a common animal, it is bridge of friendship.
    

    tmp3文件内容截图:

    一共8行
    代码运行截图:

    可以看出成功计算出了文本文件的行数,8行

    实践内容:教材练习9.4

    问题:

    编写一个C程序,计算文本文件的单词书。单词是由空格分开的一系列字符


    代码:

    #include <stdio.h>
    #include <stdlib.h>
    #define INPUT_FILE "tmp3.txt"   //同一文件夹下的输入文件
    int main()
    {
        int count = 0;
        int n = 0;
        char c;
        FILE *fp;
        if((fp=fopen(INPUT_FILE,"r"))==NULL)
        {
            printf("Can not open this file.
    ");
    	exit(0);
        }
        while (!feof(fp)) //如果输入文件不为空
        {
            c = getc(fp);
            if(c =='
    ')    //如果遇到换行符,单词数加一
                count++;
    	if(c =='	' || c == ' ')        //遇到空格,单词数加一
            {
    	    count++;
            }
        }
        printf("the word of the file is %d
    ",count+1);
        return 0;
    }
    


    tmp3文件内容同上。
    代码运行截图:

    可以看出代码运行的结果是99个单词。
    使用单词数在线统计工具的截图如下:

    可以看出在线统计工具的结果也是99。所以代码运行正确。

    第九章的内容是关于文件操作,可以说比较晦涩难懂,教材上的练习仅仅是最基础的,因此在课下还需要进一步的练习来巩固第九章的知识。

  • 相关阅读:
    观念
    DB2 SQL Error: SQLCODE=104, SQLSTATE=42601
    DB2 SQL Error: SQLCODE=302, SQLSTATE=22001
    Flex Socket编程:安全错误:Error #2048
    JSONP跨域的原理解析
    java 学习
    C语言报错 error C2143: 语法错误 : 缺少“]”(在“;”的前面)
    分享:模版方法,策略模式和状态模式之间的区别
    OracleOrSqlServer 递归查询
    asp.net页生命周期阶段
  • 原文地址:https://www.cnblogs.com/wpy-1049363419/p/15305994.html
Copyright © 2011-2022 走看看