C语言CRC校验码计算与校验

文章介绍了循环冗余校验(CRC)的概念,它是通过多项式除法进行错误检测的一种方法。在发送端,数据被一个预设的生成多项式去除,附加余数。接收端同样进行除法,若余数不为零,则表明传输有误。文中提供了一个C程序示例,用于将学号转换为二进制并计算CRC校验码,最后进行校验。
摘要由CSDN通过智能技术生成

循环冗余校验(cyclicredundancy check,CRC)对传输序列进行一次规定的除法操作,将除法操作的余数附加在传输信息的后面。在接收端,也对收到的数据做相同的除法。如果接收端除法得到的结果其余数不是零,就表明发生了错误。

循环冗余校验是将要发送的数据位序列当作一个多项式f(x)的系数,f(x)的系数只有1与0两种形式。在发送方用收发双方预定的约定的生成多项式G(x)去除,求得一个余数多项式。将余数多项式加到数据多项式之后发送到发送端。这里的除法是错位不减的模2减法,相当于异或运算。接收端采用同样的生成多项式G(x)去除接收到的数据多项式f’(x),如果传输无差错,则接收端除法运算f’(x)/G(x)的结果,其余数为零。否则就认为出现了差错。

基于除法的循环冗余校验,其计算量大于奇偶与求和校验,其差错检测的有效性也比较高,它能够检测出大约99.95%的错误。

CRC校验计算除法的公式举例

程序流程图

C程序

  #include<stdio.h>
  #include<stddef.h> //这个库里包含sizeof 
    int find(int a[],int n);
    void display(int a[],int n);
    int main()
{
    
    int i,j,z;
    long long num;
    int snum[35]={0}; 
    int res[51]={0}; //计算结果 
    int cal[51];
    int ns;
    int pol[17]={1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1};//CRC多项式 
    int np;
    int first;
    
    //输入学号进行并转成二进制 
    printf("请输入学号: ");
    scanf("%lld",&num);
    i=0;
    j=2;
    while(j) //除二的方法转成二进制 
    {
        if(num%2==1)
        {
            snum[i]=1;
        }
        if(num%2==0)
        {
            snum[i]=0;
        }
        num=num/2;
        if(num==0)
        {
            j--;
        }
        i++;
    }
    printf("\n学号的二进制:\n");    
    display(snum,35);

    //进行计算准备(加尾部的零) 
    ns=sizeof(cal)/sizeof(cal[0]);  //判断数组元素个数 
    np=sizeof(pol)/sizeof(pol[0]);  
    i=35+np-1;
    j=0;
    z=0;
    while(i)
    {
        if(j<np-1)
        {
        cal[j]=0;
        }
        if(j>=np-1)
        {
            cal[j]=snum[z];
            z++;
        }
        i--;
        j++;
    }
        
    // 计算校验码 
    printf("\n采用CRC-16\n多项式为:x^16+x^15+x^2+1\n");
    printf("\n输出计算过程:\n"); 
    first=find(cal,ns);
    display(cal,ns);
    while(first>np-2) //按位异或 
    {    
        j=0;
        for(i=first-np+1;i<=first;i++)
        {
            if(cal[i]==pol[j])
            {
                cal[i]=0;
            }
            else
            {
                cal[i]=1;
            }
            j++;
        }
        first=find(cal,ns);
        display(cal,35+np-1);
    }

    //将原码与校验码合在一起 
    i=35+np-1;
    j=0;
    z=0;
    while(i)
    {
        if(j<np-1)
        {
        res[j]=cal[j];
        }
        if(j>=np-1)
        {
            res[j]=snum[z];
            z++;
        }
        i--;
        j++;
    }
    printf("\n计算结果为:\n");
    display(res,35+np-1);
    
    //进行冗余检验
    while(first>0) //按位异或 
    {    
        j=0;
        for(i=first-np+1;i<=first;i++)
        {
            if(res[i]==pol[j])
            {
                res[i]=0;
            }
            else
            {
                res[i]=1;
            }
            j++;
        }
        first=find(res,ns);
        }
    printf("\n校验结果:\n");
    display(res,35+np-1);
    return 0;
}

    int find(int a[],int n) //find函数给一个数组和其长度 找出第一个非零元素位置 
{
    int i;
    i=n-1;
    while(a[i]==0)
    {
    if(i==0)
    {
        break;
    }
        i--;
    }
    return i;
}

 
     void display(int a[],int n) //显示数组 
 {
     while(n)
     {
     printf("%d",a[n-1]);
     n--;
     }
     printf("\n");
 }

程序运行结果

程序的CRC校验码计算采用交互式的设计,输入一个数据进行计算反馈结果,并进行模拟校验,如果计算无误(在实际应用中传输无误)校验结果显示全为0

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值