字元串是一種非常重要的數據類型,但是C語言不存在顯式的字元串類型,C語言中的字元串都以字元串常量的形式出現或存儲在字元數組中。同時,C 語言提供了一系列庫函數來對操作字元串,這些庫函數都包含在頭文件 string.h 中。 一、字元串常量和字元數組 1.1、什麼是字元串常量 C 語言雖然沒有字元串類 ...
字元串是一種非常重要的數據類型,但是C語言不存在顯式的字元串類型,C語言中的字元串都以字元串常量的形式出現或存儲在字元數組中。同時,C 語言提供了一系列庫函數來對操作字元串,這些庫函數都包含在頭文件 string.h 中。
一、字元串常量和字元數組
1.1、什麼是字元串常量
C 語言雖然沒有字元串類型,但是 C語言提是存在字元串這個概念的,也就是字元串常量:以 NUL 位元組結尾的 0 個或多個字元組成的序列。字元串常量是不可被修改的,一般用一對雙引號(" ")括起的一串字元來表示字元串常量,如:
"Hello!"、"\aWarning!\a"、"123abc\n"、""
字元串常量可以為空,如""就是一個空的字元串常量,但是即使為空,還是存在一個終止符 NUL 的。(在 C 語言中,常用轉義字元 \0 來表示 NUL)
1.2、字元串常量與指針
字元串常量與指針關係密切,因為字元串常量的值,實際上表示的是存儲這些字元的記憶體空間的地址,更準確地說是字元串常量中第 1 個字元的地址,而不是這些字元本身。因此,在 C 語言中是不能直接進行字元串賦值的(因為沒有字元串類型嘛)。在 C 語言中,常通過聲明一個指向 char 類型的指針並將其初始化為一個字元串常量的方式來訪問一個字元串:
char *message = "Hello World!"; // 上面的語句也可以拆分成下麵兩句 char *message; message = "Hello World!"; // 這句話看起來像是字元串複製,其實不是,只是涉及到指針操作
上述語句聲明瞭一個指向 char 類型的指針,並用字元串常量中第 1 個字元的地址對該指針進行初始化。可以通過字元指針 message 來訪問字元串常量:
#include <stdio.h> int main() { char *message = "Hello World!"; printf("%s\n",message); while(*message != '\0'){ printf("%c ",*message++); } printf("\n"); return 0; } /* output: * Hello World! * H e l l o W o r l d ! */
這段代碼,使用字元指針遍歷了字元串常量中的每一個字元。
1.3、字元數組
用於存放字元的數組稱為字元數組。在 C 語言中,除了字元串常量外,其他所有字元串都必須存儲於字元數組或動態分配的記憶體中。定義一個字元數組和定義一個普通數組一樣,不同的是字元數組中存放的是字元數據而已:
char charArray[] = {'H','e','l','l','o'}; // 聲明並初始化一個字元數組
這句話定義並初始化了一個字元數組 charArray。這個數組的長度實際上為 6 ,因為會自動添加一個字元串結束符 '\0'。
C 語言提供了一種更簡潔的方法來對字元數組進行初始化:
char charArray[] = "Hello World!"; // 聲明並初始化一個字元數組
上述兩種聲明方式等價。
可以對一個字元數組做出修改:
#include <stdio.h> #include <string.h> int main() { char str[] = "hello world!"; int len = strlen(str); int i; for(i = 0; i < len; i++){ if( str[i] <= 'z' && str[i] >= 'a'){ str[i] = str[i] - 32; } } printf("%s\n",str); }
這段代碼可以將字元數組中的小寫字母轉換成大寫字母後輸出。
1.4、 字元串常量與字元數組的區別
1)字元串常量是一個字元數組,但是內容和長度在初始化時就已經固定了,不可更改;可以通過一個指向字元串常量第一個元素的指針來訪問該字元串常量;
2)字元數組是一個用於存放字元的數組,字元數組的值是可以更改的。
二、獲取字元串長度
字元串的長度就是這個字元串所包含字元的個數,但是這個長度是不包含 NUL 字元的。C 語言中使用庫函數 strlen 來計算字元串長度:
size_t strlen(char const *string);
需要註意的是 strlen 的返回值類型:size_t 類型,這是一個無符號整數類型。
#include <stdio.h> #include <stdlib.h> #include <string.h> int main() { char str1[] = "Hello World!"; printf("%d\n",strlen(str1)); return 0; } /* output: * 12 */
三、複製字元串
C 語言中使用庫函數 strcpy 來進行字元串複製操作:
char *strcpy(char *dst , char const *src);
函數 strcpy 接收兩個字元串參數,並將參數 src 字元串複製到 dst 參數。使用 strcpy 函數時需要註意的是,必須保證目標字元數組 dst 的長度足夠存放源字元數組 src 的內容。如果 src 比 dst 長,則 src 剩餘部分的字元仍會被覆制,而且它們會覆蓋 dst 後面的記憶體空間的值,如果這除記憶體空間原本就存放有值,則會導致原本的數據丟失,這樣會造成很嚴重的後果。為瞭解決這個問題, C 語言中提供了一種更為安全的方式來進行字元串複製操作——strncpy 函數:
char *strncpy(char *dst , char const *src , size_t len);
strncpy 函數有三個參數,與 strcpy 函數一樣,它也是將 src 字元串中的字元複製到目標數組 dst 中去,但是 strncpy 函數提供的第三個參數 len 規定了可以向 dst 中寫入的字元的個數:
1)如果 strlen(src) > len,則只有 len 個字元被覆制到 dst 中去,此時 dst 將不會以 NUL 位元組結尾(也就是說,strncpy 調用的結果可能不是一個字元串);
2)如果 strlen(src) < len,則 src 中的字元全被覆制到 dst 中去,dst 中剩餘的部分用 NUL 填充。
四、連接字元串
C 語言中使用庫函數 strcat 來連接兩個字元串:
char *strcat(char *dst,char const *src);
函數 strcat 將參數 src 字元串連接到參數 dst 字元串的後面。與 strcpy 函數一個同樣的問題是,必須保證 dst 的剩餘空間足夠存放下 src 整個字元串。C 語言中提供了 strncat 函數來解決這個問題:
char *strncat(char *dst , char const *src , size_t len);
strncat 函數從 src 中最多複製 len 個字元到目標數組 dst 後面,並且,strncat 總是在結果字元串後面添加一個 NUL 位元組,而且不會像 strncpy 函數那樣對 dst 剩餘的空間用 NUL 進行填充。
五、字元串比較
C 語言中使用庫函數 strcmp 來進行字元串比較。strcmp 函數會對被比較的兩個字元串進行逐字元地比較,直到發現不匹配為止:最先不匹配的字元中較小的那個字元所對應的字元串即被認為小於另一個字元串;如果兩者所有字元都匹配,則認為這兩個字元串相等;
int strcmp(char const *s1 , char sonst *s2);
該函數的返回值如下:
1)s1 小於 s2,返回一個負值;
2)s1 等於 s2,返回 0;
3)s1 大於 s2,返回一個正值。
char *strncmp(char const *s1 , char const *s2 , size_t len);
可以使用 strncmp 函數限定比較的字元的個數,返回值與 strcmp 一樣,但是只針對前 len 個字元進行比較。
六、字元串的查找
6.1 查找一個字元
可以使用 strchr 函數或 strrchr 函數來在一個字元串中查找一個特定的字元:
char *strchr(char const *str,int ch); // int ch 是字元的ASCII碼值 char *strrchr(char const *str,int ch);
函數 strchr 在字元串 str 中查找字元 ch 第一次出現的位置,並返回一個指向該位置的指針;如果沒有找到相應的字元,則返回一個 NULL 指針。函數 strrchr 在字元串中查找字元 ch 最後一次出現的位置,並返回指向該位置的指針。
6.2 查找任意幾個字元
可以使用 strpbrk 函數來查找任何一組字元第一次在字元串中出現的位置:
char *strpbrk(char const *str , char const *group);
這個函數返回一個指向字元串 str 中第一個匹配 group 中任何一個字元的字元位置,如果沒有匹配到,則返回一個 NULL 指針。
6.3 查找一個子串
可以使用 strstr 函數來在一個字元串中查找一個子串:
char *strstr(char const *str1 , char const *str2);
這個函數在 str1 中查找整個字元串 str2 第一次出現的起始位置,並返回一個指向該位置的指針;如果 str2 並沒有完整的出現在 str1 中,則函數將返回一個 NULL 指針;如果 str2 是一個空字元串,則返回str1.
參考資料
《C和指針》
《C程式設計語言 第二版》