因为最近在复习C,学习数据结构,为了复习链表,用四个小时写了下面的学生管理系统。如有不当,希望各位大佬斧正。
如果有哪些地方不懂欢迎评论。
下文附有全部代码(未拆分)
全文附带注释,但是可以直接看懂需要学习链表知识。
本代码在VScode编译器编写
C语言版本:C99
本代码基于链表实现:
1.学生成绩的增加
2.学生成绩的删除
3.学生成绩的修改
4.学生成绩的查看
(1)根据学号升序\降序
(2)根据总分升序\降序
5.查看全班最高分
6.求各科平均值
7.数据的读取和存储(基于文件读取、存储实现)
(第二版新增文件存储)
(第三版新增输出方式,储存文件更加单一化从而防止文件重名)
(第四版将排序单独提出作为一个功能,排序完成进行选择如何输出)
/**
* 本代码在vscode编译器编写
* C语言版本:C99
* 本代码基于链表实现:
* 1.学生成绩的增加
* 2.学生成绩的删除
* 3.学生成绩的修改
* 4.学生成绩的查看
* (1)根据学号升序\降序
* (2)根据总分升序\降序
* 5.查看全班最高分
* 6.求各科平均值
* 7.数据的读取和存储(基于文件读取、存储实现)
*/
#include<stdio.h>
#include<stdlib.h>
//初始化学生信息的结构体
typedef struct{
int mlong; //链表长度
int id; //学号
char name[20]; //姓名
float score[3]; //学科成绩
float sum; //总分
struct STU *next; //地址区
}STU;
//创建头指针
STU * createhead(){
STU * head=(STU *)malloc(sizeof(STU));
head->mlong =0; //初始链表长度为0
head->next=NULL;
return head;
}
//传数据创建新数据
STU * createnew(int id,char name[20],float score0,float score1,float score2){
STU * new=(STU *)malloc(sizeof(STU));
new->id=id;
for(int i=0;i<20;i++){
new->name[i]=name[i];
}
new->score[0]=score0;
new->score[1]=score1;
new->score[2]=score2;
new->sum=new->score[0]+new->score[1]+new->score[2];
new->next=NULL;
return new;
}
//输入创建新数据
STU * createone(){
STU * new=(STU *)malloc(sizeof(STU));
printf("请输入学生的学号:");
scanf("%d",&new->id);
printf("请输入学生的姓名:");
scanf("%s",&new->name);
printf("请输入学生的C语言成绩:");
scanf("%f",&new->score[0]);
printf("请输入学生的C++成绩:");
scanf("%f",&new->score[1]);
printf("请输入学生的Python成绩:");
scanf("%f",&new->score[2]);
new->sum=new->score[0]+new->score[1]+new->score[2];
new->next=NULL;
return new;
}
//求最高分
float maxsum(STU * all){
STU * p = all->next;
if(p==NULL) {
return 0;
}
float max=p->sum;
while(p!=NULL){
if(p->sum>max){
max=p->sum;
}
p=p->next;
}
return max;
}
//求最大学号
int maxid(STU * all){
STU * p = all->next;
if(p==NULL) {
return 0;
}
int max=p->id;
while(p!=NULL){
if(p->id>max){
max=p->id;
}
p=p->next;
}
return max;
}
//根据学号递增排序
void allsudo1(STU * all){
int mid=maxid(all);
//创建临时表头用来排序
STU * linshi=createhead();
while(all->mlong>0){
//从0开始直到max值进行遍历排序
int i=0;
while(i<=mid){
STU * p=all;
STU * pnext=all->next;
if (pnext==NULL){
break;
}
while(pnext!=NULL){
if(pnext->id==i){
//将原链表中的数据剥离
p->next=pnext->next;
all->mlong--;
linshi->mlong++;
//查看是否存在相同数据,若有则添加到该数据后
STU * fp =linshi;
while(fp!=NULL){
if(fp->id==i){
pnext->next=fp->next;
fp->next=pnext;
break;
}
fp=fp->next;
}
if(fp!=NULL){
break;
}
//将数据添加到链表尾
STU * lp =linshi;
pnext->next=NULL;
while(1){
if(lp->next==NULL){
lp->next=pnext;
break;
}
lp=lp->next;
}
break;
}
p=p->next;
pnext=pnext->next;
}
i++;
}
}
//将数据重新连接到原表头,并释放临时表头的空间
all->next=linshi->next;
all->mlong=linshi->mlong;
free(linshi);
}
//根据学号递减排序
void allsudo2(STU * all){
int mid=maxid(all);
//创建临时表头用来排序
STU * linshi=createhead();
while(all->mlong>0){
int i=0;
while(i<=mid){
STU * p=all;
STU * pnext=all->next;
if (pnext==NULL){
break;
}
while(pnext!=NULL){
if(pnext->id==i){
//将原链表中的数据剥离
p->next=pnext->next;
all->mlong--;
linshi->mlong=linshi->mlong+1;
//查看是否存在相同数据,若有则添加到该数据后
STU * fp =linshi;
while(fp!=NULL){
if(fp->id==i){
pnext->next=fp->next;
fp->next=pnext;
break;
}
fp=fp->next;
}
if(fp!=NULL){
break;
}
//将剥离的数据连接在临时表头
pnext->next=linshi->next;
linshi->next=pnext;
break;
}
p=p->next;
pnext=pnext->next;
}
i++;
}
}
//将数据重新连接到原表头,并释放临时表头的空间
all->next=linshi->next;
all->mlong=linshi->mlong;
free(linshi);
}
//根据总分递增排序
void allsudo3(STU * all){
float msum=maxsum(all);
//创建临时表头用来排序
STU * linshi=createhead();
while(all->mlong>0){
float i=0;
while(i<=msum){
STU * p=all;
STU * pnext=all->next;
if (pnext==NULL){
break;
}
while(pnext!=NULL){
if(pnext->sum==i){
//将原链表中的数据剥离
p->next=pnext->next;
all->mlong=all->mlong-1;
linshi->mlong=linshi->mlong+1;
//查看是否存在相同数据,若有则添加到该数据后
STU * fp =linshi;
while(fp!=NULL){
if(fp->sum==i){
pnext->next=fp->next;
fp->next=pnext;
break;
}
fp=fp->next;
}
if(fp!=NULL){
break;
}
//将剥离的数据连接在临时表头
STU * lp =linshi;
pnext->next=NULL;
while(1){
if(lp->next==NULL){
lp->next=pnext;
break;
}
lp=lp->next;
}
break;
}
p=p->next;
pnext=pnext->next;
}
i++;
}
}
//将数据重新连接到原表头,并释放临时表头的空间
all->next=linshi->next;
all->mlong=linshi->mlong;
free(linshi);
}
//根据总分递减排序
void allsudo4(STU * all){
float msum=maxsum(all);
//创建临时表头用来排序
STU * linshi=createhead();
while(all->mlong>0){
float i=0;
while(i<=msum){
STU * p=all;
STU * pnext=all->next;
if (pnext==NULL){
break;
}
while(pnext!=NULL){
if(pnext->sum==i){
//将原链表中的数据剥离
p->next=pnext->next;
all->mlong=all->mlong-1;
linshi->mlong=linshi->mlong+1;
//查看是否存在相同数据,若有则添加到该数据后
STU * fp =linshi;
while(fp!=NULL){
if(fp->sum==i){
pnext->next=fp->next;
fp->next=pnext;
break;
}
fp=fp->next;
}
if(fp!=NULL){
break;
}
//将剥离的数据连接在临时表头
pnext->next=linshi->next;
linshi->next=pnext;
break;
}
p=p->next;
pnext=pnext->next;
}
i++;
}
}
//将数据重新连接到原表头,并释放临时表头的空间
all->next=linshi->next;
all->mlong=linshi->mlong;
free(linshi);
}
//打印全部数据
void showall(STU * all){
int showchoose=1;
printf("1.块输出\n");
printf("2.表输出\n");
printf("请选择你想选择的输出方式:");
scanf("%d",&showchoose);
int i=0;
STU * stu=all->next;
while(stu != NULL){
if(showchoose==1){
if(i==0){
printf("==========================================\n");
printf("-----------------------------\n");
}
i++;
printf("学生的学号:%d\n",stu->id);
printf("学生的姓名:%s\n",stu->name);
printf("学生的C语言成绩:%f\n",stu->score[0]);
printf("学生的C++成绩:%f\n",stu->score[1]);
printf("学生的Python成绩:%f\n",stu->score[2]);
printf("学生的总成绩:%f\n",stu->sum);
stu=stu->next;
printf("-----------------------------\n");
}else if(showchoose==2){
if (i==0){
printf("==========================================\n");
printf("\t----------------|---------------|---------------|---------------|---------------|----------------\n");
printf("\t id | name | C | C++ | python | sum\n");
printf("\t----------------|---------------|---------------|---------------|---------------|----------------\n");
}
printf("\t \t%d\t| %s\t\t| %f\t| %f\t| %f\t| %f\t\n",stu->id,stu->name,stu->score[0],stu->score[1],stu->score[2],stu->sum);
i++;
stu=stu->next;
}else{
printf("无此选项!请重新输入!");
}
}
if(showchoose==2){
printf("\t----------------|---------------|---------------|---------------|---------------|----------------\n");
}
}
//增加学生数据
void updatenew(STU * all){
STU * new =createone();
new->next=all->next;
all->next=new;
all->mlong+=1;
}
//删除学生数据
void delone(STU * all){
int delchoose=1;
printf("1.按学号删除\n");
printf("2.按位置删除\n");
printf("请选择:");
scanf("%d",&delchoose);
printf("==========================================\n");
int id;
STU * p=all;
STU * pnext=all->next;
if(delchoose==1){
printf("请输入该学生的学号:");
scanf("%d",&id);
while(pnext!= NULL){
if(pnext->id==id){
p->next=pnext->next;
pnext->next=NULL;
free(pnext);
all->mlong-=1;
break;
}
p=p->next;
pnext=pnext->next;
}
}else if(delchoose==2){
printf("请输入该学生的位置:");
scanf("%d",&id);
for(int i=+1; i<all->mlong+1; i++){
if(i==id){
p->next=pnext->next;
pnext->next=NULL;
free(pnext);
all->mlong-=1;
break;
}
p=p->next;
pnext=pnext->next;
}
}
}
//修改学生数据
void changeone(STU * all){
delone(all);
printf("==========================================\n");
updatenew(all);
}
//根据学号查找学生
void selone(STU * all){
int selchoose=1;
printf("1.按学号查找\n");
printf("2.按位置查找\n");
printf("请选择:");
scanf("%d",&selchoose);
printf("==========================================\n");
int id;
STU * p=all;
STU * pnext=all->next;
if(selchoose==1){
printf("请输入该学生的学号:");
scanf("%d",&id);
printf("==========================================\n");
while(pnext!= NULL){
if(pnext->id==id){
printf("学生的学号:%d\n",pnext->id);
printf("学生的姓名:%s\n",pnext->name);
printf("学生的C语言成绩:%f\n",pnext->score[0]);
printf("学生的C++成绩:%f\n",pnext->score[1]);
printf("学生的Python成绩:%f\n",pnext->score[2]);
printf("学生的总成绩:%f\n",pnext->sum);
break;
}
p=p->next;
pnext=pnext->next;
}
}else if(selchoose==2){
printf("请输入该学生的位置:");
scanf("%d",&id);
for(int i=1;i<(all->mlong+1);i++){
if(i==id){
printf("学生的学号:%d\n",pnext->id);
printf("学生的姓名:%s\n",pnext->name);
printf("学生的C语言成绩:%f\n",pnext->score[0]);
printf("学生的C++成绩:%f\n",pnext->score[1]);
printf("学生的Python成绩:%f\n",pnext->score[2]);
printf("学生的总成绩:%f\n",pnext->sum);
break;
}
p=p->next;
pnext=pnext->next;
}
}else{
printf("无此选项!");
}
}
//计算各科平均值
void showave(STU * all){
STU * p = all->next;
float ave1=0,ave2=0,ave3=0;
//将各科成绩遍历相加求和
while(p!=NULL){
ave1+=p->score[0];
ave2+=p->score[1];
ave3+=p->score[2];
p=p->next;
}
//将各科成绩除以个数得到平均值
ave1=ave1/all->mlong;
ave2=ave2/all->mlong;
ave3=ave3/all->mlong;
printf("C语言平均成绩:%f\n",ave1);
printf("C++平均成绩:%f\n",ave2);
printf("Python平均成绩:%f\n",ave3);
}
//选择排序方式
void chooseshow(STU * all){
int showchoose;
printf("1.根据学号递增排序\n");
printf("2.根据学号递减排序\n");
printf("3.根据总分递增排序\n");
printf("4.根据总分递减排序\n");
printf("请输入:");
scanf("%d",&showchoose);
if(showchoose==1){
//根据学号递增排序
allsudo1(all);
}else if(showchoose==2){
//根据学号递减排序
allsudo2(all);
}else if(showchoose==3){
//根据总分递增排序
allsudo3(all);
}else if(showchoose==4){
//根据总分递减排序
allsudo4(all);
}
printf("==========================================\n");
printf("需要查看数据吗?\n");
printf("1.查看全部学生\n");
printf("2.查找特定学生\n");
printf("9.退出\n");
printf("请选择:");
int htd=9;
scanf("%d",&htd);
printf("==========================================\n");
if(htd==1){
showall(all);
}else if(htd==2){
selone(all);
}else if(htd==9){
return;
}
}
//释放申请的全部空间
void freeall(STU * all){
STU * p = all;
while(p!= NULL){
STU * pa = p;
p=pa->next;
free(pa);
}
}
//读文件
void inputall(STU * all){
//从文件读取数据
FILE * fp1;
while(1){
if((fp1 = fopen("studentmanagedata.txt","r"))==NULL){//读前判断是否有该文件
return;//如果没有就退出函数
}else{//若有则退出循环继续运行
break;
}
}
//读取数据
while(1){
if(feof(fp1)){
break;
}
STU nstu;
fscanf(fp1, "%d-%f-%f-%f-%f-%s",&nstu.id,&nstu.score[0],&nstu.score[1],&nstu.score[2],&nstu.sum,&nstu.name);
if(nstu.id==0){
break;
}else{
STU * new=createnew(nstu.id,nstu.name,nstu.score[0],nstu.score[1],nstu.score[2]);
new->next=all->next;
all->next=new;
all->mlong+=1;
}
}
fclose(fp1);
//清空文件
FILE *fp3;
if((fp3 = fopen("studentmanagedata.txt","w"))==NULL){
printf("文件读取失败!");
exit(EXIT_FAILURE);
}
fclose(fp3);
}
//保存数据
void outputall(STU * all){
STU * p=all->next;
FILE * fp3;
if((fp3 = fopen("studentmanagedata.txt","w"))==NULL){
printf("文件读取失败!");
exit(EXIT_FAILURE);
}
while(p!=NULL){
if(p->next!=NULL){
fprintf(fp3, "%d-%f-%f-%f-%f-%s\n",p->id,p->score[0],p->score[1],p->score[2],p->sum,p->name);
}else{
fprintf(fp3, "%d-%f-%f-%f-%f-%s",p->id,p->score[0],p->score[1],p->score[2],p->sum,p->name);
}
p=p->next;
}
fclose(fp3);
}
int main(){
//创建头指针
STU * all=createhead();
//读取数据
inputall(all);
//菜单
while(1){
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");
//判断输入是否正确
int m_choose;
while(1){
printf("请输入:");
scanf("%d",&m_choose);
if(m_choose==1||m_choose==2||m_choose==3||m_choose==4||m_choose==5||m_choose==6||m_choose==7||m_choose==8||m_choose==9){
printf("==========================================\n");
break;
}else{
printf("无该项,请重新输入!\n");
printf("==========================================\n");
}
}
if(m_choose==1){
if(all->mlong!=0){
//展示全部学生信息
showall(all);
}else{
printf("无数据!\n");
}
}else if(m_choose==2){
//添加学生信息
updatenew(all);
}else if(m_choose==3){
//删除学生信息
delone(all);
}else if(m_choose==4){
//修改学生信息
changeone(all);
}else if(m_choose==5){
//查找特定学生信息
selone(all);
}else if(m_choose==6){
//查看总分的全班最高分
float msum=maxsum(all);
printf("全班最高分为:%f\n",msum);
}else if(m_choose==7){
//查看各科平均值
showave(all);
}else if(m_choose==8){
//选择排序方式
chooseshow(all);
}else if(m_choose==9){
//将数据输入到文件中
outputall(all);
//释放申请的全部空间
freeall(all);
//退出
break;
}
printf("==========================================\n");
}
}