本来已经写过一篇相关的文章,但总觉得跟书本上定义的实现算法不一样很不爽,所以按照书本上的定义,又重新编写了一遍,在这里我只跟上一篇文章做比较简单说明一下。
本次代码是基于国际标准生成码CRC16编写测试的,代码里面的注释有体现,这里就不赘述了。我只说一下它怎么实现的,copy之后怎么使用吧:
首先是算法——完全按照教材规定的计算信息码、冗余码的方式编写测试的,如果不清楚请先自行百度“crc校验”;
其次是它的局限性:这段代码把所有的从键盘输入的内容视为ASCII字符串,注意如果输入中文是没办法计算冗余码的(如果是中文输出会打印出“??”,后面我会给一个程序跑起来的图片),程序以字节为单位,将待发送的单字节信息计算为32位的int型数据,后面反向解析信息码时也是以每个32位的整型数据为单位计算结果为一个字节的char型字符。
最后是使用说明:主函数是一个可人控终止其运行的、里面把输入的信息先CRC计算再解析的一段程序。
如下图:
上图中每个char字符计算一次冗余码和真正发送的信息码,没问题!
再看下一张:
目前只支持ASCII码,不支持中文。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
unsigned crc16=0x00018005; //生成码CRC-16: 11000000000000101的十进制表示
int countBit(unsigned x) //计算某二进制整数里面'1'的个数
{
int i=0;
do
{
x=x>>1;
i++;
}while(x>0);
return i; //返回'1'的个数
}
unsigned Calcrc_16Send(unsigned x)//计算CRC检验的发送码
{
printf("原数据=%d\t",x); //调试可取消注释
int i;
unsigned y=x; //保存原始数据
for(i=0;i<16;i++) //计算校验码
{
x=x<<1;
if(x>0xffff)
{
x=x^crc16;
}
}
printf(" 冗余码=%#0x\t",x); //调试可取消注释
y=y<<16; //由于生成码17位,故原始数据左移16位
y=y|x; //相当于加上校验码,得到发送码
printf(" 发送码=%#0x\n",y); //调试可取消注释
return y;
}
char checkMess(unsigned x)//反向计算发送吗,检验收到的信息
{
unsigned y=x;
int le=1;
if(x==0)
{
return 0;
}
if(x!=0)
{
while(le)
{
le=countBit(y)-countBit(crc16); //计算原始信息与国际标准CRC-16之间'1'的差值
y=y^(crc16<<le); //求得发送码对生成码求模
if(y==0) //如果余数为0
{
return x>>16; //返回求得的信息码
}
}
}
return '?'; //如果信息码不是ascii码,则返回‘?’
}
int main()
{
int f=1,i,j;
char me[81],tm[81]; //注意每次测试的字符串不能超过80,长度可修改
unsigned bu=0;
while(f)
{
system("cls"); //清屏
fflush(stdin); //清楚缓存区数据
printf("请输入要发送的信息:\n");
gets(me);
j=strlen(me);
for(i=0;i<j;i++)
{
bu=Calcrc_16Send(me[i]); //先计算出发送码
tm[i]=checkMess(bu); //再反向求出信息码
}
tm[j]='\0';
puts(tm); //输出信息码,人为检验
printf("是否继续测试(Yes--1,No--0)?\n");
scanf("%d",&f);
}
return 0;
}