2.5、ASCII

By | 2015年1月2日

现在,我们再来了解一下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个,如下表

二进制十进制十六进制缩写/字符意义
00000000000NUL(null)空字符
00000001101SOH(start of headling)标题开始
00000010202STX (start of text)正文开始
00000011303ETX (end of text)正文结束
00000100404EOT (end of transmission)传输结束
00000101505ENQ (enquiry)请求
00000110606ACK (acknowledge)收到通知
00000111707BEL (bell)响铃
00001000808BS (backspace)退格
00001001909HT (horizontal tab)水平制表符
00001010100ALF (NL line feed, new line)换行键
00001011110BVT (vertical tab)垂直制表符
00001100120CFF (NP form feed, new page)换页键
00001101130DCR (carriage return)回车键
00001110140ESO (shift out)不用切换
00001111150FSI (shift in)启用切换
000100001610DLE (data link escape)数据链路转义
000100011711DC1 (device control 1)设备控制1
000100101812DC2 (device control 2)设备控制2
000100111913DC3 (device control 3)设备控制3
000101002014DC4 (device control 4)设备控制4
000101012115NAK (negative acknowledge)拒绝接收
000101102216SYN (synchronous idle)同步空闲
000101112317ETB (end of trans. block)传输块结束
000110002418CAN (cancel)取消
000110012519EM (end of medium)介质中断
00011010261ASUB (substitute)替补
00011011271BESC (escape)溢出
00011100281CFS (file separator)文件分割符
00011101291DGS (group separator)分组符
00011110301ERS (record separator)记录分离符
00011111311FUS (unit separator)单元分隔符

我们不用去背那些字符的ASCII是多少。

有些符号一定让你感到很奇怪,比如“传输开始”,这和计算机好像搭不上边啊。

这是因为ASCII不仅仅是为计算机之间通信而设计,在计算机与打印机之间传递信息时同样也使用ASCII(至少在以前是这样)

而这些控制字符,大多是用于打印机进行定位的

在控制字符之后,就是可以显示出来的字符了。它们是你可以直接看到的有形状的图像。

二进制十进制十六进制字符含义
1000003220(space)空格
1000013321!
1000103422"
1000113523#
1001003624$
1001013725%
1001103826&
1001113927'
1010004028(
1010014129)
101010422A*
101011432B+
101100442C,
101101452D-
101110462E.
101111472F/
11000048300
11000149311
11001050322
11001151333
11010052344
11010153355
11011054366
11011155377
11100056388
11100157399
111010583A:
111011593B;
111100603C<
111101613D=
111110623E>
111111633F?
10000006440@
10000016541A
10000106642B
10000116743C
10001006844D
10001016945E
10001107046F
10001117147G
10010007248H
10010017349I
1001010744AJ
1001011754BK
1001100764CL
1001101774DM
1001110784EN
1001111794FO
10100008050P
10100018151Q
10100108252R
10100118353S
10101008454T
10101018555U
10101108656V
10101118757W
10110008858X
10110018959Y
1011010905AZ
1011011915B[
1011100925C\
1011101935D]
1011110945E^
1011111955F_
11000009660`
11000019761a
11000109862b
11000119963c
110010010064d
110010110165e
110011010266f
110011110367g
110100010468h
110100110569i
11010101066Aj
11010111076Bk
11011001086Cl
11011011096Dm
11011101106En
11011111116Fo
111000011270p
111000111371q
111001011472r
111001111573s
111010011674t
111010111775u
111011011876v
111011111977w
111100012078x
111100112179y
11110101227Az
11110111237B{
11111001247C|
11111011257D}
11111101267E~
11111111277FDEL (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;
}

请编译并运行此程序,体会本文中所学到的知识。

发表评论

电子邮件地址不会被公开。 必填项已用*标注