运动会分数统计和容错(数据结构课程设计)

来源:互联网 发布:搜狗输入法 mac 3.0 编辑:程序博客网 时间:2024/05/17 02:49

一个程序如果没有排错功能,或者排错功能做的不好,那么这个程序不会是个好程序,程序的排错要考虑到方方面面。本程序是  分数统计的代码,共350行,对其中用户的输入做了很大程度的排错:我是一个普通的大学生,传这个的目的,想减轻学弟学妹的负担,或者说,在这个程序中,你获得了一些灵感,那么,我将感到莫大的荣幸:.在做课程设计时,我们做的是下面这道题(全部用的C语言):

参加运动会有n个学校,学校编号为1……n。比赛分成m个男子项目,和w个女子项目。项目编号为男子1……m,女子m+1……m+w。不同的项目取前五名或前三名积分;取前五名的积分分别为:7、5、3、2、1,前三名的积分分别为:5、3、2;哪些取前五名或前三名由学生自己设定。(m<=20,n<=20)

经过两天的艰苦奋战,我终于完成了这项工作,排错和输入等方面做了很多改进,用户输入的时候会有很大的容错和拍错空间。

然后我很开心  当时得了我们校唯一的一个最高分^!^







第二次选择1的时候就可以输入0--X(X=20-【已经录入的学校个数】)不再是5了

代码如下:

注意 为了达到好的效果  最好将窗口 宽度调为 135

