#include "stdafx.h"
#include <windows.h>
#include <windowsx.h>
#include <stdlib.h>
#include "resource.h"
#include "MainDlg.h"
/****************************************************************************************************************************************
第一部分:8位信息生成13位海明校验码,并且假设传输过程中出现一位错位然后实现自动纠错
**************************************************************************************************************************************/
/*********************************************
变量定义 把8位信息位生成13位海明码所需变量
*********************************************/
TCHAR bwstr[256];//存放输入的八位原信息
TCHAR intbwstr[256];//八位原信息的int格式
TCHAR pstr[10]; //5个校验位
TCHAR inthaimingstr[256];//海明码的int格式
TCHAR haimingstr[256];//海明码的char形式
/********************************************
2n函数
*******************************************/
TCHAR power(TCHAR i)
{ TCHAR k,s=1;
for(k=0;k<i;k++)
s=s*2;
return s;
}
/********************************************
将bwstr中的八位信息转为int格式的
********************************************/
void getstr(HWND hwnd)
{
GetDlgItemText(hwnd,IDC_EDIT1,bwstr,sizeof(bwstr));//获取输入的字符
TCHAR i,k;
k=0;
for(i=0;i<=20;i++)
{
if(bwstr[i]!='\0') k++;
}
if(k!=8)
MessageBox(hwnd,TEXT("暂不支持非8位计算"),TEXT("警告"),MB_OK);//当输入非8位时出错处理
for(i=0;i<=7;i++)
{
intbwstr[8-i]=bwstr[i]-48;//转换字符序
}
}
/*********************************************
生成海明校验码并显示
*********************************************/
void getp(HWND hwnd)
{
pstr[1]=(intbwstr[1]+intbwstr[2]+intbwstr[4]+intbwstr[5]+intbwstr[7])%2; //获取校验位
pstr[2]=(intbwstr[1]+intbwstr[3]+intbwstr[4]+intbwstr[6]+intbwstr[7])%2;
pstr[3]=(intbwstr[2]+intbwstr[3]+intbwstr[4]+intbwstr[8])%2;
pstr[4]=(intbwstr[5]+intbwstr[6]+intbwstr[7]+intbwstr[8])%2;
pstr[5]=(intbwstr[1]+intbwstr[2]+intbwstr[3]+intbwstr[5]+intbwstr[6]+intbwstr[8])%2;
TCHAR i,j;
for(i=2;i<=12;i++)
{
inthaimingstr[i]=0; //缓冲区全为0
}
for(i=1;i<=3;i++)
{
inthaimingstr[power(i)]=1;//特殊位全为1
}
j=1;
for(i=2;i<=12;i++) //填充信息位
{
if(inthaimingstr[i]==0) inthaimingstr[i]=intbwstr[j++];
}
j=2;
for(i=1;i<=3;i++) //填充校验位
{
inthaimingstr[power(i)]=pstr[j++];
}
inthaimingstr[1]=pstr[1];//填充最低位
inthaimingstr[13]=pstr[5];//填充最高位
for(i=1;i<=13;i++)//转换为ASCII码
{
haimingstr[i-1]=inthaimingstr[i]+48;
}
for(i=0;i<=12;i++)//重排字符序
{
inthaimingstr[12-i]=haimingstr[i];
}
inthaimingstr[13]='\0';
SetDlgItemText(hwnd,IDC_EDIT2,inthaimingstr);//显示
}
/************************************************
校验按钮函数
************************************************/
TCHAR s[10];//存储偶校验位
void getstr_2(HWND hwnd) //此函数执行后 输入的数字在intbwstr[1,2......]中
{
GetDlgItemText(hwnd,IDC_EDIT3,bwstr,sizeof(bwstr));//获取输入的字符(人工错一位的)
TCHAR i;
for(i=0;i<=12;i++)
{
intbwstr[13-i]=bwstr[i]-48;//转换字符序
}
}
void getp_2(HWND hwnd)
{
TCHAR i,j,k,n;
j=1;
for(i=0;i<=3;i++) //获取前四位校验位
{
pstr[j++]=intbwstr[power(i)];
}
pstr[5]=intbwstr[13];//获取第五位校验位
s[1]=(intbwstr[3]+intbwstr[5]+intbwstr[7]+intbwstr[9]+intbwstr[11]+pstr[1])%2; //获s
s[2]=(intbwstr[3]+intbwstr[6]+intbwstr[7]+intbwstr[10]+intbwstr[11]+pstr[2])%2;
s[3]=(intbwstr[5]+intbwstr[6]+intbwstr[7]+intbwstr[12]+pstr[3])%2;
s[4]=(intbwstr[9]+intbwstr[10]+intbwstr[11]+intbwstr[12]+pstr[4])%2;
s[5]=(intbwstr[3]+intbwstr[5]+intbwstr[6]+intbwstr[9]+intbwstr[10]+intbwstr[12]+pstr[5])%2;
n=0;
for(i=1;i<=5;i++)//计数S错位数
{
if(s[i]==1) n++;
}
switch (n)
{
case 1:
for(i=1;i<=4;i++)
{
if(s[i]==1)
{
if(intbwstr[power(i-1)]==1) intbwstr[power(i-1)]=0;
else intbwstr[power(i-1)]=1;
}
}
if(s[5]==1)
{
if(intbwstr[13]==1) intbwstr[13]=0;
else intbwstr[13]=1;
}
break;
default:
k=s[4]*power(3)+s[3]*power(2)+s[2]*power(1)+s[1];
if(intbwstr[k]==0) intbwstr[k]=1;
else intbwstr[k]=0;
}
for(i=1;i<=13;i++)//重排字符序
{
inthaimingstr[13-i]=intbwstr[i]+48;
}
inthaimingstr[13]='\0';
SetDlgItemText(hwnd,IDC_EDIT4,inthaimingstr);//显示
}
/****************************************************************************************************************************************
第二部分:对任信息位生成海明校验码
**************************************************************************************************************************************/
TCHAR chargetstr[256]; //存放用户输入字符串
TCHAR intgetstr[256]; //存放倒序后的转换为int格式的字符串
TCHAR intsetstr[256]; //存放处理后的int格式字符串
TCHAR charsetstr[256]; //最终要显示的字符串
TCHAR p[256]; //存放校验位
TCHAR how_n; //用户输入的信息位数
TCHAR how_k; //所需的校验码数
struct song //定义song结构体 h为在intgetchar的位置,d[32]为h的二进制形式
{
int h;
TCHAR d[32];
};
struct song data[100];//存放每一位数据信息便于推出各校验位值
/*********************************************************
获取字符串并将chargetstr转为intgetstr[1,2,3..........]
********************************************************/
void getcharstr(HWND hwnd)
{
GetDlgItemText(hwnd,IDC_EDIT5,chargetstr,sizeof(chargetstr));
TCHAR i;
how_n=0;
for(i=0;i<250;i++)//计算用户输入的信息位数how_n
{
if(chargetstr[i]=='\0') break;
how_n++;
}
for(i=0;i<how_n;i++)//转换为便于处理的int格式字符串intgetstr[1,2,3.....how_n]
{
intgetstr[how_n-i]=chargetstr[i]-48;
}
}
/*********************************************************
计算 how_k: 所需的校验位数
*******************************************************/
void gethow_k()
{
int i,n,j;
n=how_n+1;
for(i=1;i<150;i++)
{ j=power(i-1)-i;//j为2的i-1次方减i
if(j>=n) // 穷举法 当满足公式时退出循环
{
how_k=i; //此时计算出how_k:所需校验码位
break;
}
}
}
/*********************************************************
填充intsetstr中信息位,顺便填充data数组信息
*******************************************************/
void getdata()
{
TCHAR i,j;
for(i=1;i<=how_n+how_k;i++)//缓冲区全为0
{
intsetstr[i]=0;
}
for(i=1;i<how_k;i++)//校验位全为1
{
intsetstr[power(i-1)]=1;
}
intsetstr[how_n+how_k]=1;//最高位为特殊位也为校验位设为1
j=1;
for(i=1;i<=how_n+how_k;i++)
{
if(intsetstr[i]==0)
{
intsetstr[i]=intgetstr[j];//信息位填充
data[j].h=i; //填充data的h位:信息位在intsetstr中具体位置
j++;
}
}
}
/************************************************************
计算数组中有效位数
***********************************************************/
TCHAR use(TCHAR * s)
{
TCHAR i,k;
k=0;
for(i=0;i<32;i++)
{
if(s[i]=='\0') break;
k++;
}
return k;
}
/**************************************************************
将data中 的h值转为二进制并存在d数组中 并且向后移位d[1,2,3....]
************************************************************/
void getdata_d()
{
TCHAR i,j;
TCHAR buff[32];
ZeroMemory(buff,sizeof(buff));
for(i=1;i<=how_n;i++)
{
itoa(data[i].h,buff,2);
for(j=0;j<(use(buff));j++)
{
data[i].d[use(buff)-j]=buff[j]-48;
}
}
}
/****************************************************************
计算各校验位的值 并且写入intsetstr中
**************************************************************/
void getpsetp()
{
TCHAR i,j,s;
for(i=1;i<how_k;i++)
{
s=0;
for(j=1;j<=how_n;j++)
{
if(data[j].d[i]==1)
s=s+intgetstr[j];
}
p[i]=s%2;
}
p[how_k]=0;
for(i=1;i<=how_n;i++)
{
p[how_k]=p[how_k]+intgetstr[i];
}
for(i=1;i<how_k;i++)
{
p[how_k]=p[how_k]+p[i];
}
p[how_k]=p[how_k]%2;
j=1;
for(i=1;i<how_k;i++)
{
intsetstr[power(i-1)]=p[j++];
}
intsetstr[how_n+how_k]=p[how_k];
}
/**************************************************************************
倒序加显示
************************************************************************/
void good(HWND hwnd)
{
TCHAR i;
for(i=1;i<=how_n+how_k;i++)
{
charsetstr[how_n+how_k-i]=intsetstr[i]+48;
}
SetDlgItemText(hwnd,IDC_EDIT6,charsetstr);//显示
}
void zero()//清空缓存区
{
ZeroMemory(chargetstr,sizeof(chargetstr));
ZeroMemory(intgetstr,sizeof(chargetstr));
ZeroMemory(charsetstr,sizeof(chargetstr));
ZeroMemory(charsetstr,sizeof(chargetstr));
ZeroMemory(p,sizeof(p));
}
/*******************************************************************************************************************
结束
*****************************************************************************************************************/
BOOL WINAPI Main_Proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
HANDLE_MSG(hWnd, WM_INITDIALOG, Main_OnInitDialog);
HANDLE_MSG(hWnd, WM_COMMAND, Main_OnCommand);
HANDLE_MSG(hWnd,WM_CLOSE, Main_OnClose);
}
return FALSE;
}
BOOL Main_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam)
{
return TRUE;
}
void Main_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
{
switch(id)
{
case IDC_OK: //生成13位海明校验码
getstr(hwnd);
getp(hwnd);
break;
case IDC_BUTTON1: //自动纠错
getstr_2(hwnd);
getp_2(hwnd);
break;
case IDC_BUTTON2: //生成任意位海明校验码
zero();
getcharstr(hwnd);
gethow_k();
getdata();
getdata_d();
getpsetp();
good(hwnd);
break;
default:
break;
}
}
void Main_OnClose(HWND hwnd)
{
EndDialog(hwnd, 0);
}