語法書 / AA 競程語法書 下冊 / 第十單元 / string:更好用的字串型態

10.7 string:更好用的字串型態

8.6 學 C 字串時說過,C++ 準備了一個更方便的字串型態——現在正式登場。string 是專門裝字元序列的容器,可以想成「裝 char 的 vector」再加上一整套字串專屬功能。它定義在 <string> 裡。

宣告與初始化

string a;                  // 空字串
string b = "AACPSCHOOL";   // 用字面常數初始化
string c = b;              // 複製另一個字串(跟 vector 一樣是完整複製)
string d(5, 'A');          // 5 個 'A':"AAAAA"
char cs[] = "hello";
string e = cs;             // C 字串也能直接變成 string

讀入與輸出

cin >> s 的規則跟 8.7 讀 C 字串一模一樣:跳過空白換行,讀一個「單詞」;cout << s 整串印出;搭配上冊 4.8 的 EOF 模式 while (cin >> s) 也照舊。但用起來的感覺完全不同:

#include <iostream>
#include <string>
#include <cctype>
using namespace std;

int main() {
    string s;                      // 不用宣告大小!
    cin >> s;                      // 跟 8.7 一樣:跳過空白,讀一個單詞
    cout << s.size() << '\n';      // 長度直接問,不用數 '\0'
    s[0] = toupper(s[0]);          // s[i] 是 char:第八單元的工具全部適用
    cout << s << '\n';
    return 0;
}

執行結果(輸入 hello):

5
Hello

s[i] 拿到的就是 char——第八單元的所有本事(c - '0'isdigittoupper……)在 string 身上全部適用。

跟 C 字串比一比

事情 C 字串(8.68.8 string
宣告 char s[105];(先猜上限,幫 '\0' 留位) string s;(大小自動長)
長度 strlen(s)O(n),得先存變數) s.size()O(1)
複製 strcpy(t, s) t = s
比較 strcmp(s, t) == 0 s == ts < t
串接 strcat(t, s) t += s

三大解放:不用管 '\0'不用預先猜大小=== 直接用(string 是容器,享有 10.6 那套待遇)。C 字串還是會出現在別人的程式碼和教材裡,看得懂即可;自己寫,以後一律 string。

string 的陣列

跟 vector 一樣,string 也能宣告成陣列——8.10 的字元網格從此換個活法,一格住一整列:

#include <iostream>
#include <string>
using namespace std;

const int MAX_H = 105;
string g[MAX_H];               // string 的陣列:一格住一整列

int main() {
    int h, w;
    cin >> h >> w;
    for (int i = 0; i < h; i++) {
        cin >> g[i];           // 一次讀一整列,不用煩惱 '\0'
    }

    int cnt = 0;
    for (int i = 0; i < h; i++) {
        for (int j = 0; j < w; j++) {
            if (g[i][j] == '#') cnt++;
        }
    }
    cout << cnt << '\n';
    return 0;
}

執行結果(輸入 2 3#.#..#):

3

8.10 的範例是同一個任務——但第二維多開一格、'\0' 住哪的煩惱,全部消失了。想連列數都不固定,vector<string> 也隨時候教。

動手試試看:解掉反向字串序列——把「string 的陣列」實際用起來:收下一串字串、反向處理後交回,函式參數正是 const vector<string>&10.6 傳參考的實戰)。