• C语言初学者代码中的常见错误与瑕疵(1)


      曾在豆瓣上看到过一个小朋友贴出他自己的代码(http://www.douban.com/group/topic/40293109/),当时随口指点了几句。难得这位小朋友虚心修正、从善如流,不断地改,又不断地贴,坚持了很久。到后来这位小朋友的代码已经大有长进。

      这位小朋友犯过的很多错误都非常典型,在初学者中非常普遍,于是整理了一下,应该对其他初学者有借鉴意义。

    问题

    开灯问题

      有n盏灯,编号为1~n,第1个人把所有灯打开,第2个人按下所有编号为2 的倍数的开关(这些灯将被关掉),第3 个人按下所有编号为3的倍数的开关(其中关掉的灯将被打开,开着的灯将被关闭),依此类推。一共有k个人,问最后有哪些灯开着?输入:n和k,输出开着的灯编号。k≤n≤1000

    代码: 

     1 #include <stdio.h> 
     2 #include <math.h> 
     3 
     4 int main() 
     5 { 
     6    int a[1001],n,k,i,j; 
     7    
     8    printf("请分别输入灯和人的数量
    "); 
     9    scanf("%d%d",&n,&k); 
    10    
    11    while(1) //检验是否超出 
    12    { 
    13       if(k>=1 && k<=1000 && n>=k && n<=1000) 
    14          break; 
    15       else 
    16       { 
    17          printf("数值不符,请重新输入:
    "); 
    18          scanf("%d%d",&n,&k); 
    19       } 
    20    } 
    21    
    22    for(i=2;i<=k;i++) //每操作一次第i*j个开关,a[i*j]加1 
    23    { 
    24       for(j=1;i*j<=n;j++) 
    25       { 
    26          a[i*j]=a[i*j]+1; 
    27       } 
    28    } 
    29    
    30    for(i=1;i<=n;i++) //若操作次数为偶数,表示该位置的灯亮着 
    31    { 
    32       if(a[i]%2==0 && a[i]!=0) 
    33       printf("%d	",i); 
    34    } 
    35    
    36    printf("
    "); 
    37    return 0; 
    38 }

     测试:

    “自己测了觉得没问题..在线系统结果是WrongAnswer ..未找出原因..”

     评:

      最明显的错误就是第26行

    a[i*j]=a[i*j]+1;

    由于前面定义a数组为局部auto类别,在不进行初始化的情况下,a中的数据是垃圾值。换句话说,a中的数据是无意义的。因此a[i*j]+1这个表达式没有意义。

      此外,第22行

      for(i=2;i<=k;i++) //每操作一次第i*j个开关,a[i*j]加1

    在逻辑上也是错误的,缺乏“第1个人把所有灯打开”的步骤。

      另外 

       printf("请分别输入灯和人的数量
    "); 
       scanf("%d%d",&n,&k); 
       
       while(1) //检验是否超出 
       { 
          if(k>=1 && k<=1000 && n>=k && n<=1000) 
             break; 
          else 
          { 
             printf("数值不符,请重新输入:
    "); 
             scanf("%d%d",&n,&k); 
          } 
       }

      这段写得很丑,属于典型的谭浩强风格,C语言应该这样写: 

    printf("请分别输入灯和人的数量
    "); 
    while(scanf("%d%d",&n,&k) ,( k <1 || n<k || n>1000) ) 
    { 
       printf("数值不符,请重新输入:
    "); 
    }

      代码中还有其他一些毛病,由于不是最主要的问题,这里就不再进一步指出了。

    重构:

    #include <stdio.h> 
    
    #define MAXNUM 1000 
    #define ON 0 
    #define OFF 1 
    
    int main( void ) 
    { 
       int light[MAXNUM] = { ON } ; //把所有灯打开 
       int n , k ; 
       int i ; 
       
       printf( "请分别输入灯和人的数量
    " ); 
       while ( scanf("%d%d", & n ,& k ) ,( k < 1 || n < k || n > MAXNUM ) ) 
          printf("数值不符,请重新输入:
    "); 
       
       for ( i = 2 - 1 ; i < k ; i ++ ) //第2个人按下所有编号为2 的倍数的开关…… 
       { 
          int j ; 
          for ( j = i ; j < n ; j += i + 1) 
             light[j] = ! light[j];     
       } 
       
       for ( i = 0 ; i < n ; i ++ ) 
          if( light[i]==ON ) 
             printf( "%d " , i + 1 ); 
       putchar('
    '); 
       
       return 0; 
    }
  • 相关阅读:
    第十二章类的无参方法
    第十三章人机猜拳
    第十一章类和对象
    面向对象七大原则。
    深入类的方法。
    使用集合组织相关数据。
    .NET框架
    C#数据类型
    错误。
    实现Windows的数据绑定
  • 原文地址:https://www.cnblogs.com/pmer/p/3416379.html
Copyright © 2020-2023  润新知