語法書 / AA 競程語法書 下冊 / 第八單元 / 字元的本質:ASCII 編碼

8.1 字元的本質:ASCII 編碼

圖 8-1:ASCII 編碼的三大區段

上冊 2.4 學過:char 型態存單一個字元,佔 1 位元組,用單引號寫('A''5''+')。當時留了一句話:「每個字元背後都有一個數字」——現在正式把這件事說完。

電腦的記憶體裡只有數字,沒有「字母」這種東西。所以電腦存字元的方法很直接:幫每個字元編一個號碼,存字元=存它的號碼。這張「字元 ↔ 號碼」的對照表就是 ASCII 編碼(American Standard Code for Information Interchange),它規定了編號 0 \sim 127 各對應到什麼字元。

128 個編號分成兩類:

  • 可顯示字元(printable characters):編號 32 \sim 126,共 95 個——就是 2.4 數過的「大小寫字母 52 +數字 10 +標點符號 32 +空格 1」。空格(編號 32)雖然看不見,也算可顯示字元。
  • 控制字元(control characters):編號 0 \sim 31127,負責「動作」而不是「圖案」——最常見的是編號 10 的換行 '\n' 和編號 9 的 Tab '\t'(上冊 2.4 的跳脫字元,就是用來寫出這些看不見的字元)。

三大區段:唯一需要記的重點

整張 ASCII 表不用背。競程裡其他字元也都會出現(例如網格題的 #.、各種標點),但那些用到再查、直接拿字元比對就好;出場頻率最高、值得把編號規律記熟的,是這三個區段

字元範圍 ASCII 編號 個數 重點
'0' ~ '9' 48 \sim 57 10 個 數字字元,編號連續遞增
'A' ~ 'Z' 65 \sim 90 26 個 大寫字母,編號連續遞增
'a' ~ 'z' 97 \sim 122 26 個 小寫字母,編號連續遞增

三件事比編號本身更重要:

  1. 區段內連續'B' 的編號恰是 'A'1'7' 恰是 '0'7。這是下一節所有轉換技巧的地基。
  2. 區段的相對位置:數字 < 大寫 < 小寫。特別注意小寫字母的編號比大寫大——'a'97)比 'Z'90)還大。
  3. 大小寫的固定差距:同一個字母的小寫編號比大寫恰好32'a' = 97 = 65 + 32)。

編號實在忘了,回到本節這張表查就好;「連續」和「相對位置」這兩件事,才是需要放進腦子裡的。

範例程式碼

字元的比較,比的其實就是 ASCII 編號——這也解釋了 6.6 說「字元可以直接用 <> 比較」的原因:

#include <iostream>
using namespace std;

int main() {
    cout << ('A' < 'B') << '\n';   // 1:比的是編號,65 < 66
    cout << ('5' < '9') << '\n';   // 1:數字字元也按編號排,53 < 57
    cout << ('a' < 'A') << '\n';   // 0:小寫編號比大寫「大」,97 < 65 不成立
    return 0;
}

執行結果:

1
1
0

第三行是很多人的直覺盲點:字典裡 a 排在最前面,但在 ASCII 裡 'a''Z' 大。之後遇到「把大小寫混在一起排序」的題目,這件事會決定答案的順序。

動手試試看:先用三大區段表下面三個比較的結果,再寫程式驗證:'0' < 'A''Z' < 'a''z' < '{'(最後一個超出三大區段,印出 (int)'{' 看看它的編號是多少)。