詳解C語言字符串


1、定義字符串

C語言本身沒有string類型,通常使用char數組來表示字符串。常用的定義字符串的方式有:

char str1[] = {'C', 'h', 'i', 'n', 'a'};
char str2[] = "China";
char* str3 = "China";
  1. 與Java語言不同,C語言中數組的括號是在變量名的后面。第一條定義字符串的語句等價於Java語言中:char[] str1 = {'C', 'h', 'i', 'n', 'a'};

  2. [] 中可以填入數字,表示char數組的長度。但是,中括號中的數字必須大於等於右邊字符串數組的長度。

    • char str1[5] = {'C', 'h', 'i', 'n', 'a'}char str1[6] = {'C', 'h', 'i', 'n', 'a'}, ... , char str1[100] = {'C', 'h', 'i', 'n', 'a'} 都是合法的。
    • char str2[6] = "China";char str2[7] = "China";, ... ,char str2[100] = "China"; 都是合法的。
    • char str2[5] = "China";,如果 str2 括號內填寫的數字小於 6 就會編譯出錯,出現數組界限溢出錯誤。

2、計算char數組的長度

在Java中,數組是看作對象類型的,數組有通用的屬性 length,比如 str1.length 可以獲取數組的長度。但是 C 語言可沒有這么“友善”,想獲取char數組的長度:

char str1[] = {'C', 'h', 'i', 'n', 'a'};
int len = sizeof(str1) / sizeof(char);  // 這句話計算字符串數組的長度
printf("%d", len);
  1. sizeof 是C語言中保留關鍵字,用來計算數據類型的“寬度”。用 sizeof 可以獲得數據類型變量在內存中所占的字節數。同樣,用 sizeof 也可以獲得整個數組在內存中所占的字節數。

  2. 因為數組中每個元素的類型都是一樣的,在內存中所占的字節數都是相同的,所以 總的字節數 除以 一個元素所占的字節數 就是數組的長度。

  3. sizeof(char) 表示數據類型 char 在內存中所占的字節數,在C語言中,char占一個字節,所以 sizeof(char) == 1

  4. 我這里說的字符串數組的長度,說到底還是數組的長度。

3、字符串必須以\0結尾。如果不是,就會出現亂碼

char str1[] = { 'C', 'h', 'i', 'n', 'a' };
printf("%s\n", str1);
  1. 上面這段代碼在 Windows 上,用 Microsoft Visual Studio 運行時,會輸出亂碼。如圖所示:

  2. C語言是一直讀取到字節0作為字符串的結尾。Java則可以根據數組長度屬性length,來讀取指定長度的字符串。

  3. 所以,正確的定義方式應該是 char str1[] = { 'C', 'h', 'i', 'n', 'a', '\0'};,此時字符串數組的長度是 6。 char str1[] = { 'C', 'h', 'i', 'n', 'a', 0 }; 這樣定義也是可以的,但是更推薦前一種。

4、定義一個空的字符串數組

char str0[100] = {0}; // 用這條語句定義一個空的字符串數組
int len0 = sizeof(str0) / sizeof(char); 
printf("%d", len0); // 數組長度為100
  1. 第一條語句就等同於Java中的char[] str0 = new char[100];

  2. 第一句語句也可以寫成 char str0[100] = {};,這樣寫也是正確的。但是,char str0[] = {} 這樣寫不行,空初始值設定項對於未指定綁定的數組無效!

5、計算字符串的長度 strlen

與字符串數組的長度不同,字符串的長度是不把字節0算進去的。strlen 函數可以返回字符串的長度:

size_t strlen(const char* str);

然后來看幾個實驗:

char str1[] = {'C', 'h', 'i', 'n', 'a'};
char str2[] = "China";
char* str3 = "China";
char str4[] = {'C', 'h', 'i', 'n', 'a', '\0'};
printf("%d\n", strlen(str1)); // 輸出結果為19
printf("%d\n", strlen(str2)); // 輸出結果為5
printf("%d\n", strlen(str3)); // 輸出結果為5
printf("%d\n", strlen(str4)); // 輸出結果為5
  1. 其中,str1 所表示的字符串因為沒有以 '\0' 結尾,所以,strlen 把內存中一直到 \0 結尾的字節都看作字符串的內容,所以長度為 19。

6、字符串常量不可修改

我們先來看一段程序:

char str0[] = {'c', 'h', 'i', 'n', 'a', '\0'};
char str1[] = "china"; // 在棧上,因為重載了=操作符
char* str2 = "china"; // china\0在常量區,str1在棧上

str0[0] = 'C';
str1[0] = 'C';
//str2[0] = 'C';
//*str2 = 'C';

