第9章 I/O库函数
9.1 I/O库函数
系统调用是文件操作的基础,但他们只支持数据块的读/写。
9.2 I/O库函数与系统调用
系统调用函数:open()、read()、write()、lseek()、close()
open()用于打开一个文件并返回一个文件描述符。
read()用于从已打开的文件描述符中读取数据。
write()用于向已打开的文件描述符中写入数据。
I/O库函数:fopen()、fread()、fwrite()、fseek()、fclose()
open()用于打开一个文件,并返回一个指向 FILE 结构体的指针,以供后续对文件进行操作。"r":只读方式打开文件,文件必须存在。"w":写入方式打开文件,如果文件存在,则清空文件内容;如果文件不存在,则创建新文件。"a":追加方式打开文件,如果文件存在,则在文件末尾追加数据;如果文件不存在,则创建新文件。"rb"、"wb"、"ab" 等:以二进制方式读取或写入文件。
fread()用于从已打开的文件中读取数据,并存储到指定的缓冲区中。
fwrite()用于向已打开的文件中写入数据。
9.3 I/O库函数算法
fread()算法函数原型如下:
include <stdio.h>
size_t fread(void *ptr, size_t size, size_t count, FILE *stream);
ptr 是用于存储读取数据的缓冲区,size 是每个数据项的字节数,count 是要读取的数据项数量,stream 是指向 FILE 结构体的指针。fread() 函数会尝试从 stream 指向的文件中读取 count 个数据项,每个数据项占用 size 字节,然后将读取到的数据存储到 ptr 指向的缓冲区中。它返回实际成功读取的数据项数量,如果返回值小于 count,则可能意味着已到达文件末尾或者发生了错误。
fwrite()算法函数原型如下:
include <stdio.h>
size_t fwrite(const void *ptr, size_t size, size_t count, FILE *stream);
ptr 是待写入数据的内存地址,size 是每个数据项的字节数,count 是要写入的数据项数量,stream 是指向 FILE 结构体的指针,表示要写入的文件。fwrite() 函数会将 ptr 指向的内存中的数据写入到 stream 指向的文件中,写入的数据量为 size × count 字节。它返回实际成功写入的数据项数量,即 count 的值,如果返回值小于 count,则可能意味着发生了错误或无法继续写入。
fclose()算法函数原型如下:
include <stdio.h>
int fclose(FILE *stream);
stream 是指向 FILE 结构体的指针,表示要关闭的文件。fclose() 函数会关闭 stream 指向的文件,并将文件的缓冲区中的数据写入磁盘。它返回一个整数值作为关闭操作的结果,通常是 0 表示成功关闭,非零值表示关闭失败。
9.4 使用I/O库函数或系统调用
简单实践一下
使用一个网上得到的代码进行调试后,使其符合功能能够将文档中的大写字母改写成小写字母。
代码如下:
include <stdio.h>
FILE fp,gp;
int main()
{
int c;
fp = fopen("first.txt","r");
gp = fopen("second.txt","w");
while((c=getc(fp))!= EOF)
putc(c + 32,gp);
fclose(fp);
fclose(gp);
return 0;
}
使用命令行进行实践
对first.txt的文件进行写入
执行程序后second.txt文件得到结果如下所示
可以发现空格字符被转化成了@,但是文件末尾不应该出现*。对GPT进行查询,可有如下解释:
将second.txt的内容清空,重新运行一次代码后,便能够将错误改正。
9.5 I/O库模式
字符模式I/O
行模式I/O{char *fgets(char *buf, int size, FILE *fp);:从fp中读取最多的为一行(以\n结尾)的字符。int fputs(char *buf,FILE *fp);:将buf的一行写入fp中}
格式化I/O{1.格式化输入,2.格式化输出}
9.6 文件流缓冲
无缓冲(unbuffered)输入输出是一种操作系统提供的文件 I/O 策略,其特点是每个字符都直接通过系统调用进行读取或写入,并且不使用缓冲区来提高效率。
行缓冲(line-buffered)是一种文件 I/O 缓冲策略,其中缓冲区在遇到换行符 \n 时被刷新。
全缓冲(fully buffered)是一种文件 I/O 缓冲策略,其中数据会在缓冲区被填满或遇到特定条件时进行刷新。与行缓冲不同,全缓冲会等待缓冲区被填满或达到一个特定的大小才会将数据写入文件或从文件中读取。
9.7 变参函数
多种不同类型的可变数量参数可以调用print()
9.8 编程项目:类printf函数
项目规范
项目基本代码
myprintf()的算法
项目改进
项目演示和视力解决方案
GPT苏格拉底挑战