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 + /
)并按你代码的位运算来算。
"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’
"M"
→ "TQ=="
原字节:
'M' = 0x4D = 01001101
尾部处理分支(你代码的 if (i+1 == str.size())
):
base[0x4D >> 2]
= base[19]
= 'T'
base[(0x4D & 0x03) << 4]
= base[1 << 4]
= base[16]
= 'Q'
"=="
补齐输出:"TQ=="
"Ma"
→ "TWE="
原字节:
'M' = 0x4D = 01001101
'a' = 0x61 = 01100001
尾部处理分支(你代码的 else { ... ret += "="; }
):
base[0x4D >> 2]
= base[19]
= 'T'
base[(0x4D & 0x03) << 4 | 0x61 >> 4]
(0x4D & 3) << 4
= 1 << 4
= 160x61 >> 4
= 6'W'
base[(0x61 & 0x0f) << 2]
= base[1 << 2]
= base[4]
= 'E'
"="
输出:"TWE="
"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=