乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      C/C++——strcpy函數(shù)的幾種實(shí)現(xiàn)和詳細(xì)解析

       孤步 2012-07-25

      C/C++——strcpy函數(shù)的實(shí)現(xiàn) 和解析

       

      題目: 
          
      已知strcpy函數(shù)的原型是: 
              char * strcpy(char * strDest,const char * strSrc); 
          1.
      不調(diào)用庫函數(shù),實(shí)現(xiàn)strcpy函數(shù)。 
          2.
      解釋為什么要返回char *。

       

      (一)高質(zhì)量c++編程上的答案

      五、編寫strcpy函數(shù)(10分)

      已知strcpy函數(shù)的原型是

             char *strcpy(char *strDest, const char *strSrc);

             其中strDest是目的字符串,strSrc是源字符串。

      1)不調(diào)用C++/C的字符串庫函數(shù),請編寫函數(shù) strcpy

      char *strcpy(char *strDest, const char *strSrc)

      {

          assert((strDest!=NULL) && (strSrc !=NULL));    // 2

          char *address = strDest;                                          // 2

          while( (*strDest++ = * strSrc++) != '\0' )         // 2

                    NULL ;

          return address ;                                                  // 2

      }

      2strcpy能把strSrc的內(nèi)容復(fù)制到strDest,為什么還要char * 類型的返回值?

      答:為了實(shí)現(xiàn)鏈?zhǔn)奖磉_(dá)式。                                              // 2

      例如       int length = strlen( strcpy( strDest, “hello world”) );

       

      【規(guī)則6-2-3不要將正常值和錯(cuò)誤標(biāo)志混在一起返回。正常值用輸出參數(shù)獲得,而錯(cuò)誤標(biāo)志用return語句返回。錯(cuò)誤信息可以用throw拋出。

       

      2        建議6-2-1有時(shí)候函數(shù)原本不需要返回值,但為了增加靈活性如支持鏈?zhǔn)奖磉_(dá),可以附加返回值。

      例如字符串拷貝函數(shù)strcpy的原型:

      char *strcpy(char *strDest,const char *strSrc);

      strcpy函數(shù)將strSrc拷貝至輸出參數(shù)strDest中,同時(shí)函數(shù)的返回值又是strDest。這樣做并非多此一舉,可以獲得如下靈活性:

          char str[20];

          int  length = strlen( strcpy(str, “Hello World”) );

      ()

       

       (二)程序員面試寶典中的答案

      char* strcpy1(char *strDest, const char* strSrc)

      {

             assert(strSrc != NULL );

             assert(strDest != NULL);

             int i;

             char *address = strDest;

       

          for(i = 0; strSrc[i] != '\0'; i++)

                    strDest[i] = strSrc[i];

             strDest[i] = '\0';

       

             return address;

      }

      (三)帶有異常拋出的答案和解析
          
      解說: 
          1.strcpy
      的實(shí)現(xiàn)代碼 

       

      char * strcpy3(char * strDest,const char * strSrc /*[0]*/)

      {    

             if ((NULL == strDest)||(NULL == strSrc)) //[1]

                    throw "Invalid argument(s)"; //[2]

       

             char * strDestCopy=strDest;  //[3]

       

             while ((*strDest++=*strSrc++)!='\0'); //[4]

       

             return strDestCopy;    

      }

       

       

      /*[0]:   規(guī)則6-1-3如果參數(shù)是指針,且僅作輸入用,則應(yīng)在類型前加const,以防止該指針在函數(shù)體內(nèi)被意外修改。


          
      錯(cuò)誤的做法: 
          
      //[1]
          (A)
      如果不檢查指針的有效性,說明答題者不注重代碼的健壯性。 
          (B)
      如果檢查指針的有效性時(shí)使用((!strDest)||(!strSrc))(!(strDest&&strSrc)),說明答題者對C語言中類型的隱式轉(zhuǎn)換沒有深刻認(rèn)識。在本例中((!strDest)是將char *轉(zhuǎn)換為bool即是類型隱式轉(zhuǎn)換,這種功能雖然靈活,但更多的是導(dǎo)致出錯(cuò)概率增大和維護(hù)成本升高。所以C++專門增加了booltrue、false三個(gè)關(guān)鍵字以提供更安全的條件表達(dá)式。 
          (C)
      如果檢查指針的有效性時(shí)使用((strDest==0)||(strSrc==0)),說明答題者不知道使用常量的好處。直接使用字面常量(如本例中的0)會(huì)減少程序的可維護(hù)性。0雖然簡單,但程序中可能出現(xiàn)很多處對指針的檢查,萬一出現(xiàn)筆誤,編譯器不能發(fā)現(xiàn),生成的程序內(nèi)含邏輯錯(cuò)誤,很難排除。而使用NULL代替0,如果出現(xiàn)拼寫錯(cuò)誤,編譯器就會(huì)檢查出來。

      DNULL == strDest 常量寫在表達(dá)式的左邊,如果將表達(dá)式寫錯(cuò)了,寫成了賦值,則馬上報(bào)錯(cuò);如果 將表達(dá)式改成 strDest  ==NULL,在寫的過程中 漏寫了 一個(gè)=,變成了 strDest  = NULL,則檢查不出錯(cuò)誤來,可能會(huì)出現(xiàn)意想不到的錯(cuò)誤
          
      //[2]
          (A)return new string("Invalid argument(s)");
      ,說明答題者根本不知道返回值的用途,并且他對內(nèi)存泄漏也沒有警惕心。從函數(shù)中返回函數(shù)體內(nèi)分配的內(nèi)存是十分危險(xiǎn)的做法,他把釋放內(nèi)存的義務(wù)拋給不知情的調(diào)用者,絕大多數(shù)情況下,調(diào)用者不會(huì)釋放內(nèi)存,這導(dǎo)致內(nèi)存泄漏。 
          (B)return 0;
      ,說明答題者沒有掌握異常機(jī)制。調(diào)用者有可能忘記檢查返回值,調(diào)用者還可能無法檢查返回值(見后面的鏈?zhǔn)奖磉_(dá)式)。妄想讓返回值肩負(fù)返回正確值和異常值的雙重功能,其結(jié)果往往是兩種功能都失效。應(yīng)該以拋出異常來代替返回值,這樣可以減輕調(diào)用者的負(fù)擔(dān)、使錯(cuò)誤不會(huì)被忽略、增強(qiáng)程序的可維護(hù)性。 
         
      //[3]
          (A)
      如果忘記保存原始的strDest值(即忘記 保留strDest的頭指針),說明答題者邏輯思維不嚴(yán)密。 
          
      //[4] 
          (A)
      循環(huán)寫成while (*strDest++=*strSrc++);,同[1](B) 
          (B)
      如果循環(huán)寫成while (*strSrc!='\0') *strDest++=*strSrc++;,說明答題者對邊界條件的檢查不力。這樣的話,就是先判斷是否為零,然后再賦值,肯定是不會(huì)把結(jié)尾零賦給strDest的,而[4]中的循環(huán)是先賦值,再判斷是否為零,是會(huì)給strDest賦上結(jié)尾零的,如此這樣,這個(gè)形式循環(huán)體結(jié)束后,strDest字符串的末尾沒有正確地加上'\0'。

      要正常的話應(yīng)該寫成:

      while (*strSrc!='/0') *strDest++=*strSrc++;

      strDest[i] = '\0';// strDest字符串的末尾加上'\0'

      這里還有說一句: = * right ++ 這三個(gè)符號中,*  ++的優(yōu)先級都是2級,是對等的,其次是 = , 由于 ++的特點(diǎn):是滯后使用, 造成 會(huì)先賦值,再指針++

      也就是說:*strDest++=*strSrc++;

            *strDest++:會(huì)拆成 *strDest strDest++兩個(gè)對等的部分

      其讓人感覺到的執(zhí)行順序

      l       *strDest = *strSrc

      l       然后才能是 strDest++,strSrc++

       

      舉個(gè)例子如下:

      #define product(x) (x * x)

       int i = 3, j, k;

      j = product(i++);

      k = product(++i);

      cout << j << " " << k << endl;//輸出為949

      即使定義為#define product(x) ((x) * (x))得到的結(jié)果還是一樣
          2.
      返回strDest的原始值使函數(shù)能夠支持鏈?zhǔn)奖磉_(dá)式,增加了函數(shù)的附加值。同樣功能的函數(shù),如果能合理地提高的可用性,自然就更加理想。 
          
      鏈?zhǔn)奖磉_(dá)式的形式如: 
              int iLength=strlen(strcpy(strA,strB)); 
          
      又如: 
              char * strA=strcpy(new char[10],strB); 
          
      返回strSrc的原始值是錯(cuò)誤的。其一,源字符串肯定是已知的,返回它沒有意義。其二,不能支持形如第二例的表達(dá)式。其三,為了保護(hù)源字符串,形參用const限定strSrc所指的內(nèi)容,把const char *作為char *返回,類型不符,編譯報(bào)錯(cuò)。

       

        本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多