語法書 / AA 競程語法書 下冊 / 第八單元 / C 語言字串:帶結尾記號的字元陣列

8.6 C 語言字串:帶結尾記號的字元陣列

圖 8-2:C 字串的記憶體佈局

從這一節開始處理「一整串文字」——字串(string)。習慣上用雙引號描述字串內容:"abc""I love AACPSCHOOL"。其實你從第一支程式就在用它:cout << "Hello World" 裡的那段就是字串。

上冊 6.6 已經用字元陣列存過一串字,但當時有個不太自然的地方:題目得先告訴你長度 n,你才知道要讀幾個字、之後的處理要跑到哪。真實世界的字串(還有很多題目)不會附長度——那電腦怎麼知道一個字串到哪裡結束?

C 語言想出的辦法很簡單,C++ 也照著用到今天(名字就是這樣來的:C 語言字串,簡稱 C 字串)。做法只有兩步:

  1. 把字串的所有字元按順序放進字元陣列(連續的記憶體,上冊 6.1 學過)。
  2. 在最後一個字元的下一格放一個結尾記號空字元(null character)'\0'——ASCII 編號 0 的那個字元。

長度不用另外記——從頭開始走,撞到 '\0' 就是結束。陣列開多大不重要,'\0' 的位置才決定字串多長。

char s[10] = "abc";

索引:   0    1    2    3    4   ...   9
內容:  'a'  'b'  'c'  '\0' '\0' ... '\0'    ← 字串是前 3 格,s[3] 的 '\0' 是結尾記號

(後面幾格也是 '\0',是上冊 6.5「初始化沒給到的自動補 0」的老規則。之後若改用 cin >> s 讀進來,'\0' 後面的格子留著什麼都有可能——反正一切以第一個 '\0' 為準,後面是什麼沒人在乎。)

三個容易搞混的字元,趁現在分清楚:

寫法 ASCII 編號 是什麼
'\0' 0 空字元——C 字串的結尾記號,看不見
'0' 48 數字「零」的字元,看得見
' ' 32 空格,看不見但佔一格

雙引號字面常數,其實就是 C 字串

寫在程式裡的 "abc",編譯器會把它做成一個 C 字串:三個字母+自動附上的 '\0',共佔 4 個位元組。可以用 sizeof 驗證(上冊 2.2 的老朋友):

範例程式碼

#include <iostream>
using namespace std;

int main() {
    char s[10] = "abc";            // 前 3 格是 a b c,第 3 格之後補 '\0'

    cout << s << '\n';             // cout 遇到字元陣列:從頭印到 '\0' 為止
    cout << s[0] << s[1] << '\n';  // 也可以照舊當一般陣列逐格存取
    cout << (int)s[3] << '\n';     // 隱藏在結尾的 '\0',編號是 0
    cout << sizeof("abc") << '\n'; // 字面常數佔 4 位元組:3 個字母 + 1 個 '\0'
    return 0;
}

執行結果:

abc
ab
0
4

第一行是新魔法:cout << 一個字元陣列,會把整個字串一路印到 '\0' 前為止——不用自己寫迴圈。這也是為什麼結尾記號如此重要:沒有 '\0'cout 不知道在哪停下來。

動手試試看:把範例程式碼的 "abc" 換成空字串 "",猜猜 cout << ssizeof("") 各是什麼,再執行驗證(提示:空字串也有 '\0')。