1. 程式人生 > >14. C語言 -- 字串處理函式

14. C語言 -- 字串處理函式

本部落格主要內容為 “小甲魚” 視訊課程《帶你學C帶你飛》【第一季】 學習筆記,文章的主題內容均來自該課程,在這裡僅作學習交流。在文章中可能出現一些錯誤或者不準確的地方,如發現請積極指出,十分感謝。
也歡迎大家一起討論交流,如果你覺得這篇文章對你有所幫助,記得評論、點贊哦 ~(。・∀・)ノ゙

1. 字元陣列

  回顧 《4. C語言 – 資料型別和取值範圍》 可以知道,在 C 語言的資料型別中並沒有字串型別的。那它是如何存放和表示字串的呢?兩種方式——字串常量以及字元型別的陣列。

  比如說 “C語言”,"CSDN部落格"都是字串常量,因為是常量,所以也沒有辦法進行修改,很不方便;另一種就是字元陣列,在字元陣列中可以先定義指定長度的字元陣列,然後再給每個元素單獨賦值。

  如果給陣列中的元素一個一個的賦值的話會導致程式碼變得冗長,因此可以採用如下四種方法直接在定義的時候對字元陣列進行初始化,會方便很多

int main
{
    // 初始化字元陣列的每個元素
    char str1[10] = {'F', 'i', 's', 'h', 'C', '\0'};
    
    // 可以不寫元素的個數,因為編譯器會自動計算
    char str3[] = {'F', 'i', 's', 'h', 'C', '\0'};
    
    // 使用字串常量初始化字元陣列
    char str4[] = {"FishC"};
    
    // 使用字串常量初始化,可以省略大括號
char str5[] = "FishC"; }

在上面的這四種中,推薦使用最後一種,簡單方便。

2. 字串處理函式

  在實際開發中,你經常會聽到大牛說“避免重新造輪子”。如果能用得上官方提供的現成的函式,儘量不要自己去寫,這樣除了能夠大幅度提供工作效率外,也會使你的程式更加穩定和快速。在這裡將介紹幾個與字串有關的函式。

2.1 獲取字串的長度

  strlen 的函式原型為

#include <string.h>
...
size_t strlen ( const char * str );

  strlen 函式用於返回指定字串的長度。C 語言字串的長度取決於結束符(’\0’)的位置,一個字串的長度指的是從起始位置到結束符的字元個數(不包含結束符本身)。初學者很容易混淆字串的長度和字串陣列的大小,例如:

char mystr[100] = "I love FishC.com!";

上邊程式碼定義一個可以存放 100 個字元的陣列,但 mystr 字串只被初始化為包含 17 個字元的長度。因此,sizeof(mystr) 的結果是 100,而 strlen(mystr) 的結果則是 17。

  一個具體的例子如下所示

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

int main()
{
        char str[100] = "I love FishC.com!";
        printf("length = %u\n", strlen(str));

        return 0;
}

得到如下的結果
在這裡插入圖片描述

其中需要注意的是 size_t 被定義於 stddef.h 標頭檔案中,它事實上就是無符號整形(unsigned int),所以在列印輸出中使用 %u 進行佔位。

2.2 字串處理函式

  在字串中需要注意的是,字串不可以像常量一樣通過賦值符號進行拷貝,常用 strcpy 函式和 strncpy 函式拷貝字串。

2.2.1 strcpy 函式

  strcpy 函式用於拷貝字串,包含最後的結束符 ‘\0’。為了避免溢位,必須確保用於存放的陣列長度足以容納待拷貝的字串(注意:長度需要包含結束符 ‘\0’)。

  strcpy 的函式原型為

#include <string.h>
...
char *strcpy(char *dest, const char *src);

其中 dest 指向用於存放字串的目標陣列,src 指向待拷貝的源字串,簡單理解就是就是將位與後面字串中的內容拷貝到前面的字串中。返回值為指向目標字串的指標。

  下面是舉例說明這個函式的功能

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

int main()
{
        char str1[] = "Original String";
        char str2[] = "New String";
        char str3[100];

        strcpy(str1, str2);
        strcpy(str3, "Copy Successful");

        printf("str1: %s\n", str1);
        printf("str2: %s\n", str2);
        printf("str3: %s\n", str3);

        return 0;
}

執行上面程式碼得到如下
在這裡插入圖片描述

2.2.2 拷貝字串(受限)

  和 strcpy 函式一樣,strncpy(dest, src, n) 函式將拷貝源字串的 n 個字元到目標陣列中。如果源字串的長度小於 n,那麼就用 ‘\0’ 填充額外的空間。如果源字串的長度大於或等於 n,那麼只有 n 個字元被拷貝到目標陣列中(注意:這樣的話將不會以結束符 ‘\0’ 結尾)。為了使該函式更“安全”,建議使用 dest[sizeof(dest) - 1] = '\0'; 語句確保目標字串是以 ‘\0’ 結尾。

  它的函式原型如下

#include <string.h>
...
char *strncpy(char *dest, const char *src, size_t n);

其中 dest 指向存放字串的目標陣列,src 指向待拷貝的源字串,n 指定拷貝的最大長度,返回值是指向目標字串的指標。

  比如說執行如下的程式碼,將 str1 拷貝到 str2,將 str2 拷貝到 str3。

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

