C语言初学者代码中的常见错误与瑕疵(9)
題目
字母的個數(shù)
現(xiàn)在給你一個由小寫字母組成字符串,要你找出字符串中出現(xiàn)次數(shù)最多的字母,如果出現(xiàn)次數(shù)最多字母有多個那么輸出最小的那個。
輸入:第一行輸入一個正整數(shù)T(0<T<25)
隨后T行輸入一個字符串s,s長度小于1010。
輸出:每組數(shù)據(jù)輸出占一行,輸出出現(xiàn)次數(shù)最多的字符;
樣例:
輸入
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; }評析:
總體:
已經(jīng)學(xué)會把函數(shù)類型聲明寫在函數(shù)定義外面了,但把其他函數(shù)定義寫在main()之前,總體上還是有頭重腳輕之感。
main():
char s[1010],c[26];int T,i;
s數(shù)組顯然不應(yīng)該定義在這里,因為這個數(shù)組只在第一個for語句內(nèi)部用到。
c數(shù)組不應(yīng)該定義為26個元素,因為題目中說的是“0<T<25”。
這條語句無可指責(zé),但輸入后沒考慮數(shù)據(jù)有效性。?
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語言初學(xué)者代碼中的常見錯誤與瑕疵(5)?? 11樓~13樓)。不過話說回來,ACM對這類問題的描述確實容易讓外人誤解,ACM是否應(yīng)該自我檢討一下呢?
除了不了解ACM的套路,這里的一個有欠考慮的地方是沒有注意檢查輸入數(shù)據(jù)的有效性(當(dāng)然,ACM對此是不管不顧的)。如果考慮輸入數(shù)據(jù)的有效性應(yīng)該不理會無效數(shù)據(jù):
或者“死等”
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的測試數(shù)據(jù)不會出問題,但這是應(yīng)該考慮到的一個問題。程序員最重要的品質(zhì)應(yīng)該是思慮周到。
maxchar()函數(shù)?:
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]);
? 函數(shù)定義和函數(shù)類型聲明都存在同一個問題,就是[]內(nèi)的1010。這個是不應(yīng)該寫的,寫了編譯器也不“看”,寫得毫無意義。
int a[26]={0};? 這個寫成
int a['z'-'a'+1]={0};?為好。注意這里應(yīng)該是假定使用ASCII碼制,如果不是ASCII碼,代碼不能這樣寫。
for (i = 0,temp =0;i<strlen(x);i++){temp=x[i]-97;a[temp]+=1;}這個槽點較多。首先temp明顯多余,其次那個97太難看了,典型的譚浩強(qiáng)風(fēng)格。應(yīng)該寫為'a'。
a[temp]+=1;可以直接寫為?
a[ x[i] - 'a']+=1;再有,i<strlen(x)寫得很糟糕,因為在這里調(diào)用strlen(x),意味著在循環(huán)過程中每次循環(huán)都要調(diào)用這個函數(shù),然而對于這個循環(huán)來說,strlen(x)其實是一個常量,并不需要每次都調(diào)用。這也是初學(xué)者常見的一個毛病,總?cè)滩蛔∮姓{(diào)用庫函數(shù)的沖動,而不考慮有沒有更好的寫法。strlen(x)是被濫用最多的庫函數(shù)之一。其實這里簡單地寫x[i]!='\0'就可以了。由此可見源文件開頭的
#include <string.h>也完全是多余的。
另外這條語句的功能與下一條for語句的功能相對各自獨立,各抽象為一個獨立的函數(shù)為好。
這個地方寫得有點笨,主要是變量太多。作者用max記錄最大值元素,用j記錄其下標(biāo),其實只要一個j就夠了
for(i=1,j=0;i<26;i++){if(a[j]<a[i]){j=i; }}? 最后
return j+97;這個也是譚浩強(qiáng)之流不入流的寫法,非常難看。應(yīng)該寫為
return j+'a';?重構(gòu)
/* 字母的個數(shù) 現(xiàn)在給你一個由小寫字母組成字符串,要你找出字符串中出現(xiàn)次數(shù)最多的字母, 如果出現(xiàn)次數(shù)最多字母有多個那么輸出最小的那個。 輸入:第一行輸入一個正整數(shù)T(0<T<25) 隨后T行輸入一個字符串s,s長度小于1010。 輸出:每組數(shù)據(jù)輸出占一行,輸出出現(xiàn)次數(shù)最多的字符; 樣例:輸入 3 abcd bbaa jsdhfjkshdfjksahdfjkhsajkf 輸出: a a j作者:薛非 出處:http://www.cnblogs.com/pmer/ “C語言初學(xué)者代碼中的常見錯誤與瑕疵”系列博文 */#include <stdio.h>#define S_LEN 1009 #define MAX_LEN (S_LEN + 1) #define N(x) N_(x) #define N_(x) #xchar find_major( char * ); void count( int [] , char * ) ; unsigned be_most( int [], unsigned );int main( void ) {int T ;puts("行數(shù)?");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 ) ; //統(tǒng)計字母個數(shù) return 'a' + be_most( num , sizeof num / sizeof num[0] );//返回出現(xiàn)最多字符 }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 ;//最大值元素下標(biāo) }?
總結(jié)
以上是生活随笔為你收集整理的C语言初学者代码中的常见错误与瑕疵(9)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: nagios监控windows USBK
- 下一篇: GC.Collect如何影响垃圾回收