1 of 2

代码解析:阅读程序-3

代码要点解析

  1. 功能
    • init() 构建 Base64 编码表 base反查表 table
    • encode() 按 RFC 规则把任意字节流每 3 个字节打包成 4 个 6bit,末尾用 = 补齐到 4 的倍数。
    • decode() 把 4 个 Base64 字符解回最多 3 个字节;遇到 = 按位截断。

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
#include <iostream>
#include <string>
using namespace std;

// Base64 索引表:0..63 -> 对应字符(A-Z a-z 0-9 + /)
char base[64];
// 反查表:字符(0..255) -> 对应的索引值(0..63),无效字符置为 0xff
char table[256];

void init()
{
    // 构造 base64 字符表
    for (int i = 0; i < 26; i++) base[i] = 'A' + i;      // 0..25  -> A..Z
    for (int i = 0; i < 26; i++) base[26 + i] = 'a' + i; // 26..51 -> a..z
    for (int i = 0; i < 10; i++) base[52 + i] = '0' + i; // 52..61 -> 0..9
    base[62] = '+';                                      // 62
    base[63] = '/';                                      // 63

    // 构造反查表,默认置为无效 0xff
    for (int i = 0; i < 256; i++) table[i] = 0xff;
    // 将合法字符映射到 0..63
    for (int i = 0; i < 64; i++) table[(unsigned char)base[i]] = (char)i;
    // 填充符 '=' 特殊处理:不参与数值,还原时按 0 处理位拼接
    table[(unsigned char)'='] = 0;
}

// Base64 编码:每 3 字节 -> 4 个 6bit 单元(用 base 表转为字符)
// 不足 3 字节时使用 '=' 补齐到 4 的倍数
string encode(string str)
{
    string ret;
    int i;

    // 主循环:整块处理 3 字节
    for (i = 0; i + 3 <= (int)str.size(); i += 3) {
        // 取出 24 位:str[i], str[i+1], str[i+2]
        // 拆为 4 个 6bit:AAAAAA BBBBBB CCCCCC DDDDDD
        ret += base[(unsigned char)str[i] >> 2];                                              // A: 高 6 位
        ret += base[((str[i] & 0x03) << 4) | ((unsigned char)str[i + 1] >> 4)];               // B: 低2 | 下个高4
        ret += base[((str[i + 1] & 0x0f) << 2) | ((unsigned char)str[i + 2] >> 6)];           // C: 低4 | 下个高2
        ret += base[(unsigned char)str[i + 2] & 0x3f];                                        // D: 低6
    }

    // 处理尾部剩余的 1 或 2 字节,按规范填充 '='
    if (i < (int)str.size()) {
        ret += base[(unsigned char)str[i] >> 2]; // A

        if (i + 1 == (int)str.size()) {          // 仅剩 1 字节
            ret += base[(str[i] & 0x03) << 4];   // B:低2 << 4
            ret += "==";                         // C、D 为空,用 "=="
        } else {                                  // 剩 2 字节
            ret += base[((str[i] & 0x03) << 4) | ((unsigned char)str[i + 1] >> 4)]; // B
            ret += base[(str[i + 1] & 0x0f) << 2];                                  // C:低4 << 2
            ret += "=";                                                              // D 为空
        }
    }

    return ret;
}

// Base64 解码:每 4 字符 -> 3 字节
// 对 '=' 做截断处理;未做严格非法字符校验(见改进建议)
string decode(string str)
{
    string ret;
    int i;

    // 每 4 个字符组成一组
    for (i = 0; i < (int)str.size(); i += 4) {
        // 取 4 个字符的 6bit 值(table 把 '=' 映射为 0)
        unsigned char a = (unsigned char)table[(unsigned char)str[i]];
        unsigned char b = (unsigned char)table[(unsigned char)str[i + 1]];

        // 还原第 1 个字节:A(高6) | B(高2)
        ret += (char)((a << 2) | (b >> 4));

        if (str[i + 2] != '=') {
            unsigned char c = (unsigned char)table[(unsigned char)str[i + 2]];
            // 还原第 2 个字节:B(低4) | C(高4)
            ret += (char)(((b & 0x0f) << 4) | (c >> 2));

            if (str[i + 3] != '=') {
                unsigned char d = (unsigned char)table[(unsigned char)str[i + 3]];
                // 还原第 3 个字节:C(低2) | D(6)
                ret += (char)(((c & 0x03) << 6) | d);
            }
        }
    }
    return ret;
}

