前言
大家吼啊,快过年了,这应该是年前的最后(?)一篇博客了,这次博客主要讲一下C语言在打开文件时候发生的事情和打开文件的函数等知识,希望大家多多三连支持一下我这个可怜的跑路人.如果你是刚刚学习C语言的小白也可以和俺练习,私信我我会尽可能快的回复你的.
为什么使用文件
当我们使用需要储存内容到磁盘的程序时(如通讯录),我们就需要使用文件,不然我们所储存的内容随着程序的结束而消失会减少很多我们程序所应该有的能力.而使用了文件就可以将数据储存到我们电脑的硬板中只有当我们删除他是才会消失.
什么是文件
我们通过文件的功能不同将文件分为程序文件和数据文件.
当然通俗的讲磁盘储存的文件就是文件(好像是废话=-=)
程序文件
包括源程序文件(后缀为.c),目标文件(windows环境后缀为.obj),可执行程序(windows环境 后缀为.exe)。在预处理章节有学到,忘记的同学可以到我的主页中找.
数据文件
本章所讲的主要就是数据文件:内容不一定是程序,而是程序运行时读写的数据,比如程序运行需要从中读取数据的文件, 或者输出内容的文件。
文件名
一个文件要有一个唯一的文件标识,以便用户识别和引用。
文件名包含3部分:文件路径+文件名主干+文件后缀
如:c:\code\test.txt就是一个文件名
其中c:\code\是文件路径 test是文件名主干 .txt是文件后缀
为了方便起见我们将文件标识称为文件名.
文件名
一个文件要有一个唯一的文件标识,以便用户识别和引用。
文件名包含3部分:文件路径+文件名主干+文件后缀
如:c:\code\test.txt就是一个文件名
其中c:\code\是文件路径 test是文件名主干 .txt是文件后缀
为了方便起见我们将文件标识称为文件名.
文件的打开和关闭
当我们通过函数将文件打开的时候函数会返回一个FILE类型的指针,我们一般将它称之为文件类型指针或文件指针而FILE类型其实是我们编译器自动创建的一个结构体类型——用于储存文件的相关信息。之后我们的编译器将结构题重命名为FILE。
struct _iobuf { char *_ptr; int _cnt; char *_base; int _flag; int _file; int _charbuf; int _bufsiz; char *_tmpfname; }; typedef struct _iobuf FILE;
如我们stdio.h文件在VS2019中就有如上的结构体储存和命名,当然结构体信息的填充已经有我们的编译器完成了我们无需对其细节进行了解.
我们可以通过FILE类型的指针对我们打开的文件进行调整和编译.
文件打开和关闭的函数使用
ANSIC 规定使用fopen函数来打开文件,fclose来关闭文件。
//打开文件 FILE * fopen ( const char * filename, const char * mode ); //关闭文件 int fclose ( FILE * stream );
fopen函数使用:
返回值是我们的FILE类型的指针所以我们要用FILE类型的指针来接收,这样我们就可以通过指针来对其进行调用
filename是我们的文件主干+后缀名或文件名,当我们所创建的文件就在我们工程文件夹里时我们可以直接使用文件主干+后缀名的方式打开当我们的文件在其他文件夹里时我们需要将文件路径加上(注意\与后面的数结合会变成转义字符所以我们需要用\\才能实现)
int main() { FILE* pf = fopen("test.dat", "w");//直接通过文件主干+后缀名 return 0; } //或加上文件路径 int main() { FILE* pf = fopen("D:\\编辑语言\\the-way-of-c-language-learning\\1.26\1.26\\test.dat", "w");//通过路径+文件主干+后缀名 return 0; }
当然我们通过函数创建的文件都可以直接用文件+后缀名找到
mode是我们使用这个文件的模式。
(CSDN在传表格时实在是高血压,我就直接放截图了)
使用方式如下表格:
fclose的使用:
将要关闭的文件指针给他就好。
事例:
/* fopen fclose example */ #include <stdio.h> int main () { FILE * pFile; //打开文件 pFile = fopen ("myfile.txt","w"); //文件操作 if (pFile!=NULL)//fopen开辟失败时会返回空指针所以在使用时最好对其进行检查 { fputs ("fopen example",pFile); //关闭文件 fclose (pFile); } return 0; }
文件的顺序读写
首先引入一下流:我们程序需要输出到不同的地方,而流就是程序和需要接收信息地方中间的一个部分,流可以改变程序形式使程序和所需地方吻合。
所以也就有了上图的适用于其实就是适用于什么流。
我们在编程时默认打开了三个流
stdin 标准输入流 到键盘
stdout 标准输出流 到屏幕
stderr 标准错误流 到屏幕
前四个之间相同,博主就将前两个功能简单的介绍一下
fgetc :
int fgetc( FILE *stream );
从文件指针指向的位置读取一个字符并返回这个字符的ASCII值如果读取失败返回EOF。
fputc:
int fputc( int c, FILE *stream );
将一个字符放进文件流(或其他你传入的流)中。
对于函数的使用我就挑几个重要的进行对比
fprintf和fscanf与原函数对比
我们将printf和fprintf进行对比
fprintf和printf只多了一个流所以我们直接将文件指针传给fprintf就好,这样我们就可以像printf一样使用fprintf只不过我们面向的对象从缓冲区变成了文件。
如: fprintf(pt,"%s",“abcdef”); 就是将abcdef打印到文件中了。
fscanf 和scanf的对比
也是比scanf多了一个文件指针,他可以从文件里读取数据储存到变量中,
如fscanf(pf,"%s",arr);就是将pf文件里的一个字符串%s读取到arr中
有时也会考察sprintf、printf、sscanf、scanf之间的对比
sprintf 和sscanf与原函数的对比
sprintf:
sprintf比printf多了一个buffer,与printf不同的是sprintf会将后面的内容打印到buffer中无论后面内容是整形还是浮点型都会转换才字符串的形势打印到buffer中
sscanf:
多了一个buffer,sscanf从字符串buffer中读取信息放到后面对应内容中
fread: 把二进制文件里的信息读出并放在变量中
buffer是我们要储存信息的变量地址
size是要读取信息的大小
count是要读取信息的数量
stream是文件指针。
返回值是读到的数据个数,如果没有读到就返回0
fwrite:把输入的信息以二进制的形势储存的文件中
注意以二进制形式储存的文件不能直接打开文件阅读(毕竟你读不懂=-=)
一般会长这样:
和fread相似不过是从读变成了写。
(在使用这些函数之前记得将fopen的打开模式调整到相应的模式。)
打开使用完记得关闭和对指针进行空指针赋值。
(后面的通讯录文章会使用文件的相关知识。)