题意:有n组数据,每组数组先是给出一个tournament name,然后是t个球队的名字,然后g个比赛的结果,然后要输出每组数据的积分榜(standings),积分榜有多个域,这里points、games played、goal difference 是可以根据其他计算出来的。所以,对每支球队只需保存球队名、wins、ties、losses、goals scored、goals against即可,定义一个结构体team。这里理解题意主要是区别points和goals就可以了。
思路:主要就是读入数据,对每个比赛结果处理相应的结构体就行了。结束之后对结构体数组按题给的要求排序,输出即可。结构体排序题。(另一种想法,如果每个球队都是有比赛结果的,那么在开始的球队名称输入时,就可以忽略,然后直接处理比赛结构,每次都在tlist里找,找到了就处理,没找到就新建一个加入到数组,这样查找的量还小一点~没试过,不知道能不能AC)
注意:1.这里tournament name 和 team name 都是可以有空格的,所以不能用scanf,防溢出一般都用fgets。关键是fgets与scanf搭配用时,要特别注意前面的scanf是把换行符放回输入流的。(这个直接写的时候可能注意到,但这里是由scanf改为fgets的就容易忘!下次把scanf改成其他输入函数时,要记得看前后其他输入函数的搭配啊。)
2.这里排序的规则,注意其中是less games,以及大小写不敏感。(这里因为开始写的是升序排列,后来改成降序的时候,就忽略了是less games。所以说,修改的时候要注意题目相关要求。大小写那个倒是注意了,但是转小写的地方不知道自己怎么写成了错的代码,一直没发现~这里忽略大小写进行比较,有人用了linux下的strcasecmp或win 下的stricmp,它们是包含在strings.h头文件里的,不是C/C++的标准头文件)
3.拼写错误。这题有多个拼写错误虐了我!首先用读文件的方式测试时,文件名是.in,被我写成了.int,结果输出的n还恰好就是文件里的n=2,而tournament name输出是乱码,这个错太难找了,换了多个输入函数,一直不懂为什么n是对的而字符串就错了。原因竟然是文件名不存在,n对了只是碰巧~ 再者就是结构体的=重载函数里,把goala打成了goals,导致从第二组数据起gaols against域出错。 另外在输出的时候,%s对应的本来应该是结构体.tname,少了个tname,成为了输出结构体,这个会报这样的警告或错误[Warning] cannot pass objects of non-POD type `struct team' through `...'; call will abort at runtime
4.while循环判断的是EOF,因为EOF其实也是相当于一行结束了(最后一行结束),所以在while外,应该要有一个 和while内处理getchar='\n'类似 的语句。总是少了这个。上一题也是漏掉过。
吐槽,UVa 老是挂,不能及时地知道自己WA了,不能及时地调程序,效率低。有些地方自己可能也有些疑虑,AC了就AC了或回头看,WA了知道哪里有可能错,但是UVa 一挂,等你WA的时可能你就不知道哪里有可能是错因了。。下次还是自己先检查好再交吧~
Code:
//#define LOCAL
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<ctype.h>
#define N 35
int cmp_team(const void *_a,const void *_b);
void process(char *tm1,char *tm2,int t,int gl1,int gl2);
int find(char *s,int t);
struct team
{
char tname[N];
int win,tie,los;
int goals,goala;
team(){ memset(tname,0,sizeof(tname)); win=tie=los=goals=goala=0; }
team operator=(const char* s)
{
strcpy(tname,s);
win=tie=los=goals=goala=0; //把goala打成了goals...
return *this;
}
};
team tlist[35];
int main()
{
#ifdef LOCAL
freopen("data10194.in","r",stdin);//额,把文件名写成.int,出现了奇怪的错误
freopen("data10194.out","w",stdout);
#endif
int n;
scanf("%d",&n);
//fprintf(stderr,"n:%d\n",n);
char tourname[110];
getchar();//scanf与其他输入函数搭配时要特别注意~
while(n-->0)
{
fgets(tourname,110,stdin);
//gets(tourname);
int t;//team数
scanf("%d",&t);
//fputs(tourname,stderr);
//fprintf(stderr,"t:%d\n",t);
char temp[N];
getchar();//每次把scanf改为fgets之后还是检查一下前面是否有scanf之类的吧~
for(int i=0;i<t;++i)
{
//scanf("%s",temp);
fgets(temp,N,stdin);
int len=strlen(temp);
if(len>0) temp[len-1]='\0';//去除换行符
tlist[i]=temp;
}
int g;
scanf("%d",&g);
getchar();
char c;
char tm1[N],tm2[N];
int ln=0;
int gl1,gl2;
bool flag=0;
int num=0;//num
while(num<g && (c=getchar())!=EOF)
{
if(flag==0)
{
if(c!='#' && c!='@') tm1[ln++]=c;
else if(c=='#')
{
tm1[ln]='\0';
ln=0;
scanf("%d",&gl1);
}
else
{
scanf("%d",&gl2);
flag=1;
}
}
else
{
if(c=='\n')
{
tm2[ln]='\0';
ln=0; flag=0;
process(tm1,tm2,t,gl1,gl2);
num++;
//fprintf(stderr,"%s %s %d %d\n",tm1,tm2,gl1,gl2);
}//进入下一行
else if(c!='#') tm2[ln++]=c;
}//ifflag
}//whilec
if(c==EOF) { tm2[ln]='\0'; process(tm1,tm2,t,gl1,gl2); }//这里遇到EOF相当于遇到'\n',需要做相同的后续处理
qsort(tlist,t,sizeof(team),cmp_team);
//输出
fputs(tourname,stdout);
for(int i=0;i<t;++i)
{
int points=3*tlist[i].win+tlist[i].tie;
int games=tlist[i].win+tlist[i].tie+tlist[i].los;
int goaldif=tlist[i].goals-tlist[i].goala;
printf("%d) %s %dp, %dg (%d-%d-%d), %dgd (%d-%d)\n",i+1,tlist[i].tname,points,games,tlist[i].win,
tlist[i].tie,tlist[i].los,goaldif,tlist[i].goals,tlist[i].goala);
//这里输出的第二个参数是.tname,否则结构体输出会报警告
}
if(n!=0) printf("\n");
}//while
//system("pause");
return 0;
}
int cmp_team(const void *_a,const void *_b)
{
team *a=(team*)_a;
team *b=(team*)_b;
int points_a=3*a->win+a->tie;
int points_b=3*b->win+b->tie;
int gd_a=a->goals-a->goala;
int gd_b=b->goals-b->goala;
int games_a=a->win+a->tie+a->los;
int games_b=b->win+b->tie+b->los;
if(points_a!=points_b) return points_b-points_a;
else if(a->win!=b->win) return b->win-a->win;
else if(gd_a!=gd_b) return gd_b-gd_a;
else if(a->goals!=b->goals) return b->goals-a->goals;
else if(games_a!=games_b) return games_a-games_b;
else {
char tname1[N],tname2[N];
for(int i=0;i<strlen(a->tname);++i)
tname1[i]=tolower(a->tname[i]);//我不知道我为什么会写成这样:tname1[i]=tolower(tname1[i]);
for(int i=0;i<strlen(b->tname);++i)
tname2[i]=tolower(b->tname[i]);
return strcmp(tname1,tname2);
}
}
void process(char *tm1,char *tm2,int t,int gl1,int gl2)
{
int x=0,y=0;
x=find(tm1,t);
y=find(tm2,t);
if(x<t&&y<t)
{//处理结构体成员变量
if(gl1>gl2) { tlist[x].win++; tlist[y].los++;}
else if(gl1==gl2) { tlist[x].tie++; tlist[y].tie++; }
else { tlist[x].los++; tlist[y].win++; }
tlist[x].goals+=gl1;
tlist[x].goala+=gl2;
tlist[y].goals+=gl2;
tlist[y].goala+=gl1;
}
}
int find(char *s,int t)
{//在tlist中找teamname为s的team的下标
for(int i=0;i<t;++i)
{
if(strcmp(s,tlist[i].tname)==0) return i;
}
return t;
}