strcpy寫法及字串指標問題

來源:互聯網
上載者:User

問題是從baiyuxiong發的那個“出現頻率最高的筆試題strcpy寫法+分析zz”文章開始的:

 

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

    解說:
    1.strcpy的實現代碼

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

        {

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

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

                char * strDestCopy=strDest;  //[3]

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

                return strDestCopy;

        }

    錯誤的做法:
    [1]
    (A)不檢查指標的有效性,說明答題者不注重代碼的健壯性。
   
(B)檢查指標的有效性時使用((!strDest)||(!strSrc))或(!(strDest&&strSrc)),說明答題者
對C語言中類型的隱式轉換沒有深刻認識。在本例中char
*轉換為bool即是類型隱式轉換,這種功能雖然靈活,但更多的是導致出錯機率增大和維護成本升高。所以C++專門增加了bool、true、false
三個關鍵字以提供更安全的條件運算式。
   
(C)檢查指標的有效性時使用((strDest==0)||(strSrc==0)),說明答題者不知道使用常量的好處。直接使用字面常量(如本例中的
0)會減少程式的可維護性。0雖然簡單,但程式中可能出現很多處對指標的檢查,萬一出現筆誤,編譯器不能發現,產生的程式內含邏輯錯誤,很難排除。而使用
NULL代替0,如果出現拼字錯誤,編譯器就會檢查出來。
    [2]
    (A)return new
string("Invalid
argument(s)");,說明答題者根本不知道傳回值的用途,並且他對記憶體流失也沒有警惕心。從函數中返回函數體內分配的記憶體是十分危險的做法,他
把釋放記憶體的義務拋給不知情的調用者,絕大多數情況下,調用者不會釋放記憶體,這導致記憶體流失。
    (B)return
0;,說明答題者沒有掌握異常機制。調用者有可能忘記檢查傳回值,調用者還可能無法檢查傳回值(見後面的鏈式運算式)。妄想讓傳回值肩負返回正確值和異常
值的雙重功能,其結果往往是兩種功能都失效。應該以拋出異常來代替傳回值,這樣可以減輕調用者的負擔、使錯誤不會被忽略、增強程式的可維護性。
    [3]
    (A)忘記儲存原始的strDest值,說明答題者邏輯思維不嚴密。
    [4]
    (A)迴圈寫成while (*strDest++=*strSrc++);,同[1](B)。
    (B)迴圈寫成while (*strSrc!='/0') *strDest++=*strSrc++;,說明答題者對邊界條件的檢查不力。迴圈體結束後,strDest字串的末尾沒有正確地加上'/0'。

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

 

 

自己簡單寫了下程式:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *strcpy(char *str_dest,const char *str_src)
{
        char *str_destcopy;
        if( (str_dest==NULL) || (str_src==NULL)){
                printf("invalid parameters/n");
                return NULL;
        }

        str_destcopy = str_dest;
        while( (*str_dest++=*str_src++)!='/0');

        return str_destcopy;
}

int main(int argc, char *argv[])
{
        char *str_src="helloworld";
        char *str_dest;
        char *ret;

        str_dest=(char *)malloc(sizeof(char)*10);
        if(NULL!=str_dest){
                memset(str_dest, 0, sizeof(char)*10);
        }
        printf("str_src:%s/n",str_src);
        if( (ret=strcpy(str_dest, str_src)) == NULL)
                printf("strcpy ERROR./n");
        else
                printf("str_dest:%s/n",ret);

}
有兩點注意:
1、記得要給字串指標分配記憶體:
        str_dest=(char *)malloc(sizeof(char)*10);
        if(NULL!=str_dest){
                memset(str_dest, 0, sizeof(char)*10);
        }

最開始沒有分配記憶體,總是報段錯誤

另外也採用char str_dest[10];的方式,就不用指標了

2、另外,最開始沒有加#include <stdlib.h>和#include <string.h>兩句,編譯出現的警告:
strcpy.c:23: 警告:隱式聲明與內建函數‘malloc’不相容
strcpy.c:25: 警告:隱式聲明與內建函數‘memset’不相容
後來man了一下這兩個函數,發現缺少標頭檔,包含進來後就沒有以上錯誤了

 

環境:linux系統,gcc4.3.2

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.