beta

CS50 听课笔记:0. ASCII

CS50 全名 Introduction to Computer Science,是哈佛大学的一门非常著名的 CS 入门课程。这门课在 edX 上以 CS50x 的代号供人免费学习,试听了一下觉得非常有趣,决定将学到的东西稍作记录以备不时之需。


Nate Hardison 介绍 ASCII 的这个视频清晰地解释了设计 ASCII 的原因和方法。

计算机以二进制的形式存储数据,对于数学运算来说只需要通过进制转换就能很好地在二进制环境下工作,但如果需要表示文本、图片和音视频等数据,则需要一些规范化的通用编码方式来保证这些二进制编码在不同的计算机上都能得到一致的支持。ASCII 的名字正是由此而来:American Standard Code for Information Interchange

标准 ASCII 使用 7 个二进制位来表示一个字符,从 0000000 到 1111111,对应十进制数字 0 到 127,一共可以表示 128 个字符。其中大小写字符有 52 个,数字 10 个,标点符号一共 32 个,空白符 1 个,剩下的 33 个字符称为控制字符。控制字符最初用于控制光标在终端中的工作方式,例如 0001000 表示退格,记作 BS(Backspace);0001101 表示回车,记作 CR(Carriage Return)。

有两个特殊的控制字符值得注意,分别是 0000000 所表示的空字符 NUL,和 1111111 所表示的删除符 DEL。要理解这两个特殊的字符,就必须了解 60 年代左右流行的数据存储方式,也就是纸带,人们在纸带上横向打孔来记录二进制数据,不打孔表示该位为 0,打孔则表示 1。而 0000000 和 1111111 则是两种极端,一个是一个孔也不打 — — 这个位置上没有数据 — — 另一个是打满一排孔 — — 这个位置上的数据作废。NUL 和 DEL 两个字符由此而来。

26 个英文字母分别以大写和小写的形式在 ASCII 码表中存在了两次,大写的 ASCII 码对应的十进制数字是 65 到 90,小写则是 97 到 122,两段数字并没有连接在一起,而是空出了 6 个字符的距离。这样安排的原因可以从编码的二进制表达上找到:

1
2
3
4
5
6
7
Character | Binary | Decimal
-----------|---------|---------
A | 1000001 | 65
B | 1000010 | 66
C | 1000011 | 67
... | ... | ...
Z | 1011010 | 90

可以看到,大写字母的二进制表达是首位为 1,第三位至末位从 00001 开始按序增长。再来看小写字母:

1
2
3
4
5
6
7
Character | Binary | Decimal
-----------|---------|---------
a | 1100001 | 97
b | 1100010 | 98
c | 1100011 | 99
... | ... | ...
z | 1111010 | 122

与大写字母相比,小写字母 ASCII 码的二进制表示除了第二位设为 1 之外,其余各位没有任何区别,因此将大小写字母相互转换只需要将第二位在 0 和 1 之间变换即可。

数字 0 到 9 在 ASCII 中的位置是 48 到 57,也设计得很巧妙:

1
2
3
4
5
6
7
Character | Binary | Decimal
-----------|---------|---------
0 | 0110000 | 48
1 | 0110001 | 49
2 | 0110010 | 50
... | ... | ...
9 | 0111001 | 57

可以看到,数字的二进制表示以 011 开头,后四位正好是二进制下的这九个数字自身。