字串長度、複製、串接


在〈字元陣列與字串〉談過,在 C 語言中,字串是一個字元陣列,最後一個字元以空字元 '\0' 作結尾,若要得知字串所含字元長度(不包括空字元),則可以使用 strlen 函式:

size_t strlen( const char *str );

參數型態 const char* 表示,這邊接受一個字串,這在之後會談到為什麼字串是這個型態;size_tunsigned 型態,在大部份系統是定義為 unsigned int,但在 64 位元系統中可以是 unsigned longstrlen 會傳回字元陣列中第一個字元至空字元的長度值減 1:

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

int main(void) {
    char buf[80];

    puts("請輸入字串...");
    scanf("%s", buf);

    size_t length = strlen(buf);
    printf("字串長度:%lu\n", length);

    return 0;
}

字串相關處理函式是定義在 string.h 中,所以要將之 #include,執行結果如下:

請輸入字串...
Justin
字串長度:6

如果使用 fgets 的話,要注意它會包括最後按下 Enter 的換行字元,你可以試著上例中的 scanf 該行,換成以下:

fgets(buf, sizeof(buf) / sizeof(buf[0]), stdin);

你會發現,輸入字串 Justin 的話,會顯示長度為 7,這是因為包括了換行字元。

如果要進行字串複製,可以使用 strcpy 函式,若要複製字串中若干字元內容,可以使用 strncpy

char *strcpy( char *restrict dest, const char *restrict src );
char *strncpy( char *restrict dest, const char *restrict src, size_t count );

restrict 是 C99 制定,只能用於修飾指標的關鍵字,之後會談到,就這邊來說,表示你得保證 destsrc 是不同來源的引數。

第一個參數是目的字元陣列,第二個參數是來源字串,strncpy 第三個參數則是要複製的字元長度,要注意的是,strncpy 不會自動在目的陣列加上空字元,它只是單純的複製指定長度的字元,以下示範 strcpystrncpy

#include <stdio.h>
#include <string.h>
#define LEN 80

int main(void) {
    char buf[LEN];

    puts("請輸入名稱...");
    // fgets 會包括 enter 字元
    fgets(buf, LEN, stdin);

    int lenOfName1 = strlen(buf) + 1;
    char name1[lenOfName1];
    strcpy(name1, buf);
    printf("名稱:%s", name1);            

    // 不複製換行字元
    int lenOfName2 = lenOfName1 - 1;
    char name2[lenOfName2];
    // 設定全部字元為空字元
    memset(name2, '\0', lenOfName2);
    strncpy(name2, buf, lenOfName2);
    printf("名稱:%s", name2);

    return 0;
}

因為 strncpy 不會自動在目的陣列加上空字元,在這個範例中,使用 memset 函式將全部字元設為空字元,一個執行的範例如下所示:

請輸入名稱...
Justin Lin
名稱:Justin Lin
名稱:Justin Lin

若要串接兩個字串,則要使用 strcat,若要串接部份字串,可以使用 strncat

char *strcat( char *restrict dest, const char *restrict src );
char *strncat( char *restrict dest, const char *restrict src, size_t count );

第二個參數的字串會串接到第一個參數之後,因此第一個參數必須保留足夠的空間作為串接時使用,以下範例示範這兩個函式的使用:

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

int main(void) {
    char str1[] = "xyz";
    char str2[] = "abc";

    int len = strlen(str1) + strlen(str2) + 1;
    char concated[len];
    memset(concated, '\0', len);

    strcat(concated, str1);
    strcat(concated, str2);

    printf("串接後:%s\n", concated);

    return 0;
}

執行結果如下:

串接後:xyzabc