高手看了,掺不忍睹——关于“【ACM】杭电ACM题一直WA求高手看看代码”_.NET_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > .NET > 高手看了,掺不忍睹——关于“【ACM】杭电ACM题一直WA求高手看看代码”

高手看了,掺不忍睹——关于“【ACM】杭电ACM题一直WA求高手看看代码”

 2013/12/7 23:26:11  garbageMan  博客园  我要评论(0)
  • 摘要:按被中科大软件学院二年级研究生HCOONa骂为“误人子弟”之后(见:《中科大的那位,敢更不要脸点么?》),继续“误人子弟”。问题:见:【ACM】杭电ACM题一直WA求高手看看代码原代码:#include<stdio.h>#include<stdlib.h>#definemax1000/*runthisprogramusingtheconsolepauseroraddyourowngetch,system("pause"
  • 标签:代码 高手

按  

  被中科大软件学院二年级研究生 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很相似,有点难看。改得更漂亮一点怕初学者看不懂,就不改了。

      此外,我也不能保证我的代码一定就过,因为我从没耍过题,不清楚刷题的具体规则。

发表评论
用户名: 匿名