短学期的实践作业,感觉挺好玩的哈
自己写了一个成绩管理系统,拥有输出,新建,修改,删除,查询,排序的功能,用链表实现的(空首指针+带数据尾指针,双向链表)
你可能会觉得这种东西千篇一律,但是我觉得我写的万里挑一啊,哈哈。
要注意的东西真的好多,因为功能太多了,我又是个完美主义者,各种界面的排版优化问题花了太多的时间,而且懒得写首尾都空的链表(那么些不管删除还是插入都不用考虑位置的关系,但是插入的时候要多些几个字。哎,自己挖的坑自己踩),所以这600行代码敲了差不多八个小时才敲完。
先祭出我画了好久的代码流程图:
初始数据:
20170001 小明 90 65 37
20170002 小小 62 65 87
20170003 小智 90 69 17
20170004 小兰 83 75 97
20170005 小鹿 94 82 37
20170006 小刚 87 77 37
总体设计:
(一)数据结构描述
本程序采用链表的结构进行操作。考虑到删除时要判断位置但是插入在尾指针,所以选用了空的首指针+带数据的尾指针的结构。考虑到可能会有前继的影响,所以选用了双向链表,最后虽然用不到,但是也没有造成什么负面影响。
(二)功能模块设计
- 添加信息的实现过程:
因为用一个 back 指针指向尾节点,所以可直接插在 back 的后面 - 排序的实现过程:
考虑到冒泡和选择排序的时间复杂度较大,所以用一个指针数组记录所有节点,用 stl 库的 sort 函数对其排序后重构链表 - 遍历的实现过程:
因为 front 指针为空,所以可以now = front;while(now != back) now = now -> nex
来遍历,这样做可以不用考虑链表为空的情况 - 删除的实现过程:
要特判一下尾指针的情况,一遍都是维护一下前面节点和后面节点的nex和pre
函数功能(主块):
system(“cls”) 和 Sleep(1200) 纯属为了美观,这里不做讲解
部分函数的作用为判除错误读入,也就是找bug,这里也不讲解了
主函数从文本读入数据,并启动 init()主菜单函数
int main()
{
date_in();
printf("Loading date...\n");Sleep(2000);
CL;
init();
}
初始化数据
void date_in()
{
FILE *in=fopen("备份数据.txt","r");
int t=6;
while(t--)
{
node *tmp=new node;
push_back(tmp);
fscanf(in,"%s%s%f%f%f",&tmp->_id,&tmp->name,&tmp->point[1],&tmp->point[2],&tmp->point[3]);
tmp->point[4]=tmp->point[1]+tmp->point[2]+tmp->point[3];
tmp->point[4]/=3.0;
}
}
主菜单函数作为这个程序的主板,用于连接所有操作
void init()
{
printf("\n--> 欢迎使用学生成绩管理系统\n");
printf("\n--> 主菜单 (允许操作选择错误 ^-^)\n");
printf("\n 1: 输出\n\n 2: 新建 (id重复判错)\n\n 3: 删除\n\n 4: 询问\n\n 5: 排序\n\n 6: 退出\n\n");
int tmp;scanf("%d",&tmp); getchar();
switch(tmp)
{
case 1 :date_out();break;
case 2 :add();break;
case 3 :erase();break;
case 4 :date_find();break;
case 5 :sort();break;
case 6 :close();break;
default:error_in();
}
}
在功能函数结束后返回主界面
void return_init()
{
CL;
init();
}
链表的节点信息以及压入操作
struct node
{
node *pre,*nex; //链表指针
char _id[30],name[30]; //学号 姓名
F point[5]; //数学 语文 英语 平均分
};
node *front=new node,*back=front; //链表首尾指针
void push_back(node *tmp) //压入链尾
{
back->nex=tmp;
tmp->pre=back;
back=tmp;
}
输出所有的信息,遍历方法上文已有介绍
void date_out()
{
CL;
node *now=front;
printf("\n--> 库数据输出\n\n 学号 姓名 数学 语文 英语 均分\n\n");
while(now!=back)
{
now=now->nex;
printf("%8s%8s%8.0f%8.0f%8.0f%8.0f\n\n",now->_id,now->name,now->point[1],now->point[2],now->point[3],now->point[4]);
}
printf("\n--> 请按回车键返回上层.\n\n");
getchar();
CL;
init();
}
在主菜单选择,关闭系统相当于结束init函数
void close()
{
CL;
printf("\n--> 欢迎再次使用!\n\n");
Sleep(2000);
}
函数功能(添加)
添加界面,连接添加界面
void add()
{
CL;
printf("\n--> 操作选择\n");
printf("\n1: 手动添加\n\n2: 随机生成数据\n\n3: 返回主菜单\n\n");
int tmp;scanf("%d",&tmp);getchar();
switch(tmp)
{
case 1 :add_hand();break;
case 2 :add_random();break;
case 3 :return_init();break;
default:error_in_add();break;
}
}
判断学号是否重复,也可以直接传char*比较
char ip[30];
int find()
{
node *now=front;
while(now!=back)
{
now=now->nex;
if(strcmp(ip,now->_id)==0)
return 1;
}
return 0;
}
手动输入新建信息,注意先判断是否重复id再压入链表
void add_hand()
{
node *tmp=new node;
CL;printf("\n--> 请输入学号(8位或8位以下数字)\n\n");
scanf("%s",&tmp->_id);getchar();
memset(ip,0,sizeof(ip));
strcat(ip,tmp->_id);
if(find())
{
CL;printf("\n--> 添加失败,此学号已被占用!\n");
printf("\n--> 请按回车键返回上层.\n\n");
getchar();
CL;
init();
return ;
}
push_back(tmp);
CL;printf("\n--> 请输入姓名\n\n");
scanf("%s",&tmp->name);
CL;printf("\n--> 请分别输入数学,语文,英语成绩(<=100)\n\n");
scanf("%f%f%f",&tmp->point[1],&tmp->point[2],&tmp->point[3]);getchar();
tmp->point[4]=tmp->point[1]+tmp->point[2]+tmp->point[3];
tmp->point[4]/=3.0;
CL;printf("\n-> 添加成功\n\n添加新条目信息为:\n\n");
printf("学号: %s\n\n",tmp->_id);
printf("姓名: %s\n\n",tmp->name);
printf("数学: %.0f\n\n",tmp->point[1]);
printf("语文: %.0f\n\n",tmp->point[2]);
printf("英语: %.0f\n\n",tmp->point[3]);
printf("均分: %.0f\n\n",tmp->point[4]);
printf("--> 请按回车键返回上层.\n\n");
getchar();
CL;
init();
}
用rand函数随机生成数据,当然随机生成也会id判重
void add_random()
{
CL;
printf("\n--> 随机生成数据如下:\n\n");
node *tmp=new node;
while(1)
{
memset(tmp->_id,0,sizeof(tmp->_id));
tmp->_id[0]='2',tmp->_id[1]='0',tmp->_id[2]='1',tmp->_id[3]='7';
for(int i=4;i<8;i++)
{
tmp->_id[i]='0'+random(0,9);
}
memset(ip,0,sizeof(ip));
strcat(ip,tmp->_id);
if(!find())break;
}
push_back(tmp);
memset(tmp->name,0,sizeof(tmp->name));
int len=random(1,7);
for(int i=0;i<len;i++)
{
tmp->name[i]='a'+random(0,25);
}
for(int i=1;i<=3;i++)tmp->point[i]=(F)random(0,100);
tmp->point[4]=tmp->point[1]+tmp->point[2]+tmp->point[3];
tmp->point[4]/=3.0;
printf("学号: %s\n\n",tmp->_id);
printf("姓名: %s\n\n",tmp->name);
printf("数学: %.0f\n\n",tmp->point[1]);
printf("语文: %.0f\n\n",tmp->point[2]);
printf("英语: %.0f\n\n",tmp->point[3]);
printf("均分: %.0f\n\n",tmp->point[4]);
printf("--> 请按回车键返回上层.\n\n");
getchar();
CL;
init();
}
函数功能(删除)
删除界面,连接删除操作
void erase()
{
CL;
printf("\n--> 操作选择\n");
printf("\n1: 删除指定学号\n\n2: 删除指定姓名 (包括重名)\n\n3: 返回主菜单\n\n");
int tmp;scanf("%d",&tmp); getchar();
switch(tmp)
{
case 1 :erase_id();break;
case 2 :erase_name();break;
case 3 :return_init();break;
default:error_in_erase();break;
}
}
链表的删除节点操作
void erase_node(node *tmp)
{
if(tmp==back)
{
tmp=tmp->pre;
back=tmp;
}
else
{
tmp->pre->nex=tmp->nex;
tmp->nex->pre=tmp->pre;
}
}
按学号删除信息,判一下有没有
void erase_id()
{
CL;
printf("\n--> 请输入要删除的学号:\n\n");
char tmp[30];
scanf("%s",tmp);getchar();
node *now=front;
int flag=0;
while(now!=back)
{
now=now->nex;
if(strcmp(now->_id,tmp)==0)
{
erase_node(now);
flag=1;
break;
}
}
CL;
if(flag==1)printf("\n--> 删除成功\n");
else printf("\n--> Error: 匹配失败\n");
printf("\n--> 请按回车键返回主菜单.\n\n");
getchar();
CL;
init();
}
按姓名删除信息,注意会出现同名
void erase_name()
{
CL;
printf("\n--> 请输入要删除的姓名:\n\n");
char tmp[30];
scanf("%s",tmp);getchar();
node *now=front;
int flag=0;
while(now!=back)
{
now=now->nex;
if(strcmp(now->name,tmp)==0)
{
if(now==back)
{
erase_node(now);
flag=1;
break;
}
erase_node(now);
flag=1;
}
}
CL;
if(flag==1)printf("\n--> 删除成功\n");
else printf("\n--> Error: 匹配失败\n");
printf("\n--> 请按回车键返回主菜单.\n\n");
getchar();
CL;
init();
}
函数功能(查找)
打开查找界面,连接查找操作
void date_find()
{
CL;
printf("\n--> 操作选择\n");
printf("\n1: 查询指定学号\n\n2: 查询指定姓名 (包括重名)\n\n3: 查找指定成绩范围\n\n4: 返回主菜单\n\n");
int tmp;scanf("%d",&tmp); getchar();
switch(tmp)
{
case 1 :date_find_id();break;
case 2 :date_find_name();break;
case 3 :date_find_point();break;
case 4 :return_init();break;
default:error_in_find();break;
}
}
按学号查找信息,因为学号不会重复,所以找到一个就可以break方便很多
void date_find_id()
{
CL;
printf("\n--> 请输入要查询的学号:\n\n");
char tmp[30];
scanf("%s",tmp);getchar();
node *now=front;
int flag=0;
CL;
while(now!=back)
{
now=now->nex;
if(strcmp(now->_id,tmp)==0)
{
CL;
printf("\n--> 查询结果如下:\n\n 学号 姓名 数学 语文 英语 均分\n");
printf("\n%8s%8s%8.0f%8.0f%8.0f%8.0f\n",now->_id,now->name,now->point[1],now->point[2],now->point[3],now->point[4]);
flag=1;
break;
}
}
if(flag!=1)printf("\n--> Error: 匹配失败\n");
printf("\n--> 请按回车键返回主菜单.\n\n");
getchar();
CL;
init();
}
按姓名查找信息,也会重名
void date_find_name()
{
CL;
printf("\n--> 请输入要查询的姓名:\n\n");
char tmp[30];
scanf("%s",tmp);getchar();CL;
node *now=front;
int flag=0;
while(now!=back)
{
now=now->nex;
if(strcmp(now->name,tmp)==0)
{
if(flag==0)printf("\n--> 查询结果如下:\n\n 学号 姓名 数学 语文 英语 均分\n");
printf("\n%8s%8s%8.0f%8.0f%8.0f%8.0f\n",now->_id,now->name,now->point[1],now->point[2],now->point[3],now->point[4]);
flag=1;
}
}
if(flag!=1)printf("\n--> Error: 匹配失败\n");
printf("\n--> 请按回车键返回主菜单.\n\n");
getchar();
CL;
init();
}
按成绩查找信息,因为分别存在数组里,所以可以用下标选择来降低代码的重复情况
并且提供区间查询,左右区间的大小情况判断,以及匹配数量的输出
void date_find_point()
{
CL;
int Flag;F l,r;
printf("\n--> 请选择科目\n\n1: 数学\n\n2: 语文\n\n3: 英语\n\n4: 均分\n\n");
scanf("%d",&Flag);getchar();
CL;
if(Flag<1||Flag>4)
{
error_in_find();
return;
}
printf("\n--> 请输入要查询的成绩区间(闭区间):\n\n");
scanf("%f%f",&l,&r);getchar();
if(l>r)swap(l,r);
CL;
node *now=front;
int flag=0;
int num=0;
while(now!=back)
{
now=now->nex;
if(now->point[Flag]<=r&&now->point[Flag]>=l)
{
num++;
if(flag==0)printf("\n--> 查询结果如下:\n\n 学号 姓名 数学 语文 英语 均分\n");
printf("\n%8s%8s%8.0f%8.0f%8.0f%8.0f\n",now->_id,now->name,now->point[1],now->point[2],now->point[3],now->point[4]);
flag=1;
}
}
if(flag!=1)printf("\n--> Error: 匹配失败\n");
else printf("\n共 %d 项符合要求\n",num);
printf("\n--> 请按回车键返回主菜单.\n\n");
getchar();
CL;
init();
}
函数功能(排序)
选择,冒泡排序都没有sort快,考虑到大量数据的处理,所以选择了后者
做法是存到指针数组里再自己写cmp函数,sort后重构链表,写起来还是很快的
bool cmp11(node* a,node *b)
{
return a->point[1]<b->point[1];
}
bool cmp12(node* a,node *b)
{
return a->point[1]>b->point[1];
}
bool cmp21(node* a,node *b)
{
return a->point[2]<b->point[2];
}
bool cmp22(node* a,node *b)
{
return a->point[2]>b->point[2];
}
bool cmp31(node* a,node *b)
{
return a->point[3]<b->point[3];
}
bool cmp32(node* a,node *b)
{
return a->point[3]>b->point[3];
}
bool cmp41(node* a,node *b)
{
return a->point[1]+a->point[2]+a->point[3] < b->point[1]+b->point[2]+b->point[3];
}
bool cmp42(node* a,node *b)
{
return a->point[4] > b->point[4];
}
bool cmp51(node* a,node *b)
{
return strcmp(a->_id,b->_id)==-1;
}
bool cmp52(node* a,node *b)
{
return strcmp(a->_id,b->_id)==1;
}
bool cmp61(node* a,node *b)
{
return strcmp(a->name,b->name)==-1;
}
bool cmp62(node* a,node *b)
{
return strcmp(a->name,b->name)==1;
}
node *Y[1000];
void sort()
{
CL;
int Flag1,Flag2;
printf("\n--> 请选择排序关键词\n\n1: 数学\n\n2: 语文\n\n3: 英语\n\n4: 平均分\n\n5: 学号 (字典序)\n\n6: 姓名 (字典序)\n\n");
scanf("%d",&Flag1);getchar();
CL;
printf("\n--> 请选择排序类别:\n\n1: 升序\n\n2: 降序\n\n");
scanf("%d",&Flag2);getchar();
CL;
node *now=front;
int idx=0;
while(now!=back)
{
now=now->nex;
Y[++idx]=now;
}
if(Flag1==1&&Flag2==1)sort(Y+1,Y+1+idx,cmp11);
else if(Flag1==1&&Flag2==2)sort(Y+1,Y+1+idx,cmp12);
else if(Flag1==2&&Flag2==1)sort(Y+1,Y+1+idx,cmp21);
else if(Flag1==2&&Flag2==2)sort(Y+1,Y+1+idx,cmp22);
else if(Flag1==3&&Flag2==1)sort(Y+1,Y+1+idx,cmp31);
else if(Flag1==3&&Flag2==2)sort(Y+1,Y+1+idx,cmp32);
else if(Flag1==4&&Flag2==1)sort(Y+1,Y+1+idx,cmp41);
else if(Flag1==4&&Flag2==2)sort(Y+1,Y+1+idx,cmp42);
else if(Flag1==5&&Flag2==1)sort(Y+1,Y+1+idx,cmp51);
else if(Flag1==5&&Flag2==2)sort(Y+1,Y+1+idx,cmp52);
else if(Flag1==6&&Flag2==1)sort(Y+1,Y+1+idx,cmp61);
else if(Flag1==6&&Flag2==2)sort(Y+1,Y+1+idx,cmp62);
if(Flag1<1||Flag1>6||Flag2<1||Flag2>2)printf("\n--> QAQ , 别再考验我找bug能力了......\n");
else
{
back=front;
for(int i=1;i<=idx;i++)
{
back->nex=Y[i];
Y[i]->pre=back;
back=Y[i];
}
date_out();
reutrn;
}
printf("\n--> 请按回车键返回主菜单.\n\n");
getchar();
CL;
init();
}
代码:
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<map>
#include<windows.h>
using namespace std;
#define F float
#define stop Sleep(1200)
#define CL system("cls")
#define random(a,b) (rand()%(b-a+1)+a)
void date_in();
void error_in();
void date_out();
void add();
void error_in_erase();
void return_init();
void erase();
void init();
void date_find();
void error_in_find();
struct node //节点信息
{
node *pre,*nex; //链表指针
char _id[30],name[30]; //学号 姓名
F point[5]; //数学 语文 英语 平均分
};
node *front=new node,*back=front; //链表首尾指针
void push_back(node *tmp) //压入链尾
{
back->nex=tmp;
tmp->pre=back;
back=tmp;
}
void date_in() //初始化数据
{
FILE *in=fopen("备份数据.txt","r");
int t=6;
while(t--)
{
node *tmp=new node;
push_back(tmp);
fscanf(in,"%s%s%f%f%f",&tmp->_id,&tmp->name,&tmp->point[1],&tmp->point[2],&tmp->point[3]);
tmp->point[4]=tmp->point[1]+tmp->point[2]+tmp->point[3];
tmp->point[4]/=3.0;
}
}
void error_in() //主界面操作查找失败
{
CL;printf("\n--> QAQ , 别再考验我找bug能力了......\n");
printf("\n--> 请按回车键返回上层.\n\n") ;
getchar();
CL;
init();
}
void date_out() //库数据输出
{
CL;
node *now=front;
printf("\n--> 库数据输出\n\n 学号 姓名 数学 语文 英语 均分\n\n");
while(now!=back)
{
now=now->nex;
printf("%8s%8s%8.0f%8.0f%8.0f%8.0f\n\n",now->_id,now->name,now->point[1],now->point[2],now->point[3],now->point[4]);
}
printf("\n--> 请按回车键返回上层.\n\n");
getchar();
CL;
init();
}
char ip[30];
int find() //判断学号是否重复
{
node *now=front;
while(now!=back)
{
now=now->nex;
if(strcmp(ip,now->_id)==0)
return 1;
}
return 0;
}
void add_hand() //手动新建信息
{
node *tmp=new node;
CL;printf("\n--> 请输入学号(8位或8位以下数字)\n\n");
scanf("%s",&tmp->_id);getchar();
memset(ip,0,sizeof(ip));
strcat(ip,tmp->_id);
if(find())
{
CL;printf("\n--> 添加失败,此学号已被占用!\n");
printf("\n--> 请按回车键返回上层.\n\n");
getchar();
CL;
init();
return ;
}
push_back(tmp);
CL;printf("\n--> 请输入姓名\n\n");
scanf("%s",&tmp->name);
CL;printf("\n--> 请分别输入数学,语文,英语成绩(<=100)\n\n");
scanf("%f%f%f",&tmp->point[1],&tmp->point[2],&tmp->point[3]);getchar();
tmp->point[4]=tmp->point[1]+tmp->point[2]+tmp->point[3];
tmp->point[4]/=3.0;
CL;printf("\n-> 添加成功\n\n添加新条目信息为:\n\n");
printf("学号: %s\n\n",tmp->_id);
printf("姓名: %s\n\n",tmp->name);
printf("数学: %.0f\n\n",tmp->point[1]);
printf("语文: %.0f\n\n",tmp->point[2]);
printf("英语: %.0f\n\n",tmp->point[3]);
printf("均分: %.0f\n\n",tmp->point[4]);
printf("--> 请按回车键返回上层.\n\n");
getchar();
CL;
init();
}
void add_random() //随机生成数据
{
CL;
printf("\n--> 随机生成数据如下:\n\n");
node *tmp=new node;
while(1)
{
memset(tmp->_id,0,sizeof(tmp->_id));
tmp->_id[0]='2',tmp->_id[1]='0',tmp->_id[2]='1',tmp->_id[3]='7';
for(int i=4;i<8;i++)
{
tmp->_id[i]='0'+random(0,9);
}
memset(ip,0,sizeof(ip));
strcat(ip,tmp->_id);
if(!find())break;
}
push_back(tmp);
memset(tmp->name,0,sizeof(tmp->name));
int len=random(1,7);
for(int i=0;i<len;i++)
{
tmp->name[i]='a'+random(0,25);
}
for(int i=1;i<=3;i++)tmp->point[i]=(F)random(0,100);
tmp->point[4]=tmp->point[1]+tmp->point[2]+tmp->point[3];
tmp->point[4]/=3.0;
printf("学号: %s\n\n",tmp->_id);
printf("姓名: %s\n\n",tmp->name);
printf("数学: %.0f\n\n",tmp->point[1]);
printf("语文: %.0f\n\n",tmp->point[2]);
printf("英语: %.0f\n\n",tmp->point[3]);
printf("均分: %.0f\n\n",tmp->point[4]);
printf("--> 请按回车键返回上层.\n\n");
getchar();
CL;
init();
}
void error_in_add() //添加界面操作查找失败
{
CL;printf("\n--> QAQ , 别再考验我找bug能力了......\n");
printf("\n--> 请按回车键返回上层.\n\n") ;
getchar();
CL;
add();
}
void add() //添加界面
{
CL;
printf("\n--> 操作选择\n");
printf("\n1: 手动添加\n\n2: 随机生成数据\n\n3: 返回主菜单\n\n");
int tmp;scanf("%d",&tmp);getchar();
switch(tmp)
{
case 1 :add_hand();break;
case 2 :add_random();break;
case 3 :return_init();break;
default:error_in_add();break;
}
}
void error_in_erase() //删除界面操作查找失败
{
CL;printf("\n--> QAQ , 别再考验我找bug能力了......\n");
printf("\n--> 请按回车键返回上层.\n\n") ;
getchar();
CL;
erase();
}
void return_init() //返回主界面
{
CL;
init();
}
void erase_node(node *tmp) //删除节点
{
if(tmp==back)
{
tmp=tmp->pre;
back=tmp;
}
else
{
tmp->pre->nex=tmp->nex;
tmp->nex->pre=tmp->pre;
}
}
void erase_id() //按学号删除信息
{
CL;
printf("\n--> 请输入要删除的学号:\n\n");
char tmp[30];
scanf("%s",tmp);getchar();
node *now=front;
int flag=0;
while(now!=back)
{
now=now->nex;
if(strcmp(now->_id,tmp)==0)
{
erase_node(now);
flag=1;
break;
}
}
CL;
if(flag==1)printf("\n--> 删除成功\n");
else printf("\n--> Error: 匹配失败\n");
printf("\n--> 请按回车键返回主菜单.\n\n");
getchar();
CL;
init();
}
void erase_name() //按姓名删除信息
{
CL;
printf("\n--> 请输入要删除的姓名:\n\n");
char tmp[30];
scanf("%s",tmp);getchar();
node *now=front;
int flag=0;
while(now!=back)
{
now=now->nex;
if(strcmp(now->name,tmp)==0)
{
if(now==back)
{
erase_node(now);
flag=1;
break;
}
erase_node(now);
flag=1;
}
}
CL;
if(flag==1)printf("\n--> 删除成功\n");
else printf("\n--> Error: 匹配失败\n");
printf("\n--> 请按回车键返回主菜单.\n\n");
getchar();
CL;
init();
}
void erase() //删除界面
{
CL;
printf("\n--> 操作选择\n");
printf("\n1: 删除指定学号\n\n2: 删除指定姓名 (包括重名)\n\n3: 返回主菜单\n\n");
int tmp;scanf("%d",&tmp); getchar();
switch(tmp)
{
case 1 :erase_id();break;
case 2 :erase_name();break;
case 3 :return_init();break;
default:error_in_erase();break;
}
}
void close() //关闭系统
{
CL;
printf("\n--> 欢迎再次使用!\n\n");
Sleep(2000);
}
void date_find_name() //按姓名查找信息
{
CL;
printf("\n--> 请输入要查询的姓名:\n\n");
char tmp[30];
scanf("%s",tmp);getchar();CL;
node *now=front;
int flag=0;
while(now!=back)
{
now=now->nex;
if(strcmp(now->name,tmp)==0)
{
if(flag==0)printf("\n--> 查询结果如下:\n\n 学号 姓名 数学 语文 英语 均分\n");
printf("\n%8s%8s%8.0f%8.0f%8.0f%8.0f\n",now->_id,now->name,now->point[1],now->point[2],now->point[3],now->point[4]);
flag=1;
}
}
if(flag!=1)printf("\n--> Error: 匹配失败\n");
printf("\n--> 请按回车键返回主菜单.\n\n");
getchar();
CL;
init();
}
void date_find_point() //按成绩查找信息
{
CL;
int Flag;F l,r;
printf("\n--> 请选择科目\n\n1: 数学\n\n2: 语文\n\n3: 英语\n\n4: 均分\n\n");
scanf("%d",&Flag);getchar();
CL;
if(Flag<1||Flag>4)
{
error_in_find();
return;
}
printf("\n--> 请输入要查询的成绩区间(闭区间):\n\n");
scanf("%f%f",&l,&r);getchar();
if(l>r)swap(l,r);
CL;
node *now=front;
int flag=0;
int num=0;
while(now!=back)
{
now=now->nex;
if(now->point[Flag]<=r&&now->point[Flag]>=l)
{
num++;
if(flag==0)printf("\n--> 查询结果如下:\n\n 学号 姓名 数学 语文 英语 均分\n");
printf("\n%8s%8s%8.0f%8.0f%8.0f%8.0f\n",now->_id,now->name,now->point[1],now->point[2],now->point[3],now->point[4]);
flag=1;
}
}
if(flag!=1)printf("\n--> Error: 匹配失败\n");
else printf("\n共 %d 项符合要求\n",num);
printf("\n--> 请按回车键返回主菜单.\n\n");
getchar();
CL;
init();
}
void date_find_id() //按学号查找信息
{
CL;
printf("\n--> 请输入要查询的学号:\n\n");
char tmp[30];
scanf("%s",tmp);getchar();
node *now=front;
int flag=0;
CL;
while(now!=back)
{
now=now->nex;
if(strcmp(now->_id,tmp)==0)
{
CL;
printf("\n--> 查询结果如下:\n\n 学号 姓名 数学 语文 英语 均分\n");
printf("\n%8s%8s%8.0f%8.0f%8.0f%8.0f\n",now->_id,now->name,now->point[1],now->point[2],now->point[3],now->point[4]);
flag=1;
break;
}
}
if(flag!=1)printf("\n--> Error: 匹配失败\n");
printf("\n--> 请按回车键返回主菜单.\n\n");
getchar();
CL;
init();
}
void error_in_find() //查找界面操作查找失败
{
CL;
printf("\n--> QAQ , 别再考验我找bug能力了......\n");
printf("\n--> 请按回车键返回上层.\n\n") ;
getchar();
CL;
date_find();
}
void date_find() //查找界面
{
CL;
printf("\n--> 操作选择\n");
printf("\n1: 查询指定学号\n\n2: 查询指定姓名 (包括重名)\n\n3: 查找指定成绩范围\n\n4: 返回主菜单\n\n");
int tmp;scanf("%d",&tmp); getchar();
switch(tmp)
{
case 1 :date_find_id();break;
case 2 :date_find_name();break;
case 3 :date_find_point();break;
case 4 :return_init();break;
default:error_in_find();break;
}
}
bool cmp11(node* a,node *b) //各种排序
{
return a->point[1]<b->point[1];
}
bool cmp12(node* a,node *b)
{
return a->point[1]>b->point[1];
}
bool cmp21(node* a,node *b)
{
return a->point[2]<b->point[2];
}
bool cmp22(node* a,node *b)
{
return a->point[2]>b->point[2];
}
bool cmp31(node* a,node *b)
{
return a->point[3]<b->point[3];
}
bool cmp32(node* a,node *b)
{
return a->point[3]>b->point[3];
}
bool cmp41(node* a,node *b)
{
return a->point[1]+a->point[2]+a->point[3] < b->point[1]+b->point[2]+b->point[3];
}
bool cmp42(node* a,node *b)
{
return a->point[4] > b->point[4];
}
bool cmp51(node* a,node *b)
{
return strcmp(a->_id,b->_id)==-1;
}
bool cmp52(node* a,node *b)
{
return strcmp(a->_id,b->_id)==1;
}
bool cmp61(node* a,node *b)
{
return strcmp(a->name,b->name)==-1;
}
bool cmp62(node* a,node *b)
{
return strcmp(a->name,b->name)==1;
}
node *Y[1000];
void sort() //排序界面
{
CL;
int Flag1,Flag2;
printf("\n--> 请选择排序关键词\n\n1: 数学\n\n2: 语文\n\n3: 英语\n\n4: 平均分\n\n5: 学号 (字典序)\n\n6: 姓名 (字典序)\n\n");
scanf("%d",&Flag1);getchar();
CL;
printf("\n--> 请选择排序类别:\n\n1: 升序\n\n2: 降序\n\n");
scanf("%d",&Flag2);getchar();
CL;
node *now=front;
int idx=0;
while(now!=back)
{
now=now->nex;
Y[++idx]=now;
}
if(Flag1==1&&Flag2==1)sort(Y+1,Y+1+idx,cmp11);
else if(Flag1==1&&Flag2==2)sort(Y+1,Y+1+idx,cmp12);
else if(Flag1==2&&Flag2==1)sort(Y+1,Y+1+idx,cmp21);
else if(Flag1==2&&Flag2==2)sort(Y+1,Y+1+idx,cmp22);
else if(Flag1==3&&Flag2==1)sort(Y+1,Y+1+idx,cmp31);
else if(Flag1==3&&Flag2==2)sort(Y+1,Y+1+idx,cmp32);
else if(Flag1==4&&Flag2==1)sort(Y+1,Y+1+idx,cmp41);
else if(Flag1==4&&Flag2==2)sort(Y+1,Y+1+idx,cmp42);
else if(Flag1==5&&Flag2==1)sort(Y+1,Y+1+idx,cmp51);
else if(Flag1==5&&Flag2==2)sort(Y+1,Y+1+idx,cmp52);
else if(Flag1==6&&Flag2==1)sort(Y+1,Y+1+idx,cmp61);
else if(Flag1==6&&Flag2==2)sort(Y+1,Y+1+idx,cmp62);
if(Flag1<1||Flag1>6||Flag2<1||Flag2>2)printf("\n--> QAQ , 别再考验我找bug能力了......\n");
else
{
back=front;
for(int i=1;i<=idx;i++)
{
back->nex=Y[i];
Y[i]->pre=back;
back=Y[i];
}
date_out();
reutrn;
}
printf("\n--> 请按回车键返回主菜单.\n\n");
getchar();
CL;
init();
}
void init() //主菜单
{
printf("\n--> 欢迎使用学生成绩管理系统\n");
printf("\n--> 主菜单 (允许操作选择错误 ^-^)\n");
printf("\n 1: 输出\n\n 2: 新建 (id重复判错)\n\n 3: 删除\n\n 4: 询问\n\n 5: 排序\n\n 6: 退出\n\n");
int tmp;scanf("%d",&tmp); getchar();
switch(tmp)
{
case 1 :date_out();break;
case 2 :add();break;
case 3 :erase();break;
case 4 :date_find();break;
case 5 :sort();break;
case 6 :close();break;
default:error_in();
}
}
int main() //输出格式:分块数据 块内连续 块间换行
{
date_in();
printf("Loading date...\n");Sleep(2000);
CL;
init();
}