8.9 字典序與 strcmp(延伸知識)
整數比大小天經地義,字元比大小是比編號——那兩個字串怎麼比?競程與電腦科學的標準答案:字典序(lexicographic order),顧名思義,就是字典排單詞的方式。
比較 s 和 t 的規則:
- 把兩個字串靠左對齊,從第 0 格開始逐格比較。
- 遇到第一個不一樣的位置:該位置字元(的 ASCII 編號)較小者,整個字串字典序較小。比出勝負,結束。
- 一路都一樣,但其中一個先結束:先結束的(較短的)字典序較小——
"app"排在"apple"前面。 - 長度相同且每格都一樣:兩字串相等。
幾個例子(< 代表字典序較小):
"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
注意那些非零的值:-2、2、-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 當指派。