# include <stdio.h># include <stdlib.h># include <string.h># define N 13             //大学名称的长度=汉字个数*sizeof(char)+1# define M 20             //大学的数量,项目的数量typedef struct link{int gram[3][M];       //每一个项目gram[0]存男生,gram[1]存女生,gram[2]存这个学校中男女在此项目上的总分int sum[3]; }AA,*Aa;typedef struct HEAD{char xiangmu[M][N];char xuexiao[M][N];     //学校名称int  power[M];         //每一个项目都有选择前三名或前五名的机会int b[4];             //b[0-3]依次为(学校个数,项目个数,男生项目个数,女生项目个数int cun[M][5];         //学校排名int sex[M];         //sex[i]//录入性别,0为男,1为女struct link spot[M];     //建结构体}HEAD;void inchar(char a[],int min,int max);   //输入整形数据范围(b,c)void inint(int *p,int a,int c);      //输入字符并检验字符范围(a,c)void record(char a[][N],int b[],char c[][N],HEAD *temp);//a为项目名称,b[0-3]依次为(添加的学校个数,项目个数,男生项目个数,女生项目个数),c为学校名称int jianyan(char b[],int c);//检验b[]是否符合实际,c=1检验学校,c=2检验比赛,嵌套在record 里int KMP(char a[],char b[]);//a为主串,b为被检验的串,求b在主串a中位置的KMP算法,匹配成功返回1,失败返回0void output(HEAD *temp,int d);//输出函数d=0时输出所有学校名称,d=1时输出比赛名称void zhengli(HEAD *temp,int a);//temp里的b[0,1]里存放的分别是学校的和项目的个数,另外还有学校和项目的名称,比赛项目的前几名int jiemian();             //操作界面,返回用户的选择void printsum(HEAD *temp,int a,int b);       //a=2,3,4时进行男团,女团,学校 排序和输出void xuanzepai(int a[][M],int n,int b);     //主函数中无需调用,嵌套在printsum里void main(){int select,i,j,k;           //用户的选择char sex[][3]={"男","女"},T[][5]={"编号","名称"};int power[][5]={{5,3,2,0,0},{7,5,3,2,1}};int a[4]={-1,1,-1,M+1};            //升序a[0],降序a[1]char school[N];                  //存储用户输入的学校char ss[][5]={"男团","女团","总分"};          HEAD *head=(HEAD *)malloc(sizeof(HEAD)); //先建好接点if(!head){printf("内存不足!程序停止运行!");getchar();exit(0);}for(k=0;k<M;k++)   //对申请出来的结构体中的所有项目初始化 M*2*M次for(i=0;i<3;i++){(head->spot+k)->sum[i]=0;   //sum[]初始化for(j=0;j<M;j++)(head->spot+k)->gram[i][j]=0; //项目初始化 head->b[i]=0;}do{system("cls");       //清屏select=jiemian();   //得到用户的选择if(select==1)  //当选择为1时record(head->xiangmu,head->b,head->xuexiao,head);  //记录学校和项目else if(select>=2&&select<=4&&head->b[0]){printf("升序请按0,降序请按1:\n");inint(&a[2],0,1);                printsum(head,select,a[a[2]]);}else if(select==5&&head->b[0]){                output(head,0);printf("选项   0:按学校编号查询\t1:按学校名称查询\n输入您的选择(0-1):");inint(&a[2],0,1);printf("请输入%s:",T[a[2]]);                if(a[2])do{inchar(school,8,N);}while(jianyan(school,1));elseinint(&a[3],0,head->b[0]-1);for(i=a[2]==1?0:a[3];i<head->b[0];i++)if(KMP(head->xuexiao[i],school)&&KMP(school,head->xuexiao[i])||a[2]==0&&a[3]!=M+1){printf("匹配成功!该学校信息如下:\n学校名称:  %-13s\n\t",head->xuexiao[i]);output(head,1);for(j=0;j<3;j++){printf("%-s:",ss[j]);for(k=0;k<head->b[1];k++){if(j==head->sex[k]||j==2)printf("项目%02d:%02d分   ",k+1,(head->spot+i)->gram[j][k]);                                    elseprintf("***********   ");if((k+1)%7==0)printf("\n%-s:",ss[j]);}printf("\n");}break;}if(!KMP(head->xuexiao[i],school)&&a[2])printf("查找失败!");a[3]=M+1;}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");}}system("pause");}while(select);             } void inchar(char a[],int min,int max)  //对*a输入范围(min,max),如果字符数组中存在'\n',将其改为'\0'{int c,k;do{c=-1;k=0;fgets(a,max,stdin);while(a[++c]);c=a[c-1]=='\n'&&c<max?c-1:c;if(c>=max-1)while(getchar()!='\n')k++;elsea[c]='\0';if(k||c&&c<min)//如果用户只输入'\n'则不提示输入错误,否则提示错误printf("输入长度有误,请重新输入!\n注:只录入(%d--%d)字节:\n",min,max-1);}while(k||c<min);}void inint(int *p,int a,int c){do{scanf("%d",p);  while(getchar()!='\n'); //清除缓冲区if(*p>c||*p<a)printf("输入有误,请重新输入:");}while(*p>c||*p<a);}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.按 女团体 总分排序输出         *五名制(1,2,3,4,5)\n");printf("\t* 4.按 学校   总分排序输出         *score--7,5,3,2,1\n");printf("\t* 5.按 编号或名称 查询学校情况     *一个汉字两个字节\n");printf("\t* 6.按比赛项目查询得名次学校情况   *可分多次选择1 输入的个数会变化\n");printf("* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\n\t");printf("输入您的选择(1-6):");inint(&a,1,6);           //调用函数输入整形(1--6)return a;}void record(char a[][N],int b[],char c[][N],HEAD *temp)//记录数据最重要的一个函数,a为项目数组,b为记录,c为学校,Temp结构体{char choose[][13]={"录入几个学校","总共几个项目","男生多少项目"};//提示用户输入内容char sex[][3]={"男","女"};int scope[][3]={{5,1,0},{M,M,M}};          //输入的各个内容的范围int i,j,k,pan,cun;int power[2][5]={{5,3,2,0,0},{7,5,3,2,1}};//成绩的权int flag[2];int p=M-b[0],q=M-b[1];   //因为学校和项目最多为N,所以如果用户不停的记录总会超限,用静态变量记录用户输入的学校和项目scope[1][0]=p;scope[1][1]=q;    //每次进入此函数就要改变内容的范围,因为总数为Mif(p<M)scope[0][0]=scope[0][1]=0;//当用户已经进入此函数输入过一次后,改变条件将输入的学校个数下限改为0b[2]=b[3]=M+1;for(i=0;i<3;i++)     {printf("\t%s(%d--%d)?\n\t:",choose[i],scope[0][i],scope[1][i]);inint(&b[i],scope[0][i],scope[1][i]);if(i==1)scope[1][2]=b[1];//当输入项目完毕时,改变男生项目的长度if(i==2)b[3]=b[1]-b[2];    //男生输入完毕时,女生的项目=总项目-男生项目}for(i=M-p;i<b[0]+M-p;i++)     //每次要在末尾加入学校do{k=0;printf("请输入第%d个学校的名称(只录入%d-%d字符):\n",i+1,8,N-1);inchar(c[i],8,N);for(j=0;j<i;j++)    //对输入的学校名称进行判断if(KMP(c[j],c[i])||KMP(c[i],c[j]))//当有重复的则k+1k++;if(k)   printf("学校已经录入过!");        }while(jianyan(c[i],1)||k);for(i=M-q;i<b[1]+M-q;i++)     //和学校情况一样{temp->sex[i]=b[1]+M-q-i<=b[3]?1:0;   //录入性别,0为男,1为女do{  k=0;printf("请输入第%d个项目(%s)名称(只录入%d-%d字符):\n",i+1,sex[temp->sex[i]],4,N-1); //输入项目名称inchar(a[i],4,N);     for(j=0;j<i;j++)if(KMP(a[j],a[i]))k++;if(k)   printf("项目已经录入过!");//情况同学校                    pan=(k||jianyan(a[i],2));    //因为项目还要分录入前三名还是前五名if(!pan)//当输入满足要求时do{printf("该项目只录入: 3:前三名  5:前五名:");//询问录入的时前几名inint(&(temp->power[i]),3,5);//将第i+1个项目的分数情况放在头节点的power[i]数组里}while((temp->power[i])==4);   //只录入3和5}while(pan);   //当输入不满足要求时重新输入}flag[0]=M-q;flag[1]=b[1]+M-q;   //因为下面要改,所以项目信息存在flag[]里b[0]+=M-p;b[1]+=M-q;//b[0]改为已经录入的学校总数;b[1]改为录入的项目总数for(i=flag[0];i<flag[1];i++)//但是b[2],b[3]没改    b[2]男生b[3]女生{output(temp,0);printf("获得 %s 项目(%s子)的前%d名(写学校前的编号):\n",a[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,0,b[0]-1);inint(&cun,0,b[0]-1);//范围0-b[0]-1;temp->cun[i][j]中的数值就是第几个学校,名次为j+1(temp->cun[i][j])=cun;for(k=0;k<j;k++)//检验是否录入重复if(temp->cun[i][k]==cun){pan=1;printf("学校不能重复!\n");}}while(pan);flag[0]=power[(temp->power[i])/4][j];pan=temp->sex[i];(temp->spot+cun)->gram[pan][i]=flag[0];(temp->spot+cun)->gram[2][i]+=flag[0];(temp->spot+cun)->sum[pan]+=flag[0];(temp->spot+cun)->sum[2]+=flag[0];}}}int jianyan(char b[],int c)//检验b[]是否符合实际,c=1检验学校,c=2检验比赛{                            int d[2]={0,0},i,LEN=-1;char key[21][3]={"!","。","?","《","》",",","{","}","(",")","¥","‘","’",":",";","—","”","“","、","·","~"};char jian[20][5]={"大学","学院","华侨","校区","政法","管理","经济","科学","理工","科技","技术","职业","师范","中国","海洋","石油","分区","分校","建筑","工业"};char game[19][3]={"跳","滑","冰","射","骑","跑","拉","球","举","水","摔","爬","泳","踩","接","划","体","田","人"};int a[3]={21,20,19};//不用改下面,直接改数组while(b[++LEN]);for(i=0;i<LEN;i++)//汉字的ascll编码每一个字节为负数if(b[i]>0)return printf("输入中有含中文以外的字符!");for(i=0;i<a[0];i++)if(KMP(b,key[i]))     //用上面的非法字符匹配return printf("有非汉字的中文字符!");if(c==1){for(i=0;i<a[1];i++)if(KMP(b,jian[i]))    //一定概率防止用户乱输或输错d[1]++;if(!d[1])return printf("学校名称太奇葩!");}if(c==2){for(i=0;i<a[2];i++)if(KMP(b,game[i]))d[1]++;if(!d[1])                           //同上return printf("比赛名称太奇葩!");}return 0;//没问题返回0}int KMP(char a[],char b[])//a为主串,b为被检验的串{                     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;}void output(HEAD *temp,int d)//d==0输出学校不带\n,d=1输出项目不带\n,a为项目名称c为学校名称{                                                  int i;char kkk[][3]={"男","女"};if(d==1)for(i=0;i<temp->b[1];i++) {printf("(前%d名)%02d:(%s)%-12s ",temp->power[i],i+1,kkk[temp->sex[i]],temp->xiangmu[i]);    if((i+1)%4==0)//输出项目printf("\n\t");}else{for(i=0;i<temp->b[0];i++){printf("%02d:%-13s ",i,temp->xuexiao[i]); if((i+1)%5==0)//输出学校printf("\n");}}printf("\n");}void printsum(HEAD *temp,int a,int b)//b=1升序,b=-1降序+男团+女团+学校三合一排序{int i,k;char ss[][5]={"男团","女团","学校"};int xu[2][M];    a-=2;                                     //对a处理for(i=0;i<temp->b[0];i++)               //对结构体里面数据复制{xu[0][i]=(temp->spot+i)->sum[a];        //结构体sum[a]复制到第二行xu[1][i]=i;                            //将结构体所在的位置信息复制到第二行}printf("\t%s排名如下:\n",ss[a]);      xuanzepai(xu,temp->b[0],b);               //用选择排序    for(i=0;i<temp->b[0];i++){k=b>0?i+1:(temp->b[0])+b*i;             //对下一行的 第%d名 进行判断       printf("\t第%-02d名:%-13s %-02d分\n",k,temp->xuexiao[xu[1][i]],xu[0][i]);}}void xuanzepai(int a[][M],int n,int b)//比较函数选择排序--基础{    int i,j,k,m,temp;for(i=0;i<n-1;i++){k=i;for(j=i+1;j<n;j++)if(b==1?a[0][j]>a[0][k]:a[0][j]<a[0][k])k=j;if(k!=i)for(m=0;m<2;m++)            //a[][M]的两行都交换{temp=a[m][k];a[m][k]=a[m][i];a[m][i]=temp;}}}/*制作者 zhagoodwell*//*数据结构结业课程设计*//*  参加运动会有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)界面要求:有合理的提示,每个功能可以设立菜单,根据提示,可以完成相关的功能要求。*/


6 0
原创粉丝点击