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("請分別輸入燈和人的數量\n"); 
 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("數值不符,請重新輸入:\n"); 
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\t",i); 
34    } 
35    
36    printf("\n"); 
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("請分別輸入燈和人的數量\n"); 
   scanf("%d%d",&n,&k); 
   
   while(1) //檢驗是否超出 
   { 
      if(k>=1 && k<=1000 && n>=k && n<=1000) 
         break; 
      else 
      { 
         printf("數值不符,請重新輸入:\n"); 
         scanf("%d%d",&n,&k); 
      } 
   }

  這段寫得很丑,屬於典型的譚浩強風格,C語言應該這樣寫: 

printf("請分別輸入燈和人的數量\n"); 
while(scanf("%d%d",&n,&k) ,( k <1 || n<k || n>1000) ) 
{ 
   printf("數值不符,請重新輸入:\n"); 
}

  代碼中還有其他一些毛病,由於不是最主要的問題,這里就不再進一步指出了。

重構:

#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( "請分別輸入燈和人的數量\n" ); 
   while ( scanf("%d%d", & n ,& k ) ,( k < 1 || n < k || n > MAXNUM ) ) 
      printf("數值不符,請重新輸入:\n"); 
   
   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('\n'); 
   
   return 0; 
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM