程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C >> 關於C >> C語言初學者代碼中的常見錯誤與瑕疵(9)

C語言初學者代碼中的常見錯誤與瑕疵(9)

編輯:關於C
字母的個數   現在給你一個由小寫字母組成字符串,要你找出字符串中出現次數最多的字母,如果出現次數最多字母有多個那麼輸出最小的那個。  輸入:第一行輸入一個正整數T(0<T<25)  隨後T行輸入一個字符串s,s長度小於1010。  輸出:每組數據輸出占一行,輸出出現次數最多的字符;  樣例:   輸入  3  abcd  bbaa  jsdhfjkshdfjksahdfjkhsajkf   輸出:  a  a  j   原代碼   #include <stdio.h> #include <string.h> int maxchar(char x[1010]) {  int i,j,temp,max;  int a[26]={0};    for (i = 0,temp =0;i<strlen(x);i++)  {   temp=x[i]-97;   a[temp]+=1;  }    for(i=1,max = a[0],j=0;i<26;i++)  {   if(max<a[i])   {    j=i;    max = a[i];   }  }    return j+97; }   int maxchar(char x[1010]); int main() {    char s[1010],c[26];  int T,i;  scanf("%d",&T);    for (i=0;i<T;i++)  {   scanf("%s",s);   c[i]=maxchar(s);  }    for (i=0;i<T;i++)  {   printf("%c\n",c[i]);  }    return 0; }   評析: 總體:     已經學會把函數類型聲明寫在函數定義外面了,但把其他函數定義寫在main()之前,總體上還是有頭重腳輕之感。   main():    char s[1010],c[26];  int T,i;   s數組顯然不應該定義在這裡,因為這個數組只在第一個for語句內部用到。   c數組不應該定義為26個元素,因為題目中說的是“0<T<25”。    scanf("%d",&T);   這條語句無可指責,但輸入後沒考慮數據有效性。     for (i=0;i<T;i++)  {   scanf("%s",s);   c[i]=maxchar(s);  }    for (i=0;i<T;i++)  {   printf("%c\n",c[i]);  }     原作者顯然不了解這類ACM問題的套路(參見 C語言初學者代碼中的常見錯誤與瑕疵(5)   11樓~13樓)。不過話說回來,ACM對這類問題的描述確實容易讓外人誤解,ACM是否應該自我檢討一下呢?   除了不了解ACM的套路,這裡的一個有欠考慮的地方是沒有注意檢查輸入數據的有效性(當然,ACM對此是不管不顧的)。如果考慮輸入數據的有效性應該不理會無效數據:   scanf("%d",&T); if ( 0 <T && T <25 ) {    //求解問題 } 或者“死等”   while ( scanf("%d",&T) , !( 0 <T && T <25 ) ) {     //提示重新輸入 }   考慮的更周到些的話,可以   while ( scanf("%d",&T)!= 1 || !( 0 <T && T <25 ) ) {     while ( getchar()!='\n')         ;     //提示重新輸入 }   此外,這段代碼中的   scanf("%s",s); 這句如果寫成   scanf("%1009s",s); 就無可挑剔了。盡管ACM的測試數據不會出問題,但這是應該考慮到的一個問題。程序員最重要的品質應該是思慮周到。   maxchar()函數 :     int maxchar(char x[1010]) {  int i,j,temp,max;  int a[26]={0};    for (i = 0,temp =0;i<strlen(x);i++)  {   temp=x[i]-97;   a[temp]+=1;  }    for(i=1,max = a[0],j=0;i<26;i++)  {   if(max<a[i])   {    j=i;    max = a[i];   }  }    return j+97; }   int maxchar(char x[1010]);      函數定義和函數類型聲明都存在同一個問題,就是[]內的1010。這個是不應該寫的,寫了編譯器也不“看”,寫得毫無意義。   int a[26]={0};    這個寫成    int a['z'-'a'+1]={0};  為好。注意這裡應該是假定使用ASCII碼制,如果不是ASCII碼,代碼不能這樣寫。    for (i = 0,temp =0;i<strlen(x);i++)  {   temp=x[i]-97;   a[temp]+=1;  }   這個槽點較多。首先temp明顯多余,其次那個97太難看了,典型的譚浩強風格。應該寫為'a'。   a[temp]+=1;   可以直接寫為    a[ x[i] - 'a']+=1;   再有,i<strlen(x)寫得很糟糕,因為在這裡調用strlen(x),意味著在循環過程中每次循環都要調用這個函數,然而對於這個循環來說,strlen(x)其實是一個常量,並不需要每次都調用。這也是初學者常見的一個毛病,總忍不住有調用庫函數的沖動,而不考慮有沒有更好的寫法。strlen(x)是被濫用最多的庫函數之一。其實這裡簡單地寫x[i]!='\0'就可以了。由此可見源文件開頭的   #include <string.h> 也完全是多余的。   另外這條語句的功能與下一條for語句的功能相對各自獨立,各抽象為一個獨立的函數為好。      for(i=1,max = a[0],j=0;i<26;i++)  {   if(max<a[i])   {    j=i;    max = a[i];   }  }     這個地方寫得有點笨,主要是變量太多。作者用max記錄最大值元素,用j記錄其下標,其實只要一個j就夠了    for(i=1,j=0;i<26;i++)  {   if(a[j]<a[i])   {    j=i;      }  }      最後   return j+97; 這個也是譚浩強之流不入流的寫法,非常難看。應該寫為   return j+'a';  重構   /* 字母的個數  現在給你一個由小寫字母組成字符串,要你找出字符串中出現次數最多的字母, 如果出現次數最多字母有多個那麼輸出最小的那個。  輸入:第一行輸入一個正整數T(0<T<25)  隨後T行輸入一個字符串s,s長度小於1010。  輸出:每組數據輸出占一行,輸出出現次數最多的字符;  樣例:輸入  3  abcd  bbaa  jsdhfjkshdfjksahdfjkhsajkf  輸出:  a  a  j   作者:薛非 出處:http://www.cnblogs.com/pmer/   “C語言初學者代碼中的常見錯誤與瑕疵”系列博文    */   #include <stdio.h>   #define S_LEN 1009 #define MAX_LEN (S_LEN + 1)  #define N(x) N_(x) #define N_(x) #x   char find_major( char * ); void count( int [] , char * ) ; unsigned be_most( int [], unsigned );   int main( void ) {    int T ;      puts("行數?");    scanf("%d" , &T);        if ( ! ( 0 < T && T < 25 ) )       return 1;        while ( T -- > 0 )    {       char s[ MAX_LEN ];              scanf("%"N(S_LEN)"s" , s );       printf("%c\n" , find_major( s ) );    }        return 0; }   char find_major( char * s ) {    int num[ 'z' - 'a' + 1 ] = { 0 } ;        count( num , s ) ;                 //統計字母個數     return 'a' + be_most( num , sizeof num / sizeof num[0] );//返回出現最多字符  }   void count( int num[] , char * s )  {    while ( *s != '\0' )       num[ * s ++ - 'a' ] ++ ;  }   unsigned be_most( int a[] , unsigned n ) {    unsigned max = 0u ;    unsigned i ;        for ( i = 1u ; i < n ; i ++ )       if ( a[max] < a[i] )          max = i ;      return max ;//最大值元素下標 }
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved