数据校验
原因
数据在存储和传送过程中会发生错误,产生错误的原因有很多,例如外界高频干扰,除了提高硬件质量以外,还应该在数据编码上下文章
校验基础
当我们进行编码时,任意一个编码都由码字组成
例如用二进制表示16为10000,表示15为1111
任意两个码字之间最少变化的二进制的位数称为数据校验码的码距。
只有码距大于1时,才可以进行校验。这是因为码距为1的情况下,当一个合法码出现一位或者几位码字错误时,通常会变成另外一个合法码字。例如,使用4个二进制位表示0到15,此时的码距为1。但是如果使用4个二进制位表示0到3时,采用如下的编码方式:
字符 | 二进制表示 |
---|---|
0 | 0000 |
1 | 0101 |
2 | 0110 |
3 | 1001 |
此时的码距将变成2,当其中任何一个编码出现一位错误,从0变成1;或者从1变成0时,它将成为非法编码。此时我们就知道其出现错误。
校验的的原理就是在原有的编码中插入校验位,使码距大于1,这是最基本的要求,如果能使码距均匀的增大,如同上表所示时,校验的能力将进一步增强
编程实现汉明码校验逻辑
- 实现汉明码校验逻辑
- 模拟码字出现错误时,使用汉明码进行校验的结果
处理思路
根据有效的信息位数N和下面的公式求出校验码的位数K
2
K
−
1
≥
N
+
K
+
1
2^{K-1}\geq N+K+1
2K−1≥N+K+1
下表给出常用的信息位N和K之间的关系:
N值 | 最小K值 | N值 | 最小K值 |
---|---|---|---|
1~3 | 4 | 26~56 | 7 |
4~10 | 5 | 57~119 | 8 |
11~25 | 6 |
接下来将校验码插入到有效信息位当中,插入的规则是:
- 编号:将汉明码编号依次为 H m H m − 1 . . . H 2 H 1 H_mH_{m-1}...H_2H_1 HmHm−1...H2H1
- 插入校验位:每个校验位 P i P_i Pi分到位号为 2 i − 1 2^{i-1} 2i−1的位置上,当位置编号大于m时,改为m,其中 i = 0 , 1 , . . . i=0,1,... i=0,1,...
- 校验规则:汉明码的每一位
H
i
H_i
Hi由多个校验位校验,其关系是被校验的每一位位号等于校验它的各校验位的位号之和,即汉明码的位号实质上是参与校验的各校验位权值之和。举例说明如下
N=8时,K=5
插入校验位以后变成:
P 5 D 8 D 7 D 6 D 5 P 4 D 4 D 3 D 2 P 3 D 1 P 2 P 1 P_5 \ \ D_8 \ \ D_7 \ \ D_6 \ \ D_5 \ \ P_4 \ \ D_4\ \ D_3 \ \ D_2 \ \ P_3 \ \ D_1 \ \ P_2 \ \ P_1\\ P5 D8 D7 D6 D5 P4 D4 D3 D2 P3 D1 P2 P1
使用 X i X_i Xi表示内容为 i 的位号,则有:
X D 1 = 3 = X P 2 + X P 1 X D 2 = 3 = X P 3 + X P 1 X D 3 = 3 = X P 3 + X P 2 X D 4 = 3 = X P 3 + X P 2 + X P 1 X D 5 = 3 = X P 3 + X P 2 + X P 1 X D 6 = 3 = X P 4 + X P 2 X D 7 = 3 = X P 4 + X P 2 + X P 1 X D 8 = 3 = X P 4 + X P 3 \begin{align*} &X_{D_1}=3=X_{P_2}+X_{P_1}\\ &X_{D_2}=3 =X_{P_3}+X_{P_1}\\ &X_{D_3}=3 =X_{P_3}+X_{P_2}\\ &X_{D_4}=3 =X_{P_3}+X_{P_2}+X_{P_1}\\ &X_{D_5}=3 =X_{P_3}+X_{P_2}+X_{P_1}\\ &X_{D_6}=3 =X_{P_4}+X_{P_2}\\ &X_{D_7}=3 =X_{P_4}+X_{P_2}+X_{P_1}\\ &X_{D_8}=3 =X_{P_4}+X_{P_3} \end{align*} XD1=3=XP2+XP1XD2=3=XP3+XP1XD3=3=XP3+XP2XD4=3=XP3+XP2+XP1XD5=3=XP3+XP2+XP1XD6=3=XP4+XP2XD7=3=XP4+XP2+XP1XD8=3=XP4+XP3 - 收集:观察上面的等式,等式右边含有校验位
p
1
p_1
p1的等式左边对应的信息位,如下
D 7 D 5 D 4 D 2 D 1 D_7 \ \ D_5 \ \ D_4 \ \ D_2 \ \ D_1 D7 D5 D4 D2 D1
对上述位进行偶校验得到
P 1 = D 7 ⨁ D 5 ⨁ D 4 ⨁ D 2 ⨁ D 1 P_1=D_7 \bigoplus D_5 \bigoplus D_4 \bigoplus D_2 \bigoplus D_1 P1=D7⨁D5⨁D4⨁D2⨁D1 - 根据上面分析,便可以得到完整的校验公式
P 1 = D 1 ⨁ D 2 ⨁ D 4 ⨁ D 5 ⨁ D 7 P 2 = D 1 ⨁ D 3 ⨁ D 4 ⨁ D 6 ⨁ D 7 P 3 = D 2 ⨁ D 3 ⨁ D 4 ⨁ D 8 P 4 = D 5 ⨁ D 6 ⨁ D 7 ⨁ D 8 P_1=D_1 \bigoplus D_2 \bigoplus D_4 \bigoplus D_5 \bigoplus D_7\\ P_2=D_1 \bigoplus D_3 \bigoplus D_4 \bigoplus D_6 \bigoplus D_7\\ P_3=D_2 \bigoplus D_3 \bigoplus D_4 \bigoplus D_8 \\ P_4=D_5 \bigoplus D_6 \bigoplus D_7 \bigoplus D_8 \\ P1=D1⨁D2⨁D4⨁D5⨁D7P2=D1⨁D3⨁D4⨁D6⨁D7P3=D2⨁D3⨁D4⨁D8P4=D5⨁D6⨁D7⨁D8
在上述公式中, D 4 , D 7 D_4,D_7 D4,D7出现了三次,而 D 1 , D 2 , D 3 , D 5 , D 6 , D 8 D_1,D_2,D_3,D_5,D_6,D_8 D1,D2,D3,D5,D6,D8仅出现了两次,为此再补充 P 5 P_5 P5
P 5 = D 1 ⨁ D 2 ⨁ D 3 ⨁ D 5 ⨁ D 6 ⨁ D 8 P_5=D_1\bigoplus D_2\bigoplus D_3\bigoplus D_5\bigoplus D_6\bigoplus D_8 P5=D1⨁D2⨁D3⨁D5⨁D6⨁D8
此时任何一个信息位发生变化,必将引起3个 P i P_i Pi的值跟着改变,即合法的汉明码的码距都是4
6.校验:将接收到的汉明码按如下的关系进行偶校验
S 1 = P 1 ⨁ D 1 ⨁ D 2 ⨁ D 4 ⨁ D 5 ⨁ D 7 S 2 = P 2 ⨁ D 1 ⨁ D 3 ⨁ D 4 ⨁ D 6 ⨁ D 7 S 3 = P 3 ⨁ D 2 ⨁ D 3 ⨁ D 4 ⨁ D 8 S 4 = P 4 ⨁ D 5 ⨁ D 6 ⨁ D 7 ⨁ D 8 S 5 = P 5 ⨁ D 1 ⨁ D 2 ⨁ D 3 ⨁ D 5 ⨁ D 6 ⨁ D 8 S_1=P_1\bigoplus D_1 \bigoplus D_2 \bigoplus D_4 \bigoplus D_5 \bigoplus D_7\\ S_2=P_2\bigoplus D_1 \bigoplus D_3 \bigoplus D_4 \bigoplus D_6 \bigoplus D_7\\ S_3=P_3\bigoplus D_2 \bigoplus D_3 \bigoplus D_4 \bigoplus D_8 \\ S_4=P_4\bigoplus D_5 \bigoplus D_6 \bigoplus D_7 \bigoplus D_8 \\ S_5=P_5\bigoplus D_1\bigoplus D_2\bigoplus D_3\bigoplus D_5\bigoplus D_6\bigoplus D_8 S1=P1⨁D1⨁D2⨁D4⨁D5⨁D7S2=P2⨁D1⨁D3⨁D4⨁D6⨁D7S3=P3⨁D2⨁D3⨁D4⨁D8S4=P4⨁D5⨁D6⨁D7⨁D8S5=P5⨁D1⨁D2⨁D3⨁D5⨁D6⨁D8 - 结果分析:
这里暂且只考虑一位发生错误的情况,因为在汉明码中同时发生两位和三位错误的概率很小。但是还是通过代码模拟了两位,三位甚至是多为发生错误的情况,但是发现和教材上有出入,然后我也发电子邮件给作者了。接下来就简单介绍一下纠错的过程。
(1) S 5 S 4 S 3 S 2 S 1 S_5S_4S_3S_2S_1 S5S4S3S2S1为全0时,表明无错
(2) S 5 S 4 S 3 S 2 S 1 S_5S_4S_3S_2S_1 S5S4S3S2S1有三位不为0时,说明有一位信息位出错或者三位校验位出错,由于后一种可能性很小,通常都是前一种错误,出错的位号由 S 4 S 3 S 2 S 1 S_4S_3S_2S_1 S4S3S2S1这四位代码指明,此时不仅能检错,还可以纠错,将该位变反
设计
!!!!!所使用的数组类型均自定义,其中0号单元不使用!!!!
1. getMessage方法:接收用户输入的有效的信息,使用message数组进行存储,根据用户的输入动态分配相应的存储空间
8 16 32 64 128
2. computerCheckcode方法:计算校验码的位数:
(1)根据公式进行计算,暂且保留2^(K-1)>=N+K+1,使用暴力法可以求出K值
(2)直接查表计算
N K
1~3 4
4~10 5
11~15 6
3. insertCheck方法:在对应位置插入校验位,初始的时候每个校验位值为0,插入的位置满足2^(i-1)
1 2 4 8 16 32 ……最后一位
重新申请K+N的空间,记为hamming
使用变量index记录message里面元素移动到hamming数组里面的个数
i从1开始递增,当2^i 小于等于hamming的长度时执行如下操作
hamming[2^i]=0
j从2^i+1递增到2^(i+1)-1
hamming[j]=message[index++]
i++
4. generateCheckcode方法:生成偶校验公式,一共有K(校验位的数目)个公式,每一个公式包含很多的异或运算
定义DS二维数组(N+k)*(K)
遍历一遍hamming数组
在每一趟循环中,当前元素不是校验位时,计算下标(从1开始计数)对应的二进制代码,储存在DS数组的对应行
定义PS二维数组:K*(N)
Ps里面的第i行,存储的是pi校验位 校验的Di对应在hanmming数组(汉明码)里面的位置,举例说明
p1校验位校验D1,D2,D4,D5,D7,它们在汉明数组里面的位置是3,5,7,9,11
于是Ps数组第1行储存3,5,7,9,11
定义counts数组,长度为N+K+1,0号单元不使用,count[i]表示在hammming数组中位置为i的信息为在校验公式中出现的次数
处理DS数组
按列的顺序从右往左遍历DS数组
按行的方式从上到下遍历DS数组
元素内容为1时
记录当前位置的行坐标i在PS数组对应的位置,使用变量p表示下一记录的位置,记录完成之后p++
counts[i]++
遍历conts数组,找到最大值max
遍历counts数组,如果count[i]<max&&count[i]不为0,使用P来记录下i在Ps第K行里面的位置,在p位置赋值,p++
经过上述分析,所有的校验公式都已经生成
5. check方法:根据校验公式确定校验位
申请空间为K的数组result,存储校验位
遍历Ps数组
遍历行,行标i
遍历列,列标j
进行异或运算:result.elems[0]=result.elems[0]异或hamming[Ps.elems[i][j]]
返回result
6. insert方法:将上述返回的result(校验位插入到)填入hamming数组合适的位置(调用insert方法,实现思路和insertCheck方法类似)
7. simulation方法:模拟汉明码一位或者某几位出现错误,然后进行偶校验
可以使用循环模拟1位,两位甚至是多位出错的情况
8. finish方法:输出校验的结果,一共有K位,其中K-1位为有效位,正确结果全为0
接收正确的hamming数组hamming和突变后的errorCode
对errorCode进行偶校验,即调用check方法,得到ds_checks
对errorCode调用getCheck方法,返回在errorCode中所有的校验位ps_checks
遍历ps_checks数组
ds_checks[i]=ds_checks[i]异或ps_checks[i]
打印输出相关信息
测试数据:
N=8
K=5
message=10101100
详细代码
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
typedef struct
{
int *elems;
int length;
} Array;
typedef struct
{
/* data */
int **elems;
int m;
int n;
} Matrix;
/*
!!!!!所使用的数组类型均自定义,其中0号单元不使用!!!!
1. getMessage方法:接收用户输入的有效的信息,使用message数组进行存储,根据用户的输入动态分配相应的存储空间
8 16 32 64 128
2. computerCheckcode方法:计算校验码的位数:
(1)根据公式进行计算,暂且保留2^(K-1)>=N+K+1,使用暴力法可以求出K值
(2)直接查表计算
N K
1~3 4
4~10 5
11~15 6
3. insertCheck方法:在对应位置插入校验位,初始的时候每个校验位值为0,插入的位置满足2^(i-1)
1 2 4 8 16 32 ……最后一位
重新申请K+N的空间,记为hamming
使用变量index记录message里面元素移动到hamming数组里面的个数
i从1开始递增,当2^i 小于等于hamming的长度时执行如下操作
hamming[2^i]=0
j从2^i+1递增到2^(i+1)-1
hamming[j]=message[index++]
i++
4. generateCheckcode方法:生成偶校验公式,一共有K(校验位的数目)个公式,每一个公式包含很多的异或运算
定义DS二维数组(N+k)*(K)
遍历一遍hamming数组
在每一趟循环中,当前元素不是校验位时,计算下标(从1开始计数)对应的二进制代码,储存在DS数组的对应行
定义PS二维数组:K*(N)
Ps里面的第i行,存储的是pi校验位 校验的Di对应在hanmming数组(汉明码)里面的位置,举例说明
p1校验位校验D1,D2,D4,D5,D7,它们在汉明数组里面的位置是3,5,7,9,11
于是Ps数组第1行储存3,5,7,9,11
定义counts数组,长度为N+K+1,0号单元不使用,count[i]表示在hammming数组中位置为i的信息为在校验公式中出现的次数
处理DS数组
按列的顺序从右往左遍历DS数组
按行的方式从上到下遍历DS数组
元素内容为1时
记录当前位置的行坐标i在PS数组对应的位置,使用变量p表示下一记录的位置,记录完成之后p++
counts[i]++
遍历conts数组,找到最大值max
遍历counts数组,如果count[i]<max&&count[i]不为0,使用P来记录下i在Ps第K行里面的位置,在p位置赋值,p++
经过上述分析,所有的校验公式都已经生成
5. check方法:根据校验公式确定校验位
申请空间为K的数组result,存储校验位
遍历Ps数组
遍历行,行标i
遍历列,列标j
进行异或运算:result.elems[0]=result.elems[0]异或hamming[Ps.elems[i][j]]
返回result
6. insert方法:将上述返回的result(校验位插入到)填入hamming数组合适的位置(调用insert方法,实现思路和insertCheck方法类似)
7. simulation方法:模拟汉明码一位或者某几位出现错误,然后进行偶校验
可以使用循环模拟1位,两位甚至是多位出错的情况
8. finish方法:输出校验的结果,一共有K位,其中K-1位为有效位,正确结果全为0
接收正确的hamming数组hamming和突变后的errorCode
对errorCode进行偶校验,即调用check方法,得到ds_checks
对errorCode调用getCheck方法,返回在errorCode中所有的校验位ps_checks
遍历ps_checks数组
ds_checks[i]=ds_checks[i]异或ps_checks[i]
打印输出相关信息
测试数据:
N=8
K=5
message=10101100
*/
/************************************数组,二维数组基础操作************************************************************/
void initArray(Array &array, int length)
{
array.length = length;
array.elems = (int *)malloc(sizeof(int) * (length + 1));
for (int i = 1; i <= length; i++)
{
/* code */
array.elems[i] = 0;
}
}
void copyArray(Array origin, Array &target)
{
initArray(target, origin.length);
for (int i = 1; i <= origin.length; i++)
{
target.elems[i] = origin.elems[i];
}
}
void printArray(Array array)
{
for (int i = array.length; i >= 1; i--)
{
printf("%d\t", array.elems[i]);
}
printf("\n");
for (int i = array.length; i >= 1; i--)
{
printf("%d\t", i);
}
printf("\n");
}
void initMatrix(Matrix &martrix, int m, int n)
{
martrix.elems = (int **)malloc(sizeof(int *) * (m + 1));
for (int i = 1; i <= m; i++)
{
int *row = (int *)malloc(sizeof(int) * (n + 1));
for (int j = 1; j < n + 1; j++)
{
row[j] = 0;
}
martrix.elems[i] = row;
}
martrix.m = m;
martrix.n = n;
}
void printMataix(Matrix matrix)
{
for (int i = 1; i <= matrix.m; i++)
{
for (int j = 1; j <= matrix.n; j++)
{
/* code */
printf("%d ", matrix.elems[i][j]);
}
printf("\n");
}
}
/************************************业务逻辑************************************************************/
// 接收用户输入的有效的信息,使用message数组进行存储
void getMessage(Array &array)
{
int length;
printf("输入有效的信息的位数:\n");
scanf("%d", &length);
printf("输入有效的信息,中间使用空格区分信息元素:\n");
initArray(array, length);
for (int i = length; i >= 1; i--)
{
scanf("%d", &array.elems[i]); // 接收输入
}
}
// 计算校验码的位数
int computerCheckCode(int N)
{
if (N >= 1 && N <= 3)
{
return 4;
}
else if (N <= 10)
{
return 5;
}
else if (N < 15)
{
return 6;
}
else
{
// 根据公式进行计算,暂且保留2^(K-1)>=N+K+1,使用暴力法可以求出K值
int K = 7;
while (2 ^ (K - 1) < N + K + 1)
{
K++;
}
return K;
}
}
// 在对应位置插入校验位,初始的时候每个校验位值为0,插入的位置满足2^(i-1)
void insertCheck(Array message, int K, Array &hamming)
{
int length = message.length + K;
initArray(hamming, length);
int i = 1;
int index = 1;
hamming.elems[1] = 0;
while (pow(2, i) < length)
{
int p = pow(2, i); // 插入校验位
hamming.elems[p] = 0;
int left = p + 1;
int right = 2 * p - 1;
if (right > length)
{
right = length - 1;
}
if (right >= left)
{
for (int j = left; j <= right; j++)
{
hamming.elems[j] = message.elems[index];
index++;
}
}
i++;
}
hamming.elems[length] = 0; // 汉明码最高位为校验位
}
// 内部调用函数,返回x所对应的二进制位,使用数组存储,长度为k,二进制最高位储存在1号单元
// x=5,k=5时00101
// x=4,k=3时0011
Array binary(int x, int k)
{
Array result;
initArray(result, k);
while (x != 0)
{
/* code */
int temp = x % 2;
x = x / 2;
result.elems[k--] = temp;
}
return result;
}
// 内部调用函数,返回数组最大值
int findMax(int array[], int l, int r)
{
int result = array[l];
for (int i = l + 1; i <= r; i++)
{
if (result < array[i])
{
result = array[i];
}
}
return result;
}
// 生成偶校验公式,一共有K(校验位的数目)个公式,每一个公式包含很多的异或运算
void generateCheck(Matrix &Ds, int N, int K, Matrix &Ps, Array hamming)
{
// 定义DS二维数组(N + k) *(K)
// 定义PS二维数组:K *(N)
initMatrix(Ds, N + K, K);
initMatrix(Ps, K, N + K);
// Ps里面的第i行,存储的是pi校验位 校验的Di对应在hanmming数组(汉明码)里面的位置,举例说明
// p1校验位校验D1,
// D2, D4, D5, D7,它们在汉明数组里面的位置是3,5,7,9,11 于是Ps数组第1行储存3,5,7,9,11 int count[N + K + 1];
int i = 1;
int index = 1;
do
{
int left = pow(2, i) + 1;
int right = pow(2, i + 1) - 1;
if (right > hamming.length - 1)
{
right = hamming.length - 1;
}
// 在每一趟循环中,当前元素不是校验位时,计算下标(从1开始计数)对应的二进制代码,储存在DS数组的对应行
for (int j = left; j <= right; j++)
{
Ds.elems[j] = binary(j, K).elems;
index++;
}
i = i + 1;
} while (index <= N);
int count[N + K + 1]; // 0号单元不使用,count [i] 表示在hammming数组中位置为i的信息为在校验公式中出现的次数
for (int i = 1; i < N + K + 1; i++)
{
count[i] = 0;
}
// 按列的顺序从右往左遍历DS数组
for (int j = K; j >= 1; j--)
{
int p = 1;
// 按行的方式从上到下遍历DS数组
for (int i = 1; i <= N + K; i++)
{
if (Ds.elems[i][j] == 1)
{
// 记录当前位置的行坐标i在PS数组对应的位置,使用变量p表示下一记录的位置,记录完成之后p++ counts[i]++
Ps.elems[K - j + 1][p++] = i;
count[i]++;
}
}
}
int max = findMax(count, 1, N);
int k = 1;
for (int i = 1; i < N + K + 1; i++)
{
if (count[i] < max && count[i] != 0)
{
// 遍历counts数组,如果count[i] < max &&count[i] 不为0
// 使用P来记录下i在Ps第K行里面的位置,在p位置赋值,p++
Ps.elems[K][k++] = i;
}
}
}
//内部函数,实现两位的异或运算
int xOr(int a, int b)
{
return (!a & b) | (!b & a);
}
// 开始根据偶校验公式校验计算,连环的异或运算
Array check(Array hamming, Matrix Ps)
{
Array result;
initArray(result, Ps.m);
for (int i = 1; i <= Ps.m; i++)
{
for (int j = 1; j <= Ps.n && Ps.elems[i][j] != 0; j++)
{
// 进行异或运算:result.elems[0]=result.elems[0]异或hamming[Ps.elems[i][j]]
result.elems[i] = xOr(result.elems[i], hamming.elems[Ps.elems[i][j]]);
}
}
return result;
}
//进行total次处理,每次处理随机选取一位从0变1或从1变0
Array simulation(Array hamming, int total)
{
Array copy;
copyArray(hamming, copy);
srand((unsigned)time(NULL));
for (int i = 1; i <= total; i++)
{
int a = rand();
int position = a % (hamming.length - 1 + 1) + 1;
if (i == 1)
{
copy.elems[position] = !hamming.elems[position];
}
else
{
copy.elems[position] = !copy.elems[position];
}
}
return copy;
}
//指定位置的突变,使用数组记录突变的位置
Array simulation(Array hamming, int chagePositions[], int n)
{
Array copy;
copyArray(hamming, copy);
for (int i = 0; i < n; i++)
{
copy.elems[chagePositions[i]] = !hamming.elems[chagePositions[i]];
}
return copy;
}
// 内部函数插入根据校验公式生成的校验位
void insert(Array &hamming, Array check)
{
hamming.elems[1] = check.elems[1];
int i = 1;
while (i <= check.length - 1)
{
int p = pow(2, i);
if (p > hamming.length)
{
p = hamming.length;
}
hamming.elems[p] = check.elems[i + 1];
i++;
}
}
// 内部函数获取校验位
Array getCheck(Array hamming, int K)
{
Array result;
initArray(result, K);
result.elems[1] = hamming.elems[1];
int i = 1;
while (i <= K - 1)
{
/* code */
int p = pow(2, i);
if (p > hamming.length)
p = hamming.length;
result.elems[++i] = hamming.elems[p];
}
return result;
}
// 最终检查,校验
void finish(Array hamming,Array errorCode, Matrix Ps)
{
Array ps_checks = getCheck(errorCode, Ps.m);
Array ds_checks = check(errorCode, Ps);
printf("输出正确的结果:\n");
printArray(hamming);
for (int i = 1; i <= ps_checks.length; i++)
{
ps_checks.elems[i] = xOr(ps_checks.elems[i], ds_checks.elems[i]);
}
printf("模拟出现错误的结果:\n");
printArray(errorCode);
printf("S5到S1为:\n");
printArray(ps_checks);
}
// 辅助的测试函数,生成测试用例
/*
10101100
N=8
K=5
*/
void test(Array &message)
{
int array[] = {0, 0, 1, 1, 0, 1, 0, 1};
int N = 8;
initArray(message, N);
for (int i = 1; i <= message.length; i++)
{
message.elems[i] = array[i - 1];
}
}
int main()
{
Array message;
// getMessage(message);
// Array message;
test(message);
printf("原始的信息为:\n");
printArray(message);
int N = message.length; // 有效信息D的位数
int K = computerCheckCode(N); // 校验位P的位数
// 生成和插入校验位
Array hamming;
insertCheck(message, K, hamming);
// 进行偶校验计算
Matrix Ds; // 辅助的二维数组
Matrix Ps;
// Ps和Ds初始化时,里面所有的元素为1
// Ps里面的第i行,存储的是pi校验位校验的Di对应在hanmming数组(汉明码里面的位置),举例说明
// p1校验位校验D1,D2,D4,D5,D7,它们在汉明数组里面的位置是3,5,7,9,11
// 于是Ps数组第i行储存3,5,7,9,11
// 下面的generateCheck函数实现上述功能
printf("\n");
generateCheck(Ds, N, K, Ps, hamming);
// 检验操作
/*
1. 指定突变的位置
2. 在hamming数组进行100次处理,每次随机选择选择一位取反
*/
Array correct = check(hamming, Ps);
printf("生成的校验位为:\n");
printArray(correct);
insert(hamming, correct);
// 指定突变位置
int positions[] = {7};
Array errorCode = simulation(hamming, positions, 1);
// 在hamming数组进行100次处理,每次随机选择选择一位取反
// errorCode = simulation(hamming, 100);
// 输出最终的校验结果
finish(hamming, errorCode, Ps);
// finish(hamming, hamming, Ps);//模拟未出错的情况
return 0;
}
使用说明
进入main函数,修改相关位置代码即可,有详细的注释。
// 指定突变位置
int positions[] = {7};
Array errorCode = simulation(hamming, positions, 1);
// 在hamming数组进行100次处理,每次随机选择选择一位取反
// errorCode = simulation(hamming, 100);
// 输出最终的校验结果
finish(hamming, errorCode, Ps);
// finish(hamming, hamming, Ps);//模拟未出错的情况