CRC冗余生成及校验
前阵子写的一个CRC冗余计算的代码. - 不同类型的 CRC 矩阵直接丢二进制了 - 由于奇偶校验是一种特殊的 CRC, 直接一起写了
#include <iostream>
#include <bitset>
enum CRCType {CRC1, CRC4, CRC16, CRC32};
unsigned long leftMove(CRCType type) {
switch (type) {
case CRC1:
return 1;
break;
case CRC4:
return 4;
break;
case CRC16:
return 16;
break;
case CRC32:
return 32;
default:
return 0;
break;
}
}
unsigned long generalPolynomial(CRCType type) {
switch (type) {
case CRC1:
return 0x2;
case CRC4:
return 0x13;
break;
case CRC16:
return 0x18005;
break;
case CRC32:
return 0x104800007;
break;
default:
break;
}
}
/**
* 自用转成二进制输出
*
* @param value 输出值
*/
void log(unsigned long value) {
std::cout << std::bitset<sizeof(unsigned long)*8>(value) << std::endl;
}
/**
* 寻找1出现的最高位
*
* @param crc 现在的冗余值
*
* @return 返回位数
*/
unsigned long leftOffset(unsigned long crc) {
unsigned long length = sizeof(unsigned long)*8;
for (unsigned long i = length - 1; i < length; i--) {
unsigned long key = crc >> i;
if (key == 0x01) { return i;}
}
return 0;
}
/**
* 生成CRC
*
* @param originValue 原值
* @param type CRC类型
*
* @return 返回拼接后的编码值
*/
unsigned long generalCRC(unsigned long originValue, CRCType type) {
// 原编码移位
originValue = originValue << leftMove(type);
unsigned long CRCValue = originValue;
// 获取表达式
unsigned long polynomial = generalPolynomial(type);
unsigned long offset;
while ( (offset = leftOffset(CRCValue)) >= leftMove(type) ) {
// log(CRCValue);
// log(polynomial << (offset - (unsigned long)leftMove(type)));
CRCValue = CRCValue ^ (polynomial << (offset - (unsigned long)leftMove(type)));
// log(CRCValue);
// std::cout << std::endl;
}
std::cout << "冗余码计算结果:" << std::endl;
log(CRCValue);
std::cout << "待添加的编码:" << std::endl;
log(originValue);
originValue = originValue | CRCValue;
std::cout << "生成码计算结果:" << std::endl;
log(originValue);
std::cout << "Over" << std::endl << std::endl;
return originValue;
}
/**
* 检查CRC
*
* @param receivedValue 接受的值
* @param type CRC类型
*
* @return 返回判断结果
*/
bool checkCRC(unsigned long receivedValue, CRCType type) {
// 用户匹配出生成的冗余值的掩码
// unsigned long maskValue = (0x1 << leftMove(type)) - 1;
// 提取的冗余值
// unsigned long checkValue = receivedValue & maskValue ;
// log(checkValue);
/**
* 貌似上面这两货算出来也没什么用诶+_+ 真是醉了
*/
// 获取表达式
unsigned long polynomial = generalPolynomial(type);
unsigned long offset;
while ( (offset = leftOffset(receivedValue)) >= leftMove(type) ) {
// log(receivedValue);
// log(polynomial << (offset - (unsigned long)leftMove(type)));
receivedValue = receivedValue ^ (polynomial << (offset - (unsigned long)leftMove(type)));
// log(receivedValue);
// std::cout << std::endl;
}
if (receivedValue == 0x0) {
return true;
}
return false;
}
/**
* 用于随机翻转几位可怜的编码
*
* @param thePoorvalue 待破坏的值
* @param type CRC类型
* @param fuckTimes 破坏的位数
*
* @return 翻转后的值
*/
unsigned long randomDestory(unsigned long thePoorvalue, CRCType type, unsigned int fuckTimes) {
unsigned long resultValue = thePoorvalue;
srand((int)time(0));
unsigned int changedPosition = rand() % 32;
std::cout << "原值:\n";
log(resultValue);
for (int i = 0; i < fuckTimes; i++) {
unsigned long maskValue = 0x1 << changedPosition;
std::cout << "改变了倒数第" << changedPosition + 1 << "位\n";
resultValue = resultValue ^ maskValue;
log(resultValue);
changedPosition = changedPosition * changedPosition % 32;
}
return resultValue;
}
int main(int argc, const char * argv[]) {
unsigned long checkedValue;
checkedValue = 0x123456790;
CRCType valueCRCType = CRC4;
std::cout << "第一次直接判断\n\n";
unsigned long resultValue = generalCRC(checkedValue, valueCRCType);
if (checkCRC(resultValue, valueCRCType)) {
std::cout << "校验正确\n\n\n";
} else {
std::cout << "校验错误\n\n\n";
}
/**
* 破坏一下下, 生成新的resultValue
*/
std::cout << "进行破坏\n";
resultValue = randomDestory(checkedValue, valueCRCType, 2);
/**
* 再次检查
*/
std::cout << "第二次判断\n\n";
if (checkCRC(resultValue, valueCRCType)) {
std::cout << "校验正确\n\n\n";
} else {
std::cout << "校验错误\n\n\n";
}
// generalCRC(0x1234, CRC16);
return 0;
}