【C語言入門】171.使用函式複製字串

在這篇文章,我們來介紹怎麼使用函式來複製字串。

之前的文章,我們有提到字串的複製有一些特殊性。

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

int main()
{
    char source[5] = "test";
    char destination[5];
    destination = source;   //  (X) 編譯失敗
    printf("%s\n",destination);

    return 0;
}

陣列的複製有些限制,那就是陣列不能直接被複製。

如果我們今天想要把一個字串複製到另一個字串,當這兩個都是字元陣列的時候,destination 因為是陣列,因此不能放在等號的左邊。

因此不能把一個 source 直接複製給一個 destination。

淺複製 (shallow copy)

我們在函式間傳遞字串的時候,我們傳遞的其實是一個 pointer,是一個位置。

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

int main()
{
    char source[5] = "test";
    char *destination;

    //淺複製 (shallow copy) [同一份]
    destination = source; 

    printf("%s\n",destination);

    return 0;
}

如果 destination 是 character pointer (字元指標),而不是字元陣列的話,那 destination = source; 這個語法就是正確的。

這時候 destination 指向的陣列就是 source 本身,也就是說 destination 這個陣列,用起來跟 source 一模一樣。

當你修改 source 的內容的時候,你也會更改到 destination 的內容。

深複製(Deep copy)

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

int main()
{
    char source[5] = "test";
    char destination[5];
    
    //深複製(deep copy)
    int i;
    for(i = 0;i < 5; i++){
        destination[i] = source[i];
    }
    printf("%s\n",destination);

    return 0;
}

有的時候我們複製希望產生一份新的,不希望是同一份,這時候我們會做所謂的深層複製(Deep copy)。

在這個程式,destination 是個陣列,不能直接放在等號左邊。

但是我們可以一個元素一個元素複製,因為每個元素都是字元,字元是可以被複製的。

strcpy 函式

如果我們想要直接複製字串的函式的話,我們可以使用一個叫 strcpy 的函式。

strcpy 函式的原形

#include<string.h>
char *strcpy(char *destination, const char *source);

仔細觀察你會發現,source 是 constant character pointer,而 destination 的部分是 character pointer。

這是因為 source 是被複製的,因此必須完全一樣,因此前面修飾了一個 constant。

而 destination 是要被修改的,因此不能是 constant。

這時候我們已經清楚 strcpy 函式的定義了。

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

int main()
{
    char source[5] = "test";
    char *destination;
    
   
    strcpy(destination, source);
    
    printf("%s\n",destination);

    return 0;
}

雖然我們是照著 strcpy 函式的參數去定義 source 和 destination,不過以上的程式卻是錯誤的。

因為 strcpy 做的是一個字串的複製,它會把 destination 指向的所存的位址的陣列,一個個去修改陣列裡頭元素的內容。

因此變數本身不是關鍵,而是變數位址存的空間,是不是可以被修改。

char *destination 只有宣告一個格子去存位置,我並沒有宣告字元的格子、陣列去存字元,所以這樣寫是錯的。

當它去存取 destination 指向的空間的時候,發現根本沒指定它指向的空間

卻沒有指向一個存著可以修改內容的字元陣列。

strcpy 正確用法

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

int main()
{
    const char *source = "test";
    char destination[5];
    
   
    strcpy(destination, source);
    
    printf("%s\n",destination);

    return 0;
}

先產生可以存字元的字元陣列 destination,即可以讀,也可以寫。

然後字元陣列會隱性轉型成一個 character pointer ,這時候 source 就可以成功傳進 destination 了。

只有 destination[5] ,才會產生 5 個格子,

小結:

destination[5] 有產生格子存字元,先產生一個字元陣列,然後字元陣列隱性轉型成字元的指標。

*destination 是產生一個格子存位址,但沒有產生格子存字元,因此自然沒辦法複製。

其他寫法 1:

    const char *source = "test";

可以改成

    char *source = "test";

但是這樣的話,當我們把 source 傳到 strcpy 的第二個參數的時候,我也會做一個字元陣列轉字元指標,再轉 const 的字元指標。

其他寫法 2:

    const char *source = "test";

也可以寫成

    const char source[5] = "test";

陣列可以轉型成指標,因此這樣寫也是可以的。

Leave a Comment

Your email address will not be published. Required fields are marked *