学生成绩管理程序主菜单写出了该程序具备的功能:
一、最初的没有文件读写功能的学生成绩管理程序
我们最初的程序,实现了学生信息的增、删、改、查和打印功能,并没有文件读写功能。程序如下。
程序1:
我们昨天将学生成绩管理程序的保存功能加上了,就是说我们输入的学生信息在程序结束之前都保存到一个文件里了。
二、增加了保存文件(写文件)功能的学生成绩管理程序
我们将昨天讲的写文件的函数saveFile( )加进上述代码,即将程序1的第2部分的代码改成如下形式:
此时读文件的函数readFlie( )还没有写。
程序1的第3部分,在主函数中增加一行代码:saveFlie(a); 调用saveFile( )保存我们从键盘输入的学生信息(即数组变量a的所有元素)。
我们运行这个程序时,可以将从键盘输入的学生信息保存到文件Student.txt中。
但是当我们再次运行程序时,发现数据还是空的,为什么呢?因为我们没有把文件里的学生信息读到程序中。
今天我们把这个功能加上。
三、如何将文件的内容读出来并保存到程序的变量中?
我们先看文件Student.txt文件里面有什么信息。
文件Student.txt每一行是一个学生的信息:学号、姓名和成绩,我们要读出这个文件的内容,怎么实现呢?
先写一个读文件的简单验证程序,单纯实现读出文件的内容。
程序2:读出文件Student.txt的内容。
number是全局变量,存放学生总人数,虽然在程序2中用不到number,但是每读出文件一行信息,number就加1。
循环体中有4句:
第1句:文件输入函数fscanf( )把文件内容读出来给数组a;
第2句:每读出一行信息就让number加1,即学生总人数加1;
第3句:标准输出函数printf( )把这行信息显示出来让我们看;
第4句:i加1,即数组下标加1。
如果把函数readFile( )加到学生成绩管理程序中的时候,是不需要每读出一行信息就用printf函数把这行信息输出到显示器上,这里是为了验证,所以加了这行输出信息到显示器上的代码:
程序1运行结果:
如果我们把文件Student.txt删掉,现在这个文件Student.txt不存在,那么程序1是否还能正常运行呢?
此时程序运行结果为:
出现乱码,不对了。
我们看看是什么原因?
这是因为:
当文件不存在时,输出“文件不存在!”,然后后面有执行while(!feof(fp)),文件都不存在了还要fscanf()读信息,当然会出现乱码啦。
怎么改呢?
在if后面要加else,这个else写在while(!feof(fp))前面。代码如下:
当文件不存在时,程序1运行结果为:
显示“文件不存在!”后程序就结束了,不会出现乱码。
四、完整的学生成绩管理程序:增加了保存文件(写文件)和读文件的功能
现在我们把函数readFile( )添加到学生成绩管理程序中,在程序运行一开始就调用readFile( )把文件的内容读出到数组变量a中,此时我们把readFlie( )中的输出语句:
删掉了,这里只是读出数据赋值给数组变量a,不需要输出。
程序1的第2部分改为:
程序1的第3部分主函数中,在运行开始就调用函数readFlie( ),读出文件内容到数组变量a中,在程序准备结束时调用函数saveFile( ) 将数组变量a中所有元素写到文件中保存。
第一次运行程序,若文件Student.txt不存在,则先显示“文件不存咋!”以后再出现主菜单。
以下是完整程序代码,可以直接复制运行。
//********************程序开始************************//
#include <stdio.h>
//第1部分:定义结构类型、全局变量
struct STUD
{ int xh; // 学号
char name[20]; // 姓名
int cj; // 成绩
};
int number=0; // 全局变量,学生总数
//第2部分:函数原型声明
void f1(struct STUD a[]);
void f2(struct STUD a[]);
void f3(struct STUD a[]);
int f4(struct STUD a[]);
void f5(struct STUD a[]);
void saveFile(struct STUD a[]);//写文件
void readFile(struct STUD a[]);//读文件
void saveFile(struct STUD a[])
{ FILE *fp;
int i;
fp=fopen("Student.txt","w"); //打开方式 w, 清空原有内容,全部重写
for(i=0;i<number;i++) //共有number名学生
{
fprintf(fp,"%d %s %d\n", a[i].xh, a[i].name, a[i].cj);
}
fclose(fp);
}
void readFile(struct STUD a[])
{ FILE *fp;
int i=0; //循环变量
fp=fopen("Student.txt","r"); //打开方式 r, 读文件
if((fp=fopen("Student.txt","r")) == NULL)
{
printf("文件不存在!\n");
}
else
{
while(!feof(fp))
{ fscanf(fp,"%d %s %d\n", &a[i].xh, a[i].name, &a[i].cj);
number++; //学生人数加1
// printf("%d %s %d\n", a[i].xh, a[i].name, a[i].cj);
i++;
}
}
fclose(fp);
}
//第3部分 主函数
int main( )
{ struct STUD a[100]; int xz, f=1;
readFile(a); //调用读文件函数,读出文件内容到数组a中
while(f==1)
{ printf("\n********************\n");
printf(" *1 增加 *\n *2 删除 *\n");
printf(" *3 修改 *\n *4 查询 *\n");
printf(" *5 打印 *\n *0 退出 *\n");
printf("********************\n");
printf("请选择:");
scanf("%d", &xz);
switch(xz)
{ case 1: f1(a); break;
case 2: f2(a); break;
case 3: f3(a); break;
case 4: f4(a); break;
case 5: f5(a); break;
case 0: f=0; break;
}
}
saveFile(a); //调用写文件函数,保存数组a所有元素
return 0;
}
//第4部分 增加学生信息的函数f1
void f1(struct STUD a[]) //增加
{
int n, i;
printf("您需要增加多少个学生记录:");
scanf("%d", &n);
for(i=number;i<number+n;i++)
{
printf("请输入学号:");
scanf("%d", &a[i].xh);
printf("请输入姓名:");
scanf("%s", a[i].name);
printf("请输入成绩:");
scanf("%d", &a[i].cj);
}
number=number+n;
printf("添加成功\n");
}
//第5部分 查询学生信息的函数f4
int f4(struct STUD a[]) //查询
{
int flag; int i,x; int xz;
printf("\n请输入要修改的学号:");
scanf("%d",&x);
for(i=0;i<number;i++)
{
if(a[i].xh==x)
{
printf("找到学号为%d的学生,该生信息如下:\n",x) ;
printf("%d %s %d \n", a[i].xh,a[i].name,a[i].cj);
flag=i;
break;
}
}
if(i>=number)
{
printf("查无此人\n");
flag=-1;
}
return flag;
}
//第6部分 删除学生信息的函数f2
void f2(struct STUD a[]) //删除
{
int d=f4(a); //先调用f4查找有没有这个学生
if(d==-1)
printf(" 查无此人,无法删除\n");
else
{
a[d].xh=-1; //直接将学号改成-1
printf("删除成功\n");
}
}
//第7部分 修改学生信息的函数f3
void f3(struct STUD a[]) //修改
{
int d=f4(a); //先调用f4查找有没有这个学生
if(d==-1)
printf(" 查无此人,无法修改\n");
else
{
printf("请输入新的学号、姓名、成绩:\n");
scanf("%d%s%d",&a[d].xh,a[d].name,&a[d].cj);
printf("修改成功\n");
}
}
//第8部分 打印所有学生信息
void f5(struct STUD a[]) //打印
{
int xz, flag=1, i;
struct STUD max;
for(i=0;i<number;i++)
{
if( a[i].xh != -1 ) //把学号不等于-1的信息删除
printf("%d %s %d\n",a[i].xh,a[i].name,a[i].cj);
}
}
//********************程序结束************************//
至此我们完成了一个具有增删改查及保存功能的学生成绩管理程序。