← 目录 / 第二章 · 变量与数据类型 / 2.2 ASCII 编码

2.2 ASCII 编码

计算机底层只存储数字,字符本质上也是用整数来表示的——ASCII 就是这套字符与数字之间的映射规则。

ASCII 编码

ASCII(美国信息交换标准代码)是一种将字符映射为数字的编码系统,最初于 1963 年发布。标准 ASCII 定义了 128 个字符(0~127),包括控制字符和可显示字符。计算机底层只存储数字,字符本质上也是用整数来表示的。

2.2.1 为什么字符也是数字

计算机的存储单元里只有 0 和 1,它只会存数字,不认识"字符"这种东西。那我们平时打的字母、标点、汉字是怎么显示出来的呢?答案是:人和计算机之间需要一份"翻译词典"——大家提前约定好,数字 65 就代表字母 'A',数字 97 就代表 'a'。计算机内部只存这个数字,显示的时候再按词典"翻译"成人能看懂的字符。

这份词典就是 ASCII 编码表。它把 128 个常用字符(英文字母、数字符号、标点、常见控制符)分别对应到 0~127 这 128 个整数上,成为几乎所有编程语言和计算机系统的共同基础。

🔑
关键概念:在 C++ 里,char 类型本质上就是一个 1 字节的整数。写 char c = 'A'; 时,编译器实际存进去的是数字 65,只不过 char 在输出(如 cout)时会自动按 ASCII 表"翻译"成对应的字符显示出来。这也是为什么 char 可以像整数一样参与加减运算——它本来就是整数

2.2.2 ASCII 表结构总览

与其死记硬背 128 个数字,不如先记住 ASCII 表被分成了几大块,各块内部又是连续排列的——这比记住某个字符具体是第几号更有用:

范围类别说明
0 ~ 31 控制字符 不可打印,用来控制设备行为,如换行 '\n'(10)、制表符 '\t'(9)、回车 '\r'(13)
32 空格 唯一"看不见但占位置"的可打印字符,ASCII 表里最小的可打印字符
33 ~ 47 标点符号 ! " # $ % & ' ( ) * + , - . /
48 ~ 57 数字字符 '0' ~ '9',注意这是"字符 0",不是数值 0,两者相差 48
58 ~ 64 标点符号 : ; < = > ? @
65 ~ 90 大写字母 'A' ~ 'Z',连续排列,'A' 最小、'Z' 最大
91 ~ 96 标点符号 [ \ ] ^ _ `
97 ~ 122 小写字母 'a' ~ 'z',与对应大写字母恰好相差 32
123 ~ 126 标点符号 { | } ~
127 DEL 删除控制符,不可打印
💡
记忆诀窍:只要记住三个"锚点"—— '0' = 48,'A' = 65,'a' = 97——剩下的字符都可以通过"连续排列"和"相差 32"这两条规律直接推算出来,完全不需要死记整张表。

2.2.3 常用 ASCII 值速查

SP
32
' ' 空格,最小可显示字符
0
48
'0'~'9' 对应 48~57
A
65
'A'~'Z' 对应 65~90
a
97
'a'~'z' 对应 97~122

2.2.4 实用技巧与代码示例

正因为大写字母和小写字母在 ASCII 表里各自连续排列,且首字母恰好相差 32,数字字符 '0'~'9' 也连续排列,我们可以用简单的加减法在字符和数值之间转换,而不需要查表:

C++ · ASCII 技巧
1// 技巧 1:大小写互转(差值为 32)
2char lower = char('A' + 32); // 'a'(大写转小写)
3char upper = char('a' - 32); // 'A'(小写转大写)
4
5// 技巧 2:数字字符 → 整数
6int n = '5' - '0'; // n = 5(字符减 '0' 得数值)
7
8// 技巧 3:整数 → 数字字符
9char ch = char(5 + '0'); // ch = '5'(数值加 '0' 得字符)

以技巧 1 的大写转小写为例,把 'A' + 32 这一步拆开来看,实际发生的是"字符 → 数字 → 数字 → 字符"的过程:

'A' 65 ① 字符 'A' 本质就是数字 65
65 + 32 97 ② 做普通的整数加法
97 'a' ③ 按 ASCII 表翻译回字符,正好是小写 'a'

技巧 2、3 的道理完全一样:字符 '5' 本质是数字 53,减去字符 '0'(数字 48),得到 53 - 48 = 5,这才是我们真正想要的数值 5——而不是字符 '5' 本身的编码值。

2.2.5 更专业的写法:cctype 函数库

手动加减 32 或 48 虽然直观,但每次使用前都要先确认"这确实是个字母/数字",否则会算出无意义的结果。C++ 标准库 <cctype> 提供了一整套现成的字符判断和转换函数,更安全、更不容易出错,正式写代码时更推荐使用:

C++ · cctype 常用函数
1#include <cctype>
2
3isalpha(ch) // 是否为字母(大写或小写)
4isdigit(ch) // 是否为数字字符 '0'~'9'
5isupper(ch) // 是否为大写字母
6islower(ch) // 是否为小写字母
7isspace(ch) // 是否为空白字符(空格/换行/制表符等)
8toupper(ch) // 返回转换成大写后的字符
9tolower(ch) // 返回转换成小写后的字符

用库函数改写技巧 1 的大小写转换,不需要再关心背后的数字 32,也不用担心传入的字符本来就不是字母:

C++ · 用 cctype 改写大小写转换
1char c = 'A';
2
3if (isalpha(c)) { // 先判断确实是字母,再转换
4 char lower = char(tolower(c)); // 'a'
5}
💡
竞赛建议:手动加减 32/48 的技巧运算速度略快、代码更短,竞赛中很常见;但如果不确定输入是否一定是字母/数字(比如需要处理混合了符号的字符串),优先用 <cctype> 的判断函数打底,更不容易因为边界情况写出 bug。

2.2.6 常见陷阱与易错点

把本节内容汇总成几条最容易踩坑的规则:

1
字符 '0' 不是数值 0:'0' 的 ASCII 值是 48,不是 0。如果直接把字符当数值用(比如 int n = '5';),得到的是 53 而不是 5,一定要记得减去 '0'
2
加减 32/48 前要先确认类别:如果对一个本来就不是字母的字符(比如标点符号)执行"+32"操作,只会得到另一个无意义的字符,程序不会报错但结果毫无意义。用 isalphaisdigit 先判断更保险。
3
char 可能是有符号的:在大多数平台上 char 默认是有符号类型,取值范围是 -128~127。如果用它存储超出 127 的原始字节数据(比如图像像素值 0~255),可能会变成负数,导致比较或输出结果出乎意料。这种情况建议改用 unsigned char
4
ASCII 只覆盖英文,不包含中文:ASCII 表只有 128 个字符,只能表示英文字母、数字和常见符号。中文、日文等字符需要用 Unicode/UTF-8 等更大的编码系统表示,一个中文字符在 UTF-8 里通常占 3 个字节,不能简单套用本节的加减法技巧。