首页 > 其他分享 >学习笔记2

学习笔记2

时间:2023-09-17 14:55:40浏览次数:27  
标签:fp 文件 int 笔记 学习 模式 FILE 缓冲区

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

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

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

9.3 I/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.3.1 fread算法
    (1)在第一次调用fread()时,FILE结构体的缓冲区是空的,fread()使用保存的文件描述符fd发出一个

n=read(fd,fbuffer,BLKSIZE)

系统调用,用数据块填充内部的fbuf[]。然后,它会初始化fbuf[]的指针、计数器和状态变量,以表明内部缓冲区中有一个数据块。

(2)在随后的每次fread()调用中,它都尝试满足来自FILE结构体内部缓冲区的调用。当缓冲区变为空时,它就会发出read()系统调用来重新填充内部缓冲区

  • 9.3.2 fwrite()算法
    fwrite()算法与fread()算法相似,只是数据传输方向不同。
    开始的时候,FILE结构体的内部缓冲区是空的。在每次调用fwrite()时,它将数据写入内部缓冲区,并调整缓冲区的指针、计数器和状态变量,以跟踪缓冲区中的字节数。如果缓冲区已满,则发出 write()系统调用,将整个缓冲区写入操作系统内核。

  • 9.3.3 fclose()算法
    若文件以写的方式被打开,fclose()会先关闭文件流的局部缓冲区。然后,它会发出一个close(fd)系统调用来关闭FILE结构体中的文件描述符。最后,它会释放FILE结构体,并将FILE指针重置为NULL。

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

对于以BLKSIZE为单位的读/写数据,使用系统调用比I/O库函数更高效。
在fopen()中的模式参数中体现I/O库模式。

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

2021年大一的时候 娄老师所发的资料里有提到过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语言库宏访问参数。

chatgpt提问









问题与解决思路

看完书后了解了文件流的三种缓冲方案,但对其实质不甚清楚。

参考网站

通常,文件数据的读写效率远低于内存读写效率。如果不存在缓冲,CPU 在读取文件数据时需要先发送指令给 DMA(专门处理 IO 数据读写的硬件),而后 DMA 从文件数据读取一个 0 到内存,CPU 再处理该数据。此过程 CPU 全程参加,极大浪费了 CPU 资源 文件流缓冲的目的正是降低 IO 对于 CPU 占用。如图所示,在添加缓冲区后,DMA 可以将文件数据先读取到缓冲区中,等待缓冲区满时,再通知 CPU,此时 CPU 将缓冲区的数据读取并处理。

询问chatgpt截图

实践过程截图,代码

实践通过I/O库函数执行一些简单的操作:
1.计算文本文件行数。
2.计算文本文件单词数
3.将文本文件小写转大写。

  • 计算文本文件行数
    思路:行数的计算可以转换为计算换行符的个数,行数为换行符的数量+1。(大一看漫画学python曾学过)
    代码
#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)=='\n')
			cnt++;
		if(fgetc(fp)==EOF)
			break;
	}
	printf("Total lines:%d\n",cnt);
	return 0;
}



  • 计算文本单词数

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

#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\n",cnt);
	return 0;
}

截图:


  • 文本文件小写转大写

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

#include <stdio.h>
FILE *fp,*gp;
int main(){
        char c;
        fp=fopen("text.txt","r");
        gp=fopen("result.txt","w");
        while((c=fgetc(fp))!=EOF){
                if(c>='a'&&c<='z')c=c-32;
                fputc(c,gp);
        }
        fclose(fp);
        fclose(gp);

        return 0;
}  

截图:


标签:fp,文件,int,笔记,学习,模式,FILE,缓冲区
From: https://www.cnblogs.com/xiaoquancheng/p/17708752.html

相关文章

  • 珍惜环境,好好学习,感恩 单词
    珍惜环境,好好学习,感恩  有食物吃,有空调,就好好学习。日子怎么过的,就是有东西吃,有适宜的温度来之不易,就好好学习。   单词学习笔记:什么意思呀?这个意思对应是什么?怎么拼写呢?直背。看课本,拼写读三遍。不会的看课本加深印象。及时巩固。每天10分钟,20分钟。不熟就看书,看正确......
  • 《信息安全系统设计与实现》第二周学习笔记
    《信息安全系统设计与实现》第二周学习笔记第九章I/O库函数系统调用函数系统调用系统调用函数open():打开和创建文件read():读文件write():写文件lseek()close()I/O库函数fopen():以指定的形式打开文件fread():从给定流stream读取数据到ptr所指向的数组中fwrit......
  • 02博客:Java学习思维导图
    Java学习思维导图这一个学期学习规划安排动态调整第一个月到第二个月:重点学习、巩固并初步掌握Java入门基础知识第三个月:巩固Java基础这个阶段与其他课程有交叉部分需要一起巩固大概一个月到一个半月第四个月:与阶段三相对应,包含了MySQL、JavaWeb、Git、Linux等内容的学......
  • 《Unix/linux系统编程》教材第9章学习笔记
    结构化教材内容第9章:I/O库函数I/O库函数与系统调用系统调用是文件操作的基础,但它们只支持数据块的读/写。系统调用函数:open()、read()、write()、lseek()、close();I/O库函数:fopen()、fread()、fwrite()、fseek()、fclose();I/O库函数的根都在对应的系统调用函数中,例fopen()......
  • 高级系统架构师学习(五)软件架构设计-下篇
    一、大型网站系统架构演化【高速发展阶段】第四阶段【使用服务集群改善网站并发处理能力】背景:用户的请求由谁来转发到具体的应用服务器?用户如果每次访问到的服务器不一样,那么如何维护session的一致性?负载均衡分类:基于特定软件的负均衡(HTTP重定向)【应用层】反向......
  • yzy第二次学习笔记
    第九章I/O库函数本章讨论了I/O库函数;结识了I/O库函数的作用及其对于系统调用的优势;使用示例程序来说明I/O库函数和系统调用之间的关系,并解释了他们之间的相似性和基本区别;详细介绍了IO库函数的算法,包括fread、fwrite和fclose的算法,重点介绍了它们与read、write和close系统调......
  • 12 表单学习
    <!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>学习表单</title></head><body><h1>学习表单</h1><formaction="表格标签.html"method="pos......
  • Unix/Linux系统编程学习笔记二
    学习笔记二一、教材知识点总结1.I/O库函数程序(1)fopen()使用字符串表示模式,其中"r"表示READ"w"表示WRITE。它返回一个指向FILE结构体的指针。fopen()首先发出open()系统调用来打开文件,以获取文件描述符编号fd。如果open0系统调用失败,则fopen()会返回一个NULL指针。否则,它会......
  • 学习笔记2
    对于C语言中的文件操作:字符读写:getc:从文件中读取一个字符。putc:将一个字符写入文件。行读写:fgets:从文件中读取一行文本。fputs:将一行文本写入文件。getline:动态地读取一行文本。任意位置读写:fseek:定位文件指针到指定位置。ftell:获取当前文件指针的位置。rew......
  • 《深入LINUX内核架构》学习笔记 ——01
    模块相关的知识1.模块相较于宏内核(微内核优点)模块消除了宏内核的许多限制,包括:缺乏动态可拓展性、导致内核映像尺寸膨胀、测试新特性时必须重启系统等。2.静态链接、动态链接及模块依赖(TIPS)《深入理解计算机系统》中有这样一段话:共享库是一个目标模块,在运行或加......