1. 程式人生 > >指標和字串

指標和字串

字串回顧

一個字串由一個或多個字元組成,因此我們可以用字元陣列來存放字串,不過在陣列的尾部要加上一個空字元'\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";定義的是一個字串常量