目录
5.2 scanf fscanf sscanf 的区别(简易版)
首先,没有文件数据没法保存。文件就是用来存东西的,如果我们没有文件,我们写的程序都是存储到内存中,如果程序退出,内存就会回收,数据就没了。就像你在 剪辑视频,你忘记保存了,软件的自动保存时间也没到,电脑断电了,这时你的所有数据就G了都没了。但如果我们把数据都保存到文件里了,下次使用打开文件就可以了。数据依然存在。
文件就是你存在C盘 D盘这些盘里的东西都是文件。
但在程序设计中我们一般说的文件有两种:程序文件和数据文件
程序⽂件包括源程序⽂件(后缀为.c),⽬标⽂件(windows环境后缀为.obj),可执⾏程序(windows 环境后缀为.exe)。
⽂件的内容不⼀定是程序,⽽是程序运⾏时读写的数据,⽐如程序运⾏需要从中读取数据的⽂件,或 者输出内容的⽂件。本章讨论的是数据⽂件。在以前各章所处理数据的输⼊输出都是以终端为对象的,即从终端的键盘输⼊数据,运⾏结果显⽰到 显⽰器上。其实有时候我们会把信息输出到磁盘上,当需要的时候再从磁盘上把数据读取到内存中使⽤,这⾥处 理的就是磁盘上⽂件。
⼀个⽂件要有⼀个唯⼀的⽂件标识,以便⽤⼾识别和引⽤。⽂件名包含3部分:⽂件路径+⽂件名主⼲+⽂件后缀例如: c:\code\test.txt为了⽅便起⻅,⽂件标识常被称为⽂件名。
数据文件有两种 一种叫 文本文件一种叫 二进制文件。
因为数据在内存中是以二进制存储,如果不加转换输出,就是二进制文件。
如果输出到外存的时候以ASCII码的形式转换,那就会进行转换。这是文本文件。
⼀个数据在内存中是怎么存储的呢?字符⼀律以ASCII形式存储,数值型数据既可以⽤ASCII形式存储,也可以使⽤⼆进制形式存储。如有整数10000,如果以ASCII码的形式输出到磁盘,则磁盘中占⽤5个字节(每个字符⼀个字节),⽽⼆进制形式输出,则在磁盘上只占4个字节(VS2019测试)。

我们有一个程序,需要输出到各种设备上面,像电脑屏幕,手机屏幕,电视屏幕。同时也有从外部设备获取数据,键盘输入,手柄输入这样的指令。为了方便操作,所以抽象出了流这个概念,就像一条河里面全是数据。
C程序针对⽂件、画⾯、键盘等的数据输⼊输出操作都是同流操作的。⼀般情况下,我们要想向流⾥写数据,或者从流中读取数据,都是要打开流,然后操作。
那为什么我们用scanf printf 这类函数的时候就不需要 打开流呢?
因为c语言中自动打开了3个流:
• stdin - 标准输⼊流,在⼤多数的环境中从键盘输⼊。• stdout - 标准输出流,⼤多数的环境中输出⾄显⽰器界⾯。• stderr - 标准错误流,⼤多数环境中输出到显⽰器界⾯。stdin、stdout、stderr三个流的类型是: FILE* ,通常称为⽂件指针。C语⾔中,就是通过 FILE* 的⽂件指针来维护流的各种操作的。
每个被使⽤的⽂件都在内存中开辟了⼀个相应的⽂件信息区,⽤来存放⽂件的相关信息(如⽂件的名 字,⽂件状态及⽂件当前的位置等)。这些信息是保存在⼀个结构体变量中的。该结构体类型是由系 统声明的,取名FILE.
这是stdio .h文件中自带的文件类型声明。
- struct _iobuf {
- char *_ptr;
- int _cnt;
- char *_base;
- int _flag;
- int _file;
- int _charbuf;
- int _bufsiz;
- char *_tmpfname;
- };
- typedef struct _iobuf FILE;
可以用一个FILE* pf 指针去指向 FILE 数据类型的指针变量。
对于文件来说,如果你在读写前打开文件,结束后也得关闭文件。
在程序编写中,打开文件的同时,都要返回一个FILE*的指针变量指向文件,就等于建立了指针和文件的关系。
ANSIC规定用fopen打开文件,fclose关闭文件
// 打开⽂件FILE * fopen ( const char * filename, const c ar * mode );// 关闭⽂件int fclose ( FILE * stream );mode表⽰⽂件的打开模式
下面是文件打开方式的类型。

示例代码:
- int main()
- {
- FILE* pFile;
- //打开⽂件
- pFile = fopen("myfile.txt", "w");
- //⽂件操作
- if (pFile != NULL)
- {
- fputs("fopen example", pFile);
- //关闭⽂件
- fclose(pFile);
- }
- return 0;
- }

上⾯说的适⽤于所有输⼊流⼀般指适⽤于标准输⼊流和其他输⼊流(如⽂件输⼊流);所有输出流⼀ 般指适⽤于标准输出流和其他输出流(如⽂件输出流)。

根据参数可以看出,scanf 默认是从 键盘输入并没有 用到其他的流。
fscanf 可以用流来输入,说明fscanf 可以用键盘也可以用文件输入等等。
sscanf这里的意思就是从字符串中读取到格式化的数据,也就是说我们输入进去的数据,sscanf会转化成字符串的形式
printf 也基本同理。
根据文件指针的位置和偏移量定位文件指针
简单来说就是输入一个数字,然后找到 文件里的这个数字字节的位置。
int fseek ( FILE * stream, long int offset, int origin );(函数参数)
- #include
- int main()
- {
- FILE* pFile;
- pFile = fopen("example.txt", "wb");
- fputs("This is an apple.", pFile);
- fseek(pFile, 9, SEEK_SET);
- fputs(" sam", pFile);
- fclose(pFile);
- return 0;
- }
结果应该是 This is a sample。
返回文件指针 和起始位置之间的偏移量
long int ftell ( FILE * stream );
让文件指针的位置返回到文件起始的位置。
void rewind ( FILE * stream );
记住feof 不能用来判断文件是否结束。feof只能用来判断结束的原因是遇到文件末尾结束。
简单点说就是feof 判断 文件是否成功结束,而不是中间就断了。
1. ⽂本⽂件读取是否结束,判断返回值是否为 EOF ( fgetc ),或者 NULL ( fgets )例如:• fgetc 判断是否为 EOF .• fgets 判断返回值是否为 NULL .2. ⼆进制⽂件的读取结束判断,判断返回值是否⼩于实际要读的个数。例如:• fread判断返回值是否⼩于实际要读的个数。

在使用程序的时候系统会给正在使用的文件开辟一块“文件缓冲区”,从内存向磁盘输入数据的时候要先送向输出缓冲区,等缓冲区充满才会送上磁盘,相反也一样。最后再从缓冲区逐个把数据送到程序数据区(程序变量等。),缓冲区大小根据编译系统决定。
有缓冲区后,
这⾥可以得出⼀个结论:因为有缓冲区的存在,C语⾔在操作⽂件的时候,需要做刷新缓冲区或者在⽂件操作结束的时候关闭⽂ 件。 如果不做,可能导致读写⽂件的问题