高手看了,感觉惨不忍睹——关于“【ACM】杭电ACM题一直WA求高手看看代码”
2013-12-07 18:49
375 查看
按
被中科大软件学院二年级研究生 HCOONa 骂为“误人子弟”之后(见:《中科大的那位,敢更不要脸点么?》 ),继续“误人子弟”。问题:
见 :【ACM】杭电ACM题一直WA求高手看看代码原代码:
#include <stdio.h> #include <stdlib.h> #define max 1000 /* run this program using the console pauser or add your own getch, system("pause") or input loop */ int main(int argc, char *argv[]) { int stu[max]; //学生的ID int stur[max]; //学生的成绩 int rank,jack_id; //查找的ID int flag[101]; int i,jack,n; freopen("in.txt","r",stdin); while(scanf("%d",&jack)!=EOF){ for( i=0 ; i<max ;i++) { stu[i]=0; stur[i]=0; } for( i=0 ; i<101 ;i++) { flag[i]=1; } for( i=0 ; ;i++) { scanf("%d%d",&stu[i],&stur[i]); if(stu[i]==0&&stur[i]==0) break; } n=i; for( i=0 ; i<n ; i++) { if(jack==stu[i]) { jack_id=i; } } rank=1; for( i=0 ; i<n ; i++) { if((stur[i]>stur[jack_id])&&(flag[stur[i]]!=0)){ //找到比自己大的成绩rank++ rank++; flag[stur[i]]=0; } } printf("%d\n",rank); } return 0; }
评析:
毛病很多。据原作者说“数据测试了好几个都没问题,可以就是WA不让过”。其实我也不清楚什么原因不过,因为没玩过。只能就其中的错误说一说。并给出改进,但同样不能保证通过,因为我不知道“ACM”的规则。#include <stdlib.h>
不清楚做什么的,没用。
#define max 1000
明显违背公序良俗。宏名应该大写。
int main(int argc, char *argv[]) {
应该
int main( void ) {
代码这东西,你不把它写好就不可能把它写对。
一main()到底,也是初学者常见的幼稚病,表明根本不懂得如何组织代码。(参见:将main()进行到底)
int stu[max]; //学生的ID int stur[max]; //学生的成绩
原作者显然同样不懂得如何组织数据,还处于社会主义初级阶段。
数组尺寸为max不是不可以,但从后面的代码来看明显错了。应该是 max+1。
int flag[101];
我在《品悟C》中说过,出现flag的代码,多半早就馊了。(参见:flag标志什么?哦,它标志代码馊了——(一))
while(scanf("%d",&jack)!=EOF){
这个写得还行。问题是原问题特意强调了范围,是否视为long为好?存在这样的可能性:原题的意思是把number作为long处理,把mark作为int处理。当然这只是猜测。
for( i=0 ; i<max ;i++) { stu[i]=0; stur[i]=0; }
这里写得很傻。其实只要
while(scanf("%d",&jack)!=EOF){
int stu[max] = {0}; //学生的ID
int stur[max]= {0}; //学生的成绩
//……
}
就可以了。显然原代码中这两个数组定义的位置不当。
for( i=0 ; i<101 ;i++) { flag[i]=1; }
天知道这是在干什么,很傻很变态。
for( i=0 ; ;i++) { scanf("%d%d",&stu[i],&stur[i]); if(stu[i]==0&&stur[i]==0) break; }
这里存在越界的可能。有效成绩最多1000个,结束标志0 0 就可能是第1001个。
从这里向后,已经看不下去了,完全不之所云。不过既然至此已经存在越界错误,也没有必要再看下去了。
下面给出我的写法:
重构:
#include <stdio.h> #include <stdlib.h> typedef long num_t ; #define FN "%ld" typedef int mark_t ; #define FM "%d" typedef struct { num_t num ; mark_t mark ; } STD; int input( STD [] , num_t , mark_t * ); int rank( STD [] , int , mark_t ); int main( void ) { num_t jack_n ; while ( scanf( FN , &jack_n ) != EOF ) { STD stu[ 1000 + 1 ] ; int sum ; mark_t jack_m ; sum = input( stu , jack_n , &jack_m ); //输入并获得数据总数及Jack的成绩 printf("%d\n" , rank( stu , sum , jack_m ) );//输出Jack的名次 } system("PAUSE"); return 0; } int input( STD stu[] , num_t j_n , mark_t * p_j_m ) { STD * p_ini = stu ; while ( scanf( FN FM , &stu->num , &stu->mark ) , stu->num != j_n ) //读入数据直到Jack的 stu ++ ; * p_j_m = stu++ -> mark ; while ( scanf( FN FM , &stu->num , &stu->mark ) , stu->num != 0 || stu->mark != 0 ) //读Jack后面的 stu ++ ; return stu - p_ini ; } int rank( STD stu[] , int n , mark_t j_m ) { int r = 1 ; int i ; for ( i = 0 ; i < n ; i ++ ) if ( stu[i].mark > j_m ) r ++ ; return r ; }
小结:
input()函数中的两句while很相似,有点难看。改得更漂亮一点怕初学者看不懂,就不改了。此外,我也不能保证我的代码一定就过,因为我从没刷过题,不清楚刷题的具体规则。
再次重构:
根据 librazy 网友提供的信息:没记错的话大多数评测机中long 就是long int 就是 int。一般算法竞赛中忘了时空效率考虑都是int(除了很明显需要高精度或ll的。
以及Matrix_R 网友的意见:
不过有个小疑问,就是为什么楼主的函数声明中指针的声明方式都是清一色的[]?为了表明参数是个数组吗?我个人觉得直接用指针更好,更本质。
再次重构代码如下:
#include <stdio.h> #include <stdlib.h> typedef struct { int num ; int mark ; } STD; int input( STD * , int , int * ); int rank( STD [] , int , int ); int main( void ) { int jack_n ; while ( scanf( "%d" , &jack_n ) != EOF ) { STD stu[ 1000 + 1 ] ; int sum ; int jack_m ; sum = input( stu , jack_n , &jack_m ); //输入并获得数据总数及Jack的成绩 printf("%d\n" , rank( stu , sum , jack_m ) );//输出Jack的名次 } system("PAUSE"); return 0; } int input( STD * p_stu , int j_n , int * p_j_m ) { STD * p_ini = p_stu ; while ( scanf( "%d%d" , &p_stu->num , &p_stu->mark ) , p_stu -> num != j_n ) //读入数据直到Jack的 p_stu ++ ; * p_j_m = p_stu ++ -> mark ; while ( scanf( "%d%d" , &p_stu->num , &p_stu->mark ) , p_stu->num != 0 || p_stu->mark != 0 ) //读Jack后面的 p_stu ++ ; return p_stu - p_ini ; } int rank( STD stu[] , int n , int j_m ) { int r = 1 ; int i ; for ( i = 0 ; i < n ; i ++ ) if ( stu[i].mark > j_m ) r ++ ; return r ; }
在此向librazy 和Matrix_R两位网友表示谢意。
相关文章推荐
- 【ACM】杭电ACM题一直WA求高手看看代码
- 高手来看看这段代码是不是很杂啊!!关于API绘图的问题!
- 关于数组乱序的深挖——“感觉一直在写毒代码”
- 下面是我写的poj 1738 关于石子合并的代码,那位大侠帮我看看
- 杭电ACm水仙花数2010谁能帮忙分析一下两段代码的区别;第二个通不过啊
- 关于北大ACM1002题目的普通代码
- 杭电ACM 1030 Delta-wave java代码解析
- 关于Xcode调试的帖子,感觉不错,转来看看
- linux udp 客户端recvfrom,一直没有数据接收,谁能帮看看这代码哪里出了问题了????
- 你感觉你是个JAVA高手吗,那么就来挑战一下吧,下面可是ACM一道很经典的题目,试一吧!
- 杭电acm用Java一直不通过
- <编程珠玑>3.4 日期问题 && 杭电hdu acm 2133题目代码
- 2016 Multi-University Training Contest 2 Acperience(一直WA的小伙伴可以看看)
- 杭电ACM 今年暑假不AC 2037(关于最简单的贪心算法)
- 关于ruby和GT,个人感觉ruby是GT的翻版,看不出所谓的精简优势。同时感觉ruby和GT代码编写过程很缺乏逻辑性。
- 关于本地ACM代码的声明
- 杭电acm 1065 一直presentation error
- 杭电ACM中一部分关于string的题目
- 判断质数之简短代码(刚学C语言时感觉很简短,结果现在看看,噗~真是搞笑)
- uvaoj10562 Undraw the Trees(一直WA的快来看看)