建工网校题库,怎么优化整站,用vps做网站的流程,网页设计期末作业素材系列文章目录 前言 ✅作者简介#xff1a;大家好#xff0c;我是橘橙黄又青#xff0c;一个想要与大家共同进步的男人#x1f609;#x1f609;
#x1f34e;个人主页#xff1a;橘橙黄又青_C语言,数据结构,函数-CSDN博客
目的#xff1a;学习文件操作#xff0c;即…系列文章目录 前言 ✅作者简介大家好我是橘橙黄又青一个想要与大家共同进步的男人
个人主页橘橙黄又青_C语言,数据结构,函数-CSDN博客
目的学习文件操作即文件相关函数的学习
在这里首先放置我个人认为好的学习c语言的网站
:cplusplus.comhttps://legacy.cplusplus.com/reference/clibrary/
好了我们现在开始吧
1. 为什么使⽤⽂件 如果没有⽂件我们写的程序的数据是存储在电脑的内存中如果程序退出内存回收数据就丢失 了等再次运⾏程序是看不到上次程序的数据的如果要将数据进⾏持久化的保存我们可以使⽤⽂件。 2. 什么是⽂件 磁盘上的⽂件是⽂件。 但是在程序设计中我们⼀般谈的⽂件有两种 程序⽂件、数据⽂件 从⽂件功能的⻆度来分类 的。 2.1 程序⽂件 程序⽂件包括源程序⽂件后缀为.c,⽬标⽂件windows环境后缀为.obj,可执⾏程序windows 环境后缀为.exe。 2.2 数据⽂件 ⽂件的内容不⼀定是程序⽽是程序运⾏时读写的数据⽐如程序运⾏需要从中读取数据的⽂件或者输出内容的⽂件本章讨论的是数据⽂件。 在以前各章所处理数据的输⼊输出都是以终端为对象的即从终端的键盘输⼊数据运⾏结果显⽰到 显⽰器上。 其实有时候我们会把信息输出到磁盘上当需要的时候再从磁盘上把数据读取到内存中使⽤这⾥处 理的就是磁盘上⽂件。 2.3 ⽂件名 ⼀个⽂件要有⼀个唯⼀的⽂件标识以便⽤⼾识别和引⽤。 ⽂件名包含3部分⽂件路径⽂件名主⼲⽂件后缀 比如 c:\ code \ test . txt 3. ⼆进制⽂件和⽂本⽂件 根据数据的组织形式数据⽂件被称为⽂本⽂件或者⼆进制⽂件 ⼆进制⽂件数据在内存中以⼆进制的形式存储如果不加转换的输出到外存就是⼆进制⽂件。 ⽂本⽂件 以ASCII码的形式存储则需要在存储前转换。以ASCII字符的形式存储的⽂件就是⽂ 本⽂件。 那⼀个数据在内存中是怎么存储的呢 字符⼀律以ASCII形式存储数值型数据既可以⽤ASCII形式存储也可以使⽤⼆进制形式存储什么意思比如说 如有整数10000如果以ASCII码的形式输出把10000当作字符到磁盘则磁盘中占⽤5个字节每个字符⼀个字节⽽ ⼆进制形式输出则在磁盘上只占4个字节VS2019测试。 展示 测试代码 #include stdio.h
int main()
{int a 10000;FILE* pf fopen(test.txt, wb);fwrite(a, 4, 1, pf);//⼆进制的形式写到⽂件中fclose(pf);pf NULL;return 0;
} 在vs2022上 以二进制的方式打开我们来看看 那我们以 文本的形式打开 好啦理解二进制文件和文本文件之后接下来我们学习文件的打开和关闭。 4. ⽂件的打开和关闭 在此之前先了解一个抽象的概念 4.1 流和标准流 4.1.1 流 我们程序的数据需要输出到各种外部设备也需要从外部设备获取数据不同的外部设备的输⼊输出 操作各不相同为了⽅便程序员对各种设备进⾏⽅便的操作我们抽象出了流的概念我们可以把流 想象成流淌着字符的河。 C程序针对⽂件、画⾯、键盘等的数据输⼊输出操作都是通过流操作的。 ⼀般情况下我们要想向流⾥写数据或者从流中读取数据都是要打开流然后操作。 4.1.2 标准流 那为什么我们从键盘输⼊数据向屏幕上输出数据并没有打开流呢 那是因为C语⾔程序在启动的时候默认打开了3个流 • stdin - 标准输⼊流在⼤多数的环境中从键盘输⼊scanf函数就是从标准输⼊流中读取数据。 • stdout - 标准输出流⼤多数的环境中输出⾄显⽰器界⾯printf函数就是将信息输出到标准输出流中。 • stderr - 标准错误流⼤多数环境中输出到显⽰器界⾯。 这是默认打开了这三个流我们使⽤scanf、printf等函数就可以直接进⾏输⼊输出操作的。 stdin、stdout、stderr 三个流的类型是 FILE* 通常称为⽂件指针。 C语⾔中就是通过 FILE* 的⽂件指针来维护流的各种操作的 。 这怎么理解呢?来看图 相当于中间商处理翻译客户的文件再把以客户熟知方式的输出还给客户。 4.2 ⽂件指针 缓冲⽂件系统中关键的概念是“⽂件类型指针”简称“⽂件指针”。 每个被使⽤的⽂件都在内存中开辟了⼀个相应的⽂件信息区⽤来存放⽂件的相关信息如⽂件的名 字⽂件状态及⽂件当前的位置等。这些 信息是保存在⼀个结构体变量中的。该结构体类型是由系 统声明的取名FILE。 例如VS2013编译环境提供的 stdio.h 头⽂件中有以下的⽂件类型申明 struct _iobuf {char *_ptr;int _cnt;char *_base;int _flag;int _file;int _charbuf;int _bufsiz;char *_tmpfname;};
typedef struct _iobuf FILE; 不同的C编译器的FILE类型包含的内容不完全相同但是⼤同⼩异。 每当打开⼀个⽂件的时候系统会根据⽂件的情况⾃动创建⼀个FILE结构的变量并填充其中的信 息使⽤者不必关⼼细节。 ⼀般都是通过⼀个FILE的指针来维护这个FILE结构的变量这样使⽤起来更加⽅便。 如我们创建一个指针变量 FILE* pf;//⽂件指针变量 定义pf是⼀个指向FILE类型数据的指针变量。可以使pf指向某个⽂件的⽂件信息区是⼀个结构体变 量。通过该⽂件信息区中的信息就能够访问该⽂件。 也就是说通过⽂件指针变量能够间接找到与 它关联的⽂件 。 可以这样理解 好了接下来我们学校有关文件的函数。 4.3 ⽂件的打开和关闭 ⽂件在读写之前应该先打开⽂件在使⽤结束之后应该关闭⽂件。 在编写程序的时候在打开⽂件的同时都会返回⼀个FILE*的指针变量指向该⽂件也相当于建⽴了 指针和⽂件的关系。 ANSIC 规定使⽤ fopen 函数来打开⽂件 fclose 来关闭⽂件 。 //打开⽂件
FILE * fopen ( const char * filename, const char * mode );//两个参数一个是文件名一个是文件使用方式
//关闭⽂件
int fclose ( FILE * stream ); mode表⽰⽂件的打开模式下⾯都是⽂件的打开模式下的操作 ⽂件使⽤⽅式 含义 如果指定⽂件不存在 “r”只读 为了输⼊数据打开⼀个已经存在的⽂本⽂件 出错 “w”只写 为了输出数据打开⼀个⽂本⽂件 建⽴⼀个新的⽂件 “a”追加 向⽂本⽂件尾添加数据 建⽴⼀个新的⽂件 “rb”只读 为了输⼊数据打开⼀个⼆进制⽂件 出错 “wb”只写 为了输出数据打开⼀个⼆进制⽂件 建⽴⼀个新的⽂件 “ab”追加 向⼀个⼆进制⽂件尾添加数据 建⽴⼀个新的⽂件 “r”读写 为了读和写打开⼀个⽂本⽂件 出错 “w”读写 为了读和写建议⼀个新的⽂件 建⽴⼀个新的⽂件 “a”读写 打开⼀个⽂件在⽂件尾进⾏读写 建⽴⼀个新的⽂件 “rb”读写 为了读和写打开⼀个⼆进制⽂件 出错 “wb”读 写 为了读和写新建⼀个新的⼆进制⽂件 建⽴⼀个新的⽂件 “ab”读 写 打开⼀个⼆进制⽂件在⽂件尾进⾏读和写 建⽴⼀个新的⽂ 我们怎么理解读和写看图 这里我们演示一下打开关闭实战代码 /* fopen fclose example */
#include stdio.h
int main ()
{FILE * pFile;//打开⽂件pFile fopen (myfile.txt,w);//⽂件操作if (pFile!NULL){fputs (fopen example,pFile);//关闭⽂件fclose (pFile);}return 0;
}
5. ⽂件的顺序读写
5.1 顺序读写函数介绍 函数名 功能 适⽤于 fgetc 字符输⼊函数 所有输出流 fputc 字符输出函数 所有输出流 fgets ⽂本⾏输⼊函数 所有输出流 fputs ⽂本⾏输出函数 所有输出流 fscanf 格式化输⼊函数 所有输出流 fprintf 格式化输出函数 所有输出流 fread ⼆进制输⼊ ⽂件 fwrite ⼆进制输出 ⽂件 那好我们来一个一个介绍打开网站
https://legacy.cplusplus.com/reference/clibrary/ (1)fputc 参数是文件名和流
代码实现
#includestdio.h
#includemath.hint main()
{FILE* pf fopen(data.txt, w);//写入文件if (pf NULL){perror(fopen);return 1;}fputc(a, pf);//写入一个字符afputc(\n, pf);fputc(b, pf);fclose(pf);return 0;
} fputc只能一个一个字符的输入也可以写一个循环输入多个字符。 for (i 0; i 26; i) {fputc(a 1, pf);fputc(\n, pf);//写完换行} 2fgetc 现在先我们输入字符进“data.txt”文件中比如说输入“abcdefg,然后实现代码读操作
代码
#includestdio.h
#includemath.hint main()
{FILE* pf fopen(data.txt, r);//写入文件if (pf NULL){perror(fopen);return 1;}int ch fgetc(pf);//读取一个字符printf(%c, ch);//打印fclose(pf);pf NULL;return 0;
}
具体操作和输出结果如下 当然也可以写成循环的形式但是要注意什么时候结束比如说
下面代码
#includestdio.h
#includemath.hint main()
{FILE* pf fopen(data.txt, r);//写入文件if (pf NULL){perror(fopen);return 1;}int ch 0;while ((ch fgetc(pf)) ! ) {printf(%c, ch);//打印}fclose(pf);pf NULL;return 0;
}
两种情况 这就要看文件文本句末了避免造成死循环。 接下来我们学习一个复制文件内容的操作
假设文件里面有代码 代码实现
//从data.txt中读取数据
//写到data2.txt的文件中#define _CRT_SECURE_NO_WARNINGS#includestdio.h
#includemath.hint main()
{FILE* pfread fopen(data.txt, r);//读if (pfread NULL){perror(fopen-data1.txt);//报错详细一点return 1;}FILE* pfwrite fopen(data2.txt, w);//写if (pfwrite NULL){fclose(pfread);//如果出现错误先关闭打开文件pfread NULL;perror(fopen-data2.txt);return 1;}//数据的读写拷贝int ch 0;while ((ch fgetc(pfread)) ! EOF){fputc(ch, pfwrite);//把ch写入pfwrite}fclose(pfread);fclose(pfwrite);return 0;
}
输出结果 3fputs 代码实现
#includestdio.h
#includemath.hint main()
{FILE* pf fopen(data.txt, w);if (pf NULL){return 1;}//写文件 - 写一行fputs(abcdef\n, pf);fputs(abcdef\n, pf);fputs(abcdef\n, pf);fputs(abcdef\n, pf);fclose(pf);pf NULL;return 0;
} 输出结果 4fgets 三个参数
1. 输入地的指针
2.输入个数但是要-1因为最后要输入\0
3.流
代码实现 #includestdio.h
#includemath.hint main()
{FILE* pf fopen(data.txt, r);if (pf NULL){return 1;}//读取char arr[20] xxxxxxxxxxxxxxx;fgets(arr, 10, pf);//从流中读取9个字符有一个放入\0放入arr中fclose(pf);pf NULL;return 0;
}
输出结果 当然也可以输出到屏幕上
看代码
#includestdio.h
#includemath.hint main()
{FILE* pf fopen(data.txt, r);if (pf NULL){return 1;}//读取char arr[20] xxxxxxxxxxxxxxx;fgets(arr, 10, stdin);//标准输入流fputs(arr, stdout);//标准输出流fclose(pf);pf NULL;return 0;
}
输出结果 这里要注意的是输入流和输出流在函数的位置。
5fscanf和fprintf fprintf代码实现
#includestdio.h
#includemath.h
struct Stu
{char name[20];int age;float score;
};int main()
{struct Stu s { zhangsan, 20, 90.5f };FILE*pf fopen(data.txt, w);if (pf NULL){return 1;}//写文件//printf(%s %d %.1f, s.name, s.age, s.score)//很相似fprintf(pf, %s %d %.1f, s.name, s.age, s.score);//fclose(pf);pf NULL;return 0;
}
输出结果 同理fscanf
假设文件里有 代码
#includestdio.h
#includemath.h
struct Stu
{char name[20];int age;float score;
};int main()
{struct Stu s {0};FILE* pf fopen(data.txt, r);//读if (pf NULL){return 1;}//写读文件fscanf(pf, %s %d %f, s.name, (s.age), (s.score));fprintf(stdout, %s %d %.1f\n, s.name, s.age, s.score);//输出屏幕//fclose(pf);pf NULL;return 0;
}
输出结果 6. fwrite二进制输出
首先我们先来学习一下这个函数 代码实现
#includestdio.h
#includemath.hstruct Stu
{char name[20];int age;float score;
};int main()
{struct Stu s {zhangsan, 20, 90.5};FILE* pf fopen(data.txt, wb);//wb是以二进制的方式写入if (pf NULL){return 1;}//二进制的形式写文件fwrite(s, sizeof(s), 1, pf);fclose(pf);pf NULL;return 0;
}
输出 这里是以二进制输入的文本翻译成这样是因为文本不具备二进制翻译但是如果以二进制输出是和输入一样的结果下面我们把刚刚以二进制输入文件以二进制输出看看。
7.fread以二进制输出 这里我们可以看到参数和上面的fwite是一样的。
代码实现
#includestdio.h
#includemath.hstruct Stu
{char name[20];int age;float score;
};int main()
{struct Stu s {0};FILE* pf fopen(data.txt, rb);//rb以二进制形式读进if (pf NULL){return 1;}//二进制的形式du文件fread(s, sizeof(s), 1, pf);printf(%s %d %lf, s.name , s.age, s.score );fclose(pf);pf NULL;return 0;
} 输出结果 在这里我们在认识两个函数sscanf和sprintf. 8.sscanf和sprintf.
对比 使用
#include stdio.hstruct S
{char name[20];int age;float score;
};int main()
{struct S s { zhangsan, 20, 85.5f };struct S tmp { 0 };char arr[100] { 0 };sprintf(arr, %s %d %f, s.name, s.age, s.score);//把结构体s的数据输入arrprintf(%s\n, arr);//sscanf(arr, %s %d %f, tmp.name, (tmp.age), (tmp.score));//把arr结构体数据输入tmpprintf(%s %d %f\n, tmp.name, tmp.age, tmp.score);return 0;
} 这里要慢慢理解
6. ⽂件的随机读写
6.1 fseek和ftell
根据⽂件指针的位置和偏移量来定位⽂件指针。
什么意思来 6.2 ftell
返回⽂件指针相对于起始位置的偏移量。
函数内容
long int ftell ( FILE * stream ); 现在我们来实现fseek和ftell
代码展示
#include stdio.hint main()
{FILE* pf fopen(data.txt, r);if (pf NULL){perror(fopen);return 1;}int ch fgetc(pf);printf(%c\n, ch);ch fgetc(pf);printf(%c\n, ch);ch fgetc(pf);printf(%c\n, ch);ch fgetc(pf);printf(%c\n, ch);//让光标指向dint n ftell(pf);//计算相对起始位置的偏移量并保存printf(%d\n, n);fclose(pf);pf NULL;return 0;
} 输出结果 再看看
这个
#include stdio.hint main()
{FILE* pf fopen(data.txt, r);if (pf NULL){perror(fopen);return 1;}int ch fgetc(pf);printf(%c\n, ch);ch fgetc(pf);printf(%c\n, ch);ch fgetc(pf);printf(%c\n, ch);ch fgetc(pf);printf(%c\n, ch);//让光标指向dint n ftell(pf);//计算相对起始位置的偏移量并保存printf(%d\n, n);fseek(pf, -4, SEEK_CUR);//当前位置printf(%c\n, ch);fclose(pf);pf NULL;return 0;
}
输出结果 怎么理解 6.3 rewind
作用让⽂件指针的位置回到⽂件的起始位置 代码展示
#include stdio.h
//data.txt里面有abcdefg
int main()
{FILE* pf fopen(data.txt, r);if (pf NULL){perror(fopen);return 1;}int ch fgetc(pf);printf(%c\n, ch);ch fgetc(pf);printf(%c\n, ch);//光标指向crewind(pf);//让⽂件指针的位置回到⽂件的起始位置ch fgetc(pf);printf(%c\n, ch);fclose(pf);pf NULL;return 0;
}
输出结果 7. ⽂件读取结束的判定
7.1 被错误使⽤的 feof 牢记在⽂件读取过程中不能⽤feof函数的返回值直接来判断⽂件的是否结束。 feof 的作⽤是当⽂件读取结束的时候判断是读取结束的原因是否是遇到⽂件尾结束。 1. ⽂本⽂件读取是否结束判断返回值是否为 EOF fgetc 或者 NULL fgets 例如 • fgetc 判断是否为 EOF . • fgets 判断返回值是否为 NULL . 2. ⼆进制⽂件的读取结束判断判断返回值是否⼩于实际要读的个数。 比如 • fread判断返回值是否⼩于实际要读的个数。 ⽂本⽂件的例⼦ #include stdio.h
#include stdlib.h
int main(void)
{int c; // 注意int⾮char要求处理EOFFILE* fp fopen(test.txt, r);if (!fp) {perror(File opening failed);return EXIT_FAILURE;//1}//fgetc 当读取失败的时候或者遇到⽂件结束的时候都会返回EOFwhile ((c fgetc(fp)) ! EOF) // 标准C I/O读取⽂件循环{putchar(c);}//判断是什么原因结束的if (ferror(fp))//遇到错误结束puts(I/O error when reading);else if (feof(fp))//遇到文末结束puts(End of file reached successfully);fclose(fp);
} ⼆进制⽂件的例⼦ #include stdio.h
enum { SIZE 5 };
int main(void)
{double a[SIZE] { 1.,2.,3.,4.,5. };FILE* fp fopen(test.bin, wb); // 必须⽤⼆进制模式fwrite(a, sizeof * a, SIZE, fp); // 写 double 的数组fclose(fp);double b[SIZE];fp fopen(test.bin, rb);size_t ret_code fread(b, sizeof * b, SIZE, fp); // 读 double 的数组if (ret_code SIZE) {//判断返回值是否⼩于实际要读的个数puts(Array read successfully, contents: );for (int n 0; n SIZE; n) printf(%f , b[n]);putchar(\n);}else { // error handlingif (feof(fp))//yudao文末结束printf(Error reading test.bin: unexpected end of file\n);else if (ferror(fp)) {//遇到错误结束perror(Error reading test.bin);}}fclose(fp);
} 8. ⽂件缓冲区 ANSIC 标准采⽤“缓冲⽂件系统”处理的数据⽂件的所谓缓冲⽂件系统是指 系统⾃动地在内存中为 程序中每⼀个正在使⽤的⽂件开辟⼀块“⽂件缓冲区”。从内存向磁盘输出数据会先送到内存中的缓 冲区装满缓冲区后才⼀起送到磁盘上。如果从磁盘向计算机读⼊数据则从磁盘⽂件中读取数据输 ⼊到内存缓冲区充满缓冲区然后再从缓冲区逐个地将数据送到程序数据区 程序变量等。缓 冲区的⼤⼩根据C编译系统决定的。 例子体验缓冲区的存在 #include stdio.h
#include windows.h
//VS2019 WIN11环境测试
int main()
{FILE* pf fopen(test.txt, w);fputs(abcdef, pf);//先将代码放在输出缓冲区printf(睡眠10秒-已经写数据了打开test.txt⽂件发现⽂件没有内容\n);Sleep(10000);printf(刷新缓冲区\n);fflush(pf);//刷新缓冲区时才将输出缓冲区的数据写到⽂件磁盘//注fflush 在⾼版本的VS上不能使⽤了printf(再睡眠10秒-此时再次打开test.txt⽂件⽂件有内容了\n);Sleep(10000);fclose(pf);//注fclose在关闭⽂件的时候也会刷新缓冲区pf NULL;return 0;
} 这⾥可以得出⼀个结论 因为有缓冲区的存在C语⾔在操作⽂件的时候需要做刷新缓冲区或者在⽂件操作结束的时候关闭⽂件如果不做可能导致读写⽂件的问题。 好啦今天就到这里了都看到这里了点一个赞吧感谢观看。