int main()
{
    init();

    // 这行类似“自检”:打印 table[0] 的整数值(一般是 255,因为初始化为 0xff)
    cout << int((unsigned char)table[0]) << endl;

    int opt;
    string str;
    cin >> opt >> str;                  // 输入:opt=0 编码,opt=1 解码;str 为原文/密文(无空格)
    cout << (opt ? decode(str) : encode(str)) << endl;
    return 0;
}

encode函数详解:

当然可以!下面用几个具体输入演示 encode() 的工作流程(含位拆分和代码里每一步对应哪一行)。我用标准 Base64(A–Z a–z 0–9 + /)并按你代码的位运算来算。


例 1:正好 3 字节 —— "Man""TWFu"

原字节(十六进制/二进制):

'M' = 0x4D = 01001101
'a' = 0x61 = 01100001
'n' = 0x6E = 01101110

拼成 24 位并按 6 位切分:

010011 010110 000101 101110
   19     22      5      46   ← 十进制
   T      W      F       u    ← base[索引]

输出:"TWFu"

对应代码:

  • ret += base[str[i] >> 2]; → 0x4D >> 2 = 19 → ‘T’
  • ret += base[(str[i] & 0x03) << 4 | str[i + 1] >> 4]; → (1<<4)|(0x61>>4=6)=22 → ‘W’
  • ret += base[(str[i + 1] & 0x0f) << 2 | str[i + 2] >> 6]; → (1<<2)|(1)=5 → ‘F’
  • ret += base[str[i + 2] & 0x3f]; → 0x6E & 63 = 46 → ‘u’

例 2:只剩 1 字节尾巴 —— "M""TQ=="

原字节:

'M' = 0x4D = 01001101

尾部处理分支(你代码的 if (i+1 == str.size())):

  • A:base[0x4D >> 2] = base[19] = 'T'
  • B:base[(0x4D & 0x03) << 4] = base[1 << 4] = base[16] = 'Q'
  • C、D:没有数据,用 "==" 补齐

输出:"TQ=="


例 3:只剩 2 字节尾巴 —— "Ma""TWE="

原字节:

'M' = 0x4D = 01001101
'a' = 0x61 = 01100001

尾部处理分支(你代码的 else { ... ret += "="; }):

  • A:base[0x4D >> 2] = base[19] = 'T'
  • B:base[(0x4D & 0x03) << 4 | 0x61 >> 4]
    • (0x4D & 3) << 4 = 1 << 4 = 16
    • 0x61 >> 4 = 6
    • 合并:22 → 'W'
  • C:base[(0x61 & 0x0f) << 2] = base[1 << 2] = base[4] = 'E'
  • D:"="

输出:"TWE="


例 4:一般字符串 —— "hello""aGVsbG8="

先取前三个字节 "hel"(整组):

h = 0x68 = 01101000
e = 0x65 = 01100101
l = 0x6C = 01101100
切分:011010 000110 010101 101100
索引:  26      6      21     44
字符:  'a'    'G'    'V'     's'

得到 "aGVs"

剩余两个字节 "lo"(尾部 2 字节分支):

l = 0x6C = 01101100
o = 0x6F = 01101111

A: base[0x6C >> 2] = base[27] = 'b'
B: base[(0x6C & 3) << 4 | 0x6F >> 4] = base[0<<4 | 6] = base[6] = 'G'
C: base[(0x6F & 0x0F) << 2] = base[15<<2] = base[60] = '8'
D: '='

得到 "bG8="

拼起来:"aGVs" + "bG8=" = "aGVsbG8="


main函数

你的 main 读法是 cin >> opt >> str;(遇空格会截断),所以:

  • 输入:0 Man → 输出:TWFu
  • 输入:0 Ma → 输出:TWE=
  • 输入:0 M → 输出:TQ==
  • 输入:0 hello → 输出:aGVsbG8=


Scroll to Top