现在,我们再来了解一下ASCII。
前面我们提到过,字符在计算机中是以数字来保存的。
而字符的本质,其实是一个个图像,如果我们将这些图像和数字对应起来,再传递这些“图像”就比较方便了。
例如,我们规定1表示a,2表示b,一直到26表示z。我们向对方传送you,就只需要传送25,15,21,这3个数字
收到的人再按照我们的约定将数字转换为字符,就可以得到我们所需要的信息了
我们将这种字符和数字对应的规则成为字符编码(Character Encoding)。
我们上面使用的“字符编码”包含了26个拉丁字母,这是一个集合,我们将其称为字符集(Charset)
不同的字符集可以包含不同的字符(如中文,拉丁字母,日语),而对于相同的字符集却可以有不同的字符编码(只要它们的对应规则不同)
显然,谁都可以提出一套和别人不同的自己的编码方案,但是这样也显然会造成混乱,因为不同的对应规则会得到完全不同的字符。(如果你遇到过乱码的情况,那么你应该深有体会)
美国有关的标准化组织就出台了所谓的ASCII编码(American Standard Code for Information Interchange,美国标准信息交换代码),统一规定了上述常用符号用哪些二进制数来表示。一开始这是一个美国的国家标准,然后被国际标准化组织(International Organization for Standardization, ISO)定为国际标准,称为ISO 646标准。
它是目前最通用的(单字节)编码系统,ASCII的长度是1字节,也就是8位,理论上来说最多可以保存256过字符。但是在标准ASCII中只使用后7位,第一位永远为0,因此它只能保存128个字符。看似很少,实际上对于日常英语来说是勉强够用的。
ASCII可以分为两个部分,第一部分叫做控制字符,第二部分是显示字符。
字符不一定都是能直观显示出来的,比如你在打字中经常使用的回车键(请不要认为回车不是一个字符)。它不能显示出来,但是却可以控制显示出来的符号,这也正是这些符号的作用。
控制字符一共有32个,如下表
二进制 | 十进制 | 十六进制 | 缩写/字符 | 意义 |
---|---|---|---|---|
00000000 | 0 | 00 | NUL(null) | 空字符 |
00000001 | 1 | 01 | SOH(start of headling) | 标题开始 |
00000010 | 2 | 02 | STX (start of text) | 正文开始 |
00000011 | 3 | 03 | ETX (end of text) | 正文结束 |
00000100 | 4 | 04 | EOT (end of transmission) | 传输结束 |
00000101 | 5 | 05 | ENQ (enquiry) | 请求 |
00000110 | 6 | 06 | ACK (acknowledge) | 收到通知 |
00000111 | 7 | 07 | BEL (bell) | 响铃 |
00001000 | 8 | 08 | BS (backspace) | 退格 |
00001001 | 9 | 09 | HT (horizontal tab) | 水平制表符 |
00001010 | 10 | 0A | LF (NL line feed, new line) | 换行键 |
00001011 | 11 | 0B | VT (vertical tab) | 垂直制表符 |
00001100 | 12 | 0C | FF (NP form feed, new page) | 换页键 |
00001101 | 13 | 0D | CR (carriage return) | 回车键 |
00001110 | 14 | 0E | SO (shift out) | 不用切换 |
00001111 | 15 | 0F | SI (shift in) | 启用切换 |
00010000 | 16 | 10 | DLE (data link escape) | 数据链路转义 |
00010001 | 17 | 11 | DC1 (device control 1) | 设备控制1 |
00010010 | 18 | 12 | DC2 (device control 2) | 设备控制2 |
00010011 | 19 | 13 | DC3 (device control 3) | 设备控制3 |
00010100 | 20 | 14 | DC4 (device control 4) | 设备控制4 |
00010101 | 21 | 15 | NAK (negative acknowledge) | 拒绝接收 |
00010110 | 22 | 16 | SYN (synchronous idle) | 同步空闲 |
00010111 | 23 | 17 | ETB (end of trans. block) | 传输块结束 |
00011000 | 24 | 18 | CAN (cancel) | 取消 |
00011001 | 25 | 19 | EM (end of medium) | 介质中断 |
00011010 | 26 | 1A | SUB (substitute) | 替补 |
00011011 | 27 | 1B | ESC (escape) | 溢出 |
00011100 | 28 | 1C | FS (file separator) | 文件分割符 |
00011101 | 29 | 1D | GS (group separator) | 分组符 |
00011110 | 30 | 1E | RS (record separator) | 记录分离符 |
00011111 | 31 | 1F | US (unit separator) | 单元分隔符 |
我们不用去背那些字符的ASCII是多少。
有些符号一定让你感到很奇怪,比如“传输开始”,这和计算机好像搭不上边啊。
这是因为ASCII不仅仅是为计算机之间通信而设计,在计算机与打印机之间传递信息时同样也使用ASCII(至少在以前是这样)
而这些控制字符,大多是用于打印机进行定位的
在控制字符之后,就是可以显示出来的字符了。它们是你可以直接看到的有形状的图像。
二进制 | 十进制 | 十六进制 | 字符 | 含义 |
---|---|---|---|---|
100000 | 32 | 20 | (space) | 空格 |
100001 | 33 | 21 | ! | |
100010 | 34 | 22 | " | |
100011 | 35 | 23 | # | |
100100 | 36 | 24 | $ | |
100101 | 37 | 25 | % | |
100110 | 38 | 26 | & | |
100111 | 39 | 27 | ' | |
101000 | 40 | 28 | ( | |
101001 | 41 | 29 | ) | |
101010 | 42 | 2A | * | |
101011 | 43 | 2B | + | |
101100 | 44 | 2C | , | |
101101 | 45 | 2D | - | |
101110 | 46 | 2E | . | |
101111 | 47 | 2F | / | |
110000 | 48 | 30 | 0 | |
110001 | 49 | 31 | 1 | |
110010 | 50 | 32 | 2 | |
110011 | 51 | 33 | 3 | |
110100 | 52 | 34 | 4 | |
110101 | 53 | 35 | 5 | |
110110 | 54 | 36 | 6 | |
110111 | 55 | 37 | 7 | |
111000 | 56 | 38 | 8 | |
111001 | 57 | 39 | 9 | |
111010 | 58 | 3A | : | |
111011 | 59 | 3B | ; | |
111100 | 60 | 3C | < | |
111101 | 61 | 3D | = | |
111110 | 62 | 3E | > | |
111111 | 63 | 3F | ? | |
1000000 | 64 | 40 | @ | |
1000001 | 65 | 41 | A | |
1000010 | 66 | 42 | B | |
1000011 | 67 | 43 | C | |
1000100 | 68 | 44 | D | |
1000101 | 69 | 45 | E | |
1000110 | 70 | 46 | F | |
1000111 | 71 | 47 | G | |
1001000 | 72 | 48 | H | |
1001001 | 73 | 49 | I | |
1001010 | 74 | 4A | J | |
1001011 | 75 | 4B | K | |
1001100 | 76 | 4C | L | |
1001101 | 77 | 4D | M | |
1001110 | 78 | 4E | N | |
1001111 | 79 | 4F | O | |
1010000 | 80 | 50 | P | |
1010001 | 81 | 51 | Q | |
1010010 | 82 | 52 | R | |
1010011 | 83 | 53 | S | |
1010100 | 84 | 54 | T | |
1010101 | 85 | 55 | U | |
1010110 | 86 | 56 | V | |
1010111 | 87 | 57 | W | |
1011000 | 88 | 58 | X | |
1011001 | 89 | 59 | Y | |
1011010 | 90 | 5A | Z | |
1011011 | 91 | 5B | [ | |
1011100 | 92 | 5C | \ | |
1011101 | 93 | 5D | ] | |
1011110 | 94 | 5E | ^ | |
1011111 | 95 | 5F | _ | |
1100000 | 96 | 60 | ` | |
1100001 | 97 | 61 | a | |
1100010 | 98 | 62 | b | |
1100011 | 99 | 63 | c | |
1100100 | 100 | 64 | d | |
1100101 | 101 | 65 | e | |
1100110 | 102 | 66 | f | |
1100111 | 103 | 67 | g | |
1101000 | 104 | 68 | h | |
1101001 | 105 | 69 | i | |
1101010 | 106 | 6A | j | |
1101011 | 107 | 6B | k | |
1101100 | 108 | 6C | l | |
1101101 | 109 | 6D | m | |
1101110 | 110 | 6E | n | |
1101111 | 111 | 6F | o | |
1110000 | 112 | 70 | p | |
1110001 | 113 | 71 | q | |
1110010 | 114 | 72 | r | |
1110011 | 115 | 73 | s | |
1110100 | 116 | 74 | t | |
1110101 | 117 | 75 | u | |
1110110 | 118 | 76 | v | |
1110111 | 119 | 77 | w | |
1111000 | 120 | 78 | x | |
1111001 | 121 | 79 | y | |
1111010 | 122 | 7A | z | |
1111011 | 123 | 7B | { | |
1111100 | 124 | 7C | | | |
1111101 | 125 | 7D | } | |
1111110 | 126 | 7E | ~ | |
1111111 | 127 | 7F | DEL (delete) | 删除 |
其实最后一个字符也是不可显示的,这个字符也就是delete键输入的结果。
很明显,0-9,a-z,A-Z都是按照顺序排好的,后面我们便可以看到这样设计的好处。
既然已经认识了ASCII,下面我们就来看看,怎么让变量保存字符。
上面说道过,你不需要记住字符对应的ASCII(你也记不住),因为我们可以直接使用这些字符,他们就是数字。
(这里有一点需要强调的,有些初学者认为ASCII字符和数字间需要转换,这种认识是错误的,要知道ASCII只是一种字符和数字的对应关系,字母a的ASCII是97,那么在显示时如果将97作为一个字符,那么就会显示出字母a,如果作为数字,就会显示数字97,在计算机看来,ASCII字符和数字是没有任何区别的)
c语言中在单引号中括起来的数据就是一个字符。比如’a’,他的值就是97。
注意,’0’是不等于0的,’0’的值是“0”这个字符所对应的ASCII码,也就是48.
对变量赋值也很简单,就像数字一样使用
char ch = ‘a’;//ch的值是97,也就是a字符的ascii
ch = ch – 32;//ch的值变成了65,也就是大写A的ASCII
这样,如果再(以字符方式)输出ch,你会发现是A而不是a了
在你开始庆幸不需要背ASCII表之前,我们先来看一个问题。那就是如何表示回车?
这还不简单嘛,用 ‘ ‘ 包括起来嘛!
‘
‘
这样写?这样就错了,编译器会将你输入的回车当作空白符号,从而将两个”分开来看!
怎么办!!!
当然有办法
这时候就需要一种叫做“转义字符”的东西。因为有些字符在编程中会引起歧义,或者是这种字符键盘根本打不出来,人们就给他起了个“别名”
转义字符以“\”开始,后面跟一个字母或数字,\表示后面的字符失去了它本来的意思
但是这中间也有特殊情况,比如\这个字符。因为' '之间只能表示一个字符,所以写成'\'并不会引起歧义,所以这种写法是正确的。但是在字符串中(使用""包括),由于字符数量不能确定,就不能这样写("\"这种写法是错误的,第一个双引号被作为字符串的开始标志,随后的\和"被视作为一个转义字符,它代表的是字符",而不是字符串结束的标志)。 注意在表的最后两行,有一个\ddd 和 \xhh。这是ASCII码的两种特殊表示形式。如果想用八进制ASCII码表示字符,可以在八进制数前面加上 \ ,然后用单引号引起来。例如: beep = '\007'; 打头的那些0可以省略,也就是说,写成 '\07' 或者 '\7' 都一样。无论有没有打头的0 ,7 都会被当成八进制数处理。 至于16进制,则需要用x开头。例如: l = '\xa'; 此外,尽管 '\n'和 '\xa' ,'\a' 和 '\007' 是等价的,但是我们应该尽可能使用 '\n' 和 '\a',而不要用 '\xa' 和 '\007' 。这是因为前者更直观,否则你还要翻表才能知道它代表什么字符。 当我们在字符串中使用转移字符的时候,需要注意。如果反斜杠后面的字符不能构成转义字符。反斜杠将被忽略,如 "ab\cde\fg" 它和"abcde\fg"等价 最后我们来学习字符的输出, 我们可以使用putc来输出一个字符,使用puts来输出一个字符串
#include <stdio.h> int main(void) { char a = 'a'; putc(a); putc('\n'); a = a - 32; putc(a); puts("\nHello!\n"); return 0; }请编译并运行此程序,体会本文中所学到的知识。