这是C语言入门的第27篇文章。
今天讲学生成绩管理程序的完善:怎样利用文件来保存数据。
还是昨天的问题:我怎么知道一个文件的内容是什么?我怎么知道比如一行有多少个数,多少个数以后是换行?
这是因为文件是我们自己创建的,我们当然知道有什么内容。
一般一个程序要创建的文件,肯定是先写,然后才读。
那么如果一个文件的内容不知道,我又想读出它的内容,可以吗?
这种情况最好是用到二进制文件的读写,因为二进制文件不管什么整数实数或字符,统统按字符形式读出来,读到文件末结束。
文本文件(即格式化文件)的读写函数用fscanf和fprintf:
二进制文件的读写函数用fread()和fwrite():
但我们主要讲格式化文件(文本文件)的读写,二进制文件的读写待深入学习后再说。
另外,写文件时,该文件是否存在都无关紧要,若不存在会创建新文件。
但读文件时,这个文件必须存在,否则打开文件时会出错。
也就是说:
若以w、aw等方式打开文件(写文件)时,文件是否存在无关紧要;
但以r的方式打开文件(读文件)时,文件必须存在。
所以一般在读文件时,打开文件的语句放在一个if语句里面。
我们不会直接写:
而是写成:
意思是若文件Student.txt不存在时,打开文件的操作返回值为空NULL,赋值给指针变量fp2,fp2就是空指针。
现在来看一个程序,直接读出文件内容:
程序1:
假设AAA.txt的内容为:
则运行结果为:
这里当然是因为我们知道了文件AAA.txt的格式是一行三个整数,所以fscanf里面输入三个整数后要加一个换行。
另外我们打开文件时,用
文件名是”AAA.txt”,表示打开的是当前文件夹里的文件。
如果我要打开一个文件不是当前文件夹里的,比如是存在D盘下的一个文件夹MyC的文件AAA.txt,则文件名前面要加上路径:
写文件时也一样。
之前讲过一个学生成绩管理程序,主菜单如图,输入数字进行相应的操作。如按1键实现“增加学生信息”功能,按2键实现“查找学生”功能,按3键实现“修改学生信息”功能,按4键实现“删除学生信息”功能,按5键实现“显示所有学生信息”功能,按0键实现“退出系统”功能。
实现了上述所有功能的程序2:
运行结果如下:
假设一个班有50名学生,那么我添加完50名学生的信息,进行相应操作后,结束程序。
第2天我再运行这个程序,昨天输入的50名学生的信息又没有了,又得进行重新输入,太麻烦了。
所以今天我们来完善这个程序,我们要把所有的学生信息在程序结束前要保存起来,这样第二天再运行这个程序就不需要重新输入了。
所以添加两个函数,一个函数是把数据保存到文件里(写文件),文件名命名为Student.txt,一个函数是把文件里的数据读出来(读文件)。
写文件的函数我命名为saveFile,形式参数为结构体数组变量a,这个数组存放了所有学生的信息,所以形参为struct STUD a[ ],函数类型为void,函数原型声明为:
void saveFile( struct STUD a[ ] ) ;
读文件的函数我命名为reafFile,形式参数为结构体数组变量a,要将文件里的所有信息读到这个数组,所以形参为struct STUD a[ ] ,函数类型为void,函数原型声明为:
void readFile( struct STUD a[ ] ) ;
首先在第2部分函数原型声明那里加上这两个函数的声明:
保存数据(写文件)的函数saveFile定义如下:
形参为结构数组变量a,函数体中用到了全局变量number,number存放学生总人数。
文件操作4步骤:
第1步:定义文件指针变量:
FILE *fp;
第2步:打开文件:
fp=fopen("Student.txt","w");
注意这里打开方式为”w“,而不是”aw”,这是因为每次我们保存数据到文件就是把数组a的全部数据,从a[0]到a[number-1]全部保存到文件里,文件原有内容清空,因为a是最新的数据。
第3步:写文件:
fprintf(fp,"%d%s%d\n", a[i].xh, a[i].name, a[i].cj);
循环执行这个写命令,循环次数从0到number-1,就是将数组a[0]到a[numer-1]的元素全部写到文件Student.txt里。
第4步:关闭文件:
fclose(fp);
这个函数在主函数main中调用,在程序结束前加上这句:saveFile(a);
程序第2部分修改:
增加了两个函数saveFile和reafFile的函数原型声明,以及写文件函数saveFile的实现代码,如图:
程序第3部分主函数main的代码改为:
运行结果:
这是在当前文件夹可以看到有一个文件Student.txt,打开这个文件,内容如下:
刚才输入的三个学生信息已经保存到文件里了。
我们再次运行程序,得到运行结果:
不对呀,我们刚刚不是已经输入了学号为1姓名为张三的学生信息了吗?怎么查不到?
因为程序3还没有读文件。
读文件的函数readFile在main函数中被调用,这个调用要放在所有操作之前,比如放在菜单出现之前。
先自己试着完善一下这个程序,加上读文件的操作。