Skip to content

第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 ~ 5710 个数字,编号连续
大写字母 'A' ~ 'Z'65 ~ 9026 个大写字母,编号连续
小写字母 'a' ~ 'z'97 ~ 12226 个小写字母,编号连续
制表符 '\t'9Tab,跳到下一个制表位
换行符 '\n'10LF(Line Feed),换行
回车符 '\r'13CR(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字节         │
└─────────────────────────────────────────────────────┘

百炼成钢,融会贯通