語法書 / AA 競程語法書 下冊 / 第八單元 / 字典序與 strcmp(延伸知識)

8.9 字典序與 strcmp(延伸知識)

整數比大小天經地義,字元比大小是比編號——那兩個字串怎麼比?競程與電腦科學的標準答案:字典序(lexicographic order),顧名思義,就是字典排單詞的方式。

比較 st 的規則:

  1. 把兩個字串靠左對齊,從第 0 格開始逐格比較。
  2. 遇到第一個不一樣的位置:該位置字元(的 ASCII 編號)較小者,整個字串字典序較小。比出勝負,結束。
  3. 一路都一樣,但其中一個先結束:先結束的(較短的)字典序較小——"app" 排在 "apple" 前面。
  4. 長度相同且每格都一樣:兩字串相等

幾個例子(< 代表字典序較小):

"CA"  < "CCD"     ← 第 1 格:'A' < 'C',勝負已定(後面不用看)
"app" < "apple"   ← 前 3 格全同,"app" 先結束
"Z"   < "a"       ← 'Z' 是 90、'a' 是 97:大寫都排在小寫前面!
"10"  < "9"       ← 第 0 格:'1' < '9'。字串的「10」不是數字的 10!

最後兩個例子提醒你:字典序比的是 ASCII 編號,不是人類直覺——大小寫混排時大寫全體優先(8.1 的相對位置),而數字字串按字典序排和按數值排是兩回事

strcmp 比較

C 字串不能用 ==< 直接比(原因見下方 danger),要用 8.8 見過的 strcmp(s, t)

  • s 字典序較小 → 回傳負數
  • 兩字串相等 → 回傳 0
  • s 字典序較大 → 回傳正數

範例程式碼

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

int main() {
    char s[10] = "CA";
    char t[10] = "CCD";
    char u[10] = "CA";
    char v[10] = "CCDEE";

    cout << strcmp(s, t) << '\n';   // s < t:第 1 格 'A' < 'C' → 負數
    cout << strcmp(t, u) << '\n';   // t > u → 正數
    cout << strcmp(s, u) << '\n';   // 相等 → 0
    cout << strcmp(t, v) << '\n';   // 前 3 格同,t 先結束 → t 較小 → 負數

    if (strcmp(s, u) == 0) {
        cout << "s and u are equal" << '\n';
    }
    return 0;
}

執行結果(本站評測環境):

-2
2
0
-69

注意那些非零的值:-22-69——strcmp 只保證正負號,不保證數值(不同環境可能回傳不同的正數/負數;只有「相等回傳 0」是精確保證)。所以判斷式永遠寫成「跟 0 比較」:

if (strcmp(s, t) < 0)  { ... }   // s 字典序較小
if (strcmp(s, t) == 0) { ... }   // 相等
if (strcmp(s, t) > 0)  { ... }   // s 字典序較大

動手試試看:讀入 3 個字串(長度 \le 100),輸出字典序最小的那個。提示:上冊 6.4 找最小值的套路+strcmp 當比較、strcpy 當指派。