【C++】循环数组实战:base16编码分析
Base16 编码
Base16,也称为 Hex(十六进制)编码,是一种将二进制数据转换为可打印字符的编码方式。它使用 16 个字符(0-9 和 A-F)来表示数据,每个字符对应 4 位二进制(半字节,nibble)。
编码过程:
将二进制数据按 4 位(半字节)分组。
每个半字节映射到一个十六进制字符。
十六进制字符:
0123456789ABCDEF
编码示例
将字符串 "AB" 转换为 Base16:
字符串 "AB" 的 ASCII 值为:
'A' = 65(十进制) = 01000001(二进制)
'B' = 66(十进制) = 01000010(二进制)
每个字节分为两个半字节:
0100 0001 → 0100(4)和 0001(1) → 4 和 1 → 十六进制为 41
0100 0010 → 0100(4)和 0010(2) → 4 和 2 → 十六进制为 42
最终编码结果:4142
解码过程:
将每两个十六进制字符转换回 8 位(1 字节)二进制数据。
组合所有字节,恢复原始二进制数据。
解码示例
将 Base16 编码 "4142" 解码为原始数据:
将每两个字符分组:
41 → 十进制 65 → ASCII 字符 'A'
42 → 十进制 66 → ASCII 字符 'B'
最终解码结果:"AB"
基础知识
二进制的高位和低位
高位(MSB):
二进制数中,最左边的位(最高权重位)。
对数值大小的影响最大。例如,在8位二进制数 00000000变为10000000,这个数的值从0变为128。
低位(LSB):
二进制数中,最右边的位(最低权重位)。
对数值大小的影响最小。例如,在8位二进制数 00000000变为00000001,这个数的值从0变为 1。
与或非&|!
复习一下与或非
与 &
都1才1
0 & 1 = 0 ; 0 & 0 = 0 ; 1 & 1 = 1 ;
或 |
有1则1
0 | 0 = 0 ; 0 | 1 = 1 ;1 | 1 = 1 ;
非 !
!0 = 1 ; ! 1 = 0 ;
二进制 & 二进制 则是每位分别对应进行&操作
1010 & 0110
= 1&0 0&1 1&1 0&0
=0010
代码部分
工具>选项>设置一个字体,防止0Oo不好区分

准备工作:命名空间和头文件

定义一个编码表,类型为静态 常量
静态常量字符串 base16_enc_tab,用于将字节的高4位和低4位映射到Base16字符。

声明了一个字符串 base16str,用于存储Base16编码后的结果。

转化的代码如下

for (unsigned char c : teststr)使用范围for循环遍历 teststr 中的每个字节。
unsigned char是 C++ 中的一种基本数据类型,用于表示无符号的 8 位整数。它的取值范围是从 0 到 255,这使其非常适合用于表示单个字节的数据,特别是在处理二进制数据或字符编码时。
尽管 char 通常用于表示字符,但在某些情况下,unsigned char 更适合,特别是当你需要确保字符值不被解释为负数时。例如,在处理 UTF-8 编码的字符时,字节值可能大于 127,使用 unsigned char 可以避免符号扩展问题。
比如:一个字符”你“占三个字节,每个字节对应8位二进制:11100100 10111101 10100000将这些二进制转换为十进制就是228 189 160
char的范围是-128 到 127,unsigned char范围是0 到 255,明显后者合适
for (unsigned char c : teststr)
{
}
h 是通过将
字节 c 的二进制右移4位得到的,这相当于提取了字节的高4位。
例如字节为0100 0001,二进制右移4位为:0000 0100,成功得到高4位
char h = c >> 4;
l 是通过将
字节 c 的二进制与二进制00001111(0b表示二进制) 进行&操作得到的,这相当于提取了字节的低4位。
因为不管谁&0000都是0000,不管谁&1111都是它本身
例如字节为0100 0001,&二进制00001111为0000 0001成功得到低4位
char l = c & 0b00001111;
base16_enc_tab 是一个包含Base16字符的字符串,用于将高4位和低4位映射到对应的十六进制字符。
这两行代码将高4位和低4位分别转换为Base16字符,并将它们追加到 base16str 中。
base16str += base16_enc_tab[h];
base16str += base16_enc_tab[l];
输出转换的Base16字符的字符串
cout << "Base16:\t" << base16str << endl;
解码的代码如下

定义字符串用于存放解码后的数据
string ostr; //解码的数据
定义一个编码表,类型为静态 常量
静态常量字符串 base16_dec_tab,用于将 ASCII 码映射到十六进制字符的数值表示。
ASCII '0'-'9' 的值是 48-57,'A'-'F' 的值是 65-70。
const vector<char> base16_dec_tab{
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, //0~9
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, //10~19
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, //20~29
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, //30~39
-1,-1,-1,-1,-1,-1,-1,-1, //40~47
0,1,2,3,4,5,6,7,8,9, //48~57
-1,-1,-1,-1,-1,-1,-1, //58~64
10,11,12,13,14,15 //65~70
};
for 循环用于遍历字符串 base16str,每次迭代增加 2 个索引。这种模式通常用于处理十六进制字符串,其中每两个字符表示一个字节(8 位)的数据。
for (int i = 0; i < base16str.size();i += 2)
{
}
char ch = base16str[i];:从字符串 base16str 中提取第 i 个字符,并将其存储在字符变量 ch 中。
char cl = base16str[i + 1];:从字符串 base16str 中提取第 i + 1 个字符,并将其存储在字符变量 cl 中。
这样提取到了两个base16字符为一对
例如一个十六进制字符串E4BDA0提取后变为"E4", "BD", "A0"
char ch = base16str[i];
char cl = base16str[i + 1];
unsigned char h = base16_dec_tab[ch];和unsigned char l = base16_dec_tab[cl];
使用了查找表(lookup table)的方式将十六进制字符转换为对应的数值。
例如"E4", "BD", "A0",
'E'的ASCII 值为69对应数字为14(十进制),'4' 的ASCII 值为4转换为 4(十进制)。
'B' 的ASCII值是66对应11,'D'的ASCII值是66对应13
'A' 的ASCII值是65对应10,'0' 的ASCII值是48对应0
unsigned char h = base16_dec_tab[ch];
unsigned char l = base16_dec_tab[cl];
将h的二进制位数左移
14 的二进制是 1110 =》 1110 0000
11 的二进制是 1011 =》 1011 0000
10 的二进制是 1010 =》 1010 0000
将h的二进制
|l的二进制4 的二进制是 0100
13 的二进制是 1101
0 的二进制是 0000
1110 0000 | 0100 = 1110 0000 | 0000 0100 = 1110 0100
1011 0000 | 1101 = 1011 0000 | 0000 1101 = 1011 1101
1010 0000 | 0000 = 1010 0000 | 0000 0000 = 1010 0000
ostr += (h << 4 | l);
将二进制输出为字符串
cout << "解码后为:" << ostr << endl;

浙公网安备 33010602011771号