• 20191320-2021-2022-1-diocs 学习笔记2


    第9章 I/O库函数——教材知识点归纳

    9.1~9.2系统调用和I/O库函数

    系统调用:操作系统中,进程以两种不同的方式运行:内核模式(Kmode)和用户模式(Umode)。Umode权限有限,特殊权限的操作需要在Kmode下进行。系统调用(System Call)机制允许进程进入Kmode,执行更高权限的操作。
    系统调用和I/O库函数不同,但I/O库函数建立在系统调用的基础上。如:fopen()依赖于open()fread()依赖于read()

    9.3I/O库函数的算法

    I/O库函数的算法分为fread算法、fwrite算法、fclose算法

    读取:size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
    写入:size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
    关闭:int fclose(FILE *stream);

    9.4~9.5使用I/O库函数、I/O库模式

    在fopen()中的模式参数中体现I/O库模式。
    I/O库模式中的字符模式有:

    r:只读模式,文件必须存在,否则打开失败。
    w:只写模式,若文件存在,则清除原文件内容后写入;否则,新建文件后写入。
    a:追加模式。若文件存在,则位置指针移到文件末尾,在文件尾部追加写入。若文件不存在,则打开失败。
    r+:表示读/写,不会截断文件。
    w+:表示读/写,但是先截断文件,如果文件不存在,就先创建文件。
    a+:表示通过追加的方式读/写;如果文件不存在就创建文件。

    查阅资料,得知I/O库模式也有二进制模式,和字符模式类似,只是以二进制的方式进行读写。相应模式有:

    rb:只读模式,文件必须存在,否则打开失败。
    wb:只写模式,若文件存在,则清除原文件内容后写入;否则,新建文件后写入。
    ab:追加模式。若文件存在,则位置指针移到文件末尾,在文件尾部追加写入。若文件不存在,则打开失败。
    rb+:表示读/写,不会截断文件。
    wb+:表示读/写,但是先截断文件,如果文件不存在,就先创建文件。
    ab+:表示通过追加的方式读/写;如果文件不存在就创建文件。

    字符模式I/O
    字符模式I/O以字符为单位存取,文件在流中。

    从文件指针中读取一个字符:int fgetc(FILE *fp);
    向文件流中退回一个字符: int ungetc(int c, FILE *fp);
    向文件流中存放一个字符:int fputc(int c, FILE *fp);

    注意读取到文件结束时,会返回一个值-1,将它与文件流中其他字符区分。同时应注意返回值的类型是整数。

    行模式I/O
    行模式I/O以文本文件的行为单位进行存取。

    读取一行:char *fgets(char *buf,int size, FILE *fp);
    写入一行:int fputs(char *buf, FILE *fp);

    格式化I/O:
    格式化输入和格式化输出就是我们C语言课常用的scan和print类型,scanf和printf指定输入输出流为stdin和stdout,而fscanf和fprintf就可以指定输入流和输出流了。
    格式化输入:

    从stdin输入:scanf(char *FMT,&items);
    从指定流输入:fscanf(fp,char *FMT, &items);

    格式化输出:

    输出到stdout: printf(char *FMT,&items);
    输出到指定流:fprintf(fp,char *FMT, &items);

    9.6文件流缓冲

    每个文件流都有一个FILE结构体,其中包含一个内部缓冲区,对文件流进行读写要遍历FILE缓冲区,文件缓冲可以使用三种缓冲方案的一种。

    无缓冲:尽快单独传输,如stderr就是通常无缓冲的。
    行缓冲:遇到换行符时进行缓冲,逐行输入输出,如stdout。
    全缓冲:以块大小传输到文件或者从文件传输,文件流常用的就是全缓冲。

    9.7变参函数

    在学习C语言时,我们发现printf、scanf函数在传入参数时,参数的个数是不确定的,在学习本章后发现,原来它们都是变参函数。变参函数使用至少一个参数声明,后面跟三个点。如:
    int function(int m, int n . . . );
    在函数内部,可以通过C语言库宏访问参数。

    实践内容过程和问题解决过程

    实践通过I/O库函数执行一些简单的操作:

    1. 将文本文件小写转大写。
    2. 计算文本文件行数。
    3. 计算文本文件单词数。

    1.文本文件小写转大写

    思路:读取一个文件,然后判断文件中的每个字符,如果为小写,就将其进行转换,整体较为简单。
    代码:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int is_low_letter(char letter){
            return letter>='a'&&letter<='z';
    }
    
    int main(int argc, char* argv[]){
            FILE *fp,*gp;
            char ch;
            fp = fopen("text","r");
            if(fp == NULL){
                    printf("Can't read file "%s"
    ",argv[i]);
                    return -1;
            }
            gp = fopen("upper","w");
            while(1){
                    ch = fgetc(fp);
                    if(is_low_letter(ch))ch+=('A'-'a');
                    fputc(ch,gp);
                    if(ch==EOF)break;
            }
            fclose(fp);
            return 0;
    }
    


    成功读取了一个文件,然后将其中的小写字母转换为大写字母,然后存在了另一个文档中。

    遇到问题和解决:
    在尝试的过程中,原本计划将小写转换为大写,读取和存储都在同一个文件,但最终出现问题,改为存到另一个文件中。在读取和写入的时候,注意读取和写入的库模式,否则就会出错。

    2.计算文本文件行数

    思路:行数的计算可以转换为计算换行符的个数,行数为换行符的数量+1。
    代码:

    #include <stdio.h>
    #include <stdlib.h>
    
    int main(int argc, char* argv[]){
    	int cnt=1;
    	FILE *fp;
    	fp=fopen("countline.txt","r");
    	while(1){
    		if(fgetc(fp)=='
    ')
    			cnt++;
    		if(fgetc(fp)==EOF)
    			break;
    	}
    	printf("Total lines:%d
    ",cnt);
    	return 0;
    }
    

    运行截图:

    3.计算文本文件单词数

    思路:单词,可以理解为连续的字母,如果出现连续的字母,就将计数器加一,即可实现。
    代码:

    #include <stdio.h>
    #include <stdlib.h>
    
    int is_letter(char ch){
    	if(ch>='a'&&ch<='z'||ch>='A'&&ch<='Z')
    		return 1;
    	return 0;
    }
    
    int main(){
    	int cnt=0;
    	FILE *fp;
    	fp=fopen("countword.txt","r");
    	while(1){
    		if(fgetc(fp)==EOF)
    			break;
    		if(is_letter(fgetc(fp))){
    			cnt++;
    			while(is_letter(fgetc(fp)));
    		}
    	}
    	printf("Number of words:%d
    ",cnt);
    	return 0;
    }
    

    运行截图:

    代码链接

    代码包括一些以前的代码,在码云。链接:https://gitee.com/Ressurection20191320/code/tree/master/IS

  • 相关阅读:
    repo manifest xml 文件修改后提交命令
    linux下i2c驱动笔记 转
    这么多年至今今天遇到的一件令我气愤还无法想象的,希望看到的人引以为戒吧。不明白现在的孩子怎么了!
    GitLab 之 Linux十分钟快装
    Mongodb For Mac OSX && 登录验证
    Grunt 5分钟上手:合并+压缩前端代码
    回顾:前端模块化和AMD、CMD规范(全)
    通过NPM快速发布你的NodeJS模块(组件包)
    【linux】netlink
    【Java基础知识】JNI入门
  • 原文地址:https://www.cnblogs.com/Ressurection-20191320/p/15311921.html
Copyright © 2020-2023  润新知