第九章学习笔记

第九章学习笔记

一、课本知识

1. I/O库函数

I/O库函数,实质上是一系列方便用户使用,提高了整体效率的文件操作函数,

2.I/O库函数与系统调用

在Unix/Linux中,I/O库函数建立在系统调用的基础上

  • 系统调用函数:open() read() write() lseek() close()

  • I/O库函数:fopen() fread() fwrite() fseek() fclose()

  • fopen()使用字符串表示模式,在失败时会返回一个NULL指针

  • 每个I/O库函数的根都在对应的系统调用函数中。

3. I/O函数的算法

1.fread算法:

  • 在第一次调用fread()时,FILE结构体的缓冲区是是空的,fread()使用保存的文件描述符fg发出一个 n = read(fd,fbuffer,BLKSIZE); 系统调用,用数据块填充内部的fbuf[]。

  • 在随后的每次fread(调用中,它都尝试满足来自FILE结构体内部缓冲区的调用。当缓冲区变为空时,它就会发出reado系统调用来重新填充内部缓冲区。因此,fread0一方面接受来自用户程序的调用,另一方面向操作系统内核发出 readO系统调用。除了read0系统调用之外,所有fread0处理都在用户模式映像中执行。

2.fwrite算法:

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

include<string.h>

int main()
{ FILE*fp;
int c;
fp=fopen("file1.txt","r");
if(fp==NULL)
{ printf("File cannot be opened.");
return 1; }
while((c=fgetc(fp))!=EOF)
{ printf("%c",c); }
fclose(fp);
return 0; }`

3.fclose算法

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

4.使用I/O库函数或系统调用

fread()依赖read()将数据从内核赋值到内部缓冲区,然后从内部缓冲区将数据复制到程序缓冲区,他传输了两次数据相反,read()将数据从内核直接复制到程序的缓冲区,只复制一次。

5.I/O库模式

fopen()中的模式参数可以指定为:"r"、" w"、"a”,分别代表读、写、追加。 每个模式字符串可包含一个+号,表示同司时读写,或者在写入、追加情况下,如果文件不存在则创建文件。

1.字符模式I/O

  • fgetc()返回的是整数,而不是字符。

  • 对于fp=stdin或stdout,可能会使用c=getchar();putchar();来代替

2.行模式I/O char *fgets(char *buf, int size,FILE*fp) 从fp中读取最多为一行(以\n结尾)的字符

int fputs(char *buf,FILE*fp) 将buf中的一行写人fp中

3.格式化I/O 格式化输入:(FMT=格式字符串)

scanf(char*FMT, &items); // from stdin fscanf(fp,char *FMT, &items); // from file stream

格式化输出

printf(char *FMT, items); // to stdout fprintf(fp,char *FMT, items); // to file stream

4.内存中的转换函数

sscanf(buf,FMT,&items); //inputfrom buf[]in memory sprintf(buf,FMT,items); //print to buf[]in memroy

sscanf()和sprintf0并非I/O函数,而是内存中的数据转换函数。例如,atoi()是一个标准库函数,将一串AscII数字转换成整数,但是大多数Unix/Linux系统没有itoA0) 函数,因为转换可由sprintf(完成,所以不需要它。

5. 其他I/O库函数

  • fseek()、ftell()、rewind():更改文件流中的读/写字节位置

  • feof()、ferr()、fileno():测试文件流状态

  • fdopen():用文件描述符打开文件流

  • freopen():以新名称重新打开现有的流

  • setbuf0、setvbuf():设置缓冲方案

  • popen():创建管道,复刻子进程来调用sh

6.文件流缓冲

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

  • 无缓冲:从非缓冲流中写入或读取的字符将尽快单独传输到文件或从文件中传输。例如,文件流stderr通常无缓冲。到stderr的所有输出都会立即发出。

  • 行缓冲:遇到换行符时,写入行缓冲流的字符以块的形式传输。例如,文件流stdout 通常是行缓冲,逐行输出数据。

  • 全缓冲:写入全缓冲流或从中读取的字符以块大小传输到文件或从文件传输。这是文件流的正常缓冲方案。

通过fopen()创建文件流之后,在对其执行任何操作之前,用户均可发出一个

setvbuf(FILE_stream,char_buf,int node, int size)

调用来设置缓冲区(buf)、缓冲区大小(size)和缓冲方案(mode),它们必须是以下一个宏:

  • _IONBUF:无缓冲

  • _IOLBUF:行缓冲

  • _IOFBUF:全缓冲

此外,还有其他的setbuf()函数,是setvbuf()的变体。对于行缓冲流或全缓冲流,可用fflush(stream)立即清除流的缓冲区。

7.变参函数

在I/O库函数中, printf()相当独特,因为多种不同类型的可变数量参数可以调用它。C语言和C++仍然允许参数数量可变的函数。这些函数必须至少使用一个参数进行声明,后跟3个点。

二、知识点挑战

1.I/O库函数中fread、fwrite、fclose算法




2.I/O库模式

输入图片说明
输入图片说明
输入图片说明
输入图片说明

三、遇到的问题

1.fwrite函数问题

在实践fwrite代码的过程中,出现了如下情况

一开始我认为是代码语法有错误,于是拿着代码询问chatgpt 输入图片说明

在得到没有语法错误的回答后,我询问了终端显示这串字符的原因 输入图片说明 之后选择尝试让chatgpt改进这一代码 输入图片说明

于是利用该代码完成了这一实践(见学习笔记)

2.markdown文档

markdown文档对我来说,是一样完全未曾接受过的,全新的写作、记录的方式。
在接触它之前,有一种对陌生事物的好奇与担忧,好奇这到底是怎样一种技术,又担忧老师口中那神乎其神的markdown文档的门槛又到底是怎样一种高度。
但好在学习它的资源有很多,而我也可以在实践中学习。在找寻编辑器、实践动手,导入导出的一些步骤里,虽然之前给人感觉抽象模糊,但也是在敲下一个个符号时将对它的不确定度慢慢降低,获取到越来越多的信息,也对划分标题、创造列表、插入文件等操作愈发得心应手。
而在其中最大的困难,还是图片的插入问题。当我初步做好文档后,便将其导出,并发布在了博客园里。但我回忆起老师上课时讲述的图片问题,便注意查看了一下,却是发现文档内的图片全都丢失。在查询chatgpt后,初步归因为链接放置错误。
回答图片丢失
于是向其他有经验的同学问询,得到了他的解决办法,那便是先将本地图片上传至网络,再向文档插入网络链接。于是便通过该方法,我成功在文档内插入图片。

posted @ 2023-09-17 09:41  20211113  阅读(31)  评论(0)    收藏  举报