printf("%s\n", str0);
printf("%s\n", str1);
printf("%s\n", str2);
  1. 運行結果是,str0[0] = 'C'str1[0] = 'C' 這兩句可以正常運行。但是 str2[0] = 'C'*str2 = 'C' 會報錯。

  2. char str1[] = "china"char* str2 = "china" 字符串存放的內存區域不同:前者存放在棧中,可以修改;后者存放在常量區,不可修改。

  3. 0xC0000005:安全點就是通過這個技術暫停所有線程的。

7、拷貝字符串strcpy

C語言 strcpy() 函數用於對字符串進行復制(拷貝)。

頭文件:string.h

語法/原型:

char* strcpy(char* strDestination, const char* strSource);

參數說明:

  • strDestination:目的字符串。
  • strSource:源字符串。

strcpy() 會把 strSource 指向的字符串復制到 strDestination。

必須保證 strDestination 足夠大,能夠容納下 strSource,否則會導致溢出錯誤。

返回值:目的字符串,也即 strDestination。

示例:

#include <string.h>

int main() {
  char dest[] = {0};
  char src[] = "Hello, Han Meimei!";

  strcpy(dest, src);

  printf("%s", dest);
  return 0;
}

8、連接字符串strcat

頭文件:string.h
語法:

char* strcat(char* strDestination, const char* strSource);

參數說明:

  • strDestination:目的字符串;
  • strSource:源字符串。

strcat() 函數把 strSource 所指向的字符串追加到 strDestination 所指向的字符串的結尾,所以必須要保證 strDestination 有足夠的內存空間來容納兩個字符串,否則會導致溢出錯誤。

注意:strDestination 末尾的\0會被覆蓋,strSource 末尾的\0會一起被復制過去,最終的字符串只有一個\0。

返回值:指向 strDestination 的指針。

#include <string.h>

int main() {
  char dest[] = "Hello";
  char src[] = " World!";

  strcat(dest, src);

  printf("%s", dest);
  return 0;
}

8、比較字符串strcmp

C語言 strcmp() 函數用於對兩個字符串的內容進行比較(區分大小寫)。

頭文件:string.h

語法/原型:

int strcmp(const char* stri1,const char* str2);
  • 參數 str1 和 str2 是參與比較的兩個字符串。

strcmp() 會根據 ASCII 編碼依次比較 str1 和 str2 的每一個字符,直到出現不到的字符,或者到達字符串末尾(遇見\0)。

返回值:

  • 如果返回值 < 0,則表示 str1 小於 str2。
  • 如果返回值 > 0,則表示 str2 小於 str1。
  • 如果返回值 = 0,則表示 str1 等於 str2。

示例:

#include <string.h>

int main() {
  char str1[] = {'C', 'h', 'i', 'n', 'a', '\0'};
  char* str2 = "China";

  int result = strcmp(str1, str2);
  printf("%d", result); // 輸出結果為0
  return 0;
}

9、字符查找函數strchr

C語言 strchr() 函數用於查找給定字符串中某一個特定字符。

頭文件:string.h

語法/原型:

char* strchr(const char* str, int c);

參數說明:

  • str:被查找的字符串。
  • c:要查找的字符。

strchr() 函數會依次檢索字符串 str 中的每一個字符,直到遇見字符 c,或者到達字符串末尾(遇見\0)。

返回值:返回在字符串 str 中第一次出現字符 c 的位置,如果未找到該字符 c 則返回 NULL。

示例:

#include <string.h>

int main() {
  char str1[] = {'C', 'h', 'i', 'n', 'a', '\0'};
  printf("%p\n", str1);

  char* p1 = strchr(str1, 'b');
  printf("%p\n", p1); // 輸出結果為0,str1中不包含字符b

  char* p2 = strchr(str1, 'h');
  printf("%p\n", p2); // 輸出結果比 str1 的內存地址多一個字節
  return 0;
}

運行結果如下圖所示:

10、查找子字符串strstr

C語言 strstr() 函數在字符串中查找子字符串。

語法/原型

char *strstr(const char *haystack, const char *needle)

參數說明:

  • haystack -- 要被檢索的 C 字符串。
  • needle -- 在 haystack 字符串內要搜索的小字符串。

返回值
該函數返回在 haystack 中第一次出現 needle 字符串的位置,如果未找到則返回 null。

示例:

char haystack[20] = "RUNOOB";
char needle[10] = "NOOB";
 
char *ret = strstr(haystack, needle);
 
printf("子字符串是: %s\n", ret);
   
return 0;

運行結果:

參考文檔

  1. Go to 《數組的長度,C語言獲取數組長度詳解》


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM