伪Base16的构思和实现

      最近看见了一个迅雷地址,发现将其转换为普通链接的工具后,发现所谓专用地址地址就是原地址前加一个表示迅雷的前缀,后进行Base64编码。查阅Base64编码过程后,突发奇想:能否做一个Base16算法?再查Base16,发现已经有具体的算法,而且比较复杂。于是,打算做一个山寨的Base16算法,这个算法相对于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混淆。

      代码实现很简单,我也不注释了,直接贴出来吧,本程序的作用是把一个字符串转化为Base16编码后转回原字符串。当然,我考虑的较简单,本程序只能做到仅含有ASCII字符的字符串转化。

#include <iostream>

#include <string>

const char Base16[]={'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P'};

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]=Base16[hig];

        code[(i<<1)+1]=Base16[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;

}

你可能感兴趣的:(实现)