【C語言】13-指針和字符串


說明:這個C語言專題,是學習iOS開發的前奏。也為了讓有面向對象語言開發經驗的程序員,能夠快速上手C語言。如果你還沒有編程經驗,或者對C語言、iOS開發不感興趣,請忽略

字符串回顧

一個字符串由一個或多個字符組成,因此我們可以用字符數組來存放字符串,不過在數組的尾部要加上一個空字符'\0'。

char s[] = "mj";

上面的代碼定義了一個字符數組s來存儲字符串"mj",系統會自動在尾部加上一個空字符'\0'。

內存分布大致如右圖所示:

 

從上一篇文章《十二、指向一維數組元素的指針》中可以看出指針和數組的關系非常密切,因此我們也可以使用指針來操作字符串。

一、用指針遍歷字符串的所有字符

 1 // 定義一個指針p
 2 char *p;
 3 
 4 // 定義一個數組s存放字符串
 5 char s[] = "mj";
 6 
 7 // 指針p指向字符串的首字符'm'
 8 p = s; // 或者 p = &s[0];
 9 
10 for (; *p != '\0'; p++) {
11     printf("%c \n", *p);
12 }

執行完第8行后,內存分布如右圖:

有了前面指針與數組的基礎相信大家能看到第9行之后的代碼了:每次遍歷之前先判斷p當前指向的字符是否為空字符\0,如果不是空字符,就打印當前字符,然后執行p++讓指針p指向下一個字符元素。

最后的輸出結果:

 

二、用指針直接指向字符串

從前面可以看出,指針確實可以指向字符串並操作字符串。不過前面的做法是:先定義一個字符串數組存放字符串,然后將數組首地址傳給指針p,讓p指向字符串的首字符。

1.我們也可以直接用指針指向一個字符串,省略定義字符數組這個步驟

 1 #include <string.h>
 2 
 3 int main()
 4 {
 5     // 定義一個字符串,用指針s指向這個字符串
 6     char *s = "mj";
 7     
 8     // 使用strlen函數測量字符串長度
 9     int len = strlen(s);
10     
11     printf("字符串長度:%D", len);
12     return 0;
13 }

注意第6行,我們直接用指針s指向了字符串"mj",並沒有先創建一個字符數組。看第9行,將指針s傳入到strlen函數中,說明之前所學習的字符串處理函數依然可以正常使用。輸出結果:

 

2.我們再看看strlen函數在string.h中的聲明

size_t     strlen(const char *);

strlen函數中的形參是指向字符變量的指針類型,在《十、字符和字符串常用處理函數》中我們可以將一個字符數組名傳進去,這一點又說明了指針與數組的密切關系,肯定有JQ。其實,調用strlen函數時,你傳一個地址給它就行了,它會從這個地址開始計算字符的個數,直到遇到空字符'\0'位置,因此傳入指針變量或者數組名都可以。

其他字符串處理函數也是一樣的:

1 char    *strcpy(char *, const char *); // 字符串拷貝函數
2 char    *strcat(char *, const char *); // 字符串拼接函數
3 int     strcmp(const char *, const char *); // 字符串比較函數

它們的參數都是指向字符變量的指針類型,因此可以傳入指針變量或者數組名。

因此printf函數依然可以正常使用:

char *s = "mj";
printf("%s", s);

輸出結果:

 

3.指針指向字符串的其他方式

char *s;
s = "mj";

上面的指向方式也是正確的:先定義指針變量,再指向字符串。如果是字符數組就不允許這樣做,下面的做法是錯誤的:

1 char s[10];
2 s = "mj";

編譯器肯定報第2行的錯,因為s是個常量,代表數組的首地址,不能進行賦值運算。

還需要注意的是,下面的做法也是錯誤的:

1 char *s = "mj";
2 
3 *s = "like";

第3行代碼犯了2個錯誤:

  • 3行代碼相當於把字符串"like"存進s指向的那一塊內存空間,由第1行代碼可以看出,s指向的是"mj"的首字符'm',也就是說s指向的一塊char類型的存儲空間,只有1個字節,要"like"存進1個字節的空間內,肯定內存溢出
  • 由第1行代碼可以看出,指針s指向的是字符串常量"mj"!因此是不能再通過指針來修改字符串內容的!就算是*s = 'A'這樣"看起來似乎正確"的寫法也是錯誤的,因為s指向的一個常量字符串,不允許修改它內部的字符。

 

三、指針處理字符串的注意

現在想將字符串"lmj"的首字符'l'改為'L',解決方案是多種的

1.第一種方案

1 // 定義一個字符串變量"lmj"
2 char a[] = "lmj";
3 
4 // 將字符串的首字符改為'L'
5 *a = 'L';
6 
7 printf("%s", a);

程序正常運行,輸出結果:

 

2.應該有人能馬上想到第二種方案

1 char *p2 = "lmj";
2 *p2 = 'L';
3 
4 printf("%s", p2);

看起來似乎是可行的,但這是錯誤代碼,錯在第2行。首先看第1行,指針變量p2指向的是一塊字符串常量,正因為是常量,所以它內部的字符是不允許修改的。

有人可能搞蒙了,這里的第1行代碼char *p2 = "lmj";跟第一種方案中的第2行代碼char a[] = "lmj";不是一樣的么?這是不一樣的。

  • char a[] = "lmj";定義的是一個字符串變量
  • char *p2 = "lmj";定義的是一個字符串常量


免責聲明!

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



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