<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    qileilove

    blog已經轉移至github,大家請訪問 http://qaseven.github.io/

    邊界測試——讓BUG現形

      題目:寫一個函數,輸入一行字符,將此字符串中最長的單詞輸出。

    #include <stdio.h>

    #include <string.h>

    int main()

    {int alphabetic(char);

    int longest(char []);

    int i;

    char line[100];

    printf("input one line:\n");

    gets(line);

    printf("The longest word is:");

    for(i=longest(line);alphabetic(line[i]);i++)

    printf("%c",line[i]);

    printf("\n");

    return 0;

    }



    int alphabetic(char c)

    {

    if((c>='a'&&c<='z')||(c>='A'&&c<='z'))

    return(1);

    else

    return(0);

    }



    int longest(char string[])

    {int len=0,i,length=0,flag=1,place=0,point;

    for(i=0;i<=strlen(string);i++)

    if(alphabetic(string[i]))

    if(flag)

    {point=i;

    flag=0;

    }

    else

    len++;

    else

    {flag=1;

    if(len>=length)

    {length=len;

    place=point;

    len=0;

    }

    }

    return(place);

    }

      運行結果:

      input a line:             
      I am a student.           
      The longest word is : student

      題目要求“寫一個函數,輸入一行字符,將此字符串中最長的單詞輸出”,可是無論alphabetic()還是longest()函數都沒有實現“輸入一行字符,將此字符串中最長的單詞輸出”這個功能要求。疑惑很久,發現實現這個功能的函數居然是main()。這就難免讓人貽笑大方了。因為按照常規的慣例,要求寫一個函數實現某個功能,從來不是要求寫main(),盡管不能說main()不是“一個函數”。然而如果是要求main()完成的事情,通常是作為一個完整的問題提出的,不會提出“寫一個函數”這樣的要求。如果硬要狡辯“寫一個函數”也不排除是寫main(),就牽強的近乎強詞奪理了。不過設若真的有人如此嘴硬,你還真拿他沒什么辦法。

      既然是不見棺材不掉淚,那就不妨繼續往下看。

      在代碼中一眼瞄見了flag這個變量。經驗表明,凡是有這個flag變量的代碼,80%以上都是垃圾代碼。道理很簡單:首先,多數問題根本不需要設置這個別別扭扭標志變量,只有那些善于把自己的思維扭曲得如同爛麻花一樣的人才喜歡時不時地祭出flag這個破爛的法寶。其次,即使需要設置標準變量,優秀的代碼作者也不會使用這個含義模糊不清的名字作為標志變量名,而會用一個更貼切、意義更明確恰當更適合描述問題的名字。所以,一般來說,flag往往反映了代碼的垃圾度。


      對于垃圾代碼,沒必要進行過于細致的分析,只要指出錯誤即可。不要試圖了解這種代碼的思路,因為這種代碼的思路本來就是錯亂不堪的,就如同不要試圖理解瘋子的胡言亂語一樣。不要試圖修繕一座胡亂搭建起來的破爛不堪的危房,推倒重來才是明智的選擇。

      然而,找出程序的漏洞或錯誤,往往比完成程序要難得多。而且越是垃圾的代碼越難查錯,因為垃圾代碼往往也不具備良好的可測試性。

      但是對付這種可測試性極差的垃圾代碼,有一些簡單的辦法往往非常容易奏效,比如邊界檢查。訓練有素的程序員通常都特別注意邊界,無論是寫代碼時還是檢查代碼時。因為他們知道這里非常容易出錯,而且往往失之毫厘謬之千里。但垃圾代碼的作者,由于代碼是東拼西補、胡亂拼湊而成的,所以往往顧不上或考慮不到這些,因此垃圾代碼很容易被“邊界檢查”這把小刀輕而易舉地戳破。以alphabetic()函數為例,只要簡單地考察一下其中if語句所要求的表達式——(c>='a'&&c<='z')||(c>='A'&&c<='z'),就不難發現c<='z'這個子表達式是c<='Z'之誤。這樣就充分說明原代碼中存在著BUG。

      順便說一下,alphabetic()函數中的if-else語句用得非常愚蠢,因為(c>='a'&&c<='z') || (c>='A'&&c<='Z')這個表達式的值本身就只能為0或1,所以直接返回這個表達式的值就可以了。壓根用不著脫褲子放屁地寫一個if-else語句。

    int alphabetic(char c)
    {
       return   (c>='a'&&c<='z'
            ||  (c>='A'&&c<='Z');
    }

      或許,有人會認為這是一個簡單的筆誤或印刷錯誤,修正了這個錯誤原來的代碼是正確的。那么好吧,下面改正這個錯誤后再來運用一次簡單的邊界測試。

      由于問題要求輸出一行字符中最長的單詞,而一行字符中可能有0個單詞、1個單詞、2個單詞……。注意,這里0個單詞的情況就是一種邊界情況,運行這個程序并輸入0個單詞(輸入一行不含任何字母的字符,因為代碼作者把連續的若干字母字符作為一個單詞),后果居然是——運行時程序崩潰了。這個結果絕對可以充分說明原來的代碼是錯誤的。

      這個結果是如何產生的呢?只要在紙上走查一遍,就不難發現,輸入一行不含任何字母的字符時,longest()函數中嵌套在for語句內部的if語句將毫無意義地反復執行

        {flag=1;
    if(len>=length)
    {length=len;
    place=point;
    len=0;
    }
    }

      部分,而其中的賦值給place的point卻居然是一個不確定的垃圾值。

      應該如何正確地給出這個問題的代碼呢?正確解決問題的前提是正確地提出問題。原來問題的提法本身就有很多不正確或不嚴謹的地方。例如,“將此字符串中最長的單詞輸出”,這個要求本身就是似是而非很不明確的。比如,字符串中有兩個單詞長度相同且都長于其他單詞,究竟應該輸出這兩個單詞中的任何一個還是需要同時輸出這兩個單詞?再有,要求函數“輸入一行字符”也非常無聊。為了能正確地解決問題,有必要對原問題的錯誤要求進行如下更正:

      寫一個函數,輸出字符串中的任一長度最長的單詞。這里所謂的單詞,是指不含空白字符的連續字符序列。

    #include <stdio.h>  
       
    void print_a_longestword ( const char [] ) ;  
    int  be_white  ( const char )  ;  
    int  find_begin( char const [] , unsigned ) ;  
    int  find_end  ( char const [] , unsigned ) ;  
    void output    ( char const [] , unsigned , unsigned ) ;  
       
    int main( void )  
    {  
       printf("%s中一最長單詞為:","");            //測試""   
       print_a_longestword("");  
          
       printf("%s中一最長單詞為:"," \n\t ");      //測試" \n\t "  
       print_a_longestword(" \n\t ");  
       
       printf("%s中一最長單詞為:"," abc ");       //測試" abc "  
       print_a_longestword(" abc ");  
       
       printf("%s中一最長單詞為:"," abc \tabcd  "); //測試" abc \tabcd  "  
       print_a_longestword(" abc \tabcd  ");  
             
       return 0;  
    }  
       
    void output( char const str[] , unsigned from , unsigned to )  
    {  
       while(from < to)  
          putchar(str[from ++]);  
       putchar('\n');     
    }  
       
    int find_end (  const char str[] , unsigned from )  
    {  
          while( str[from]!='\0' && ! be_white( str[from] ) )  
             from ++ ;  
          return from ;     
    }  
       
    int find_begin (  const char str[] , unsigned from )  
    {  
          while( be_white( str[from] ) )  
             from ++ ;  
          return from ;     
    }  
       
    int be_white( const char c )  
    {  
       return       c == ' '    ||  
                 c == '\t'  ||  
                 c == '\n'  ;  
    }  
       
    void print_a_longestword ( char const line[] )  
    {  
       unsigned site = 0U ;     
       unsigned begin_longest , end_longest ;  
       begin_longest = end_longest = site    ;  
          
       do{  
          int this_begin , this_end  ;  
             
          site = this_begin = find_begin ( line , site )    ;//單詞開頭   
          site = this_end  = find_end   ( line , site )     ;//單詞結尾        
       
          if(   ( this_end    - this_begin )   
              > ( end_longest - begin_longest ) ){  
             begin_longest = this_begin ;  
             end_longest   = this_end   ;       
          }       
       
       }while( line[ site ] != '\0') ;     
       
       output( line , begin_longest , end_longest );  
    }

    posted on 2011-12-05 09:38 順其自然EVO 閱讀(136) 評論(0)  編輯  收藏


    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    <2011年12月>
    27282930123
    45678910
    11121314151617
    18192021222324
    25262728293031
    1234567

    導航

    統計

    常用鏈接

    留言簿(55)

    隨筆分類

    隨筆檔案

    文章分類

    文章檔案

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 亚洲成在人线中文字幕| 在线精品一卡乱码免费| mm1313亚洲国产精品美女| 亚洲熟女www一区二区三区| 色窝窝免费一区二区三区 | 最近2022中文字幕免费视频| 亚洲精品色午夜无码专区日韩| 亚洲一区二区三区免费| 亚洲永久无码3D动漫一区| AAAAA级少妇高潮大片免费看| 区久久AAA片69亚洲| 久久久高清日本道免费观看| 久久精品国产亚洲AV网站| 50岁老女人的毛片免费观看| 亚洲国色天香视频| 成人黄18免费视频| 视频一区二区三区免费观看| 中国人xxxxx69免费视频| 88xx成人永久免费观看| 久久综合亚洲鲁鲁五月天| AV无码免费永久在线观看| 亚洲日本天堂在线| 可以免费观看一级毛片黄a | 四虎影视在线永久免费观看| 手机永久免费的AV在线电影网| 亚洲国产综合无码一区| 18禁美女黄网站色大片免费观看| 亚洲人成色4444在线观看| 亚洲毛片不卡av在线播放一区| 日本在线免费观看| 亚洲18在线天美| 亚洲人成网站18禁止一区| 久久99热精品免费观看动漫| 丁香婷婷亚洲六月综合色| 亚洲精品无码专区2| 最近免费视频中文字幕大全| 亚洲av无码专区在线电影| 亚洲精品无码专区在线在线播放| 在线看片免费不卡人成视频| 免费无码又爽又黄又刺激网站| 久久亚洲成a人片|