一、前言
时光匆匆,当年在实验室苦逼的敲代码的小学弟已经成了现在的大四老学长o(╥﹏╥)o,经过四年的洗礼,依然是个菜鸡。不过技术还是有所精进,最近考研复习数据结构又翻到了这个大一时候写的项目,然后发现有点小bug当时没有解决,于是强迫症又犯了,决定给它修好。现在针对第一版修复了以下功能:
1、增强了系统的安全性
2、修复了文件读取的错误
3、将冒泡排序修改为快速排序
如有问题可以在评论区反馈,有时间我会在修改。后续可能也会尝试使用其它数据结构来重构系统或者使用java来重写项目。
二、代码实现
#include<stdio.h> // bug 成绩输入时输入字母或者特殊字符会使程序崩溃
#include<string.h>
#include <stdlib.h>
struct student //结构体
{
char ID[20];
char name[20];
int eng,chn,cop; //英语 思修 体育
float ave; //用来对成绩排序
};
struct student st[10000]; //定义结构体变量
int num=0; //全局变量
void display() //主菜单
{
system("color 0");
printf(" *欢迎使用学生成绩管理系统* \n");
printf("********************************************************************************\n");
printf(" *请用户根据以下提示进行操作(温馨提示:请在成绩录入后再使用其它功能)* \n");
printf("*******************************************************************************\n");
printf("0.退出系统 1.成绩录入 2.计算平均成绩 3.成绩输出\n");
printf("4.成绩排序(按平均成绩) 5.成绩查找 6.成绩修改 7.成绩追加\n");
printf("8.删除成绩 9.成绩分段 10.文件存储 11.文件输出\n");
printf("*******************************************************************************\n");
printf(" *如需退出系统请按0* \n" );
}
void entry() //成绩录入
{
int i=0;
char a;
while(1)
{
printf("请输入学号:");
scanf("%s",st[num].ID );
printf("请输入姓名:");
scanf("%s",st[num].name );
printf("请输入英语成绩:");
scanf("%d",&st[num].eng );
printf("请输入思修成绩:");
scanf("%d",&st[num].chn );
printf("请输入体育成绩:");
scanf("%d",&st[num].cop );
num++;
printf("任意键继续,n退出:");
getchar();
if(getchar()=='n')
{
break;
}
}
for(i=0;i<num;i++) //计算平均成绩 (个人)
{
st[i].ave=(st[i].chn+st[i].cop+st[i].eng)/3.0;
}
}
void average() //平均分(班级)
{
system("cls");
display();
float socer=0,s1=0,s2=0,s3=0;
float aver,aver1,aver2,aver3;
int i;
for(i=0;i<num;i++)
{
socer=socer+st[i].ave;
}
aver=socer/num;
for(i=0;i<num;i++)
{
s1=s1+st[i].eng;
}
aver1=s1/num;
for(i=0;i<num;i++)
{
s2=s2+st[i].chn;
}
aver2=s2/num;
for(i=0;i<num;i++)
{
s3=s3+st[i].cop;
}
aver3=s3/num;
printf("班级平均分 英语平均分 思修平均分 体育平均分\n");
printf("------------------------------------------------------------\n");
printf("%.2f ",aver);
printf("%.2f ",aver1);
printf("%.2f ",aver2);
printf("%.2f \n",aver3);
}
void OUTPUT() //成绩输出
{
system("cls");
display();
int i;
printf("%s %s %s %s %s %s\n","学号","姓名","思修","体育","英语","平均分");
printf("--------------------------------------------------------\n");
for (i=0;i<num;i++)
{
printf("%s %s %d %d %d %.2f\n",st[i].ID,st[i].name,st[i].chn,st[i].cop,st[i].eng,st[i].ave);
}
}
void sort(student arr[],int left,int right) //快速排序
{
if(left>right){
return;
}
student baseStu = arr[left];
double base = arr[left].ave;
int i = left;
int j = right;
student temp;
while(i != j){
while(arr[j].ave >= base && i<j){
j--;
}
while(arr[i].ave <= base && i < j){
i++;
}
if(i < j){
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
arr[left] = arr[i];
arr[i] = baseStu;
sort(arr,left,i-1);
sort(arr,i+1,right);
}
void displaySort(){
system("cls");
display();
printf("按平均成绩排序后的结果为:\n");
printf("----------------------------------------------------------------------\n");
printf("%s %s %s %s %s %s\n","学号","姓名","思修","体育","英语","平均分");
for(int i=num-1;i>=0;i--)
{
printf("%s %s %d %d %d %.2f\n",st[i].ID,st[i].name,st[i].chn,st[i].cop,st[i].eng,st[i].ave);
}
printf("\n");
}
int findname(char name[]) //返回数组下标的函数 返回值为int型
{
int i;
for(i=0;i<num;i++)
{
if(strcmp(st[i].name,name)==0) //比较原数据与传入的数据是否相等,若相等则返回姓名下标
{
return i;
}
else if(strcmp(st[i].ID,name)==0) //返回ID下标
{
return i;
}
}
return -1; //若姓名和ID均没有相同的,则返回-1
}
void display1(int a);
void find1() //按姓名或者学号查找学生
{
system("cls");
display();
int i,t=0;
printf("学生名单:\n");
printf("****************************************************************************\n");
for(i=0;i<num;i++)
{
printf("%s %s\t",st[i].ID,st[i].name);
t++;
if(t==5)
{
printf("\n");
t=0;
}
}
printf("\n");
while(1)
{
char name[20];
int a;
printf("请输入要查询的学生信息:");
scanf("%s",name);
printf("\n");
getchar(); //不可省略
a=findname(name);
if(a==-1)
{
printf("学生信息有误,请重新输入!\n");
}
else
{
printf("您要查询的学生信息为:\n");
printf("****************************************************************************\n");
display1(a);
}
printf("任意键继续,n退出:");
if(getchar()=='n')
{
break;
}
}
}
void display1(int a) //单一学生信息显示
{
printf("%s %s %s %s %s %s\n","学号","姓名","思修","体育","英语","平均分");
printf("----------------------------------------------------------------------------\n");
printf("%s %s %d %d %d %.2f\n",st[a].ID,st[a].name,st[a].chn,st[a].cop,st[a].eng,st[a].ave);
}
void subsection() //成绩分段
{
system("cls"); //清屏函数
display(); //使菜单始终显示在顶端
int i;
int b=0;
int t1=0,t2=0,t3=0;
printf("优秀学生名单:\n"); //通过三个循环将优秀、优良、差生分别累加并分类显示
printf("--------------------------------------------------------------------\n");
for(i=0;i<num;i++)
{
b=b+st[i].chn+st[i].cop+st[i].eng;
if(b>=211&&b<=300)
{
t1++;
printf("%s %s %d %d %d %.2f\n",st[i].ID,st[i].name,st[i].chn,st[i].cop,st[i].eng,st[i].ave);
}
b=0;
}
b=0;
printf("--------------------------------------------------------------------\n");
printf("优良学生名单:\n");
printf("--------------------------------------------------------------------\n");
for(i=0;i<num;i++)
{
b=b+st[i].chn+st[i].cop+st[i].eng;
if(b>=180&&b<=210)
{
t2++;
printf("%s %s %d %d %d %.2f\n",st[i].ID,st[i].name,st[i].chn,st[i].cop,st[i].eng,st[i].ave);
}
b=0;
}
b=0;
printf("--------------------------------------------------------------------\n");
printf("差生名单:\n");
printf("--------------------------------------------------------------------\n");
for(i=0;i<num;i++)
{
b=b+st[i].chn+st[i].cop+st[i].eng;
if(b>=0&&b<=179)
{
t3++;
printf("%s %s %d %d %d %.2f\n",st[i].ID,st[i].name,st[i].chn,st[i].cop,st[i].eng,st[i].ave);
}
b=0;
}
b=0;
printf("\n");
printf("********************************************************************\n");
printf("\n");
printf("优等生 优良生 差生\n");
printf("--------------------------------------------------------------------\n");
printf("%d个 %d个 %d个\n",t1,t2,t3);
printf("\n");
}
void output() //文件输出或者存储
{
system("cls");
display();
int i;
FILE *fp;
fp=fopen("student.txt","w+");
if(fp==NULL)
{
printf("文件打开错误!");
exit(0);
}
for(i=0;i<num;i++)
{
fprintf(fp,"%s %s %d %d %d %.2f\n",st[i].ID,st[i].name,st[i].chn,st[i].cop,st[i].eng,st[i].ave);
//fprintf(fp,"\n");
}
fclose(fp);
}
void modify() //学生成绩修改
{
system("cls");
display();
int a;
int i;
char name[20];
printf("学生名单:\n"); //显示学生的姓名以备教师查看
printf("**************************************************************************\n");
for(i=0;i<num;i++)
{
printf("%s\t",st[i].name);
}
printf("\n");
printf("\n");
while(1)
{
printf("请输入要修改的学生的姓名:");
scanf("%s",&name);
a=findname(name); //通过姓名找到数组下标
if(a==-1) //如果没找到就接收到-1,从而报错
{
printf("学生信息有误!!!");
}
else
{
printf("需要修改的信息为:\n");
display1(a); //将需要修改的学生信息显示出来
int q;
printf("请输入要修改成绩的序号(1.英语 2.思修 3.体育):"); //选择要修改的科目
scanf("%d",&q);
if(q==1) //判断要修改的科目
{
printf("请输入要修改的英语成绩:");
scanf("%d",&st[a].eng); //重新输入要修改的成绩(将原先覆盖)
st[a].ave=(st[a].chn+st[a].cop+st[a].eng)/3.0; //对已修改的学生的平均分进行重新计算
getchar();
printf("任意键继续修改,n退出:");
if(getchar()=='n')
{
break;
}
}
if(q==2)
{
printf("请输入要修改的思修成绩:");
scanf("%d",&st[a].chn);
st[a].ave=(st[a].chn+st[a].cop+st[a].eng)/3.0;
getchar();
printf("任意键继续修改,n退出:");
if(getchar()=='n')
{
break;
}
}
if(q==3)
{
printf("请输入要修改的体育成绩:");
scanf("%d",&st[a].cop);
st[a].ave=(st[a].chn+st[a].cop+st[a].eng)/3.0;
getchar();
}
printf("任意键继续修改,n退出:");
if(getchar()=='n')
{
break;
}
}
}
}
void write()
{
FILE *fp;
int i;
if ((fp=fopen("student.txt","rb"))==NULL)
{
printf("不能打开文件!\n");
return;
}
fseek(fp, 0, SEEK_END);
int nFileSize = ftell(fp);
fseek(fp, 0, SEEK_SET);
char *buf = new char[nFileSize +1+1];
memset(buf, 0, nFileSize +1+1);
fread(buf, nFileSize, 1, fp);
fclose(fp);
char *p1, *p2;
p2 = buf;
int nRet;
int counts = 0;
for(nRet = 0; nRet < 10000;nRet++)
{
p1 = p2;
while(*p2 != '\n' && *p2 != 0)
{
p2++;
}
p2[0] = 0;
p2++;
if(sscanf(p1, "%s %s %d %d %d", &st[i].ID,&st[i].name,&st[i].chn,&st[i].cop,&st[i].eng) != 5)// num name a b c : 5
{
//st[i] = st[i-1];
counts++;
break;
}
i++;
counts++;
}
num = counts - 1;
delete buf;
for(int i=0;i<num;i++){
st[i].ave = (st[i].chn+st[i].cop+st[i].eng)/3.0;
}
OUTPUT();
fclose(fp);
}
void Delete() //删除学生信息
{
system("cls");
display();
int i;
printf("学生名单:\n");
printf("*************************************************\n");
for(i=0;i<num;i++)
{
printf("%s\t",st[i].name);
}
printf("\n");
printf("*************************************************\n");
while(1)
{
char name[20];
int a;
printf("请输入要删除的学生姓名:"); //ID也可以实现,原理类似
scanf("%s",name);
a=findname(name); //确定数组下标
if(a==-1) //如果返回值为-1,提醒出错
{
printf("学生不存在!\n");
}
else
{
printf("你要删除的学生信息为:\n");
display1(a); //显示要删除的学生信息
printf("是否删除(确认请按y):");
getchar();
if(getchar()=='y')
{
for(i=a;i<num-1;i++)
{
st[i]=st[i+1]; //把后边的对象都向前移动
}
num--; //学生人数减去一,最后一位(即要删除的学生)就不会被显示了
}
}
getchar();
printf("任意键继续,n退出:");
if (getchar()=='n')
{
break;
}
}
}
void isEmptyWarming(){
if(num <= 0){
printf("请先输入学生信息!");
}
}
int main() //主函数
{
display();
char i[200];
int b;
char p[30];
char a[60];
int flag = 0;
while(1)
{
printf("请输入密码:"); //密码 zhang 中国智造2025
scanf("%s",a);
if(strcmp(a,"zhang")==0) //设置简单的密码,如果输入的与设置的一致则程序继续运行,否则报错。
{
system("cls");
display();
while(1)
{
if(num <= 0){
printf("%s","学生信息为空,是否从文件读取(1/0):");
scanf("%d",&flag);
if(flag){
printf("\n");
write();
}else{
system("cls");
display();
printf("请先输入学生信息。\n");
entry();
}
}else{
printf("\n请选择功能:");
scanf("%s",i); //判断用户输入的是否在0-11数字范围内,若输入字母或特殊符号则报错!
printf("\n");
if(strcmp(i,"1")==0)b=1;
else if(strcmp(i,"0")==0)b=0; //起
else if(strcmp(i,"2")==0)b=2;
else if(strcmp(i,"3")==0)b=3;
else if(strcmp(i,"4")==0)b=4;
else if(strcmp(i,"5")==0)b=5;
else if(strcmp(i,"6")==0)b=6;
else if(strcmp(i,"7")==0)b=7;
else if(strcmp(i,"8")==0)b=8;
else if(strcmp(i,"9")==0)b=9;
else if(strcmp(i,"10")==0)b=10;
else if(strcmp(i,"11")==0)b=11; // 终
else
{
b=-1;
}
if(b>=0&&b<=11) //b的范围在0-11之间
{
switch(b)
{
case 1:entry();break; //录入信息
case 2: //求班级总体的平均分
{
isEmptyWarming();
average();
break;
}
case 3: //输出学生信息
{
isEmptyWarming();
OUTPUT();break;
}
case 4: //排序
{
isEmptyWarming();
sort(st,0,num-1);displaySort();break;
}
case 5: //按学号或者姓名查找
{
isEmptyWarming();
find1();break;
}
case 6: //修改
{
isEmptyWarming();
modify();break;
}
case 7:entry();break; //追加/
case 8: //删除
{
isEmptyWarming();
Delete();break;
}
case 9: //成绩分段
{
isEmptyWarming();
subsection();break;
}
case 10: //输出到文件
{
isEmptyWarming();
output();break;
}
case 11:write();break; //从文件读取信息
case 0:exit(0);break; //退出系统
}
}
else if(b=-1) //如果b=-1,则报错
{
printf("暂未建设此功能,请重新选择!\n");
}
}
}
}
else
{
printf("密码错误请重新输入!\n");
}
}
}