天天看點

詳解C語言字元串 strcpystrcatstrcmpstrchrstrstr

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 運作時,會輸出亂碼。如圖所示:
    詳解C語言字元串 strcpystrcatstrcmpstrchrstrstr
  2. C語言是一直讀取到位元組 作為字元串的結尾。Java則可以根據數組長度屬性length,來讀取指定長度的字元串。
    詳解C語言字元串 strcpystrcatstrcmpstrchrstrstr
  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。
    詳解C語言字元串 strcpystrcatstrcmpstrchrstrstr

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'

    會報錯。
    詳解C語言字元串 strcpystrcatstrcmpstrchrstrstr
  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

文法:

char* strcat(char* strDestination, const char* strSource);
           
  • strDestination:目的字元串;

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() 函數用于對兩個字元串的内容進行比較(區分大小寫)。

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() 函數用于查找給定字元串中某一個特定字元。

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;
}
           

運作結果如下圖所示:

詳解C語言字元串 strcpystrcatstrcmpstrchrstrstr

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;
           

運作結果:

詳解C語言字元串 strcpystrcatstrcmpstrchrstrstr

參考文檔

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

繼續閱讀