Professional Documents
Culture Documents
演算法筆記 - Code
演算法筆記 - Code
Code
Code
資訊替換成代號,以代號記載資訊。這些代號稱做「碼」。
99,3qㄋ姑力i讀豬,偶會+ Uㄉ!
口以ㄇ?ㄅ口以!
(゚д゚)
程式設計就是將「電腦的工作資訊」替換成「程式碼」。
int main() {
int n = 1 + 1;
return 0;
}
數學式子也是一種碼。大部分人類都不清楚原本的資訊為何。
eiπ + 1 = 0
011000100110100101101110011000010111001001111001
⠃ ⠗ ⠁ ⠊ ⠇ ⠇ ⠑
http://www.csie.ntnu.edu.tw/~u91029/Code.html 1/10
3/10/2018 演算法筆記 - Code
「外星人編碼」,一根棒子,精準地刻一刀,就能記載世上所有
知識。找到刻記的高度,占筷子全長的幾分之幾,計算小數點後面所
有位數,就得到了碼。無論要談什麼,只要刻一刀就好。
UVa 508
Encode / Decode
「編碼」,資訊轉碼。「解碼」,碼轉資訊。
編碼 「cat」--->「011000110110000101110100」
解碼 「cat」<---「011000110110000101110100」
資訊和碼最好一一對應,讓編碼與解碼不生歧義。只要知道每種
碼的意義,就能獲知原本的資訊。火星文就是一種很不好的碼。
文字編碼
文字、聲音、圖像、動作、感受,通通可以編碼。以下我們只討
論文字編碼 ── 最簡單、最基礎的編碼。
ASCII
英文字母a變成二元碼01100001,符號=變成二元碼00111101。
繁體中文變成二元碼,是參照現時流行的「萬國碼 Unicode 」
或者逐漸落寞的「大五碼 Big5 」。
Unicode
中文字「大」變成二元碼0101100100100111。(十六進位數字5927)
Big5
中文字「大」變成二元碼1010010001101010。(十六進位數字a46a)
GB2312
中文字「大」變成二元碼1011010011110011。(十六進位數字b4f3)
文字編碼是以字符為基本單位,從頭到尾掃描。
http://www.csie.ntnu.edu.tw/~u91029/Code.html 2/10
3/10/2018 演算法筆記 - Code
編碼。從頭到尾掃描文字,每當發現一段文字有其對應的碼,就
馬上換成碼。持續掃描下去,讓碼越接越長。
編碼cat
掃描c,換成01100011
掃描a,換成01100001
掃描t,換成01110100
最後得到011000110110000101110100
解碼。從頭到尾掃描碼,每當發現一段碼有其對應的文字,就馬
上換成文字。持續掃描下去,讓文字越接越長。
解碼011000110110000101110100
掃描0
掃描1
掃描1
……
掃描第8個位元1,發現01100011是字母c的碼,換成c
……
掃描第16個位元1,發現01100001是字母a的碼,換成a
……
掃描第24個位元0,發現01110100是字母t的碼,換成t
最後得到cat
設計碼,有兩種策略。
「固定長度編碼」令每個字符的碼一樣長。比如 ASCII 。
A 00001
B 00010
C 00011
D 00100
⋮ ⋮
Z 11010
「可變長度編碼」令各個字符的碼不等長。比如 UTF-8 。
A 000
B 001
C 0100
D 0101
⋮ ⋮
Z 11111
當兩個碼相同,解碼將產生歧義。
A 00001
B 00010
C 00001
解碼00001...
掃描前五個位元,得到00001,可能是A,也可能是B。
當一個碼是另一個碼的開頭,解碼將產生歧義。
A 011
B 0111
C 00111
解碼011111...
掃描前三個位元,得到011,可能是A。
掃描前四個位元,得到0111,也可能是B。
碼的長度
ASCII
ASCII Table
NUL 00000000 00100000 @ 01000000 ` 01100000
SOH 00000001 ! 00100001 A 01000001 a 01100001
STX 00000010 " 00100010 B 01000010 b 01100010
ETX 00000011 # 00100011 C 01000011 c 01100011
EOT 00000100 $ 00100100 D 01000100 d 01100100
ENQ 00000101 % 00100101 E 01000101 e 01100101
ACK 00000110 & 00100110 F 01000110 f 01100110
BEL 00000111 ' 00100111 G 01000111 g 01100111
BS 00001000 ( 00101000 H 01001000 h 01101000
HT 00001001 ) 00101001 I 01001001 i 01101001
LF 00001010 * 00101010 J 01001010 j 01101010
VT 00001011 + 00101011 K 01001011 k 01101011
FF 00001100 , 00101100 L 01001100 l 01101100
CR 00001101 - 00101101 M 01001101 m 01101101
SO 00001110 . 00101110 N 01001110 n 01101110
SI 00001111 / 00101111 O 01001111 o 01101111
DLE 00010000 0 00110000 P 01010000 p 01110000
DC1 00010001 1 00110001 Q 01010001 q 01110001
DC2 00010010 2 00110010 R 01010010 r 01110010
DC3 00010011 3 00110011 S 01010011 s 01110011
DC4 00010100 4 00110100 T 01010100 t 01110100
NAK 00010101 5 00110101 U 01010101 u 01110101
SYN 00010110 6 00110110 V 01010110 v 01110110
ETB 00010111 7 00110111 W 01010111 w 01110111
CAN 00011000 8 00111000 X 01011000 x 01111000
EM 00011001 9 00111001 Y 01011001 y 01111001
SUB 00011010 : 00111010 Z 01011010 z 01111010
ESC 00011011 ; 00111011 [ 01011011 { 01111011
FS 00011100 < 00111100 \ 01011100 | 01111100
GS 00011101 = 00111101 ] 01011101 } 01111101
RS 00011110 > 00111110 ^ 01011110 ~ 01111110
US 00011111 ? 00111111 _ 01011111 DEL 01111111
註:有框框的是特殊字元,沒有實際的外型,無法顯示在螢幕上。
註:第二排第一個是空白鍵。
http://www.csie.ntnu.edu.tw/~u91029/Code.html 4/10
3/10/2018 演算法筆記 - Code
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+----------------------------------------------------------------
0 | NUL SOH STX ETX EOT ENQ ACK BEL BS HT LF VT FF CR SO SI
16 | DLE DC1 DC2 DC3 DC4 NAK SYN ETB CAN EM SUB ESC FS GS RS US
32 | ! " # $ % & ' ( ) * + , - . /
48 | 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
64 | @ A B C D E F G H I J K L M N O
80 | P Q R S T U V W X Y Z [ \ ] ^ _
96 | ` a b c d e f g h i j k l m n o
112| p q r s t u v w x y z { | } ~ DEL
128 種字元當中,有些字元沒有實際的外型,通常作為特殊用
途。例如編號 0 號的字元,在 C 程式語言當中用來當作字串的結尾
符號。
大部分的字元,在鍵盤上面都有對應的按鍵,例如 qwe123`-=
等等。少部分的字元,則沒有對應的按鍵,必須預先按住 shift 或者
ctrl 之後才能輸入。
ASCII 有英文字母、標點符號、數字、四則運算符號等等,卻沒
有中文字、注音符號、微積分符號、可愛小圖示之類的。這是因為當
初設計 ASCII 的人,從未想過電腦會普及遍佈全世界,所以只設計
了一些簡易的符號。
1 byte
寫程式處理 ASCII
任何一本程式語言的書籍一定都有介紹,此處就不贅述了。
1. void process_ASCII()
2. {
3. // 在電腦螢幕上顯示字元
4. cout << "Hello World!";
5.
6. // 用while迴圈不斷擷取鍵盤輸入的字元。
7. // cin.get()會暫停執行程式,
8. // 直到使用者輸入之後,才回傳字元,繼續執行程式。
http://www.csie.ntnu.edu.tw/~u91029/Code.html 5/10
3/10/2018 演算法筆記 - Code
9. char c;
10. while (c = cin.get())
11. {
12. // 在電腦螢幕上顯示字元
13. cout << c;
14.
15. // 小寫字母改成大寫字母
16. if (c >= 'a' && c <= 'z')
17. cout << c - 'a' + 'A';
18. }
19. }
Big5
Code Page
ASCII 只有英文字,沒有其他文字。世界各國為了讓電腦處理自
家文字,以及處理原本就有的英文(以便讓電腦正常運作),於是世
界各國皆以 ASCII 作為基礎,各自創造自己的碼以及編碼解碼方
式,稱作「內碼表」。
同樣的碼,套用不同的內碼表,解碼出來的文字就完全不同!想
要處理其他國家的檔案文件、網站頁面、軟體程式,就必須使用該國
的內碼表!例如瀏覽日本網站就得換日文內碼表,閱讀西歐文件就得
換西歐文字內碼表。
Big5
寫程式處理 Big5
我尚未找到好讀的資料,請讀者各顯神通。
http://libai.math.ncu.edu.tw/~shann/Chinese/big5.html
Big5 的瑕疵:他國無法執行軟體
直到現今,大家還是習慣使用自家的內碼表編寫程式。
採用 Big5 製作軟體,凡出現繁體中文字,在繁體中文作業系統
會顯示正確文字,在其他語言作業系統則會顯示亂碼。甚至當 Big5
http://www.csie.ntnu.edu.tw/~u91029/Code.html 6/10
3/10/2018 演算法筆記 - Code
與他國內碼表的解碼規則差太多時,解讀長度不一致,讀得太多太
少,將造成程式指令大亂、程式當機。
相對地,世界上所有國家都有這樣的問題。為了解決這個問題,
微軟設計了 AppLocale 軟體,幫忙套用正確的內碼表。日文電腦遊
戲玩家一定聽過 AppLocale 。
Big5 的瑕疵:無法同時顯示多國文字
採用 Big5 製作文件,只能同時看到英文字和繁體中文字,無法
看到其他文字。為了同時看到其他文字,熱心人士推動了「 Unicode
補完計劃」,把簡體中文字、日文字硬是補進 Big5 裡面。靈感來自
於當時正在發展的 Unicode 。
Big5 的瑕疵:許功蓋問題
1. // 執行成功
2. cout << "OK!"; // 這行將接續上一行,變成註解,不會執行。
Unicode
Unicode
替世界上的每一個文字暨符號,設定獨一無二的編號。簡單來
說,就是把世上所有字符一一編號。
建立 Unicode 是一件浩大的工程,人類從二十幾年前就開始動
工,迄今已經接近完成,也相當普及了。詳細的發展歷程可以參考維
基百科: http://zh.wikipedia.org/wiki/Unicode 。
編號大體上是這樣安排:
前128個編號,與ASCII完全相同。
再來到前65536 = 2byte個編號,是世界各國常見文字。
再來到前4294967296 = 4byte個編號,是世界各國罕見文字。
編號通常使用十六進位表示法,開頭加上 U+ 。
U+0041 <-> A
U+FF21 <-> A
U+FF1F <-> ?
http://www.csie.ntnu.edu.tw/~u91029/Code.html 7/10
3/10/2018 演算法筆記 - Code
U+00E6 <-> æ
U+597D <-> 好
U+3042 <-> あ
U+2260 <-> ≠
U+32A3 <-> ㊣
U+262F <-> ☯
U+1F513 <->
U+2019F <-> 𠆟
U+1F323 <->
字型未包含的字元,則顯示成一個框框,裡面寫出編號。
UTF-8
簡易說明
UTF-8:http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.htm
詳細規格
UTF-8:http://tools.ietf.org/html/rfc3629#page-4
UTF-16:http://tools.ietf.org/html/rfc2781#section-2
寫程式處理 UTF-8
一、IDE必須能夠顯示UTF-8格式的程式碼。
二、Compiler必須能夠編譯UTF-8格式的程式碼。
三、C/C++規格書必須定義UTF-8的變數、函式庫,Compiler也必須支援。
四、OS必須能夠把系統資訊以UTF-8的格式呈現,像是目錄名稱、檔案名稱。
五、Console必須能夠顯示UTF-8格式的文字。
http://www.cplusplus.com/reference/codecvt/
Base64
Base64
https://zh.wikipedia.org/wiki/Base64
先前是把字符變成二元碼。此處則是角色互換,把二元碼變成可
見字符。
http://www.csie.ntnu.edu.tw/~u91029/Code.html 8/10
3/10/2018 演算法筆記 - Code
Base64 1. void encode(unsigned char* in, int n,
2. unsigned char* out, int& m)
3. {
4. static char encode_table[] =
5. "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef"
6. "ghijklmnopqrstuvwxyz0123456789+/";
7.
8. int i = 0, j = 0;
9. while (i < n)
10. {
11. unsigned int x = 0;
12. if (i < n) x |= (unsigned int)in[i++] << 16;
13. if (i < n) x |= (unsigned int)in[i++] << 8;
14. if (i < n) x |= (unsigned int)in[i++];
15. out[j++] = encode_table[(x>>18) & 0x3f];
16. out[j++] = encode_table[(x>>12) & 0x3f];
17. out[j++] = encode_table[(x>>6) & 0x3f];
18. out[j++] = encode_table[ x & 0x3f];
19. }
20. if (n % 3 == 2) out[j++] = '=';
21. if (n % 3 == 1) out[j++] = '=';
22. // m = 4 * ((n + 2) / 3);
23. m = j;
24. }
25.
26. void decode(unsigned char* in, int n,
27. unsigned char* out, int& m)
28. {
29. static unsigned int decode_table[256];
30. for (int i='A'; i<='Z'; i++) decode_table[i] = i -
'A';
31. for (int i='a'; i<='z'; i++) decode_table[i] = i -
'a' + 26;
32. for (int i='0'; i<='9'; i++) decode_table[i] = i -
'0' + 52;
33. decode_table['+'] = 62;
34. decode_table['/'] = 63;
35. decode_table['='] = 0;
36.
37. m = n / 4 * 3;
38. if (in[n-1] == '=') m--;
39. if (in[n-2] == '=') m--;
40.
41. int i = 0, j = 0;
42. while (i < n)
http://www.csie.ntnu.edu.tw/~u91029/Code.html 9/10
3/10/2018 演算法筆記 - Code
43. {
44. unsigned int x = 0;
45. x |= decode_table[in[i++]] << 18;
46. x |= decode_table[in[i++]] << 12;
47. x |= decode_table[in[i++]] << 6;
48. x |= decode_table[in[i++]];
49. if (j < m) out[j++] = (x>>16) & 0xff;
50. if (j < m) out[j++] = (x>>8) & 0xff;
51. if (j < m) out[j++] = x & 0xff;
52. }
53. }
http://www.csie.ntnu.edu.tw/~u91029/Code.html 10/10