前言
海明(汉明)码是广泛采用的一种有效的校验码,它实际上是一种多重奇偶校验码。
海明码的原理就是在有效信息位中加入几个校验位形成海明码,并把海明码的每一个二进制分配到几个奇偶校验中。当某一位出错的时候,不仅能检错,还能发现出错位的位置。假设校验位有k位,那么校验码最多有2k个,显然其中有一个校验码是正确的,那么就能校验出2k-1个错位。所以,如果能满足一个n位数n+k<=2k-1,则在理论上即可判断出哪一位数出错。
C++代码
C++实现海明码如下代码,Vs2017编译通过。
#define JHM(value) ((value==1||value==49)?1:(value==0||value==48)?0:0)
// 支持序列长度为:3~11位
char *TrickTest::TotalHMCodec(char *hm)
{
if (!hm) { return nullptr; }
// 计算k k^2≥k+n+1
unsigned short hmLen = strlen(hm);
if (hmLen <= 1) { return nullptr; }
unsigned short K = 0;
if (hmLen <= 4) { K = 3; }
else if (hmLen <= 11) { K = 4; }
else if (hmLen <= 26) { K = 5; }
else if (hmLen <= 26) { K = 5; }
// 创建处理新字符串
int *HM = new int[hmLen * sizeof(int)], *pHM = HM;
memset(HM, 0, hmLen * sizeof(int));
for (short index = hmLen - 1; index >= 0; *pHM++ = hm[index], --index);
pHM = nullptr;
// 构建表格
const unsigned short tableLen = K + hmLen;
char *tableBuf = new char[tableLen +1];
memset(tableBuf, 0, tableLen+1);
std::vector<unsigned short> nTmp;
for (unsigned short index = 0; index < K; nTmp.push_back(pow(2, index)-1), ++index);
// 表格填充
pHM = HM;
for (unsigned short index = 0; index < tableLen; ++index)
{
if (std::find(nTmp.begin(), nTmp.end(), index) == nTmp.end()) { tableBuf[index] = *pHM++; }
else { tableBuf[index] = '-'; }
}
if (HM) { delete[]HM; }
HM = pHM = nullptr;
// 异或运算
int *kBuf = new int[K * sizeof(int)];
memset(kBuf, 0, K * sizeof(int));
for (unsigned short index = 0; index < K; ++index)
{
if (index + 1 == 1)
{
if (tableLen == 5 || tableLen == 6) { kBuf[index] = JHM((int)(tableBuf[2] ^ tableBuf[4])); } // 6
else if (tableLen == 7 || tableLen == 8) { kBuf[index] = JHM((int)(tableBuf[2] ^ tableBuf[4] ^ tableBuf[6])); } // 7
else if (tableLen == 9 || tableLen == 10) { kBuf[index] = JHM((int)(tableBuf[2] ^ tableBuf[4] ^ tableBuf[6] ^ tableBuf[8])); } // 9
else if (tableLen == 11 || tableLen == 12) { kBuf[index] = JHM((int)(tableBuf[2] ^ tableBuf[4] ^ tableBuf[6] ^ tableBuf[8] ^ tableBuf[10])); }
}
else if (index + 1 == 2)
{
if (tableLen == 5) { kBuf[index] = JHM((int)(tableBuf[2])); }
else if (tableLen == 6) { kBuf[index] = JHM((int)(tableBuf[5])); } // 6
else if (tableLen >= 7 && tableLen <= 9) { kBuf[index] = JHM((int)(tableBuf[5] ^ tableBuf[6])); } // 7 9
else if (tableLen == 10) { kBuf[index] = JHM((int)(tableBuf[2] ^ tableBuf[5] ^ tableBuf[6] ^ tableBuf[9])); }
else if (tableLen == 11 || tableLen == 12) { kBuf[index] = JHM((int)(tableBuf[2] ^ tableBuf[5] ^ tableBuf[6] ^ tableBuf[9] ^ tableBuf[10])); }
}
else if (index + 1 == 3)
{
if (tableLen == 5) { kBuf[index] = JHM((int)(tableBuf[4])); }
else if (tableLen == 6) { kBuf[index] = JHM((int)(tableBuf[4] ^ tableBuf[5])); } // 6
else if (tableLen >=7 && tableLen <=11) { kBuf[index] = JHM((int)(tableBuf[4] ^ tableBuf[5] ^ tableBuf[6]));} // 7 9
else if (tableLen == 12) { kBuf[index] = JHM((int)(tableBuf[4] ^ tableBuf[5] ^ tableBuf[6] ^ tableBuf[11])); }
}
else if (index + 1 == 4)
{
if (tableLen == 9) { kBuf[index] = JHM((int)(tableBuf[8]));} // 9
else if (tableLen == 10) { kBuf[index] = JHM((int)(tableBuf[8] ^ tableBuf[9])); }
else if (tableLen == 11) { kBuf[index] = JHM((int)(tableBuf[8] ^ tableBuf[9] ^ tableBuf[10])); }
else if (tableLen == 12) { kBuf[index] = JHM((int)(tableBuf[8] ^ tableBuf[9] ^ tableBuf[11] ^ tableBuf[11])); }
}
}
// 填充完善
if (K == 3 || K == 4)
{
tableBuf[0] = (char)(kBuf[0]+48);
tableBuf[1] = (char)(kBuf[1]+48);
tableBuf[3] = (char)(kBuf[2]+48);
if (K == 4) { tableBuf[7] = (char)(kBuf[3] + 48); }
}
if (kBuf) { delete[]kBuf; }kBuf = nullptr;
// 翻转
for (unsigned short index = 0; index < tableLen / 2; ++index)
{
char tmp = tableBuf[index];
tableBuf[index] = tableBuf[tableLen - 1 - index];
tableBuf[tableLen - 1 - index] = tmp;
}
std::cout << tableBuf;
// 调用者需要释放
return tableBuf;
}
关注
笔者 - jxd
微信公众号搜索 “码农总动员” 或 微信扫描下方二维码,了解更多你不知道的XX,O(∩_∩)O