海明(汉明)码是广泛采用的一种有效的校验码,它实际上是一种多重奇偶校验码。
海明码的原理就是在有效信息位中加入几个校验位形成海明码,并把海明码的每一个二进制分配到几个奇偶校验中。当某一位出错的时候,不仅能检错,还能发现出错位的位置。假设校验位有k位,那么校验码最多有2k个,显然其中有一个校验码是正确的,那么就能校验出2k-1个错位。所以,如果能满足一个n位数n+k<=2k-1,则在理论上即可判断出哪一位数出错。
有兴趣可以看我的另一文对 海明码原理校验方法
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