涉及知识:
链表、指针、结构体、枚举类型、简单的刷屏操作
代码如下:
#include<stdio.h>
#include<stdlib.h>
int Max_num=-1; /*用一个全局变量,保证最大学号*/
int page=0;
enum sex{男=1,女=2};
struct StuLink{
int xh;
char xm[20];
enum sex xb;
int cj;
char dj;
int mc;
struct StuLink *next;
}stu; /*单链表类型声明*/
void CreatFile(); /*初始化文件*/
struct StuLink *ReadFromFile(); /*从文件中读取数据并生成单链表*/
struct StuLink *InsertNode(struct StuLink *head); /*在链表尾插入新结点*/
struct StuLink *EditNode(struct StuLink *head,int num); /*修改链表中指定学号结点,修改后成绩等级都变化*/
struct StuLink *DeleteNode(struct StuLink *head,int num); /*删除指定学号结点*/
void QueryNode(struct StuLink *head,int num); /*查找指定学号结点并输出*/
void QueryLink(struct StuLink *head); /*查找指定所有成绩不及格结点,并显示出来*/
struct StuLink *RankLink(struct StuLink *head); /*计算链表中每个结点的名次*/
struct StuLink *Count_Grade(struct StuLink *head); /*统计链表中每一个节点的等级*/
void AnalysisLink(struct StuLink *head); /*统计并返回各等级人数*/
void SortLink(struct StuLink *head,int sel2); /*按指定数据项的顺序【学号(升序)】或者【成绩(降序)】对学生链表进行排序*/
void OutputLink_1(struct StuLink *head);
/*按指定数据项的顺序【学号(升序)】或者【成绩(降序)】输出学生成绩表、各等级人数*/
void OutputLink_2(struct StuLink *head); /*分页显示全部学生的信息*/
void WriteIntoFile(struct StuLink *head);/*退出程序时将学生链表中的数据逐行保存到文件*/
void CreatFile(){
FILE *fp;
int index,sex; /*用于判断文件是否为空*/
if((fp=fopen("student.txt","r"))==NULL){
printf("不能打开文件!");
exit(0);
}
if(fscanf(fp,"%d",&index)==EOF){
printf("请输入学生的信息(学号由系统顺序生成,当输入EOF时输入结束!):\n姓名 性别(1-男,2-女) 成绩\n");
while(scanf("%s%d%d",stu.xm,sex,&stu.cj)!=EOF){ /*当输入EOF时,循环结束*/
stu.xh=++Max_num;
fprintf(fp,"%d %s %d %d\n",stu.xh,stu.xm,sex,stu.cj); /*将数据写入文件中*/
}
}
else{
printf("正在从文件中读取信息....\n");
}
if(fclose(fp)){
printf("关闭文件失败!");
exit(0);
}
}
struct StuLink *ReadFromFile(){ /*从文件中读取数据生成链表*/
struct StuLink *head=NULL, *p1, *p2=NULL;
FILE *fp;
int sex;
int flag; /*用来判断是否跳出循环*/
if((fp=fopen("student.txt","r"))==NULL){
printf("不能成功打开文件!\n");
exit(0);
}
while(!feof(fp)){
if((p1=(struct StuLink*)malloc(sizeof(struct StuLink)))==NULL){
printf("分配空间失败!\n");
exit(0);
}
flag=fscanf(fp,"%d%s%d%d",&p1->xh,p1->xm,&sex,&p1->cj);
if(sex==1)
p1->xb=(enum sex)1;
else
p1->xb=(enum sex)2;
p1->next=NULL;
if(flag==EOF)
break;
if(head==NULL){
head=p1;
p2=head;
}
else{
p2->next=p1;
p2=p1;
}
}
if(fclose(fp)){
printf("关闭文件失败!\n");
exit(0);
}
return head;
}
struct StuLink *InsertNode(struct StuLink *head){ /*在链表尾插入一个新结点。新结点的学号是链表中最大学号加1,姓名和成绩从键盘输入*/
struct StuLink *p1=NULL,*p2=head,*p3=head;
char flag;
int num=0;
int sex;
while(p3!=NULL){
if(num<=p3->xh){
num=p3->xh;
p3=p3->next;
}
}
while(p2->next!=NULL){
p2=p2->next;
}
if((p1=(struct StuLink*)malloc(sizeof(struct StuLink)))==NULL){
printf("分配空间失败!\n");
exit(0);
}
printf("请输入插入学生的姓名 性别 成绩:\n");
p1->xh=++num;
scanf("%s%d%d",p1->xm,&sex,&p1->cj);
if(sex==1)
p1->xb=(enum sex)1;
else
p1->xb=(enum sex)2;
p2->next=p1;
p1->next=NULL;
printf("\n插入结点完成!\n");
printf("/n/n按回车键返回主菜单......\n");
scanf("%c",&flag);
getchar();
return head;
}
struct StuLink *EditNode(struct StuLink *head,int num){ /*修改链表中指定学号的结点*/
struct StuLink *p=head;
char flag;
while(p->xh!=num)
p=p->next;
printf("修改前学生的信息:\n");
printf("学号 姓名 性别 成绩 等级 名次\n");
head=Count_Grade(head);
head=RankLink(head);
printf("%d %s ",p->xh,p->xm);
switch(p->xb){
case 男:
printf("男 ");break;
case 女:
printf("女 ");break;
default:break;
}
printf("%d %c %d\n",p->cj,p->dj,p->mc);
printf("请输入修改后的成绩:\n");
scanf("%d",&p->cj);
switch (p->cj/10){
case 10:p->dj='A';break;
case 9: p->dj='A';break;
case 8: p->dj='B';break;
case 7: p->dj='C';break;
case 6: p->dj='D';break;
default:p->dj='E';break;
}
head=RankLink(head);
printf("\n修好后学生的信息:\n");
printf("学号 姓名 性别 成绩 等级 名次\n");
printf("%d %s ",p->xh,p->xm);
switch(p->xb){
case 男:
printf("男 ");break;
case 女:
printf("女 ");break;
default:break;
}
printf("%d %c %d\n",p->cj,p->dj,p->mc);
printf("\n\n按回车键返回主菜单......\n");
scanf("%c",&flag);
getchar();
return head;
}
struct StuLink *DeleteNode(struct StuLink *head, int num){
struct StuLink *p1=head,*p2=head;
char flag;
while((p1->xh!=num)&&(p1->next!=NULL)){
p2=p1;
p1=p1->next;
}
if(p1->xh==num){
head=Count_Grade(head);
head=RankLink(head);
printf("需要删除结点的学生信息:\n");
printf("学号 姓名 性别 成绩 等级 名次\n");
printf("%d %s ",p1->xh,p1->xm);
switch(p1->xb){
case 男:
printf("男 ");break;
case 女:
printf("女 ");break;
default:break;
}
printf("%d %c %d\n",p1->cj,p1->dj,p1->mc);
if(head==p1)
head=head->next;
else
p2->next=p1->next;
free(p1);
}
else {
printf("无删除结点!\n");
printf("\n\n按回车键返回主菜单......\n");
scanf("%c",&flag);
getchar();
return head;
}
printf("\n删除结点完成!\n");
printf("\n\n按回车键返回主菜单.........\n");
scanf("%c",&flag);
getchar();
return head;
}
void QueryNode(struct StuLink *head,int num){
struct StuLink *p1=head;
char flag;
while((p1->xh!=num)&&(p1->next!=NULL)){
p1=p1->next;
}
if((p1->xh!=num)&&(p1->next==NULL)){
printf("没有该学号!\n");
printf("按回车键返回主菜单.........\n");
scanf("%c",&flag);
getchar();
return;
}
printf("输出学生信息:\n");
printf("学号 姓名 性别 成绩 等级 名次\n");
printf("%d %s ",p1->xh,p1->xm);
switch(p1->xb){
case 男:
printf("男 ");break;
case 女:
printf("女 ");break;
default:break;
}
printf("%d %c %d\n\n",p1->cj,p1->dj,p1->mc);
printf("按回车键返回主菜单.........\n");
scanf("%c",&flag);
getchar();
}
void QueryLink(struct StuLink *head) /*查找指定所有成绩不及格结点,并显示出来*/
{
int count=0; /*计算不及格学生人数*/
struct StuLink *p1=head;
char flag;
head=Count_Grade(head);
head=RankLink(head);
while(p1!=NULL){
if(p1->cj<60){
if(count==0){
printf("不及格学生信息:\n");
printf("学号 姓名 性别 成绩 等级 名次\n");
}
printf("%d %s ",p1->xh,p1->xm);
switch(p1->xb){
case 男:
printf("男 ");break;
case 女:
printf("女 ");break;
}
printf("%d %c %d\n",p1->cj,p1->dj,p1->mc);
count++;
}
p1=p1->next;
}
if(count==0)
printf("不及格学生人数为0!\n");
printf("\n\n按回车键返回主菜单.......\n");
scanf("%c",&flag);
getchar();
}
struct StuLink *RankLink(struct StuLink *head) /*计算链表中每个结点的名次*/
{
int count,len=0,i;
struct StuLink *p1=head,*p2=head;
if(p1==NULL){
printf("链表为空!\n");
return head;}
while(p1!=NULL){
len++;
p1=p1->next;
}
for(i=1;i<=len;i++){
if(i==1)
p1=head;
else
p1=p1->next;
count=1;
p2=head;
while(p2!=NULL){
if(p2->cj>p1->cj){
count++;
p1->mc=count;
}
else
p1->mc=count;
p2=p2->next;
}
}
return head;
}
struct StuLink *Count_Grade(struct StuLink *head){
struct StuLink *p1=head;
while(p1!=NULL){
if(p1->cj>=90&&p1->cj<=100)
p1->dj='A';
else if(p1->cj>=80&&p1->cj<90)
p1->dj='B';
else if(p1->cj>=70&&p1->cj<80)
p1->dj='C';
else if(p1->cj>=60&&p1->cj<70)
p1->dj='D';
else
p1->dj='E';
p1=p1->next;
}
return head;
}
void AnalysisLink(struct StuLink *head) /*统计并返回各等级人数*/
{
struct StuLink *p1=head;
int A=0,B=0,C=0,D=0,E=0;
char flag;
while(p1!=NULL){
if(p1->dj=='A')
A++;
else if(p1->dj=='B')
B++;
else if(p1->dj=='C')
C++;
else if(p1->dj=='D')
D++;
else
E++;
p1=p1->next;
}
printf("各等级人数:\n");
printf("A B C D E\n");
printf("%d %d %d %d %d\n",A,B,C,D,E);
printf("\n\n按回车键返回主菜单\n");
scanf("%c",&flag);
getchar();
}
void SortLink(struct StuLink *head,int sel2) /*按指定数据项的顺序【学号(升序)】或者【成绩(降序)】对学生链表进行排序*/
{
struct StuLink *p0=head,*p1=p0->next,*p3;
int i,len=0,k;
p3=(struct StuLink*)malloc(sizeof(struct StuLink));
if(head==NULL){
printf("链表为空!\n");
return;
}
while(p0!=NULL){
len++;
p0=p0->next;
}
if(sel2==1){
for(i=1;i<len;i++){
p0=head;
p1=p0->next;
for(k=i;k<len;k++){
if(p0->xh>p1->xh){
p3->xh=p0->xh;
p3->xm[20]=p0->xm[20];
p3->xb=p0->xb;
p3->cj=p0->cj;
p3->dj=p0->dj;
p3->mc=p0->mc;
p0->xh=p1->xh;
p0->xm[20]=p1->xm[20];
p0->xb=p1->xb;
p0->cj=p1->cj;
p0->dj=p1->dj;
p0->mc=p1->mc;
p1->xh=p3->xh;
p1->xm[20]=p3->xm[20];
p1->xb=p3->xb;
p1->cj=p3->cj;
p1->dj=p3->dj;
p1->mc=p3->mc;
}
p0=p0->next;
p1=p0->next;
}
}
}
if(sel2==2){
for(i=1;i<len;i++){
p0=head;
p1=p0->next;
for(k=i;k<len;k++){
if(p0->cj<p1->cj){
p3->xh=p0->xh;
p3->xm[20]=p0->xm[20];
p3->xb=p0->xb;
p3->cj=p0->cj;
p3->dj=p0->dj;
p3->mc=p0->mc;
p0->xh=p1->xh;
p0->xm[20]=p1->xm[20];
p0->xb=p1->xb;
p0->cj=p1->cj;
p0->dj=p1->dj;
p0->mc=p1->mc;
p1->xh=p3->xh;
p1->xm[20]=p3->xm[20];
p1->xb=p3->xb;
p1->cj=p3->cj;
p1->dj=p3->dj;
p1->mc=p3->mc;
}
p0=p0->next;
p1=p0->next;
}
}
}
}
void OutputLink_1(struct StuLink *head){
/*按指定数据项的顺序【学号(升序)】或者【成绩(降序)】输出学生成绩表、各等级人数*/
struct StuLink *p1=head;
int index;
char flag;
printf("请选择排列的顺序:\n");
printf("---------------------------------\n");
printf("1-按学号升序 2-按成绩降序\n");
printf("---------------------------------\n");
scanf("%d",&index);
if(index<1||index>2){
printf("选择错误!\n");
printf("\n\n按回车键返回主菜单........");
scanf("%c",&flag);
getchar();
return;
}
SortLink(head,index);
head=Count_Grade(head);
head=RankLink(head);
printf("输出成绩表:\n");
printf("----------------------------------------------------\n");
printf("学号 姓名 性别 成绩 等级 名次\n");
while(p1!=NULL){
printf("%d %s ",p1->xh,p1->xm);
if(p1->xb==男) printf("男 ");
else printf("女 ");
printf("%d %c %d\n",p1->cj,p1->dj,p1->mc);
p1=p1->next;
}
printf("---------------------------------------------------\n");
printf("按回车键返回主菜单......\n");
scanf("%c",&flag);
getchar();
}
void OutputLink_2(struct StuLink *head){ /*分页显示全部学生的信息*/
struct StuLink *p1=head;
int i,index,Max_page=0,len=0;
char flag;
head=Count_Grade(head);
head=RankLink(head);
while(p1!=NULL){
len++;
p1=p1->next;
}
p1=head;
if(len%10==0)
Max_page=len/10;
else
Max_page=len/10+1;
system("cls");
for(i=1;i<=10*page;i++)
p1=p1->next;
printf("---------------------------------------------\n");
printf("学号 姓名 性别 成绩 等级 名次\n");
for(i=1;i<=10&&p1!=NULL;i++){
printf("%d %s ",p1->xh,p1->xm);
if(p1->xb==男)
printf("男 ");
else
printf("女 ");
printf("%d %c %d\n",p1->cj,p1->dj,p1->mc);
p1=p1->next;
}
printf("----------------------------------------------\n");
printf("当前页数为第%d页\n",page+1);
printf("1-上一页 2-下一页 0-返回\n\n");
printf("请输入您的选择:\n");
scanf("%d",&index);
switch(index){
case 1:
if(page==0){
printf("此页为第一页!\n");
printf("按回车键继续......\n");
scanf("%c",&flag);
getchar();
}
else
page--;
OutputLink_2(head);
break;
case 2:
if(page==Max_page-1){
printf("此页为最大页数!\n");
printf("按回车键继续......\n");
scanf("%c",&flag);
getchar();
OutputLink_2(head);
break;
}
page++;
OutputLink_2(head);
break;
default:break;
}
}
void WriteIntoFile(struct StuLink *head){/*退出程序时将学生链表中的数据逐行保存到文件*/
struct StuLink *p1=head;
FILE *fp;
int sex;
if((fp=fopen("student.txt","w"))==NULL){
printf("不能打开文件!");
exit(0);
}
while(p1!=NULL){
fprintf(fp,"%d %s %d %d\n",p1->xh,p1->xm,sex,p1->cj);
if(sex==1)
p1->xb=(enum sex)1;
else
p1->xb=(enum sex)0;
p1=p1->next;
}
if(fclose(fp)){
printf("关闭文件失败!\n");
exit(0);
}
}
void main(){
int sel=0,sel2=0; /*sel:一级菜单选择, sel2 :二级菜单选择*/
struct StuLink *head=NULL;
char flag; /*用于标记完成此功能*/
CreatFile();
head=ReadFromFile();
/*显示菜单*/
while(1){
if(sel>=0&&sel<=4)
system("cls");
printf("学生成绩管理程序:\n");
printf("主菜单:\n");
printf("==============================\n");
printf("1-数据维护 2-数据查询 \n3-统计分析 4-报表输出 \n0-退出程序\n");
printf("==============================\n");
printf("请输入选择(0-4):\n");
/*一级菜单选择*/
scanf("%d",&sel);
while(1){ /*设置内循环,当二级菜单选择错误时,重新选择*/
if(sel!=0)
printf("二级菜单:\n");
switch(sel){
/*显示二级菜单*/
case 1:
printf("数据维护菜单:\n");
printf("==============================\n");
printf("1-数据插入 2-数据修改\n3-数据删除 0-返回主菜单\n");
printf("==============================\n");
printf("请输入二级菜单选择(0-4):\n");
scanf("%d",&sel2);
switch(sel2){
case 1:InsertNode(head);break;
case 2:
printf("请输入修改信息学生学号:\n");
scanf("%d",&sel2);
EditNode(head,sel2);break;
case 3:
printf("请输入需要删除的学号:\n");
scanf("%d",&sel2);
head=DeleteNode(head,sel2);
break;
case 0:break;
default:
printf("输入错误,按回车键返回主菜单....\n\n\n");
scanf("%c",&flag);
getchar();
break;
}
break;
case 2:
printf("数据查询菜单:\n");
printf("==============================\n");
printf("1-学号查询 2-不及格学生查询\n");
printf(" 0-返回主菜单 \n");
printf("==============================\n");
printf("请输入二级菜单选择(0-2):\n");
scanf("%d",&sel2);
switch(sel2){
case 1:
printf("请输入查找学号:\n");
scanf("%d",&sel2);
head=RankLink(head);
head=Count_Grade(head);
QueryNode(head,sel2);break;
case 2:QueryLink(head);break;
case 0:printf("返回主菜单!\n");break;
default:
printf("输入错误,按回车键返回主菜单......\n");
scanf("%c",&flag);
getchar();
break;
}
break;
case 3:
printf("统计分析菜单:\n");
printf("==============================\n");
printf("1-成绩名次计算 2-成绩频度分析\n");
printf(" 0-返回主菜单 \n");
printf("==============================\n");
printf("请输入二级菜单选择项:\n");
scanf("%d",&sel2);
switch(sel2){
case 1:
RankLink(head);
printf("\n\n计算完成!\n");
printf("\n\n按回车键返回主菜单.......\n");
scanf("%c",&flag);
getchar();
break;
case 2:AnalysisLink(head);break;
case 0:printf("返回主菜单!\n");break;
default:
printf("输入错误,按回车键返回主菜单.....\n");
scanf("%c",&flag);
getchar();
break;
}
break;
case 4:
printf("报表输出菜单:\n");
printf("==============================================\n");
printf("1-排序显示学生信息 2-分页显示学生信息\n");
printf(" 0-返回主菜单 \n");
printf("==============================================\n");
printf("请输入菜单选择(0-2):\n");
scanf("%d",&sel2);
switch(sel2){
case 1:
OutputLink_1(head);break;
case 2: OutputLink_2(head);break;
default:
printf("输入错误,按回车键返回主菜单.......\n");
scanf("%c",&flag);
break;
}
break;
case 0:
printf("退出程序!\n");break;
default:
printf("\n\n输入错误,按回车键返回主菜单......\n");
scanf("%c",&flag);
break;
}
break; /*退出内部循环*/
}
if(sel==0)
break;
}
WriteIntoFile(head);
system("pause");
}
运行界面: