/****************** 卷积码 **********************/
#include<iostream>
#include<cmath>
#include<string>
#include<stdio.h>
using namespace std;
int m[50],c[50],G[50][50];
int g[]={1,1,1,0,1,1}; // 由生成多项式得到生成矢量
int n,k,L;
string message,codein,codeout;// 存储信息码元以及译码时的码字序列
int codelen,error;// 记录译码时的错误个数
int accepterror;
// 读入生成向量,并构造出生成矩阵
void readdata()
{
memset(m,50,sizeof(int)); // 初始化
cout<<"请输入信息码元: ";
cin>>message;
for(int i=0;i<message.length();i++)
m[i]=(message[i]!='0')?1:0;
k=message.length();
L=n=2;
for(int j=0;j<n*(L+1);j++)// 生成矩阵G
G[0][j]=g[j];
for(i=1;i<k;i++)
for(int j=0;j<n*(L+k);j++)
{
if((j-2)>=0&&(G[i-1][j-2]==1))
G[i][j]=G[i-1][j-2];
else G[i][j]=0;
}
}
// 对信息码进行(2,1,2)卷积码编码
void encode()
{
for(int i=0;i<k;i++)
for(int j=0;j<n*(L+k);j++)
G[i][j]=m[i]*G[i][j];
printf("卷积编码后的码字为: ");
for(int j=0;j<n*(L+k);j++)
{
int temp=0;
for(i=0;i<k;i++)
temp+=G[i][j];
m[j]=temp%2;
if(j<n*k)
printf("%d",m[j]);
}
}
// 模拟信道中噪声干扰
void noise()
{
printf("\n请指定错误位置(模拟信道噪声干扰):");
char ch=getchar();
int temp=0;
do{
ch=getchar();
if(ch>='0' && ch<='9')
temp = temp*10+(ch-'0');
else if(temp>0)
{
m[temp-1]=1-m[temp-1];// 错误位置取反
temp=0;
}
}while(ch!='\n');
printf("噪声干扰后码字为: ");
for(int j=0;j<n*k;j++)
printf("%d",m[j]);
printf("\n");
}
// 描述(2,1,2)卷积码的状态图
void turnnext(int step,int statu,string now,int err){
if(step>=codelen){ // 转移步骤数超出码长时,译码结束
if(err<error){
codeout=now; error=err;// 把临时数组中的值作为译码结果输出
}
}else{// 若译码未结束,则根据状态图中转移条件逐步判断
if(err>error) return; //err>accepterror
int tempr=(codein[step*2]-'0')*2+(codein[step*2+1]-'0');
if(statu==0 || statu==1){// 处在状态00和01时可能的变化
if(tempr==1 || tempr==2){
turnnext(step+1,0,now+"0",err+1);
turnnext(step+1,2,now+"1",err+1);
}else if((tempr==0 && statu==0) || (tempr==3 && statu==1)){
turnnext(step+1,0,now+"0",err);
turnnext(step+1,2,now+"1",err+2);
}else{
turnnext(step+1,0,now+"0",err+2);
turnnext(step+1,2,now+"1",err);
}
}else{ // 处在状态10和11时可能的变化
if(tempr==0 || tempr==3){
turnnext(step+1,1,now+"0",err+1);
turnnext(step+1,3,now+"1",err+1);
}
else if((tempr==1 && statu==2) || (tempr==2 && statu==3)){
turnnext(step+1,1,now+"0",err+2);
turnnext(step+1,3,now+"1",err);
}
else{
turnnext(step+1,1,now+"0",err);
turnnext(step+1,3,now+"1",err+2);
}
}
}
}
// 译码
void decode(){
for(int j=0;j<n*k;j++) // 把信道干扰后的码字作为译码过程的输入
{
if(m[j]) codein+='1';
else codein+='0';
}
codelen=codein.length()/2;
accepterror=2;
error=accepterror+1;
codeout="";
turnnext(0,0,"",0); //以00位起始状态遍历状态图,并找出错误最小的译码结果
if(codeout!=""){
printf("viterib译码得码字: %s\n",codeout.c_str());
printf("错误位数: %d\n",error);
}
else printf("can not decode!\n");
}
int main()
{
printf("***********(2,1,2) 卷积码***********\n");
readdata();
encode();
noise();
decode();
return 0;
}
评论0