how-to-use/cpp/algorithm/类似Base64算法.cpp

86 lines
3.0 KiB
C++

#include <iostream>
#include <bitset>
#include <cstring>
// 问题:将一个二进制流转换成可阅读的字符串,字符串为:大写字母加数字,去除0和O,I和1相近字符。
const int g_bitNum = 5;
const char* g_Coder = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
int Encode(const char* pData, int nLen, char* res)
{
int totalLen = nLen * 8;
int resLen = totalLen / g_bitNum;
if (totalLen % g_bitNum != 0) ++resLen;
if (res == nullptr) {
return resLen;
}
for (int i = 0; i < resLen; ++i) {
unsigned char nIndex = 0;
int index = i * g_bitNum;
for (int j = 0; j < g_bitNum && index + j < totalLen; ++j) {
// bitValue 这一行只管取出下一位的值,放在哪里不管。
// index 是连续的(相当于大组里面内增,换个大组继续内增)
// index / 8 或者 index % 8 就是锁定第几组char的第几个,移动到最低位取出。
unsigned char bitValue = ((pData[index / 8] >> (7 - index % 8)) & 1);
// value 这一行只管把值放到对应的位置,与上面不要联系。
// 这里对 value 高位到低位的放
nIndex |= (bitValue << (g_bitNum - 1 - j));
// 关键点:value 和 bitValue 各管各的。
++index;
}
res[i] = g_Coder[nIndex];
}
res[resLen] = '\0';
return resLen;
}
int Decode(const char* pData, unsigned char* res)
{
int len = static_cast<int>(std::strlen(pData));
int codeBitCount = len * g_bitNum;
int resCnt = codeBitCount / 8;
if (res == nullptr) {
return resCnt;
}
std::memset(res, 0, resCnt * sizeof(char));
for (int i = 0; i < len; ++i) {
const char key = pData[i];
int nIndex = static_cast<int>(std::strchr(g_Coder, key) - g_Coder);
for (int j = 0; j < g_bitNum && i * g_bitNum + j < codeBitCount; ++j) {
// bitValue 这一行,只管取出每一位
int bitValue = ((nIndex >> (g_bitNum - 1 - j)) & 1);
// nOffset 是原始数据位索引
int nOffset = i * g_bitNum + j;
res[nOffset / 8] |= (bitValue << (7 - nOffset % 8));
}
}
return resCnt;
}
int main()
{
int data[] = {12345, 45678};
std::cout << "Original Data Len: " << sizeof(data) << std::endl;
char* szEncode = nullptr;
int size = Encode((const char*)data, sizeof(data), szEncode);
std::printf("Encode Data Len: %d\n", size);
szEncode = new char[size + 1];
Encode((const char*)data, sizeof(data), szEncode);
std::printf("Encode Data: %s\n", szEncode);
unsigned char * szDecode = nullptr;
int osize = Decode((const char *)szEncode, szDecode);
std::printf("Decode Data Len: %d\n", osize);
szDecode = new unsigned char [osize + 1];
Decode((const char*)szEncode, szDecode);
int* pInt = (int *)szDecode;
std::printf("Int[0]:%d, Int[1]:%d\n", pInt[0], pInt[1]);
delete[] szDecode;
delete[] szEncode;
return 0;
}