Appearance
第5章 ASCII编码
🎯 本章学习目标
学完本章,你将能够:
- ✅ 说出 ASCII 编码的基本概念(7位、128个字符)
- ✅ 背出三个锚点:'0'=48、'A'=65、'a'=97
- ✅ 掌握大小写字母相差 32 的规律
- ✅ 熟练进行字符与 ASCII 码的相互转换
- ✅ 掌握数字字符与数值的互转('5'-'0'=5)
- ✅ 理解 char 参与运算时的整型提升现象
- ✅ 学会判断字符类型(大写/小写/数字)的方法
- ✅ 掌握大小写转换的编程写法
- ✅ 了解扩展 ASCII 与中文字符编码的区别
- ✅ 认识 cctype 库中的字符处理函数
🗺️ 本章知识图谱
ASCII编码
├── 基本概念
│ ├── 7位二进制 = 128个字符(0~127)
│ ├── 控制字符(0~31、127)vs 可打印字符(32~126)
│ └── 存储占1字节,最高位为0
├── 必背锚点 ⭐⭐⭐
│ ├── 空格 ' ' = 32
│ ├── 数字 '0' = 48('0'~'9' 连续:48~57)
│ ├── 大写 'A' = 65('A'~'Z' 连续:65~90)
│ └── 小写 'a' = 97('a'~'z' 连续:97~122)
├── 三大规律
│ ├── 同组字符编号连续
│ ├── 大小写相差32(小写更大)
│ └── 数字字符与数值差48
├── C++ 字符运算
│ ├── char 本质是1字节整数
│ ├── 参与算术自动提升为 int
│ ├── 想输出字符需强转回 char
│ └── cctype 库函数(isupper/toupper等)
├── 常用转换公式
│ ├── 数字字符→数值:ch - '0'
│ ├── 数值→数字字符:'0' + n
│ ├── 大写→小写:ch + 32
│ ├── 小写→大写:ch - 32
│ └── 判断范围:>= 起点 && <= 终点
└── 扩展知识
├── 扩展ASCII:8位、256个字符
├── 中文不属于ASCII(GBK/UTF-8多字节)
└── Unicode 与 UTF-8一、字符也要有"编号":认识 ASCII
计算机内部只存储二进制数字,那么字符 'A' 该怎么存?人们的办法是:给每个字符分配一个唯一的整数编号,字符在计算机中就以这个编号的二进制形式存储。这套编号规则就是字符编码。
ASCII(American Standard Code for Information Interchange,美国信息交换标准代码)是最早通用的字符编码标准:
- 标准 ASCII 用 7 位二进制表示一个字符,共 2⁷ = 128 个字符(编号 0 ~ 127)
- 实际存储时占用 1 个字节(8 位),最高位为 0
- 128 个字符分为两大类:
| 分类 | 编号范围 | 包含内容 |
|---|---|---|
| 控制字符 | 0 ~ 31,外加 127 | 换行、回车、制表符、响铃等,屏幕上不显示 |
| 可打印字符 | 32 ~ 126 | 空格、数字、大小写字母、常用标点符号 |
易错点 ⚠️: ASCII 只有 128 个字符(0~127),用 7 位二进制即可表示;"ASCII 有 256 个字符"的说法指的是扩展 ASCII(见第五节),考试要注意审题。
二、必背的 ASCII 编码表 ⭐⭐⭐⭐⭐
二级考试不要求背完整张 ASCII 表,但下面这些必须脱口而出:
| 字符 | ASCII(十进制) | 说明 |
|---|---|---|
空格 ' ' | 32 | 最常见的空白分隔字符 |
数字字符 '0' ~ '9' | 48 ~ 57 | 10 个数字,编号连续 |
大写字母 'A' ~ 'Z' | 65 ~ 90 | 26 个大写字母,编号连续 |
小写字母 'a' ~ 'z' | 97 ~ 122 | 26 个小写字母,编号连续 |
制表符 '\t' | 9 | Tab,跳到下一个制表位 |
换行符 '\n' | 10 | LF(Line Feed),换行 |
回车符 '\r' | 13 | CR(Carriage Return) |
记忆时只需抓住 三个起点数字:
🔑
'0'= 48,'A'= 65,'a'= 97 同组字符编号连续递增,知道起点就能推出任意字符:'D'= 65 + 3 = 68,'f'= 97 + 5 = 102,'9'= 48 + 9 = 57。
高频考点 🔥: 三个起点值 48 / 65 / 97 是选择题的"万能钥匙"。常考方式:"已知 'A' 的 ASCII 码为 65,求 'M' 的 ASCII 码"——字母表中排第几位,就用起点加偏移量。
易错点 ⚠️(头号大坑):
'0'不等于 0! 字符'0'的编号是 48,整数0就是数值零。数字字符的 ASCII 编号 ≠ 它表示的数值:'7'的编号是 55,不是 7!类似地,'A'不是 1,它的编号是 65。
三、藏在编号里的三大规律
ASCII 表并非随意排列,里面藏着三个让编程变得极其方便的规律。
规律 1:同组字符编号连续
字母表顺序就是编号递增顺序,数字顺序也是:
'B' - 'A' = 1 (B 比 A 晚 1 个)
'Z' - 'A' = 25 (Z 是第 26 个字母,偏移 25)
'9' - '0' = 9规律 2:大小写字母相差 32(小写编号更大)
'a' - 'A' = 97 - 65 = 32
'z' - 'Z' = 122 - 90 = 32从二进制看更直观:'A' = 0100 0001,'a' = 0110 0001,两者只有值为 32 的那一位不同。所以:
- 大写转小写:编号 + 32
- 小写转大写:编号 − 32
规律 3:数字字符与数值相差 48
'7' - '0' = 55 - 48 = 7 (字符 '7' 减去 '0',正好得到数值 7)
'0' + 7 = 55 = '7' (数值 7 加上 '0',正好得到字符 '7')常用转换公式大全
| 转换需求 | 公式 | 例子 |
|---|---|---|
| 数字字符 → 数值 | ch - '0' | '7' - '0' = 7 |
| 数值 → 数字字符 | '0' + n | '0' + 7 = '7' |
| 大写 → 小写 | ch - 'A' + 'a'(或 ch + 32) | 'G' → 'g' |
| 小写 → 大写 | ch - 'a' + 'A'(或 ch - 32) | 'm' → 'M' |
| 判断大写字母 | c >= 'A' && c <= 'Z' | 'Q' 为真 |
| 判断小写字母 | c >= 'a' && c <= 'z' | 'q' 为真 |
| 判断数字字符 | c >= '0' && c <= '9' | '7' 为真 |
易错点 ⚠️: 做 ±32 大小写转换前,一定要先确认字符是字母!若对数字字符
'5'(编号 53)盲目加 32,会得到 85 号字符'U',结果荒谬。考试中"无条件 +32"是典型错误选项。更稳妥的写法是先判断范围,或直接使用下一节的toupper/tolower函数。
四、C++ 中的字符与整数互转
在 C++ 中,char 本质上就是一个 1 字节的整数,存的就是字符的 ASCII 编码值。因此字符可以直接参与算术运算、与整数互相赋值和转换。
4.1 查看编码与字符运算
cpp
#include <iostream>
using namespace std;
int main() {
// ===== 1. 查看常用字符的 ASCII 编码(char 转 int)=====
cout << "数字字符: " << (int)'0' << " ~ " << (int)'9' << endl; // 48 ~ 57
cout << "大写字母: " << (int)'A' << " ~ " << (int)'Z' << endl; // 65 ~ 90
cout << "小写字母: " << (int)'a' << " ~ " << (int)'z' << endl; // 97 ~ 122
cout << "空格: " << (int)' ' << endl; // 32
cout << "换行: " << (int)'\n' << endl; // 10
cout << "制表符: " << (int)'\t' << endl; // 9
cout << "回车: " << (int)'\r' << endl; // 13
// ===== 2. 字符与整数互相转换 =====
cout << (int)'A' << endl; // 65:查字符的编号
cout << (char)65 << endl; // A :按编号找字符
// ===== 3. 字符直接参与算术运算 =====
cout << 'a' - 'A' << endl; // 32:字符相减,结果是整数
cout << 'C' - 'A' << endl; // 2 :C 在字母表中比 A 晚 2 位
char c = 'A';
cout << c << endl; //输出字符 A(直接输出 char 变量)
cout << c + 1 << endl; // 66:整型提升!输出的是整数,不是字符
cout << (char)(c + 1) << endl; // B :强制转回 char,才输出字符
return 0;
}高频考点 🔥(程序阅读题最爱):
char参与算术运算时会发生整型提升——'A' + 1的结果是int类型的 66,直接cout输出整数 66;想输出字符'B',必须(char)('A' + 1)强转回来。
4.2 大小写转换、数字转换与 cctype 函数
cpp
#include <iostream>
#include <cctype> // isupper / islower / isdigit / isalpha / toupper / tolower
using namespace std;
int main() {
// ===== 1. 数字字符转数值 / 数值转数字字符 =====
char dc = '7';
int num = dc - '0'; // 55 - 48 = 7
cout << num << endl; // 7(整数)
int n = 9;
cout << (char)('0' + n) << endl; // 9(字符 '9')
// ===== 2. 大小写转换:推荐"减起点 + 加终点"的通用公式 =====
char up = 'G';
char low1 = up - 'A' + 'a'; // 大写转小写:65→97
char low2 = up + 32; // 等价写法:直接加 32
cout << low1 << " " << low2 << endl; // g g
char low = 'm';
char up1 = low - 'a' + 'A'; // 小写转大写
cout << up1 << endl; // M
// ===== 3. 用比较运算判断字符范围(布尔值输出 1/0)=====
char ch = '5';
cout << (ch >= '0' && ch <= '9') << endl; // 1:是数字字符
cout << (ch >= 'A' && ch <= 'Z') << endl; // 0:不是大写字母
cout << (ch >= 'a' && ch <= 'z') << endl; // 0:不是小写字母
// ===== 4. <cctype> 字符处理函数 =====
cout << (bool)isupper('A') << endl; // 1:是大写字母
cout << (bool)islower('a') << endl; // 1:是小写字母
cout << (bool)isdigit('7') << endl; // 1:是数字字符
cout << (bool)isalpha('x') << endl; // 1:是字母
cout << (bool)isalpha('5') << endl; // 0:数字不是字母
cout << (char)toupper('b') << endl; // B:转大写(返回 int,需强转 char)
cout << (char)tolower('Q') << endl; // q:转小写
return 0;
}<cctype> 头文件中的常用函数:
| 函数 | 作用 | 示例 | 返回结果 |
|---|---|---|---|
isupper(c) | 是否为大写字母 | isupper('A') | 真(非 0) |
islower(c) | 是否为小写字母 | islower('a') | 真(非 0) |
isdigit(c) | 是否为数字字符 | isdigit('7') | 真(非 0) |
isalpha(c) | 是否为字母 | isalpha('x') | 真(非 0) |
toupper(c) | 返回对应的大写字母 | toupper('b') | 'B'(int) |
tolower(c) | 返回对应的小写字母 | tolower('Q') | 'q'(int) |
易错点 ⚠️:
toupper/tolower的返回值是int,输出字符时要写成(char)toupper(c);若传入的不是字母,函数会原样返回该字符,不会报错——所以转换前判断范围依然是好习惯。toupper/tolower的参数建议写为(unsigned char)c,避免传入负值导致未定义行为(一级、二级考试中传入普通字母不会触发,但养成好习惯)。
五、扩展 ASCII 与中文字符
标准 ASCII 只用了 1 个字节的低 7 位(0~127),最高位闲着也是闲着,于是人们把它利用起来:
- 扩展 ASCII:使用完整 8 位,共 2⁸ = 256 个字符(0~255),新增了一些特殊符号、表格线、西欧字母等。但扩展部分没有统一标准,不同代码页(如CP437、ISO-8859-1)的字符内容不同。
那汉字怎么办?汉字有成千上万个,1 个字节能表示的 256 个编号远远不够:
- 中国制定了 GB2312 / GBK 等编码,一个汉字占 2 个字节;
- 国际通用的 Unicode 为每个字符分配统一码位(如
'中'的码位是 20013),在 UTF-8 编码中一个汉字通常占 3 个字节。
高频考点 🔥: 中文字符不属于 ASCII! 判断题中出现"ASCII 编码包含汉字""一个汉字占 1 个字节""汉字和英文字母一样用 ASCII 表示"等说法,全部错误。C++ 中一个
char存不下一个汉字(汉字占多字节);
六、📝 实战练习
练习题 1(单选题)
题目: 已知大写字母 'A' 的 ASCII 码为 65,小写字母 'a' 的 ASCII 码为 97,则字符 'M' 和 'm' 的 ASCII 码分别是( )
A. 76 和 108 B. 77 和 109 C. 77 和 108 D. 78 和 110
🔑 点击查看答案与解析
答案: B
解析: 'M' 是字母表中第 13 个字母,相对 'A' 的偏移量是 12,因此 'M' = 65 + 12 = 77;对应小写 'm' = 97 + 12 = 109(或 77 + 32 = 109)。
- A 选项 76 和 108 是
'L'和'l'(差一位,偏移量算成 11); - D 选项 78 和 110 是
'N'和'n'(偏移量算成 13,典型的"第几个就加几"错误)。
选 B。
练习题 2(单选题)
题目: 以下 C++ 程序的输出是( )
cpp
#include <iostream>
using namespace std;
int main() {
char c = '7';
cout << c - '0' << " ";
char d = 'A';
cout << (char)(d + 32) << " ";
cout << 'z' - 'a' << endl;
return 0;
}A. 7 a 25 B. 55 a 25 C. 7 A 26 D. 55 A 26
🔑 点击查看答案与解析
答案: A
解析:
c - '0':'7'(55)−'0'(48)= 7,字符相减得到整数;(char)(d + 32):'A'(65)+ 32 = 97,强转 char 后输出小写字母a;'z' - 'a':122 − 97 = 25(26 个字母,首尾偏移 25,注意不是 26!)。
干扰项拆解:55 是忘了减
'0'、直接把'7'当结果;A是忘了小写字母编号更大、转换方向搞反;26 是"字母个数"与"偏移量"混淆。
选 A。
练习题 3(多选题)
题目: 下列关于 ASCII 编码的说法,正确的有( )
① 标准 ASCII 码用 7 位二进制表示,共可表示 128 个字符 ② 字符 '0' 的 ASCII 码值等于整数 0 ③ 小写字母的 ASCII 码比对应的大写字母大 32 ④ 换行符 '\n' 的 ASCII 码值为 10
A. ①②③ B. ①③④ C. ②③④ D. ①②③④
🔑 点击查看答案与解析
答案: B
解析:
- ① 正确 ✅:标准 ASCII 为 7 位编码,2⁷ = 128 个字符;
- ② 错误 ❌:
'0'的 ASCII 码是 48,不是 0!这是本书反复强调的头号易错点; - ③ 正确 ✅:
'a' - 'A'= 97 − 65 = 32,小写编号更大; - ④ 正确 ✅:换行
'\n'= 10,回车'\r'= 13,制表符'\t'= 9。
选 B(①③④)。
练习题 4(判断题)
题目: 在 C++ 中,字符变量本质上存储的是字符的 ASCII 编码值(一个整数),因此 char c = 'A'; cout << c + 1; 会输出整数 66。( )
🔑 点击查看答案与解析
答案: ✓ 正确
解析: char 就是 1 字节整数。c + 1 运算时发生整型提升,结果为 int 类型的 65 + 1 = 66,cout 输出整数 66;若想输出字符 'B',必须写 cout << (char)(c + 1);。
练习题 5(程序阅读题)
题目: 阅读以下 C++ 程序,写出 5 行输出:
cpp
#include <iostream>
using namespace std;
int main() {
char ch1 = 'D';
char ch2 = '8';
cout << ch1 - 'A' + 1 << endl; // 行1
cout << (char)(ch1 + 32) << endl; // 行2
cout << ch2 - '0' << endl; // 行3
cout << (char)('0' + 6) << endl; // 行4
cout << 'Y' - 'A' + 'a' << endl; // 行5
return 0;
}🔑 点击查看答案与解析
答案:
4
d
8
6
121解析:
- 行1:
'D'-'A' = 3(D是第4个字母,偏移量为3),再加 1 = 4(求字母在字母表中的序号:减'A'加1); - 行2:
'D'(68) + 32 = 100,强转 char →d(大写转小写); - 行3:
'8' - '0'= 56 − 48 = 8(数字字符转数值); - 行4:
'0'(48) + 6 = 54,54 号字符是'6'→6(数值转数字字符); - 行5:
'Y'-'A' = 24,再加'a'(97) = 121(这是小写'y'的 ASCII 码,但因为没有强转,cout 输出整数)。
🔥 高频考点:字符相减得整数偏移量,字符加/减整数得新字符(需强转才显示字符)。
'Y'-'A'+'a'这种"大写变小写"的写法(减起点加终点)比直接 ±32 更通用,也更不容易记反方向。
练习题 6(单选题)
题目: 下列说法正确的有( )
① 'a' > 'Z' 这个表达式的值为真 ② 在 C++ 中,char 类型变量不能参与算术运算 ③ toupper('3') 的返回值是字符 '3'(非字母原样返回) ④ 中文字符在 ASCII 编码中占 2 个字节
A. ①② B. ①③ C. ②③ D. ②④
🔑 点击查看答案与解析
答案: B
解析:
- ① 正确 ✅:
'a'的 ASCII 码是 97,'Z'是 90,97 > 90 为真。小写字母的 ASCII 码比大写字母大,这是一个常考结论; - ② 错误 ❌:
char本质是 1 字节整数,完全可以参与算术运算,运算时自动提升为 int; - ③ 正确 ✅:
toupper(c)对字母执行大写转换,对非字母字符原样返回,不会报错; - ④ 错误 ❌:ASCII 编码不包含汉字。中文使用 GBK、UTF-8 等编码,占 2~3 个字节。
选 B(①③)。
💡 小技巧:判断字符大小时,记住"排序顺序"——控制字符 < 空格 < 数字 < 大写字母 < 小写字母。所以
'0' < 'A' < 'a',数字字符比字母小。
练习题 7(编程题)
题目: 输入一行字符(仅包含大小写字母和数字,以回车结束),统计其中大写字母、小写字母、数字字符各有多少个。
输入样例:
Abc123XYZ输出样例:
大写:4 小写:2 数字:3🔑 点击查看答案与解析
参考代码(C++):
cpp
#include <iostream>
using namespace std;
int main() {
char c;
int upper = 0, lower = 0, digit = 0;
// 逐个读取字符,遇到换行结束(cin >> c 会跳过空白,所以用 cin.get())
while (cin.get(c) && c != '\n') {
if (c >= 'A' && c <= 'Z') {
upper++; // 大写字母计数
} else if (c >= 'a' && c <= 'z') {
lower++; // 小写字母计数
} else if (c >= '0' && c <= '9') {
digit++; // 数字字符计数
}
}
cout << "大写:" << upper << " 小写:" << lower << " 数字:" << digit << endl;
return 0;
}
// 输入 Abc123XYZ → A(大) b(小) c(小) 1(数) 2(数) 3(数) X(大) Y(大) Z(大)
// 输出:大写:4 小写:2 数字:3 ✅解析要点:
- 判断字符类型用范围比较:
c >= 'A' && c <= 'Z'判断大写字母,这是最经典的写法; - 利用"同组字符编号连续"的规律,只需比较首尾就能判断归属;
- 也可以用
<cctype>的isupper(c)、islower(c)、isdigit(c)函数,代码更直观。
🍎 生活比喻:ASCII 码表就像一个按顺序排号的小区,数字住 48~57 号楼,大写字母住 65~90 号楼,小写字母住 97~122 号楼。想知道一个字符"住在哪片区域",只要比较它的楼号(ASCII 码)在不在对应的区间里就行。
练习题 8(编程题)
题目: 输入一个由大写字母组成的加密字符串和一个整数 k(偏移量),输出解密后的字符串。解密规则:每个字母向前偏移 k 位(即加密时向后移了 k 位),超出 A 时从 Z 绕回。
输入样例:
KHOOR 3输出样例:
HELLO(解释:K 向前 3 位 = H,H 向前 3 位 = E,O 向前 3 位 = L,O 向前 3 位 = L,R 向前 3 位 = O)
🔑 点击查看答案与解析
参考代码(C++):
💡 说明:下面参考代码使用
string(字符串)类型,属于 GESP 三级内容;二级若尚未学字符串,可用char数组或逐字符处理实现同一思路,这里给出更简洁的写法供参考。
cpp
#include <iostream>
#include <string>
using namespace std;
int main() {
string s;
int k;
cin >> s >> k;
for (int i = 0; i < s.size(); i++) {
// 转成 0~25 的偏移量,减 k,加 26 取模防止负数,再转回字符
int offset = s[i] - 'A'; // 字母→序号(0~25)
offset = (offset - k + 26) % 26; // 向前移 k 位,+26 防负
s[i] = 'A' + offset; // 序号→字母
}
cout << s << endl;
return 0;
}
// 输入 KHOOR 3:
// K(10)-3=7 → H, H(7)-3=4 → E, O(14)-3=11 → L, O(14)-3=11 → L, R(17)-3=14 → O
// 输出 HELLO ✅解析要点:
- 凯撒密码的核心是"字符 → 序号 → 加减 → 取模 → 转回字符"的套路;
(offset - k + 26) % 26中加 26 是为了防止 offset < k 时出现负数,确保取模结果在 0~25 范围内;- 这道题是字符运算最经典的综合应用,考试中常以"加密""解密""移位密码"等形式出现。
💡 记忆口诀:字符转序号,加减再取模,序号转字符,加密解密都靠它。
七、📊 考点总结表
| 考点 | 重要程度 | 出题形式 | 高频易错点 |
|---|---|---|---|
| ASCII 基本概念(7 位、128 个) | ⭐⭐⭐ | 选择/判断 | 与扩展 ASCII(256 个)混淆 |
| 常用编码值(48/65/97、32/10/9/13) | ⭐⭐⭐⭐⭐ | 选择/程序阅读 | 把 '0' 当成 0;起点值记不牢 |
| 大小写差 32 | ⭐⭐⭐⭐⭐ | 选择/编程 | 转换方向搞反(小写编号更大) |
| 字符与整数互转 | ⭐⭐⭐⭐ | 程序阅读/编程 | 忘记强转,'A'+1 输出 66 |
数字字符转数值 ch-'0' | ⭐⭐⭐⭐ | 编程 | 直接拿字符编号当数值用 |
| 字符范围判断 | ⭐⭐⭐ | 选择/编程 | 边界值记错(如 65/90 记反) |
| cctype 函数 | ⭐⭐⭐ | 选择/编程 | toupper 返回 int 未强转; |
| 中文与扩展 ASCII | ⭐⭐⭐ | 判断 | 误以为汉字属于 ASCII、占 1 字节 |
⭐ 必背速记卡
┌─────────────────────────────────────────────────────┐
│ 1. ASCII用7位二进制,共128个字符(0~127) │
│ 2. 三个锚点必须背:'0'=48, 'A'=65, 'a'=97 │
│ 3. 空格 ' ' = 32,换行 '\n'=10,制表 '\t'=9 │
│ 4. 数字字符 '0'~'9':48~57(连续10个) │
│ 5. 大写字母 'A'~'Z':65~90(连续26个) │
│ 6. 小写字母 'a'~'z':97~122(连续26个) │
│ 7. 大小写相差32,小写更大:小写-32=大写 │
│ 8. 数字字符转数值:ch - '0' = 数值 │
│ 9. 数值转数字字符:'0' + 数值 = 字符 │
│ 10. char 本质是1字节整数,参与算术自动提升为 int │
│ 11. 字符运算结果是int,想输出字符需强转 (char) │
│ 12. 判断大写:c >= 'A' && c <= 'Z' │
│ 13. 判断数字:c >= '0' && c <= '9' │
│ 14. 字符大小顺序:控制符 < 空格 < 数字 < 大写 < 小写 │
│ 15. 中文不属于ASCII,GBK占2字节、UTF-8占3字节 │
└─────────────────────────────────────────────────────┘