久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

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

 孤步 2012-07-25

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

 

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

 

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

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

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

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

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

1)不調用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的內容復制到strDest,,為什么還要char * 類型的返回值,?

答:為了實現(xiàn)鏈式表達式。                                              // 2

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

 

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

 

2        建議6-2-1有時候函數(shù)原本不需要返回值,,但為了增加靈活性如支持鏈式表達,可以附加返回值,。

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

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

strcpy函數(shù)將strSrc拷貝至輸出參數(shù)strDest中,同時函數(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
的實現(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ù)是指針,且僅作輸入用,,則應在類型前加const,,以防止該指針在函數(shù)體內被意外修改。


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

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

要正常的話應該寫成:

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

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

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

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

      *strDest++:會拆成 *strDest strDest++兩個對等的部分

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

l       *strDest = *strSrc,;

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

 

舉個例子如下:

#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))得到的結果還是一樣
    2.
返回strDest的原始值使函數(shù)能夠支持鏈式表達式,,增加了函數(shù)的附加值,。同樣功能的函數(shù),如果能合理地提高的可用性,,自然就更加理想,。 
    
鏈式表達式的形式如: 
        int iLength=strlen(strcpy(strA,strB)); 
    
又如: 
        char * strA=strcpy(new char[10],strB); 
    
返回strSrc的原始值是錯誤的。其一,,源字符串肯定是已知的,,返回它沒有意義。其二,,不能支持形如第二例的表達式,。其三,為了保護源字符串,,形參用const限定strSrc所指的內容,,把const char *作為char *返回,,類型不符,編譯報錯,。

 

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

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多