CRC循环校验C语言版本

本来已经写过一篇相关的文章,但总觉得跟书本上定义的实现算法不一样很不爽,所以按照书本上的定义,又重新编写了一遍,在这里我只跟上一篇文章做比较简单说明一下。

本次代码是基于国际标准生成码CRC16编写测试的,代码里面的注释有体现,这里就不赘述了。我只说一下它怎么实现的,copy之后怎么使用吧:
首先是算法——完全按照教材规定的计算信息码、冗余码的方式编写测试的,如果不清楚请先自行百度“crc校验”;
其次是它的局限性:这段代码把所有的从键盘输入的内容视为ASCII字符串,注意如果输入中文是没办法计算冗余码的(如果是中文输出会打印出“??”,后面我会给一个程序跑起来的图片),程序以字节为单位,将待发送的单字节信息计算为32位的int型数据,后面反向解析信息码时也是以每个32位的整型数据为单位计算结果为一个字节的char型字符。
最后是使用说明:主函数是一个可人控终止其运行的、里面把输入的信息先CRC计算再解析的一段程序。
附图如下:
先来正常运行的
在这里插入图片描述

上图中每个char字符计算一次冗余码和真正发送的信息码,没问题!
再看下一张:
在这里插入图片描述

看到了吧,识别不了中文,每个中文字符(两个字节)会打印出两个“?”。所以不要用它发中文给女神表白,会翻车的!?

#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;
}
发布了25 篇原创文章 · 获赞 9 · 访问量 6204

猜你喜欢

转载自blog.csdn.net/qq_42144047/article/details/90241248
今日推荐