数据结构结业课程设计--运动会计分系统
/* 参加运动会有n个学校,学校编号为1……n。比赛分成m个男子项目,和w个女子项目。项目编号为男子1……m,女子m+1……m+w。不同的项目取前五名或前三名积分;取前五名的积分分别为:7、5、3、2、1,前三名的积分分别为:5、3、2;哪些取前五名或前三名由学生自己设定。(m<=20,n<=20)【基本要求】
(1)可以输入各个项目的前三名或前五名的成绩;
(2)能统计各学校总分,
(3)可以按学校编号或名称、学校总分、男女团体总分排序输出;
(4)可以按学校编号查询学校某个项目的情况;可以按项目编号查询取得前三或前五名的学校。
(5)存储结构自选,但要求运动会的相关数据存入并能随时查询
(6)规定:输入数据形式和范围:可以输入学校的名称,运动项目的名称
(7)输出形式:有中文提示,各学校分数为整形
(8)界面要求:有合理的提示,每个功能可以设立菜单,根据提示,可以完成相关的功能要求。*/
直接上代码:
# include <stdio.h>
# include <stdlib.h>
# define N 12 //大学和项目名称的长度=汉字个数*sizeof(char)
# define M 20 //大学的数量
# define Q 20 //项目的数量
# define H 5 //调整每一行输出的学校或项目数量 现在一行输出5个
# define MIN(a,b) (a)<(b)?(a):(b)
const char wenjian[]="out.bin";//文件名
typedef struct link
{
int gram[3][Q]; //每一个项目gram[0]存男生,gram[1]存女生,gram[2]存这个学校中男女在此项目上的总分
int sum[3];
} AA,*Aa;
typedef struct HEAD
{
int b[4]; //b[0-3]依次为(学校个数,项目个数,男生项目个数,女生项目个数
char xuexiao[M][N+1]; //M个学校的名称
int sex[M]; //sex[i]//录入性别,0为男,1为女
struct link spot[M]; //接上M个学校的信息
char xiangmu[Q][N+1]; //Q个项目的名称
int power[Q]; //每一个项目都有选择前三名或前五名的机会 POW存 3 或者 5
int cun[Q][5]; //M个项目的学校编号排名1--3 或者 1--5
} HEAD;
char sex[][3]= {"男","女"};
int power[][5]= {{5,3,2,0,0},{7,5,3,2,1}}; //积分
char ss[][5]= {"男团","女团","学校"};
int gainchar(char A[],int min,int max); //输入字符串的字节范围[min,max]
int gainint(int *p,int a,int b);//输入int *p直至满足[a,b]输入结束,并返回*p的位数
int BF(char a[],char b[]);//BF算法 a为主串,b为被检验的串`返回b在a中的第一个下标 若无返回0
void record(char school[][N+1],char game[][N+1],int b[],HEAD *temp);//记录数据最重要的一个函数,a为项目数组,b为记录,c为学校,Temp结构体
int jiemian();//用户显示界面
int jianyan(char b[],int T);//检验b[]是否符合实际,T=0检验当前字符串是否全为汉字 T=1检验学校,T=2检验比赛 检验符合返回0
void xuanzepai(HEAD *temp,int select);//选择排序
/*下面是检查用的数组 用在jianyan 函数中*/
char key[][3]= {"!","。","?","《","》",",","{","}","(",")","¥","‘","’",":",";","—","”","“","、","·","~","\0"};
char school[][5]= {"大学","学院","华侨","校区","政法","管理","经济","科学","理工","科技","技术","职业","师范","中国","海洋","石油","分区","分校","建筑","工业","\0"};
char program[][3]= {"拉","球","举","泳","踩","接","划","跳","滑","冰","射","水","摔","爬","骑","跑","体","田","人","\0"};
int DU(HEAD *head)
{
FILE *fp;
if ((fp = fopen(wenjian, "rb")) == NULL)
{
if ((fp = fopen(wenjian, "wb+")) != NULL)
{
fclose(fp);
if ((fp = fopen(wenjian, "rb")) == NULL)
return printf("文件读取失败!\n");
}
}
fread(head,sizeof(HEAD), 1, fp);
fclose(fp);
free(fp);
return 0;
}
int XIE(HEAD *head)
{
FILE *fp;
if ((fp = fopen(wenjian, "wb")) == NULL)
return printf("文件打开失败!\n");
if(fwrite(head,sizeof(HEAD), 1, fp)!=1)
return printf("文件写入失败!\n");
fclose(fp);
free(fp);
return 0;
}
int main()
{
HEAD SG= {0},*head=&SG;
int i,j,k,select,choice,now,next;
if(DU(head))
{
printf("请按任意键继续…\n");
getchar();
}
do
{
system("cls");//清屏
select=jiemian();
if(select==1)
record(head->xuexiao,head->xiangmu,head->b,head); //记录学校和项目
else if(head->b[0])
{
if(select>=2&&select<=4)
xuanzepai(head,select-2);//选择排序
else if(select==5)
{
for(k=0; k<head->b[0]; k++) //输出学校名称选项 每五个一行
printf("%d:%-13s%c",k+1,head->xuexiao[k],(k+1)%H?' ':'\n');
printf("\n输入学校前的编号[1,%d]:",head->b[0]);
choice=gainint(&choice,1,head->b[0])-1;
next=0;
while(next<head->b[1])
{
now=next;
next=MIN(next+H,head->b[1]);
for(i=now; i<next; i++) //输出项目信息
printf("(%s-%d>%-8s ",sex[head->sex[i]],head->power[i],head->xiangmu[i]);
printf("\n");
for(j=0; j<3; j++)
{
printf("%-s: ",ss[j]);
for(k=now; k<next; k++)
{
if(j==head->sex[k]||j==2)
printf("%02d分 \t",(head->spot+choice)->gram[j][k]);
else
printf("****** \t");
}
printf("\n");
}
printf("\n");
}
}
else if(select==6)
{
for(i=0; i<head->b[1]; i++)
{
printf("\t\t第%d个比赛项目: %-13s<%s子> 只录入前%d名\n",i+1,head->xiangmu[i],sex[head->sex[i]],head->power[i]);
for(j=0; j<head->power[i]; j++)
{
printf("\t第%d名:%-13s%02d分",j+1,head->xuexiao[head->cun[i][j]],power[(head->power[i])/4][j]);
}
printf("\n\n");
}
}
else //保存文件
{
if(select==9)
{
printf("确认清空请按1 否则请按0:");
if(gainint(&choice,0,1))
for(k=0; k<Q; k++) //对申请出来的结构体中的所有项目初始化 M*2*M次
for(i=0; i<3; i++)
{
(head->spot+k)->sum[i]=0; //sum[]初始化
for(j=0; j<Q; j++)
(head->spot+k)->gram[i][j]=0; //项目初始化
head->b[i]=0;
}
}
if(XIE(head))return 0;
DU(head);
}
}
printf("\n请按任意键继续…\n");
getchar();
}
while(select!=8);
return 0;
}
int BF(char a[],char b[])//BF算法 a为主串,b为被检验的串`返回b在a中的第一个下标 若无返回0
{
int i=0,j=0;
while (a[i]&&b[j])
if (a[i++]==b[j])++j; // 继续比较后继字
else (i-=j)&&(j=0);
return b[j]?0:i-j+1;
}
int gainint(int *p,int a,int b)//输入int *p直至满足[a,b]输入结束,并返回*p的值
{
do
{
*p=a-1; //此处是为了减少意外情况的发生 虽然那种意外情况不常见
scanf("%d",p);
while(getchar()!='\n');
if(*p>b||*p<a)
printf("输入有误,请重新输入[%d--%d]:",a,b);
}while(*p>b||*p<a);
return *p;
}
int gainchar(char A[],int min,int max)//长度在[min,max] <闭区间> 之间时 函数结束 返回字符串A的长度
{
int B,C;
do
{
A[max]=B=C=0;
while((A[B++]=getchar())!='\n'&&B<max);
if(A[B-1]!='\n')while(getchar()!='\n'&&++C);
else A[--B]=0;
if(C||B&&B<min)
printf("您录入的字符串长度:%d字节\n只录入(%d--%d)个字节!\n",B+C,min,max);
}
while(C||B<min);
return B;
}
int jiemian()
{
int a;
printf("\t\t\t\t运动会分数统计\n");
printf("* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * \n");
printf("\t* 1.添加 学校 项目 *三名制(1,2,3)\n");
printf("\t* 2.按 男团体 总分排序输出 *score--5,3,2\n");
printf("\t* 3.按 女团体 总分排序输出 *\n");
printf("\t* 4.按 学校 总分排序输出 *五名制(1,2,3,4,5)\n");
printf("\t* 5.按 编号或名称 查询学校情况 *score--7,5,3,2,1\n");
printf("\t* 6.显示比赛项目各学校名次情况 *\n");
printf("\t* 7.保存录入信息 *一个汉字两个字节\n");
printf("\t* 8.保存信息并退出 *可分多次选择1\n");
printf("\t* 9.清空+恢复初始化 *录入项目时默认先男后女\n");
printf("* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n\t");
printf("输入您的选择(1-9):");
return gainint(&a,1,9); //调用函数输入整形(1--6)
}
void record(char school[][N+1],char game[][N+1],int b[],HEAD *temp)//记录数据最重要的一个函数,a为项目数组,b为记录,c为学校,Temp结构体
{
char choose[][13]= {"录入几个学校","总共几个项目","男生多少项目"}; //提示用户输入内容
int scope[][3]= {{5,1,0},{M,Q,M}}; //输入的各个内容的范围
int i,j,k,pan,cun,choice,man;
scope[1][0]=M-b[0];//剩余录入的学校的数量
scope[1][1]=Q-b[1];//剩余录入的项目的数量
if(b[0])scope[0][0]=scope[0][1]=0;//当用户已经进入此函数输入过一次后,改变条件将学校个数项目个数下限改为0
for(i=0; i<3; i++)
{
printf("\t%s(%d--%d)?\n\t:",choose[i],scope[0][i],scope[1][i]);
gainint(&b[i],scope[0][i],scope[1][i]);
if(i==1)
{
scope[1][2]=b[1];//当输入项目完毕时,改变男生项目的长度
if(!b[0]&&!b[1])
{
b[2]=b[1];
i++;
}
}
if(i==2) b[3]=b[1]-b[2]; //男生输入完毕时,女生的项目=总项目-男生项目
}
for(i=M-scope[1][0]; i<b[0]+M-scope[1][0]; i++) //每次要在结构体末尾加入学校
do
{
k=0;
printf("请输入第%d个学校的名称(只录入%d-%d字符):\n",i+1,8,N);
gainchar(school[i],8,N);
for(j=0; j<i; j++) //对输入的学校名称进行判重
if(BF(school[j],school[i])&&BF(school[i],school[j]))//当有之前的学校和当前录入的学校重复
k++;
if(k)printf("学校已经录入过!");
}
while(jianyan(school[i],1)||k);
b[0]+=M-scope[1][0];//计算出目前的学校总数
for(i=Q-scope[1][1]; i<b[1]+Q-scope[1][1]; i++) //录入项目
{
temp->sex[i]=(b[1]+Q-scope[1][1]-i)<=b[3];//确定性别,0为男,1为女
do
{
k=0;
printf("请输入第%d个项目(%s)名称(只录入%d-%d字符):\n",i+1,sex[temp->sex[i]],4,N); //输入项目名称
gainchar(game[i],4,N);
for(j=0; j<i; j++)
if(BF(game[j],game[i]))
k++;
if(k) printf("项目已经录入过!");//情况同学校
pan=(k||jianyan(game[i],2)); //因为项目还要分录入前三名还是前五名
if(!pan)//当输入满足要求时 继续询问项目的录入名次
do
{
printf("该项目只录入: 3:前三名 5:前五名:");//询问录入的时前几名
gainint(&(temp->power[i]),3,5);//将第i+1个项目的分数情况放在头节点的power[i]数组里
}
while((temp->power[i])==4); //只录入3和5
}
while(pan); //当输入不满足要求时重新输入
system("cls");
for(k=0; k<b[0]; k++) //输出学校名称选项 每五个一行
printf("%d:%-13s%c",k+1,school[k],(k+1)%H?' ':'\n');
printf("\n\n获得 %s:(%s子)的前%d名(填学校前的编号):\n",game[i],sex[temp->sex[i]],temp->power[i]);
for(j=0; j<temp->power[i]; j++) //每次录入的项目个数=temp->power[i]
{
do
{
pan=0;
printf("第%d名(%d-%d):",j+1,1,b[0]);
cun=gainint(&cun,1,b[0])-1;//范围1-b[0]
(temp->cun[i][j])=cun;//temp->cun[i][j]中的数值就是第i个学校,名次为j
for(k=0; k<j; k++) //检验名次是否录入重复
if(temp->cun[i][k]==cun)
pan=printf("一个学校只有一个名次!\n");
}
while(pan);
choice=power[(temp->power[i])/4][j];
man=temp->sex[i];
(temp->spot+cun)->gram[man][i]=choice;//把choice积分存入第cun个学校的第i个项目 的gram[man][i]里
(temp->spot+cun)->gram[2][i]+=choice;//修改第cun个学校的该项目总分
(temp->spot+cun)->sum[man]+=choice;//修改第cun个学校的m男女团体总积分
(temp->spot+cun)->sum[2]+=choice;//修改学校的总积分
}
}
b[1]+=Q-scope[1][1];//修改录入的项目的总数量
}
int jianyan(char b[],int T)//检验b[]是否符合实际,T=1检验学校,T=2检验比赛
{
int d=0,i,LEN=-1,F;
while(b[++LEN]);//求b的字节
for(i=0; i<LEN; i++) //汉字的ascll编码每一个字节为负数
if(b[i]>0)
return printf("输入中有含中文以外的字符!");
for(i=0; key[i][0]; i++)
{
F=BF(b,key[i]);//匹配中文标点符号
if(F&&F%2)
return printf("有非汉字的中文字符!");
}
if(T==1)//检验学校的名称
{
for(i=0; school[i][0]; i++)
{
F=BF(b,school[i]);
if(F&&F%2)d++;
}
if(!d)return printf("学校名称太奇葩!");
}
if(T==2)//检验比赛的名称
{
for(i=0; program[i][0]; i++)
{
F=BF(b,program[i]);
if(F&&F%2)d++;
}
if(!d)return printf("项目名称太奇葩!");
}
return 0;//没问题返回0
}
void xuanzepai(HEAD *temp,int select)//选择排序
{
int i,j,k,m,a,b,n,school[2][M]= {0};
n=temp->b[0];
printf("升序请按0 降序请按1:");
gainint(&b,0,1);
for(i=0; i<n; i++)
{
school[1][i]=i;//记录学校当前的位置编号
school[0][i]=(temp->spot+i)->sum[select];
}
printf("%s排名如下\t<以第%d列分数为准>:\n\n",ss[select],select+1);
for(i=0; i<n-1; i++)
{
k=i;
for(j=i+1; j<n; j++)
if(b?school[0][j]>school[0][k]:school[0][j]<school[0][k])
k=j;
if(k!=i)
for(m=0; m<2; m++) //a[][M]的两行都交换
{
a=school[m][k];
school[m][k]=school[m][i];
school[m][i]=a;
}
}
printf("名次: 学校名称 男团 女团 学校总分\n");
for(i=0; i<n; i++)
{
k=(b?i+1:n-i);//计算排名的名次显示方向
j=school[1][i];//j记录学校的编号
printf("第%02d:%-13s%02d分\t%02d分\t%02d分\n",k,temp->xuexiao[j],(temp->spot+j)->sum[0],(temp->spot+j)->sum[1],(temp->spot+j)->sum[2]);
}
}