日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

strcpy函数实现的几种方式

發布時間:2025/5/22 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 strcpy函数实现的几种方式 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

C/C++——strcpy函數的實現?和解析

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


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

五、編寫strcpy函數(10分)

已知strcpy函數的原型是

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

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

(1)不調用C++/C的字符串庫函數,請編寫函數?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

}

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

答:為了實現鏈式表達式。??????????????????????????????????????????????// 2分

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

?

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

?

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

例如字符串拷貝函數strcpy的原型:

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

strcpy函數將strSrc拷貝至輸出參數strDest中,同時函數的返回值又是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的實現代碼?

?

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]:???規則6-1-3】如果參數是指針,且僅作輸入用,則應在類型前加const,以防止該指針在函數體內被意外修改。


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

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

要正常的話應該寫成:

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

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

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

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

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

其讓人感覺到的執行順序

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

關于鏈式表達式

已知strcpy函數的原型是 char *strcpy(char *strDest, const char *strSrc);

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

(1)不調用C++/C的字符串庫函數,請編寫函數

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分

}

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

?答:為了實現鏈式表達式。 // 2分

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

?--------------------------------------------------------------------------------------------------------------------------------

看到了這個詞:鏈式表達式,之前沒有聽過,所以去百度了一下,發現有人解釋的還算明白:

-------------------------------------------------------------------------------------------------------------------------------- http://topic.csdn.net/t/20061123/21/5180993.html 1,

就是方便一些,否則就要這樣寫:

char strDest[12];

strcpy( strDest, “hello world”);

int length = strlen(strDest);

什么鏈式就是一連串寫下來的意思。。。

?--------------------------------------------------------------------------------------------------------------------------------

?其實,說白了,就是如果上面的字符串拷貝函數strcopy的返回值是void,那么,上面那句:

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

?就要像上面那位的回答,寫成好幾句了:

char strDest[12];

?strcpy( strDest, “hello world”);

int length = strlen(strDest);

而這種直接返回char *的手段,就是為了后來函數調用者方便而設計的.不用你這么麻煩用上述方法去使用了,而直接可以使用拷貝后的dest字符串了.這種方便的實現方法,看起來就是鏈子鏈在一起的,所以稱為 鏈式表達式

如此而已.呵呵.


關于鏈式表達式

已知strcpy函數的原型是 char *strcpy(char *strDest, const char *strSrc);

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

(1)不調用C++/C的字符串庫函數,請編寫函數

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分

}

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

?答:為了實現鏈式表達式。 // 2分

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

?--------------------------------------------------------------------------------------------------------------------------------

看到了這個詞:鏈式表達式,之前沒有聽過,所以去百度了一下,發現有人解釋的還算明白:

-------------------------------------------------------------------------------------------------------------------------------- http://topic.csdn.net/t/20061123/21/5180993.html 1,

就是方便一些,否則就要這樣寫:

char strDest[12];

strcpy( strDest, “hello world”);

int length = strlen(strDest);

什么鏈式就是一連串寫下來的意思。。。

?--------------------------------------------------------------------------------------------------------------------------------

?其實,說白了,就是如果上面的字符串拷貝函數strcopy的返回值是void,那么,上面那句:

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

?就要像上面那位的回答,寫成好幾句了:

char strDest[12];

?strcpy( strDest, “hello world”);

int length = strlen(strDest);

而這種直接返回char *的手段,就是為了后來函數調用者方便而設計的.不用你這么麻煩用上述方法去使用了,而直接可以使用拷貝后的dest字符串了.這種方便的實現方法,看起來就是鏈子鏈在一起的,所以稱為 鏈式表達式

如此而已.呵呵.


總結

以上是生活随笔為你收集整理的strcpy函数实现的几种方式的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。