int main()
{
        char str1[] = "To be or not to be";
        char str2[40];
        char str3[40];

        strncpy(str2, str1, sizeof(str2));
        strncpy(str3, str2, 5);
        str3[5] = '\0';

        printf("%s\n", str1);
        printf("%s\n", str2);
        printf("%s\n", str3);

        return 0;
}

其中需要注意的是,我們特意加上 str3[5] = '\0';,確保目標字串是以 ‘\0’ 結尾。執行可以得到如下的結果

To be or not to be
To be or not to be
To be

2.3 連線字串

  同樣連線字串也有 strcat 函式和 strncat 函式兩種。

2.3.1 strcat 函式

  strcat 函式用於連線兩個字串。將源字串拷貝並連線到目標陣列存放的字串後邊,此過程將覆蓋第一個引數的結束符 ‘\0’。

  具體的函式原型為

#include <string.h>
...
char *strcat(char *dest, const char *src);

其中 dest 指向用於存放字串的目標陣列,它應該包含一個字串,並且提供足夠容納連線後的總字串長度的空間(包含結束符 ‘\0’);src 指向待連線的源字串,該引數不應該與 dest 引數指向的位置發生重疊;返回值是指向目標字串的指標。

  比如執行如下的程式

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

int main()
{
        char str1[100] = "Original String";
        char str2[] = "New String";

        strcat(str1, " ");
        strcat(str1, str2);

        printf("str1: %s\n", str1);
        return 0;
}

執行上面的程式碼可以得到如下的結果

str1: Original String New String

其中需要注意的是,我們首先在 str1 的後面連線了一個空格,之後在連線的 str2 ,否則顯示的時候兩個字串會連在一起。

2.3.2 strncat 函式

  strncat 函式用於拷貝源字串中的 n 個字元到目標陣列的字串後邊,並在末尾新增結束符 ‘\0’。如果源字串的長度小於 n,那麼不會像 strncpy 函式那樣使用 ‘\0’ 進行填充(但結束符 ‘\0’ 還是有的)。另外,目標陣列中的原有的字串並不算在 n 中。

  函式原型如下

#include <string.h>
...
char *strncat(char *dest, const char *src, size_t n);

其中 dest 指向用於存放字串的目標陣列,它應該包含一個字串,並且提供足夠容納連線後的總字串長度的空間(包含結束符 ‘\0’);src 指向待連線的源字串,該引數不應該與 dest 引數指向的位置發生重疊;n 指定待連線的源字串的最大長度。返回值是指向目標字串的指標。

  下面是strncat 函式的舉例說明

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

int main()
{
        char str1[20] = "I ";
        char str2[20] = "love ";
        char str3[20] = "FishC.com!";

        strncat(str1, str2, 5);
        strncat(str1, str3, 10);

        printf("str1: %s\n", str1);

        return 0;
}

執行得到如下的結果

str1: I love FishC.com!

2.4 比較字串

2.4.1 strcmp 函式

  strcmp 函式用於比較兩個字串。該函式從第一個字元開始,依次比較每個字元的 ASCII 碼大小,直到發現兩個字元不相等或抵達結束符(’\0’)為止。

  函式原型如下

#include <string.h>
...
int strcmp(const char *s1, const char *s2);

其中s1 指向待比較的字串 1,s2 指向待比較的字串 2。當字串 1 的字元小於字串 2 對應位置的字元,返回值 < 0;當兩個字串的內容完全一致,返回值 = 0;字串 1 的字元大於字串 2 對應位置的字元,返回值 > 0。

  如下所示

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

int main()
{
        char str1[10] = "FishC.com";
        char str2[20] = "FishC.com";

        if (!strcmp(str1, str2)){
                printf("兩個字串完全一致!\n");
        }
        else{
                printf("兩個字串不同!\n");
        }

        return 0;
}

執行程式碼可得

兩個字串完全一致!

2.4.2 strncmp 函式

  strncmp 函式用於比較兩個字串的前 n 個字元。該函式從第一個字元開始,依次比較每個字元的 ASCII 碼大小,發現兩個字元不相等或抵達結束符(’\0’)為止,或者前 n 個字元完全一樣,也會停止比較。

  函式原型如下

#include <string.h>
...
int strncmp(const char *s1, const char *s2, size_t n);

s1 指向待比較的字串 1,s2 指向待比較的字串 2,n 指定待比較的字元數,返回值與上面 strcmp 的返回值相同。

  比如執行如下的程式碼

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

int main()
{
        char str1[40] = "FishC";
        char str2[40] = "FishC.com";

        if (!strncmp(str1, str2, 5))
        {
                printf("str1和str2前5個字元相同!\n");
        }
        else
        {
                printf("str1和str2前5個字元不同!\n");
        }

        return 0;
}

可以得到如下的結果

str1和str2前5個字元相同!

參考

[1] “小甲魚” 視訊課程《帶你學C帶你飛》【第一季】P19

歡迎大家關注我的知乎號(左側)和經常投稿的微信公眾號(右側)
在這裡插入圖片描述