又是跌跌撞撞完成的一道题,我对于位运算和进制转化这块知识点太欠缺了,写了这么久c的题目也没用过几次
知识点
1.取出低七位bit
使用&位运算符 与0x7F可以取出当前数的二进制最低七位,这里即使是整数参与运算,也会自动被转换成二进制数参与运算,因为十六进制数7F表示二进制值为 01111111
,即低7位全为1,最高位为0的字节
unsigned char byte = num & 0x7F;
2.判断是否需要在当前字节的最高位设置为1
num > 0x7F
检查当前数字是否大于该所能表示的最大值,也就是检查是否还有剩余的数字需要编码。如果 num
大于 0x7F
,说明还有剩余数字需要编码,此时需要将当前字节的最高位设置为1,表示后续还有字节,如果不是会自动高位补0.
3.最高位设置为1
0x80
十进制为 128,二进制表示为 10000000
。这个二进制数的最高位是1,其他位都是0,当我们执行 byte |= 0x80;
这条语句时,按位或操作符 |
会将 byte
的当前值与 0x80
进行按位或操作。按位或操作的规则是,只要有一个操作数的对应位为1,结果的对应位就为1,否则为0
(多说一下,这一步是没有什么直观理解的,我想了很久,如果用最高位的数字表示后面还有没有要存储的会不会影响原本数据的储存,但这就是变长编码的规则,相当于一个约定俗成,只用按题目意思走就可以了)
4.右移7位,继续处理下一个字节
使用位运算符>>
5.格式化输入 unsigned long long 类型值
scanf("%llu", &num);
//变长编码
#include <stdio.h>
//计算正整数的变长编码
void variableLengthEncoding(unsigned long long num) {
// 定义一个数组用于存储每个字节的值
unsigned char bytes[10];
// 定义一个变量用于记录字节数
int byteCount = 0;
// 将正整数按规则进行变长编码
while (num > 0) {
// 取出低7位
unsigned char byte = num & 0x7F;
// 如果还有剩余的数字需要编码,则将最高位设置为1,表示后续还有字节
if (num > 0x7F) {
byte |= 0x80;
}
// 将该字节存入数组
bytes[byteCount++] = byte;
// 右移7位,继续处理下一个字节
num >>= 7;
}
// 输出变长编码的每个字节
int i;
for ( i = 0;i <= byteCount - 1; i++) {
printf("%02X", bytes[i]); // 以十六进制格式输出,两位表示一个字节
if (i != byteCount - 1) {
printf(" "); // 字节之间用空格分隔
}
}
printf("\n");
}
int main() {
unsigned long long num;
scanf("%llu", &num); //格式化输入
variableLengthEncoding(num);
return 0;
}