字串的儲存方式有字元陣列和字元指標,我們先來看看字元陣列。
因為字串是由多個字元組成的序列,所以要想儲存一個字串,可以先把它拆成一個個字元,然後分別對這些字元進行儲存,即通過字元陣列儲存。字元陣列是一個陣列,且是儲存字元的陣列,該陣列中一個元素存放字串的一個字元。
字元陣列的定義
因為字元陣列首先是一個陣列,所以前面講的陣列內容通通都適用。其次它是存放字元的陣列,即陣列的型別是 char 型。比如:
char name[10];
表示定義了 10 位元組的連續記憶體空間。
1) 如果字串的長度大於 10,那麼就存在語法錯誤。這裡需要注意的是,這裡指的“字串的長度”包括最後的 ''。也就是說,雖然系統會自動在字串的結尾加 '',但它不會自動為 '' 開闢記憶體空間。所以在定義陣列長度的時候一定要考慮 ''。
2) 如果字串的長度小於陣列的長度,則只將字串中的字元賦給陣列中前面的元素,剩下的記憶體空間系統會自動用 ' 填充。
字元陣列的初始化
字元陣列的初始化與陣列的初始化一樣,要麼定義時初始化,要麼定義後初始化。下面寫一個程式來說明這個問題:
# include <stdio.h>
int main(void)
{
char a[10];
a[0] = 'i'; a[1] = ' '; a[2] = 'l'; a[3] = 'o'; a[4] = 'v';
//空格字元的單引號內一定要敲空格
a[5] = 'e'; a[6] = ' '; a[7] = 'y'; a[8] = 'o'; a[9] = 'u';
//空格字元的單引號內一定要敲空格
a[10] = '';
char b[10];
b[0] = 'i'; b[1] = ' '; b[2] = 'm'; b[3] = 'i'; b[4] = 's';
//空格字元的單引號內一定要敲空格
b[5] = 's'; b[6] = ' '; b[7] = 'y'; b[8] = 'o'; b[9] = 'u';
//空格字元的單引號內一定要敲空格
char c[] = "i believe you";
char d[] = {'i', ' ', 'l', 'i', 'k', 'e', ' ', 'y', 'o', 'u',''};
//空格字元的單引號內一定要敲空格
char e[] = {'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd'};
//空格字元的單引號內一定要敲空格
char f[] = "上課睡覺覺, 下課打鬧鬧, 考試死翹翹";
char g[10] = "";
printf("a = %sn", a); //輸出字串用%s, 輸出引數必須寫陣列名
printf("b = %sn", b);
printf("c = %sn", c);
printf("d = %sn", d);
printf("e = %sn", e);
printf("f = %sn", f);
printf("g = %sn", g);
return 0;
}
輸出結果是:
a = i love you
b = i miss you燙i love you
c = i believe you
d = i like you
e = Hello World蘨 like you
f = 上課睡覺覺, 下課打鬧鬧, 考試死翹翹
g =
首先要說明的是,這個程式只有在 .cpp 檔案中才能執行,在 .c 檔案中會有很多錯誤。因為我們在前面講過,C89 標準規定變數的定義只能在程式的開頭,或者說定義變數的前面不能有其他非宣告或非定義的語句。而 .cpp 檔案是編寫 C++ 程式的,C++ 向下完全相容 C,而且它對變數定義的位置沒有特殊要求,只要在使用位置之前即可。
陣列 a 是先定義後初始化。一方面與以前講的數值型陣列一樣,先定義後初始化必須一個一個地進行賦值,不能整體賦值;另一方面與以前講的數值型陣列又不一樣,對於字串,先定義後初始化也可以整體賦值,但是要呼叫 strcpy 函數,這點稍後再講。
總之上面這個程式中給陣列 a 一個一個進行初始化的方式很麻煩。而且這樣寫需要注意:前面講過系統會在字串的最後自動新增結束標誌符 '',但是當一個一個賦值時,系統不會自動新增 '',必須手動新增。如果忘記新增,雖然語法上沒有錯誤,但是程式將無法達到我們想要的功能。陣列 b 就是這樣的例子。
此外,空格字元必須要在單引號內“敲”一個空格,不能什麼都不“敲”,什麼都不“敲”就是語法錯誤。也不能多“敲”,因為一個單引號內只能放一個字元,“敲”多個空格就是多個字元了。
陣列b就是最後沒有手動新增 '' 的例子。程式是希望陣列 b 輸出“i miss you”,但輸出結果是“i miss you燙i love you”。原因就是系統沒有在最後新增''。
雖然程式中對陣列 b 的長度進行了限制,即長度為 10,但是由於記憶體單元是連續的,對於字串,系統只要沒有遇到 '',就會認為該字串還沒有結束,就會一直往後找,直到遇到 '' 為止。被找過的記憶體單元都會輸出,從而超出定義的 10 位元組。
陣列 c 是定義時初始化。定義時初始化可以整體賦值。整體賦值有一個明顯的優點——方便。定義時初始化可以不用指定陣列的長度,而先定義後初始化則必須要指定陣列的長度,如陣列 a 和陣列 b。不用指定陣列長度有一個好處:不用人為確定需要多少位元組的記憶體空間,系統會根據初始化的內容自動分配數量正好的記憶體空間。而且對於陣列 c 的寫法系統會自動在最後新增結束標誌符 '',不需要人為新增。
陣列 d 也是定義時初始化,但它既屬於整體賦值,也屬於一個一個賦值。說它是整體賦值是因為不用寫 d[0]、d[1]…而說它是一個一個賦值是因為它把整個句子分成了一個一個的字元。還是陣列 c 的寫法比較方便,而且對於陣列d的寫法系統也不會自動在最後新增結束標誌符 '',必須人為新增。如果忘記新增就會出現與陣列 b 同樣的錯誤。從陣列 e 的輸出結果可以看出這一點。
陣列 f 是儲存漢字,漢字不能像陣列 a 或陣列 d 那樣分開一個一個賦值。因為一個漢字占 2 位元組,若分開賦值,由於一個單引號內只能放一個字元,即一位元組,所以將佔 2 位元組的漢字放進去當然就出錯了。因此如果用字元陣列儲存漢字的話必須整體賦值,即要麼定義時初始化,要麼呼叫 strcpy 函數。
陣列 g 初始化為一對雙引號,表示該字元陣列中 10 個元素的內容都為 ''。下面寫一個程式驗證一下:
# include <stdio.h>
int main(void)
{
char str[3] = "";
str[2] = 'a';
printf("str = %sn", str);
return 0;
}
輸出結果是:
str =
程式中定義了一個長度為 3 的字元陣列,然後給第三個元素賦值為 'a',然後將整個字元陣列輸出。但是輸出結果什麼都沒有,原因就是其直接初始化為一對雙引號,此時字元陣列中所有元素都是 ''。所以雖然第三個元素為 'a',但因為第一個元素為 '',而 '' 是字串的結束標誌符,所以無法輸出。
需要注意的是,使用此種初始化方式時一定要指定陣列的長度,否則預設陣列長度為 1。
總結,字元陣列與前面講的數值陣列有一個很大的區別,即字元陣列可以通過“%s”一次性全部輸出,而數值陣列只能逐個輸出每個元素。