学生成绩管理系统功能
- 菜单
- 查询学生信息
- 修改学生信息
- 删除学生信息
- 显示学生信息
- 各科成绩各分数段人数统计
- 退出系统
- 异常输入报错
学生成绩管理系统代码(含注释)
Function.h文件代码:
#ifndef _CHANGEINFOR_H
#define _CHANGEINFOR_H
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
#define ClassNum 3
//结构体
struct Student
{
int id;
char name[10];
float Class[ClassNum];//三门科目
float total;
int Rank;
struct Student *next;
};
//函数声明
void ChangeInfor(struct Student *h,char *title);
int ClassfyGrade(struct Student *h);
struct Student *create();
struct Student *InforDelete(struct Student *h,char *title );
int openfile(struct Student *h );
void ReCalculate(struct Student *h);
void ReRank(struct Student *h);
int SaveNew(struct Student *h , char *s);
void SearchStu(struct Student *h,char *title);
void ShowStuInfor(struct Student *h);
int title(char *a);
#endif
main.cpp文件代码:
/*作者:karthus 完成时间:2019/12/13 16:06
程序名称:学生成绩管理系统
程序用途:
(1) 学生成绩信息保存在文件中
(2) 学生成绩信息查询、删除、修改和显示
(3) 学生成绩总分计算和排名
(4) 学生成绩信息的统计:根据科目统计每个分数段的人,统计结果可以保存文件中。
(5) 利用菜单管理
*/
#include "Function.h"
int main()
{
int i,check;
char Title[50];
Student *head;
title(Title);//把.txt文件第一行标题拷入Title数组中
head = create();//提前创建一个结点,作为头指针
openfile(head);//读取信息,将信息存入链表并计算总分和排名
do
{
printf(" \n");
printf(" \n");
printf(" \n");
printf(" \n");
printf(" \n");
printf(" ********************************学生管理系统********************************\n");
printf(" * *\n");
printf(" *您可以选择: *\n");
printf(" * 1:查询学生信息 *\n");
printf(" * 2:修改学生信息 *\n");
printf(" * 3:删除学生信息 *\n");
printf(" * 4:显示学生信息 *\n");
printf(" * 5:各科成绩个分数段人数 *\n");
printf(" * 0:退出系统 *\n");
printf(" * *\n");
printf(" ****************************************************************************\n");
printf(" 您选择:");
scanf("%d",&i);
if(getchar() == '\n')
{
switch(i)
{
case 1:
{
system("CLS");
SearchStu(head,Title);//查找学生信息
check = 0;
break;
}
case 2:
{
system("CLS");
ChangeInfor(head,Title);//改变学生信息
ReCalculate(head);//信息改变后,总分和排名可能也改变了,重新计算总分
ReRank(head);//重新计算排名
check = 0;
break;
}
case 3:
{
system("CLS");
head = InforDelete(head,Title);//删除一整个学生信息,由于可能删除的是头指针,所以需要重新返回头指针
ReRank(head);//删除信息后需要重新排名
check = 0;
break;
}
case 4:
{
system("CLS");
printf("------------------------------------------------------\n");
printf("%s",Title);
ShowStuInfor(head);//显示学生所有信息,包括排名和总分,并保存至data3.txt
printf("------------------------------------------------------\n");
check = 0;
break;
}
case 5:
{
system("CLS");
printf("\t\t各科成绩个分数段人数\n\n");
printf("-----------------------------------------------------------------------------\n");
ClassfyGrade(head);//各科分数分类并且保存于data2.txt
printf("-----------------------------------------------------------------------------\n");
check = 0;
break;
}
case 0:
{
system("CLS");
printf("\t\t\t\t\t退出系统\n");
SaveNew(head,Title);//退出后保存修改后信息到data3.txt
check = 1;
break;
}
default:
{
printf("\a");
printf("输入错误,按任意键开始重新输入\n");
check = 0;
}
}
}
else
{
printf("输入不合法,请重新输入\n");
}
if(check == 1)
{
break;
}
else
{
system("pause");
system("CLS");
}
fflush(stdin);
}while(1);
return 0;
}
Function.cpp文件代码:
#include"Function.h"
//把data1.txt文件第一行标题读出来并保存于传入指针所指的数组中
int title(char *a)
{
int i,j,n,k;
FILE *fp1;
struct Student *p1,*p2,*p3;
if(( fp1 = fopen("data1.txt","r")) == NULL )//以读的方式打开文件data1.txt
{
printf("can't open file\n");
return -1;
}
fgets( a , 50 , fp1 );//把标题读出来存入数组title
return 0;
}
//创建一个结点
//无传入参数,返回结点指针
struct Student *create()
{
Student *p;
p = (Student *)malloc(sizeof(struct Student));//开辟一个Student结构体空间
p->next = NULL;
return p;
}
//读取信息,将信息存入链表并计算总分和排名
//传入参数为链表头指针,返回值0或-1
int openfile(struct Student *h)
{
int i,j,n,k;
char title[50];
FILE *fp1;
struct Student *p1,*p2,*p3;
if(( fp1 = fopen("data1.txt","r")) == NULL )//以读的方式打开文件data1.txt
{
printf("can't open file\n");
return -1;
}
fgets( title , 50 , fp1 );//把标题读出来存入数组title
p2 = p1 = h;
fscanf(fp1 ,"%d%s%f%f%f" ,&p1->id,&p1->name,&p1->Class[0],&p1->Class[1],&p1->Class[2]);
p1->total = p1->Class[0] + p1->Class[1] + p1->Class[2];//计算总分
p1->Rank = 1;//初始化排名
i = 1;
while( !feof(fp1) )
{
p1 = create();
fscanf(fp1 ,"%d%s%f%f%f" ,&p1->id,&p1->name,&p1->Class[0],&p1->Class[1],&p1->Class[2]);
p1->total = p1->Class[0] + p1->Class[1] + p1->Class[2];//计算总分
p1->Rank = 1;//初始化排名
p3 = h;
for(j = 0; j < i;j++)//擂台法排名,p3从head开始
{
if((p1->total) > (p3->total))
{
p3->Rank = p3->Rank + 1;
}
else if((p1->total) < (p3->total))
{
p1->Rank = p1->Rank + 1;
}
p3 = p3->next;
}
p2->next = p1;//将前一个结点与新建结点链接起来
p2 = p1;
i++;
}
fclose(fp1);
return 0;
}
//查找学生信息
void SearchStu(struct Student *h,char *title)
{
char s[50],c;
int check ,choose,ID,check3;
struct Student *p;
while(1)
{
check = 0;
check3 = 0;
p = h;
printf("\t\t\t\t查询方式:\n\n\t\t\t\t\t1.姓名查询\n\n\t\t\t\t\t2.学号查询\n\n\t\t\t\t你的选择是:");
scanf("%d",&choose);
if(getchar() == '\n')
{
if(choose == 1)
{
printf("请输入您想查询学生的姓名:");
scanf("%s",s);
fflush(stdin);
while(p)
{
if(strcmp(p->name , s ) == 0 )
{
printf("------------------------------------------------------\n");
printf("%s",title);
printf("%d\t%s\t%.2f\t%.2f\t%.2f\t%.2f\t %d\n",p->id ,p->name,p->Class[0],p->Class[1],p->Class[2],p->total,p->Rank);
printf("------------------------------------------------------\n");
check = 1;
}
p = p->next;
}
}
else if(choose == 2)
{
printf("请输入您想查询学生的学号:");
scanf("%d",&ID);
fflush(stdin);
while(p)
{
if( p->id == ID )
{
printf("------------------------------------------------------\n");
printf("%s",title);
printf("%d\t%s\t%.2f\t%.2f\t%.2f\t%.2f\t %d\n",p->id ,p->name,p->Class[0],p->Class[1],p->Class[2],p->total,p->Rank);
printf("------------------------------------------------------\n");
check = 1;
break;
}
p = p->next;
}
}
else
{
printf("输入错误,请重新输入!\n");
continue;
}
if(check == 0)
{
printf("找不到该同学信息!\n");
}
while(1)
{
printf("是否再次查询(y / n)\n");
scanf("%c",&c);
if(getchar() == '\n')
{
fflush(stdin);
if( c == 'n'||c == 'N')
{
check3 = 1;
break;
}
else if( c == 'y'||c == 'Y')
{
break;
}
else
{
printf("输入不合法,请重新输入\n");
}
}
else
{
printf("输入不合法,请重新输入\n");
}
fflush(stdin);
}
if(check3 == 1)
{
break;
}
}
else
{
printf("输入不合法,请重新输入\n");
}
fflush(stdin);
printf("\n");
}
}
//修改学生信息(姓名,科目一,科目二,科目三)
//传入参数为链表的头指针,无返回值
void ChangeInfor(struct Student *h,char *title)
{
char s[50],choice,c,name;
int check ,ID,choose,check2=0,check3 = 0;
struct Student *p;
while(1)
{
check = 0;
check2 = 0;
check3 = 0;
p = h;
while(1)
{
printf("\t\t\t\t查询方式:\n\n\t\t\t\t\t1.学生姓名\n\n\t\t\t\t\t2.学生学号\n\n\t\t\t\t您的选择是:");
scanf("%d",&choose);
if(getchar() == '\n')
{
if(choose == 1)
{
printf("请输入您想修改信息的学生姓名:");
scanf("%s",&s);
fflush(stdin);
//check2 = strcmp(h->name,s);
break;
}
else if(choose == 2)
{
printf("请输入您想修改信息的学生学号:");
scanf("%d",&ID);
fflush(stdin);
//check2 = (ID == h->id);
break;
}
else
{
printf("输入不合法,请重新输入!\n");
}
}
else
{
printf("输入不合法,请重新输入\n");
}
fflush(stdin);
}
while(p)
{
if(choose == 1)
{
check2 = !(strcmp(p->name,s));
}
else
{
check2 = (ID == p->id);
}
if(check2 )
{
printf("------------------------------------------------------\n");
printf("%s",title);
printf("%d\t%s\t%.2f\t%.2f\t%.2f\n",p->id ,p->name,p->Class[0],p->Class[1],p->Class[2]);
printf("------------------------------------------------------\n");
check = 1;
printf("");
while(1)
{
printf("是否修改学号?(y/Y or n/N)");
scanf("%c",&choice);
if(getchar() == '\n')
{
if(choice == 'Y' || choice == 'y')
{
printf("请输入新学号:");
scanf("%d",&p->id );
fflush(stdin);
break;
}
else if(choice == 'N'||choice == 'n')
{
break;
}
else
{
printf("输入错误,请重新输入\n");
}
}
else
{
printf("输入不合法,请重新输入\n");
}
fflush(stdin);
}
while(1)
{
printf("是否修改姓名?(y/Y or n/N)");
scanf("%c",&choice);
if(getchar() == '\n')
{
if(choice == 'Y' || choice == 'y')
{
printf("请输入新姓名:");
scanf("%s",p->name );
fflush(stdin);
break;
}
else if(choice == 'N'||choice == 'n')
{
break;
}
else
{
printf("输入错误,请重新输入\n");
}
}
else
{
printf("输入不合法,请重新输入\n");
}
fflush(stdin);
}
while(1)
{
printf("是否修改课程1成绩?(y/Y or n/N)");
scanf("%c",&choice);
if(getchar() == '\n')
{
if(choice == 'Y' || choice == 'y')
{
printf("请输入新成绩:");
scanf("%f",&(p->Class[0]));
fflush(stdin);
break;
}
else if(choice == 'N'||choice == 'n')
{
break;
}
else
{
printf("输入错误,请重新输入\n");
}
}
else
{
printf("输入不合法,请重新输入\n");
}
fflush(stdin);
}
while(1)
{
printf("是否修改课程2成绩?(y/Y or n/N)");
scanf("%c",&choice);
if(getchar() == '\n')
{
if(choice == 'Y' || choice == 'y')
{
printf("请输入新成绩:");
scanf("%f",&(p->Class[1]));
fflush(stdin);
break;
}
else if(choice == 'N'||choice == 'n')
{
break;
}
else
{
printf("输入错误,请重新输入\n");
}
}
else
{
printf("输入不合法,请重新输入\n");
}
fflush(stdin);
}
while(1)
{
printf("是否修改课程3成绩?(y/Y or n/N)");
scanf("%c",&choice);
if(getchar() == '\n')
{
if(choice == 'Y' || choice == 'y')
{
printf("请输入新成绩:");
scanf("%f",&(p->Class[2]));
fflush(stdin);
break;
}
else if(choice == 'N'||choice == 'n')
{
break;
}
else
{
printf("输入错误,请重新输入\n");
}
}
else
{
printf("输入不合法,请重新输入\n");
}
fflush(stdin);
}
//
}
p = p->next;//指向下一个节点
}
if(check == 0)
{
printf("找不到该同学信息!\n");
}
while(1)
{
printf("是否再次修改(y / n)\n");
scanf("%c",&c);
if(getchar() == '\n')
{
if( c == 'n'||c == 'N')
{
check3 = 1;
break;
}
else if( c == 'y'||c == 'Y')
{
break;
}
else
{
printf("输入不合法,请重新输入\n");
}
}
else
{
printf("输入不合法,请重新输入\n");
}
fflush(stdin);
}
if(check3 == 1)
{
break;
}
printf("\n");
}
}
//不同分数段的各科分数进行分段,然后记录并保存在data2文件中
//传入参数为链表头指针,返回值为0(正常结束)或-1(文件打开失败)
int ClassfyGrade(struct Student *h)
{
int A[ClassNum],B[ClassNum],C[ClassNum],D[ClassNum],E[ClassNum],s[5],i,TotalP=0;
FILE *fp;
double grade,sum = 0,average,a,max = 0,min = 100;
struct Student *p;
if(( fp = fopen("data2.txt","w")) == NULL )
{
printf("can't open file\n");
return -1;
}
printf("\t100~90\t89~80\t79~70\t69~60\t不及格\t总人数\t平均分\t最高分\t最低分\n\n");
fprintf(fp,"\t\t 100~90\t 89~80\t 79~70\t 69~60\t 不及格\t 总人数\t 平均分\t 最高分\t 最低分\n\n");
for(i = 0 ;i < ClassNum ; i++)//i用来分别调用三科成绩
{
p = h;
sum = 0;
max = 0;
min = 100;
TotalP = 0;
A[i] = B[i] = C[i] = D[i] = E[i] = 0;
while(p)
{
grade = p->Class[i];
if( grade<=100 && grade>=90 )
{
A[i] = A[i] + 1;
}
else if( grade<=89 && grade>=80 )
{
B[i] = B[i] + 1;
}
else if( grade<=79 && grade>=70 )
{
C[i] = C[i] + 1;
}
else if( grade<=69 && grade>=60 )
{
D[i] = D[i] + 1;
}
else
{
E[i] = E[i] + 1;
}
a = grade;
if(a > max)
{
max = a;
}
else if( a < min)
{
min = a;
}
sum =sum + grade;
TotalP++;//总人数
p = p->next;//指向下一个节点
}
printf("课程%d",i+1);
printf("\t%d",A[i]);
printf("\t%d",B[i]);
printf("\t%d",C[i]);
printf("\t%d",D[i]);
printf("\t%d",E[i]);
printf("\t%d",A[i]+B[i]+C[i]+D[i]+E[i]);
printf("\t%.2f",sum / TotalP );
printf("\t%.2f",max);
printf("\t%.2f\n",min);
printf("\n");
fprintf(fp,"课程%d",i+1);
fprintf(fp,"\t\t%d",A[i]);
fprintf(fp,"\t\t\t%d",B[i]);
fprintf(fp,"\t\t\t%d",C[i]);
fprintf(fp,"\t\t\t%d",D[i]);
fprintf(fp,"\t\t\t%d",E[i]);
fprintf(fp,"\t\t\t%d",A[i]+B[i]+C[i]+D[i]+E[i]);
fprintf(fp," \t\t%.2f",sum / TotalP );
fprintf(fp," \t%.2f",max);
fprintf(fp," \t%.2f\n\n",min);
fprintf(fp,"\n");
//p = h;//重新赋予头指针,便于从头开始索引下一科目成绩
}
s[0] = A[0] + A[1] + A[2];
s[1] = B[0] + B[1] + B[2];
s[2] = C[0] + C[1] + C[2];
s[3] = D[0] + D[1] + D[2];
s[4] = E[0] + E[1] + E[2];
printf("总人数\t%d\t%d\t%d\t%d\t%d\t%d\n",s[0],s[1],s[2],s[3],s[4],s[0]+s[1]+s[2]+s[3]+s[4]);
fprintf(fp,"总人数\t\t%d\t\t\t%d\t\t\t%d\t\t\t%d\t\t\t%d\t\t\t%d\n",s[0],s[1],s[2],s[3],s[4],s[0]+s[1]+s[2]+s[3]+s[4]);
return 0;
}
//删除学生信息
//传入参数为链表头指针,返回值为链表头指针
struct Student *InforDelete(struct Student *h ,char *title)
{
char s[100],c;
int check,ID,choose,check2,check3;//用于检测是否找到学生
struct Student *p1,*p2,*p3,*p4;
p1 = h;
while(1)
{
check = 0;
check3 = 0;
p3 = h;
while(1)
{
printf("\t\t\t\t查询方式:\n\n\t\t\t\t\t1.姓名查询\n\n\t\t\t\t\t2.学号查询\n\n\t\t\t\t您的选择是:");
scanf("%d",&choose);
if(getchar() == '\n')
{
if(choose == 1 || choose == 2)
{
fflush(stdin);
break;
}
else
{
printf("输入错误,请重新输入\n");
}
}
else
{
printf("输入错误,请重新输入\n");
}
fflush(stdin);
}
if(choose == 1)
{
printf("请输入需要删除的学生姓名:");
scanf("%s",s);
fflush(stdin);
while(p3)//查找同名的学生
{
if(strcmp(p3->name,s) == 0)
{
check = 1;
printf("------------------------------------------------------\n");
printf("%s",title);
printf("%d\t%s\t%.2f\t%.2f\t%.2f\n",p3->id ,p3->name,p3->Class[0],p3->Class[1],p3->Class[2]);
printf("------------------------------------------------------\n");
while(1)
{
printf("是否要删除该学生(y / n)\n");
check2 = 0;
scanf("%c",&c);
if(getchar() == '\n')
{
fflush(stdin);
if( c == 'n'||c == 'N')
{
break;
}
else if( c == 'y'||c == 'Y')
{
check2 = 1;
break;
}
else
{
printf("输入不合法,请重新输入\n");
}
}
else
{
printf("输入不合法,请重新输入\n");
}
fflush(stdin);
}
if(check2 == 1)
{
if(p1 == p3)//如果删除的是头结点
{
p2 = p3;
p4 = p3->next;//p2指向下一个结点
printf("%s已经被删除\n",p3->name);
free(p2);
h = p4;//返回第二个结点的指针,作为头结点
}
else
{
p2 = p3;
p3 = p3->next;
p1->next = p3;//将被删除结点且一个结点的next指针指向被删除结点的下一个结点
printf("%s已经被删除\n",p2->name);
free(p2);
}
}
}
p1 = p3;
p3 = p3->next;
}
}
else if(choose == 2)
{
printf("请输入需要删除的学生学号:");
scanf("%d",&ID);
if(getchar() == '\n' )
{
//fflush(stdin);
while(p3)//查找同名的学生
{
if(p3->id == ID)
{
check = 1;
break;//如果第一次循环就跳出,说明删除的是头指针,此时p1和h都指向头结点
//如果是其他时候跳出,那么h指向要删除的结点,p1指向前一个结点
}
p1 = p3;
p3 = p3->next;
}
if(check == 1)//如果找到该学生
{
if(p1 == p3)//如果删除的是头结点
{
p2 = p3->next;//p2指向下一个结点
printf("%s已经被删除\n",p3->name);
free(p3);
return p2;//返回第二个结点的指针,作为头结点
}
else
{
p2 = p3->next;
p1->next = p2;//将被删除结点且一个结点的next指针指向被删除结点的下一个结点
printf("%s已经被删除\n",p3->name);
free(p3);
}
}
else
{
printf("未找到该同学\n");
}
}
else
{
printf("输入不合法\n");
}
fflush(stdin);
}
else
{
printf("输入错误\n");
}
while(1)
{
printf("是否再次删除(y / n)\n");
scanf("%c",&c);
if(getchar() == '\n')
{
fflush(stdin);
if( c == 'n'||c == 'N')
{
check3 = 1;
break;
}
else if( c == 'y'||c == 'Y')
{
break;
}
else
{
printf("输入不合法,请重新输入\n");
}
}
else
{
printf("输入不合法,请重新输入\n");
}
fflush(stdin);
}
if(check3 == 1)
{
break;
}
printf("\n");
}
return h;
}
//重新计算学生总分
//传入参数为链表头指针,无返回值
void ReCalculate(struct Student *h)
{
struct Student *p;
p = h;
while(p)
{
p->total = p->Class[0] + p->Class[1] + p->Class[2];
p = p->next;
}
}
//重新排名
void ReRank(struct Student *h)
{
struct Student *p1,*p3;
int j = 0 , i = 1;
p1 = h;
p1->Rank = 1;
p1 = h->next;
while(p1)
{
p1->Rank = 1;
p3 = h;
for(j = 0; j < i;j++)//擂台法排名,p3从head开始,一直比到p3与p1指向同一个结点就结束循环
{
if((p1->total) > (p3->total))
{
p3->Rank = p3->Rank + 1;
}
else if((p1->total) < (p3->total))
{
p1->Rank = p1->Rank + 1;
}
p3 = p3->next;
}
i++;
p1 = p1->next;
}
}
//保存修改后的信息到data3.txt
int SaveNew(struct Student *h , char *s)
{
FILE *fp;
struct Student *p;
if(( fp = fopen("data3.txt","w")) == NULL )//在指定位置建立一个新的txt文件
{
printf("can't bulid file\n");
return -1;
}
p = h;
fputs(s,fp);
while(p)
{
fprintf(fp,"%d\t%s\t%.2f\t%.2f\t%.2f\t%.2f\t %d\n",p->id,p->name,p->Class[0],p->Class[1],p->Class[2],p->total,p->Rank);
p = p->next;
}
fclose(fp);
return 0;
}
//显示学生全部信息
void ShowStuInfor(struct Student *h)
{
struct Student *p;
p = h;
while(p)
{
printf("%d\t%s\t%.2f\t%.2f\t%.2f\t%.2f\t %d\n",p->id,p->name,p->Class[0],p->Class[1],p->Class[2],p->total,p->Rank);
p = p->next ;
}
}
学生成绩管理系统显示
- 菜单
- 查询
- 修改
- 删除
- 显示所有人信息
- 各科分数段人数统计
- 退出
- 数据样式(data1.txt)
- 数据样式(data2.txt)
- 数据样式(data3.txt)