最近看见了一个迅雷地址,发现将其转换为普通链接的工具后,发现所谓专用地址地址就是原地址前加一个表示迅雷的前缀,后进行Base64编码。查阅Base64编码过程后,突发奇想:能否做一个Base32算法?再查Base32,发现已经有具体的算法,而且比较复杂。于是,打算做一个山寨的Base32算法,这个算法相对于Base64算法有如下优点:
1.不会出现字节非3的整倍数而产生的补位填充问题。
2.实现简单,只要将高低位分区。
接下来开始构思。Encode部分问题不大,用一个low(0x0f)、high(0xf0)与原数进行与预算来区分高低位。0x0f转为二进制即为00001111,0xf0即为11110000。与low进行与运算会舍弃高位,与high进行与运算会舍弃低位,当然还需要右移4位。接下来就可以按照码表输出。而Decode部分花的时间较多,先是想到了顺序查找,需要大概32条运算,后想到了二分查找,运算只要4条(当然,这里都是往小了算),最后我考虑到了码表数据的单调性:码表中数据只可能是A-Z和2-7,所以只要简单做一下字符比较,区分字母和数字,最后进行ASCII运算即可,只要1条运算。为什么码表中数字选的是2-7而不是0-5呢?原因很简单,0容易和O混淆,1则容易和l混淆。
代码实现很简单,我也不注释了,直接贴出来吧,本程序的作用是把一个字符串转化为Base32编码后转回原字符串。当然,我考虑的较简单,本程序只能做到仅含有ASCII字符的字符串转化。
#include <iostream> #include <string> const char base32[]={‘A‘,‘B‘,‘C‘,‘D‘,‘E‘,‘F‘,‘G‘,‘H‘,‘I‘,‘J‘,‘K‘,‘L‘,‘M‘,‘N‘,‘O‘,‘P‘,‘Q‘,‘R‘,‘S‘,‘T‘,‘U‘,‘V‘,‘W‘,‘X‘,‘Y‘,‘Z‘,‘2‘,‘3‘,‘4‘,‘5‘,‘6‘,‘7‘}; const int Bin_high=0xf0; const int Bin_low=0x0f; using namespace std; int get(const char); int main(void){ string Toencode; int hig=0,low=0; cin>>Toencode; //Encode char code[Toencode.length()*2+1]; for (unsigned int i=0;i<Toencode.length();++i){ hig=(Toencode[i]&Bin_high)>>4; low=Toencode[i]&Bin_low; code[i<<1]=base32[hig]; code[(i<<1)+1]=base32[low]; } code[Toencode.length()*2]=‘\0‘; cout<<code<<endl; //Decode for (unsigned i=0;i<Toencode.length()*2;i+=2){ int nIA=get(code[i]); int nIB=get(code[i+1]); char deencode=(nIA<<4)+nIB; cout<<deencode; } return 0; } int get(const char n){ if ((n>=‘A‘)and(n<=‘Z‘)){ return (n-65); } return n-24; }
时间: 2024-10-06 09:48:15