C语言实现 汉明码校验仿真

基本要求
选择一种校验方法用高级语言编写代码来实现对存储器读写校验的仿真。
基本思想
以汉明码为容错编码来实现存储器读写校验的仿真实验。
1、 输入要传送的二进制数,按照配偶原则来配置汉明码。
2、 输入接收到的汉明码,更根据汉明码的纠错过程(假设仅仅只有一个数个数为发生错误,因为汉明码是具有一位纠错能力的编码)对接收到的汉明码进行校验。

 对新增添的检测位数k的确定
设欲检测的二进制代码为n位,为使其具有纠错能力,需增添k位检测位,组成n+k位的代码(即汉明码)。更具公式
2^k >= n + k + 1
可以计算出k的值。
代码实现 while(1<<p[0]<p[0]+bin[0]+1)p[0]++;
( << 左移运算符, 1<<p[0]相当于把1的二进制值左移p[0]位,左移1位相当于乘以2,那么左移n位就是乘以2的n次方了。k = p[0];)
 对新增添的检测位的位置确定
设n+k位代码自左至右依次编为第1,2,3,……,n+k位,而将k位检测位记作Ci(i=1,2,4,8,……),分别安插在n+k位代码编号的第1,2,4,8,……,2^(k-1)位上。这些检测位的位置设置是为了保证它们能分别承担n+k位的信息中不同数位所组成的“小组”的奇偶检测任务。由汉明码检测位位置的特点,可以根据 <<(左移运算符),
循环{
1 << i ;
i ++; (i初始为0) }
来确定检测位的位置。
 对新增添的检测位所负责检测小组的位的确定
根据对汉明码的了解,检测位和它所负责检测的小组的具体分配如下:
C1检测的小组包含1,2,4,7,9,11,……位
C2检测的小组包含2,3,6,7,10,11,14,15,……位
C4检测的小组包含4,5,6,7,12,13,14,15,……位
根据小组划分的特点,通过以下代码来实现找到检测的小组的各个位:

1.	//找到汉明码检测小组中的各个位
2.	int pos(int i){ //找到汉明码检测小组中的各个位
3.	    int c=0;
4.	    int pos=2,n=4;
5.	    while(c<i){
6.	        pos++;
7.	        if(pos==n)n*=2,c--;
8.	        c++;
9.	    }
10.	    return pos;
11.	}

 对新增添的检测位的值的确定
找到每个检测位所负责的小组的各个位,把每个检测位所负责检测的小组位上的二进制数加起来,对其和进行摸2计算。按配偶原则配置,当检测小组的1为奇数个时,其和摸2的结果为1,则检测位的值为1;当检测小组的1为偶数个时,其和摸2的结果为0,则检测位的值位0。

代码实现

#include<bits/stdc++.h>

//输入二进制数
void in_bin(int bin[]){
    char binary[100];
    int i=0;
    printf("请输入要传送的二进制数:");
    scanf("%s",binary);
    while(binary[i]){
        bin[i+1]=binary[i]-48;
        i++;
    }
    bin[0]=i;//bin[0]记录输入的二进制数的个数 
}

//输出二进制数
void out_bin(int bin[]){
    printf("输入要传送的二进制数:");
    for(int i=1;i<=bin[0];i++){
        printf("%d",bin[i]);
    }
    printf("\n");
}

//输出汉明码位上的数
void out_p(int p[]){
    printf("汉明码位上的数为:");
    for(int i=1;i<=p[0];i++){
        printf("%d",p[i]);
    }
    printf("\n");
}

//输出汉明码
void out_haiming(int bin[],int p[],int place=0){
    printf("汉明码为:");
    int i,n=1;
    int pp=1,pb=1;
    for(i=1;i<=bin[0]+p[0];i++)
        if(i==n){
            printf("%d",p[pp++]);
            n=n*2;
        }
        else{
            printf("%d",bin[pb++]);
        }
    printf("\n");
}

//找到汉明码检测小组中的各个位
int pos(int i){//找到汉明码检测小组中的各个位
    int c=0;
    int pos=2,n=4;
    while(c<i){
        pos++;
        if(pos==n)n*=2,c--;
        c++;
    }
    return pos;
}

