学生成绩管理系统
期末了,老师布置了C语言综合实验,程序写完了,结果答辩被取消了,有点可惜,现在把它放在这里。(直接看源代码的请划到最后)
实验题目
一、实验目的
通过该实验把C语言中基本知识(如:顺序结构、选择结构、循环结构、数组、函数、指针、链表等)得到综合应用。完成学生成绩管理系统基本功能设计,提高学生的编程能力和分析问题、解决问题的能力。
二、设备环境
硬件:多媒体计算机
软件:Windows系列或DOS系列的操作系统、C语言。
三、实验内容
实验内容
- 学生基本信息录入(包括学号,姓名,至少三门课成绩)
- 学生基本信息的输出
- 按学号查询学生信息
- 按学号修改某学生信息并输出
- 求每个人平均成绩
- 删除某学生信息
- 添加某学生信息
- 输出平均分大于80分的同学信息
- 根据总成绩或平均成绩综合排名(此功能用链表处理的同学可不做)
实验要求
a、用结构体数组或链表存储学生信息
b、基本功能用函数实现
c、至少完成实验内容中5个功能,学生可以自己增加或减少题目功能
d、程序能正确执行、输入与输出有必要的提示信息、界面美观
e、用菜单调用加分,用链表加分、用文件加分。
-------------------------------分界线-------------------------------
程序部分
根据要求,学生信息至少包括学生、学号和至少三门课的成绩,在这里假设三门课为语文、数学和英语。定义结构体stduent。
struct student//结构体student定义
{
int number;//学号
char name[20];//姓名
int account_chinese;//语文成绩
int account_math;//数学成绩
int account_english;//英语成绩
};
目录部分,使用switch+while语句实现,在此程序中,我使用了直接对文件中的学生信息读取,每一次在对学生信息读取完毕后,把数据临时存储在结构体stduent数组里,对学生数据操作完毕后,在将原来的数据文件删除,再把数据写入到新的文件里。因此,在case分支中使用了goto语句在执行完相应功能后删除原来存储的临时数据,使用free(),并跳转到程序开始重新读取文件,从而重新读取新的临时数据。
int main(void)
{
//变量声明
FILE* pfile;
char ch;
int i, n;
struct student* pdata;
//开始文件读取,通过文件的数据的行数,计算结构体student素组的元素个数
flag1:
pfile = NULL, i = 0, n = 0, pdata = NULL, ch = 0;
pfile = fopen("1.txt", "r+");
printf("文件正在读取中...\n");
while ((ch = fgetc(pfile)) != EOF)
{
if (ch == '\n')
i++;
}
n = i;
pdata = (struct student*)malloc(i * sizeof(struct student));//申请分配动态内存
i = 0;
rewind(pfile);
while (i < n)
{
fscanf(pfile, "%d %s %d %d %d", &pdata[i].number, pdata[i].name, &pdata[i].account_chinese, &pdata[i].account_math, &pdata[i].account_english);
i++;
//利用fscanf()从文件内读取数据
}
rewind(pfile);
fclose(pfile);
system("cls");
printf("读取完毕\n");
puts("***************MENU***************");
printf("1:学生信息录入\n2:学生基本信息输出\n3:按学号查询学生信息\n4:按学号修改某学生的信息并输出\n5:求每个人的平均成绩\n6:删除某学生的信息\n7:添加某学生信息\n8:输出平均分大于80分学生的同学信息\n9:根据总成绩或平均成绩综合排名\nq:退出\n");
while ((ch = getchar()) != 'q')//switch与while实现菜单的交互功能
{
//在对源文件进行了覆盖操作后,关闭文件指针,重新打开新文件,这里利用了goto实现
switch (ch)
{
case'1':
sutdents_information_input();
free(pdata);
getchar();
goto flag1;
break;
case'2':
students_information_output(pdata, n);
free(pdata);
getchar();
goto flag1;
break;
case'3':
students_information_search(pdata, n);
free(pdata);
getchar();
goto flag1;
break;
case'4':
students_information_modify(pdata, n);
free(pdata);
getchar();
goto flag1;
break;
case'5':
account_average(pdata, n);
free(pdata);
getchar();
goto flag1;
break;
case'6':
delete(pdata, n);
free(pdata);
getchar();
goto flag1;
break;
case'7':
add(pdata, n);
free(pdata);
getchar();
goto flag1;
break;
case'8':
account_select(pdata, n);
free(pdata);
getchar();
goto flag1;
break;
case'9':
bank(pdata, n);
free(pdata);
getchar();
goto flag1;
break;
default:
printf("输入错误请重试\n");
}
}
fclose(pfile);
free(pdata);
return 0;
}
其中调用函数的原型如下
void sutdents_information_input(void);//学生信息输入
void students_information_output(struct student* p, int i);//学生信息输出
void students_information_search(struct student* p, int i);//学生信息查找
void students_information_modify(struct student* p, int i);//学生信息修改并输出
void account_average(struct student* p, int i);//计算学生的综合成绩
void delete(struct student* p, int i);//删除学生的信息
void add(struct student* p, int i);//增加学生的信息
void account_select(struct student* p, int i);//查找平均分大于80分的学生的信息
void bank(struct student* p, int i);//排名
学生信息录入部分使用了windows命令行打开当前目录下的数据文件,在这里使用system()实现,在录入数据时,应在数据文本末尾加回车,方便main()中对结构体数组的元素个数进行计数。函数定义如下。
void sutdents_information_input(void)
{
printf("请于记事本中进行信息录入\n");
system("1.txt");//利用命令行打开文件1.txt进行编辑
}
学生信息输出部分采用直接对读取到的临时数据进行输出即可。函数定义如下。
void students_information_output(struct student* p, int i)
{
int n = 0;
printf("学号 姓名 语文 数学 英语 \n");
while (n < i)
{
printf("%7d %-15s %5d %5d %5d\n", p[n].number, p[n].name, p[n].account_chinese, p[n].account_math, p[n].account_english);
n++;//利用printf()实现格式化输出
}
printf("任意按键请继续...");
getchar();
}
对学生信息的查找使用了顺序查找,原因是在源数据文件中的数据排次并不是按大小依次录入的。函数定义如下。
void students_information_search(struct student* p, int i)
{
int search = 0, n = 0;
_Bool flag = 1;
//设立search存储查找目标,flag用于标记是否查找成功,n为循环自变量
printf("请输入您要查找的学生学号:");
scanf("%d", &search);
getchar();
while (n < i)//在这里使用了顺序查找
{
if (p[