// 学生成绩管理系统
// Created by mac on 2021/6/15.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//定义学生结构体
typedef struct Node
{
char num[20];//学号
char name[20];//姓名
double grade[6];//各科成绩:数据结构、高等数学、大学英语、线性代数、职业规划、思修道德
double sum;//总分
int good_count;//优秀科目数目
int bad_count;//挂科科目数目
int rank[2];//总分排名,rank[0]为第一组数据排名
int up_or_down;//排名升降
struct Node *next;//指针域
}node;
//定义链表
node List_RJ_1;//软件工程三个班第一组数据
node List_RJ_2;//软件工程三个班第二组数据
node List_RJ_3;//软件工程三个班第一组数据
//测试数据说明:
//1.总分排行榜测试文本RJ_1
//2.优秀排行榜测试文本RJ_2
//3.挂科排行榜测试文本RJ_3
//4.进步排行榜:测试两个文本数据RJ_1、RJ_2,rank比较得出排名升降
//5.增加、删除、修改、查询、删除学生信息均测试文本RJ_1
//**********************************************文件函数声明**********************************************//
int ReadFile1(node *L);//1.读取文本RJ_1
int ReadFile2(node *L);//2.读取文本RJ_2
int ReadFile3(node *L);//3.读取文本RJ_3
int SaveFile(node *L);//2.保存文本
//**********************************************功能函数声明**********************************************//
void Menu(void);//0.主菜单界面
void TotalScoreRanking(node *L);//1.总分排行榜
void ExcellentRanking(node *L);//2.优秀排行榜
void HangingSubjectRankings(node *L);//3.挂科排行榜
void PrintProgressLeaderboard(node *L1,node *L2);//4.进步排行榜
void PrintAddStuInfo(node *L);//5.增加学生信息
void PrintDeleteStuInfo(node *L);//6.删除学生信息
void PrintFixStuInfo(node *L);//7.修改学生信息
void PrintSearchStuInfo(node *L);//8.查询学生信息
node* SearchStuInfo1(char num[],node *L);//查找学号函数
void PrintStuInfo(node *L);//9.输出学生信息
void EscProgrammer(void);//10.退出管理系统
//***********************************************主函数***********************************************//
int main()
{
ReadFile1(&List_RJ_1);//读入测试文本RJ_1,即软件工程三个班第一组数据
ReadFile2(&List_RJ_2);//读入测试文本RJ_2,即软件工程三个班第二组数据
ReadFile3(&List_RJ_3);//读入测试文本RJ_3,即软件工程三个班第三组数据
int choice=0;
while(1)
{
Menu();
scanf("%d",&choice);
switch (choice)
{
case 1:
printf("1.总分排行榜:\n");
TotalScoreRanking(&List_RJ_1);break;//总分排行榜测试文本RJ_1
case 2:
printf("2.优秀排行榜:\n");
ExcellentRanking(&List_RJ_2);break;//优秀排行榜测试文本RJ_2
case 3:
printf("3.挂科排行榜:\n");
HangingSubjectRankings(&List_RJ_3);break;//挂科排行榜测试文本RJ_3
case 4:
printf("4.进步排行榜:\n");
PrintProgressLeaderboard(&List_RJ_1,&List_RJ_2);break;
case 5:
printf("5.增加学生信息:\n");
PrintAddStuInfo(&List_RJ_1);break;
case 6:
printf("6.删除学生信息:\n");
PrintDeleteStuInfo(&List_RJ_1);break;
case 7:
printf("7.修改学生信息:\n");
PrintFixStuInfo(&List_RJ_1);break;
case 8:
printf("8.查询学生信息:\n");
PrintSearchStuInfo(&List_RJ_1);break;
case 9:
printf("9.输出学生信息:\n");
PrintStuInfo(&List_RJ_1);break;
case 10:
printf("10.退出管理系统:\n");
EscProgrammer();break;
}
printf("是否需要继续操作?(是:1/否:0):");
scanf("%d",&choice);
if(choice==0)
break;
}
return 0;
}
//***********************************************文件函数***********************************************//
//1.读取文本RJ_1
int ReadFile1(node *L)
{
FILE *fpr=fopen("RJ_1.txt","r");//文件指针
node st;
node *s;
node *t=L;//头结点
if(fpr==NULL)//输入失败,返回0
return 0;
else
{
while(fscanf(fpr,"%s %s %lf %lf %lf %lf %lf %lf",st.num,st.name,&st.grade[0],&st.grade[1],&st.grade[2],&st.grade[3],&st.grade[4],&st.grade[5])!=EOF)
{//字符串输入不用取地址符
s=(node *)malloc(sizeof(node));
*s=st;
t->next=s;//尾插法
t=s;
t->next=NULL;
}
}
return 1;//输入成功,返回1
}
//2.读取文本RJ_2
int ReadFile2(node *L)
{
FILE *fpr=fopen("RJ_2.txt","r");//文件指针
node st;
node *s;
node *t=L;//头结点
if(fpr==NULL)//输入失败,返回0
return 0;
else
{
while(fscanf(fpr,"%s %s %lf %lf %lf %lf %lf %lf",st.num,st.name,&st.grade[0],&st.grade[1],&st.grade[2],&st.grade[3],&st.grade[4],&st.grade[5])!=EOF)
{//字符串输入不用取地址符
s=(node *)malloc(sizeof(node));
*s=st;
t->next=s;//尾插法
t=s;
t->next=NULL;
}
}
return 1;//输入成功,返回1
}
//3.读取文本RJ_3
int ReadFile3(node *L)
{
FILE *fpr=fopen("RJ_3.txt","r");//文件指针
node st;
node *s;
node *t=L;//头结点
if(fpr==NULL)//输入失败,返回0
return 0;
else
{
while(fscanf(fpr,"%s %s %lf %lf %lf %lf %lf %lf",st.num,st.name,&st.grade[0],&st.grade[1],&st.grade[2],&st.grade[3],&st.grade[4],&st.grade[5])!=EOF)
{//字符串输入不用取地址符
s=(node *)malloc(sizeof(node));
*s=st;
t->next=s;//尾插法
t=s;
t->next=NULL;
}
}
return 1;//输入成功,返回1
}
//4.保存文件
int SaveFile(node *L)
{
FILE *fpw=fopen("Student.txt","w");
if(fpw==NULL)//打开失败,返回0
return 0;
//保存格式:fprintf(fpw,"xxx",xxx);
node *p=L->next;//首结点
while(p!=NULL)
{
fprintf(fpw,"%s %s %lf %lf %lf %lf %lf %lf\n",p->num,p->name,p->grade[0],p->grade[1],p->grade[2],p->grade[3],p->grade[4],p->grade[5]);
p=p->next;//指针移动
}
fclose(fpw);
return 1;//打开成功,返回1
}
//***********************************************功能函数***********************************************//
//0.主菜单界面
void Menu()
{
printf("***********************************************\n");
printf("******************学生管理系统*******************\n");
printf("*** 1.总分排行榜 ***\n");
printf("*** 2.优秀排行榜 ***\n");
printf("*** 3.挂科排行榜 ***\n");
printf("*** 4.进步排行榜 ***\n");
printf("*** 5.增加学生信息 ***\n");
printf("*** 6.删除学生信息 ***\n");
printf("*** 7.修改学生信息 ***\n");
printf("*** 8.查询学生信息 ***\n");
printf("*** 9.输出学生信息 ***\n");
printf("*** 10.退出管理系统 ***\n");
printf("***********************************************\n");
printf("请输入对应的功能键(数字):");
}
//1.总分排行榜
//思路:定义一个排序规则、排序函数、输出总分表
int Compare(node a,node b)//排序规则
{
a.sum=a.grade[0]+a.grade[1]+a.grade[2]+a.grade[3]+a.grade[4]+a.grade[5];
b.sum=b.grade[0]+b.grade[1]+b.grade[2]+b.grade[3]+b.grade[4]+b.grade[5];
if(a.sum>b.sum)//如果学生a的总分大于b,返回1
return 1;
else
return 0;
}
void PrintScoreRanking(node *L)//输出总分表
{
node *p=L->next;
int i=0;
printf("----------------------------------------------------------------------------------------\n");
printf("|排名 |学号 |姓名 |数据结构|高等数学|大学英语|线性代数|职业规划|思修道德| |总分|\n");
printf("----------------------------------------------------------------------------------------\n");
if(p!=NULL)
{
while(p!=NULL)
{
p->sum=p->grade[0]+p->grade[1]+p->grade[2]+p->grade[3]+p->grade[4]+p->grade[5];//存储总分
p->rank[0]=++i;//存储排名
printf("%d\t %s\t %s\t %.0f\t %.0f\t %.1f\t %.0f\t %.0f\t %.0f\t %.0f\n",p->rank[0],p->num,p->name,p->grade[0],p->grade[1],p->grade[2],p->grade[3],p->grade[4],p->grade[5],p->sum);
printf("----------------------------------------------------------------------------------------\n");
p=p->next;
}
}
}
void TotalScoreRanking(node *L)//排序函数
{
node t;
for(node *p=L->next;p!=NULL;p=p->next)
for(node *q=p;q!=NULL;q=q->next)
{
if(!Compare(*p, *q))
{
//交换数据域
t=*p;
*p=*q;
*q=t;
//处理指针域
t.next=p->next;
p->next=q->next;
q->next=t.next;
}
}
PrintScoreRanking(L);//输出
}
//2.优秀排行榜
//思路:定义一个计数函数、排序函数、输出优秀排行榜表
void GoodCount(node *L)//计数函数,统计优秀科目个数
{
node *p=L->next;//定义移动指针,从首结点开始
while(p!=NULL)
{
p->good_count=0;//优秀科目清零
for(int i=0;i<6;i++)
if(p->grade[i]>=85)//科目分数大于85为优秀,计数器加一
p->good_count++;
p=p->next;
}
}
void PrintExcellentRanking(node *L)//输出优秀排行榜表
{
node *p=L->next;
int i=0;
printf("---------------------------------------------------------------------------------------------\n");
printf("|排名 |学号 |姓名 |数据结构|高等数学|大学英语|线性代数|职业规划|思修道德| |优秀科目个数|\n");
printf("---------------------------------------------------------------------------------------------\n");
if(p!=NULL)
{
while(p!=NULL)
{
printf("%d\t %s\t %s\t %.0f\t %.0f\t %.1f\t %.0f\t %.0f\t %.0f\t %d\n",++i,p->num,p->name,p->grade[0],p->grade[1],p->grade[2],p->grade[3],p->grade[4],p->grade[5],p->good_count);
printf("---------------------------------------------------------------------------------------------\n");
p=p->next;
}
}
}
void ExcellentRanking(node *L)//排序函数
{
node t;
GoodCount(L);//计数优秀科目
for(node *p=L->next;p!=NULL;p=p->next)
for(node *q=p;q!=NULL;q=q->next)
{
int a=p->good_count;
int b=q->good_count;
int i=!Compare(*p, *q);
if( a<b || (a==b&&i) )//交换的两种情况: 1.p的优秀科目小于q
{ //2.优秀科目相同的前提下,q的总分大于p
//交换数据域
t=*p;
*p=*q;
*q=t;
//处理指针域
t.next=p->next;
p->next=q->next;
q->next=t.next;
}
}
PrintExcellentRanking(L);
}
//3.挂科排行榜
//思路:定义一个计数函数、排序函数、输出挂科排行榜表
void BadCount(node *L)//计数函数,统计挂科科目个数
{
node *p=L->next;//定义移动指针,从头结点开始
while(p!=NULL)
{
p->bad_count=0;//挂科科目清零,非常重要,非常重要,非常重要
for(int i=0;i<6;i++)
if(p->grade[i]<60)//科目分数小于60为挂科,计数器加一
p->bad_count++;
p=p->next;
}
}
void PrintHangingSubjectRankings(node *L)//输出挂科排行榜表
{
node *p=L->next;
int i=0;
printf("---------------------------------------------------------------------------------------------\n");
printf("|排名 |学号 |姓名 |数据结构|高等数学|大学英语|线性代数|职业规划|思修道德| |挂科科目个数|\n");
printf("---------------------------------------------------------------------------------------------\n");
if(p!=NULL)
{
while(p!=NULL)
{
printf("%d\t %s\t %s\t %.0f\t %.0f\t %.1f\t %.0f\t %.0f\t %.0f\t %d\n",++i,p->num,p->name,p->grade[0],p->grade[1],p->grade[2],p->grade[3],p->grade[4],p->grade[5],p->bad_count);
printf("---------------------------------------------------------------------------------------------\n");
p=p->next;
}
}
}
void HangingSubjectRankings(node *L)
{
node t;
BadCount(L);//计数挂科科目
for(node *p=L->next;p!=NULL;p=p->next)
for(node *q=p;q!=NULL;q=q->next)
{
int a=p->bad_count;
int b=q->bad_count;
int i=Compare(*p, *q);
if( a<b || (a==b&&i) )//交换的两种情况: 1.p的挂科科目小于q
{ //2.挂科科目相同的前提下,q的总分小于p
//交换数据域
t=*p;
*p=*q;
*q=t;
//处理指针域
t.next=p->next;
p->next=q->next;
q->next=t.next;
}
}
PrintHangingSubjectRankings(L);
}
//4.进步排行榜
//思路:调用两个计数函数:统计排名和进步名次,一个排序函数、一个输出排行榜函数
void CountRanking(node *L,int j)//计算排名
{
//排序
node t;
for(node *p=L->next;p!=NULL;p=p->next)
for(node *q=p;q!=NULL;q=q->next)
{
if(!Compare(*p, *q))
{
//交换数据域
t=*p;
*p=*q;
*q=t;
//处理指针域
t.next=p->next;
p->next=q->next;
q->next=t.next;
}
}
//排名赋值
node *pre=L->next;
int i=0;
while(pre!=NULL)
{
pre->rank[j]=++i;//存储排名
pre=pre->next;
}
}
void CountUpAndDown(node *L1,node *L2)//计算进步名次
{
CountRanking(L1,0);//计算排名
CountRanking(L2,1);
node *p;
node *q;
for(p=L1->next;p!=NULL;p=p->next)
for(q=L2->next;q!=NULL;q=q->next)
{
if(strcmp(p->num,q->num)==0)//字符串比较函数,相等返回0
q->rank[0]=p->rank[0];//找到目标值,将第一次成绩的排名存储到p->rank[0]
}
q=L2->next;
while(q!=NULL)
{
q->up_or_down=q->rank[0]-q->rank[1];//计算进步名次
q=q->next;
}
}
void ProgressLeaderboard(node *L1,node *L2)//排序函数
{ //传入两组数据,L1为上次考试数据,L2为这次考试数据,L2-L1为升降
node t;
CountUpAndDown(L1,L2);//计算进步名次
for(node *p=L2->next;p!=NULL;p=p->next)
for(node *q=p;q!=NULL;q=q->next)
{
int a=p->up_or_down;
int b=q->up_or_down;
int i=Compare(*p, *q);
if( a<b || (a==b&&i) )//交换的两种情况: 1.p的进步名次小于q
{ //2.进步名次相同的前提下,q的总分小于p
//交换数据域
t=*p;
*p=*q;
*q=t;
//处理指针域
t.next=p->next;
p->next=q->next;
q->next=t.next;
}
}
}
void PrintProgressLeaderboard(node *L1,node *L2)//输出进步排行榜
{
ProgressLeaderboard(L1, L2);
node *p=L2->next;
int i=0;
printf("----------------------------------------------------------------------------------------\n");
printf("|排名 |学号 |姓名 |数据结构|高等数学|大学英语|线性代数|职业规划|思修道德| |进步名次|\n");
printf("----------------------------------------------------------------------------------------\n");
if(p!=NULL)
{
while(p!=NULL)
{
printf("%d\t %s\t %s\t %.0f\t %.0f\t %.1f\t %.0f\t %.0f\t %.0f\t %d\n",++i,p->num,p->name,p->grade[0],p->grade[1],p->grade[2],p->grade[3],p->grade[4],p->grade[5],p->up_or_down);
printf("----------------------------------------------------------------------------------------\n");
p=p->next;
}
}
}
//5.增加学生信息
//思路:设置一个打印函数和插入函数,界面与功能实现分离
void InsertStuInfo(node *L,node e)//插入函数
{
//头插法
node *head=L;//头结点
node *s=(node *)malloc(sizeof(node));
*s=e;
s->next=head->next;
head->next=s;
SaveFile(L);//插入后保存
}
void PrintAddStuInfo(node *L)//打印函数
{
node std;//新增结点存放新增同学
printf("请输入新增学生相关信息:\n");
printf("学号:");
scanf("%s",std.num);
printf("姓名:");
scanf("%s",std.name);
printf("数据结构、高等数学、大学英语、线性代数、职业规划、思修道德的成绩:");
scanf("%lf %lf %lf %lf %lf %lf",&std.grade[0],&std.grade[1],&std.grade[2],&std.grade[3],&std.grade[4],&std.grade[5]);
InsertStuInfo(L,std);
}
//6.删除学生信息
//思路:设置一个前驱结点查找函数、结点删除函数、打印函数,实现界面与功能分离
node* DifferSearchStu(char num[],node *L)//查找学号函数,返回结点的前驱结点地址
{
node *p=L;//定义移动指针,从头结点开始
while(p->next!=NULL)//外部不为空
{
if(strcmp(num,p->next->num)==0)//字符串比较函数,相等返回0
return p;//找到目标值,返回
p=p->next;
}
return NULL;
}
void DeleteStuInfo(node *pre)//结点删除函数
{
node *s=pre->next;//s指向目标删除结点
pre->next=s->next;
s->next=NULL;
free(s);
}
void PrintDeleteStuInfo(node *L)//打印函数
{
char num[20];
printf("请输入要查找的学生学号:");
scanf("%s",num);
node *std=DifferSearchStu(num, L);//返回前驱结点地址
node *pre=std;//pre指向前驱结点
if(std->next==NULL)
{
printf("查无此人\n");
return;
}
else//查找成功,先给出该学生的相关信息
{
printf("要删除学生的信息如下:\n");
printf("-----------------------------------------------------------------------\n");
printf("|学号 |姓名 |数据结构|高等数学|大学英语|线性代数|职业规划|思修道德|\n");
printf("-----------------------------------------------------------------------\n");
printf("%s\t %s\t %.0f\t %.0f\t %.1f\t %.0f\t %.0f\t %.0f \n",std->next->num,std->next->name,std->next->grade[0],std->next->grade[1],std->next->grade[2],std->next->grade[3],std->next->grade[4],std->next->grade[5]);
printf("-----------------------------------------------------------------------\n");
}
DeleteStuInfo(pre);
SaveFile(L);//删除后保存
}
//7.修改学生信息
void PrintFixStuInfo(node *L)
{
int choice;
char num[20];
printf("请输入要修改的学生学号:");
scanf("%s",num);
node *std=SearchStuInfo1(num, L);//返回结点地址
if(std==NULL)
{
printf("查无此人\n");
return;
}
else//查找成功,先给出该学生的相关信息
{
printf("该学生的信息如下:\n");
printf("-----------------------------------------------------------------------\n");
printf("|学号 |姓名 |数据结构|高等数学|大学英语|线性代数|职业规划|思修道德|\n");
printf("-----------------------------------------------------------------------\n");
printf("%s\t %s\t %.0f\t %.0f\t %.1f\t %.0f\t %.0f\t %.0f \n",std->num,std->name,std->grade[0],std->grade[1],std->grade[2],std->grade[3],std->grade[4],std->grade[5]);
printf("-----------------------------------------------------------------------\n");
}
while(1)
{
printf("修改学生姓名---------1\n");
printf("修改数据结构成绩------2\n");
printf("修改高等数学成绩------3\n");
printf("修改大学英语成绩------4\n");
printf("修改线性代数成绩------5\n");
printf("修改职业规划成绩------6\n");
printf("修改思修道德成绩------7\n");
printf("输入要修改的信息:");
scanf("%d",&choice);
switch(choice)
{
case 1:
printf("请输入修改后的姓名:");
scanf("%s",std->name);
break;
case 2:
printf("请输入修改后的数据结构成绩:");
scanf("%lf",&std->grade[0]);//&不要忘了
break;
case 3:
printf("请输入修改后的高等数学成绩:");
scanf("%lf",&std->grade[1]);
break;
case 4:
printf("请输入修改后的大学英语成绩:");
scanf("%lf",&std->grade[2]);
break;
case 5:
printf("请输入修改后的线性代数成绩:");
scanf("%lf",&std->grade[3]);
break;
case 6:
printf("请输入修改后的职业规划成绩:");
scanf("%lf",&std->grade[4]);
break;
case 7:
printf("请输入修改后的思想道德成绩:");
scanf("%lf",&std->grade[5]);
break;
}
printf("是否继续修改该学生信息?(是:1/否:0):");
scanf("%d",&choice);
if(choice==0)
break;
}
//输出修改完成后的学生信息
printf("该学生修改后的信息为:\n");
printf("-----------------------------------------------------------------------\n");
printf("|学号 |姓名 |数据结构|高等数学|大学英语|线性代数|职业规划|思修道德|\n");
printf("-----------------------------------------------------------------------\n");
printf("%s\t %s\t %.0f\t %.0f\t %.1f\t %.0f\t %.0f\t %.0f \n",std->num,std->name,std->grade[0],std->grade[1],std->grade[2],std->grade[3],std->grade[4],std->grade[5]);
printf("-----------------------------------------------------------------------\n");
SaveFile(L);//修改后保存
}
//8.查询学生信息
//思路:设置一个打印函数和查找函数,界面与功能实现分离
node* SearchStuInfo1(char num[],node *L)//查找学号函数,返回结点地址
{
node *p=L;//定义移动指针,从头结点开始
while(p!=NULL)//外部不为空
{
if(strcmp(num,p->num)==0)//字符串比较函数,相等返回0
return p;//找到目标值,返回
p=p->next;
}
return NULL;
}
void PrintSearchStuInfo(node *L)//打印函数
{
char num[20];
node *std;
printf("请输入要查询学生的学号:");
scanf("%s",num);
std=SearchStuInfo1(num,L);
if(std==NULL)
printf("查无此人\n");
else
{
printf("-----------------------------------------------------------------------\n");
printf("|学号 |姓名 |数据结构|高等数学|大学英语|线性代数|职业规划|思修道德|\n");
printf("-----------------------------------------------------------------------\n");
printf("%s\t %s\t %.0f\t %.0f\t %.1f\t %.0f\t %.0f\t %.0f \n",std->num,std->name,std->grade[0],std->grade[1],std->grade[2],std->grade[3],std->grade[4],std->grade[5]);
printf("-----------------------------------------------------------------------\n");
}
}
//9.输出学生信息
void PrintStuInfo(node *L)
{
TotalScoreRanking(L);//调用总分榜
}
//10.退出管理系统
void EscProgrammer(void)
{
printf("欢迎下次使用~\n");
exit(0);//结束程序
}
大一实训作业—成绩管理系统代码
最新推荐文章于 2024-05-21 08:17:21 发布