//计算汉明码检测位上的值
void in_p(int p[],int bin[]){
    int i,j;
    p[0]=1;
    while(1<<p[0]<p[0]+bin[0]+1)p[0]++;//此语句求新增添的检测位的个数:公式->2^k>=n+k+1
//	<< 左移运算符, 1<<p[0]相当于把1的二进制值左移p[0]位,左移1位相当于乘以2,那么左移n位就是乘以2的n次方了
//	p[0]记录汉明码的个数; 
//    printf("汉明码个数:%d\n",p[0]);//输出汉明码的个数
    for(i=1;i<100;i++)p[i]=0;//初始化
    for(i=1;i<=p[0];i++){
        for(j=1;j<=bin[0];j++){
//            printf("%d ",pos(j)&(1<<(i-1))); //确定k位检测位分别安插的代码位的编号
            if(pos(j)&(1<<(i-1))){
//            	printf("%d",j);
//				printf("%d",pos(j));
//				printf("%d",1<<(i-1));
                p[i]=(p[i]+bin[j])%2;
				//printf("%d",pos(j));
				//printf("%d",j);
            }
			//printf("\n%d",i);
        }
    }
 }
 
//输入接收到的汉明码 
void in_reacice(int r[]){
	char recive[100];
    int i=0;
    scanf("%s",recive);
    while(recive[i]){
        r[i+1]=recive[i]-48;
        i++;
    }
    r[0]=i;//r[0]记录输入的二进制数的个数 
}

//校验接收到的汉明码是否出错
void  check_reacive(int p[],int r[],int q[]){
	int i,j,k;
	int flag[100];
	int bins[100];
	for(i=0;i<100;i++)q[i]=0;//初始化
	
	k = 1;
	for(i=0;i<p[0];i++){
		flag[k] = 1<<i;//记录汉明码检测位的位置 
		q[k] = r[flag[k]];//记录汉明码检测位所在的值 
		k ++; 
		flag[0] ++;
		q[0] ++;
    }
    int c = 0;
    k = 1;
    bins[0] = 0;
	for(i = 1;i <= r[0];i ++){
		c = 0;
		for(j = 1;j <= flag[0];j ++){
			if(i == flag[j]) c = 1;
		}
		if(c == 0){
			bins[k] = r[i];//把汉明码的检测位与实际传入的二进制数进行分离 
			k ++;
			bins[0] ++; 
		}
	}
	//纠错 
	for(i=1;i<=q[0];i++){
        for(j=1;j<=bins[0];j++){
            if(pos(j)&(1<<(i-1))){
                q[i]=(q[i]+bins[j])%2;
            }
        }
    }
    int y = q[0] - 1;
    int s = 0;
    for(i = q[0];i > 0;i --){
    	s += (1<<y) * q[i]; //计算最后出现错误的位置 
    	y --;
	}
	if(s == 0){
		printf("\n传送和接收过程中,信息未出现错误!\n"); 
	}else{
		printf("\n错误!!!汉明码的第%d位出现错误!",s);
		
		if(r[s] == 1){
			r[s] = 0;
		}else{
			r[s] = 1;
		}
		printf("\n\n纠错后的汉明码为:");
		for(i = 1;i <= r[0];i ++){
			printf("%d",r[i]);
		}
		printf("\n");
	}
	 
} 
 
int main(){
    int bin[100];
    int p[100];
    int r[100];
	int q[100];
	 
    in_bin(bin);
    in_p(p,bin);
    out_bin(bin);
    out_p(p);
    out_haiming(bin,p);
    printf("-----------------------------\n");
    printf("请输入接收到的汉明码:"); 
    in_reacice(r);
	check_reacive(p,r,q);
	
	return 0;
}

测试样例数据显示:
测试1.(校验四位二进制数)
在这里插入图片描述

测试2.(校验六位二进制数)
在这里插入图片描述

测试3.(校验七位二进制数)
在这里插入图片描述

测试4.(校验十五位二进制数)
在这里插入图片描述


个人认为最难解决的是对检测位的值的确定,检测位的个数可以通过对 <<(左移运算符) 很轻易的根据公式计算出来,检测位所在的位置也可以根据 << (左移运算符)的特点很容易的得到,然而检测位的值的确定是对每个检测位所负责的检测小组的1 的个数的奇偶判断,只有了解了对检测小组的划分特点,解决了检测小组的各个位的的位置计算后,一切问题都迎刃而解了。

  • 14
    点赞
  • 76
    收藏
    觉得还不错? 一键收藏
  • 13
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值