您的位置:首页 > 其它

通信系统传输模型仿真实现

2015-12-02 20:49 344 查看
#include<iostream>

#include<stdlib.h>

#include<fstream>

#include<string>

#include<conio.h>

#include <algorithm>

#include <queue>

#include <iomanip>

#define max 1000

using namespace std;

string remfile[10000000];//此数组存储读取文件的字符流   此处原文定义为string

int filecount = 0;  //计数,看文件总共有多少个字符

float   bitecount = 0;//记录二进制码的个数;

char str1[1500000];  //存取7位二进制码的十进制表示

struct hufffile  //存放读入文件字符的结构体,data为字符,count为计数

{
char data;
int Count;

};

int Count = 1;//计数,看字符总种类数,与上面的count无关

hufffile huff[max];

bool charis_exist(char c)

{
for (int i = 1; i <= Count; i++) {
if (huff[i].data == c) {
//如果字符出现过,则计数加1
huff[i].Count++;
return true;
}
}
return false;

}

void char_new(char c)

{
huff[Count].data = c;
huff[Count++].Count++;

}

struct huff_tree 

{
int weight;//权值
int flag;
//标记
int parent; //双亲结点下标
int leftchild; //左孩子下标
int rightchild; //右孩子下标

};

huff_tree huffman[max];

int sum;//huffman树中结点的个数;

void creathuffman()//构造huffman树的函数

{

int min1, min2;//指示权值最小;
int loc1, loc2;//指向权值最小的两个数的位置;

for (int i = 1; i <= sum; i++)
{   //对huffman树的结点进行初始化;
huffman[i].parent = 0;
huffman[i].leftchild = 0;
huffman[i].rightchild = 0;
huffman[i].weight = 0;

}
for (int ii = 1; ii<Count; ii++)//将权值赋给huffman[].weight;
huffman[ii].weight = huff[ii].Count;
sum = 2 * Count - 3;

for (int j = Count; j <= sum; j++)
{
loc1 = loc2 = 0;//权值最小的
min1 = min2 = 2000000;
for (int k = 1; k <= j - 1; k++)//求权值最小的两个地址;
if (huffman[k].parent == 0)
if (huffman[k].weight <= min1)
{
min2 = min1; min1 = huffman[k].weight;
loc2 = loc1; loc1 = k;
}
else
if (huffman[k].weight <= min2)
{
min2 = huffman[k].weight; loc2 = k;
}
////////////将求出的两个权值最小的结点合并为新的结点,并将新的结点存入数组中
huffman[loc1].parent = j;
huffman[loc2].parent = j;
huffman[j].leftchild = loc1;
huffman[j].rightchild = loc2;
huffman[j].weight = huffman[loc1].weight + huffman[loc2].weight;

}

}

struct  huffcode

{
string bit[100];//存放解码
int start;//编码的起始下标
int Count; //字符的权值
string c;  //存放字符  此处不同

};

huffcode hcode[100]; 

void huffmancode()//编码函数

{

int rem, p; int count1 = 0;
for (int y = 1; y <= Count; y++)
{//编码部分;
rem = y;
hcode[y].start = sum;
//最后一位为2*n-3
hcode[y].c = huff[y].data;  //将字符赋给编码
p = huffman[y].parent;  
while (p != 0)
{
if (huffman[p].leftchild == rem)hcode[y].bit[++count1] = '0';  //左孩子分支编码为0,右孩子分支编码为1
else   hcode[y].bit[++count1] = '1';
rem = p;
p = huffman[p].parent;
}
hcode[y].Count = count1;
count1 = 0;
}
cerr << "字符以及其编码:" << endl;
for (int t = 1; t <= Count; t++)//输出所编的码;
{
cerr << "字符" << hcode[t].c << ";编码:  ";
int r = hcode[t].Count;
while (r)
cerr << hcode[t].bit[r--];
cerr << endl;
}

}

int tot = 0;

void yasuo()

{
ifstream fp1;
ofstream fp2;
fp1.open("g://test2.txt");
if (!fp1)//检查文件是否打开。
{
cerr << "不能打开文件" << endl;//输出文件未打开的标志。
exit(0);
}
fp2.open("g://test3.txt"); //将huffman1.txt文件中的二进制编码7位7位的存成一个ascII值存入test3.txt
if (!fp2)//检查文件是否打开。
{
cerr << "不能打开文件" << endl;//输出文件未打开的标志。
exit(0);
}
char c1, c2;
int t = 0, f = 0,f1=0,s;
while (!fp1.eof())
{
fp1 >> c1;
s = c1 - '0';
t *= 2;
t += s;  //t为7位二进制码的10进制表示
f++;
f1++;
if (f == 7){
c2 = t;
t = 0;
fp2 << c2;
str1[tot++] = c2;
f = 0;
f1 = 0;
}
if (((tot + 1) * 7-1) > bitecount) {
//此处为添加使余7存入
if (bitecount == (7 * tot-1)) {
break;
}
int x;
x = bitecount - tot * 7; //x即为mod7余数
if (f1 == x) {
x = 2 ^ (7 - x);
t = t*x;
c2 = t;
fp2 << c2;
str1[tot++] = c2;
}
}

}
/*cout << "输出tot值和sum0的值:" << endl;
cout << tot <<"  ***   "<<bitecount<< endl;*/
str1[tot] = '\0';
fp1.close();
fp2.close();

}

int xindaocount = 0; 

void encode() //信道编码

{
ifstream fp1;
ofstream fp2;
int c1[3], c2[7];
fp1.open("g://test2.txt");
if (!fp1) {
cerr << "不能打开文件!" << endl;
exit(0);
}
fp2.open("g://test4.txt"); 
if (!fp2)//检查文件是否打开。
{
cerr << "不能打开文件" << endl;//输出文件未打开的标志。
exit(0);
}
char  str[10000];
int i = 0;
while (!fp1.eof()) {
fp1 >> str[i];
i++;
}
i--;
/*cout << "输出i和bitecount的结果:" << endl;
cout << i <<" *****   "<<bitecount<< endl;*/
int x1;
x1 = (i+1) % 3;
int f = 0,f1=0;
for (int j = 0; j < i; j++) {
f++;
f1++;
if (f == 3) {
c1[0] = str[j - 2 ]-'0';
c1[1] = str[j -1]-'0';
c1[2] = str[j ]-'0';
c2[0] = c1[0];
c2[1] = c1[1];
c2[2] = c1[2];
c2[3] = c1[0] + c1[2];
c2[4] = c1[0] + c1[1] + c1[2];
c2[5] = c1[0] + c1[1];
c2[6] = c1[1] + c1[2];
for (int e = 0; e < 7; e++) {
if (c2[e] == 2) {
c2[e] = 0;
}
else if (c2[e] == 3) {
c2[e] = 1;
}
fp2 << c2[e];
}
f = 0;
f1 = 0;
xindaocount++;
}

if (f1 == x1&&(i-j)<3&&(x1!=0)) {
if (x1 == 1) {
c1[0] = str[j ] - '0';
c1[1] = 0;
c1[2] = 0;
c2[0] = c1[0];
c2[1] = c1[1];
c2[2] = c1[2];
c2[3] = c1[0] + c1[2];
c2[4] = c1[0] + c1[1] + c1[2];
c2[5] = c1[0] + c1[1];
c2[6] = c1[1] + c1[2];
for (int e = 0; e < 7; e++) {
if (c2[e] == 2) {
c2[e] = 0;
}
else if (c2[e] == 3) {
c2[e] = 1;
}
fp2 << c2[e];
}

}
if (x1 == 2) {
c1[0] = str[j -1] - '0';
c1[1] = str[j ] -'0';
c1[2] = 0;
c2[0] = c1[0];
c2[1] = c1[1];
c2[2] = c1[2];
c2[3] = c1[0] + c1[2];
c2[4] = c1[0] + c1[1] + c1[2];
c2[5] = c1[0] + c1[1];
c2[6] = c1[1] + c1[2];
for (int e = 0; e < 7; e++) {
if (c2[e] == 2) {
c2[e] = 0;
}
else if (c2[e] == 3) {
c2[e] = 1;
}
fp2 << c2[e];
}
}
}

}
fp1.close();
fp2.close();

}

void decode() //信道译码


ifstream fp1;
ofstream fp2;
char c1,c2;
int c[3];
fp1.open("g://test4.txt");
if (!fp1) {
cerr << "不能打开文件!" << endl;
exit(0);
}
fp2.open("g://test5.txt"); 
if (!fp2)//检查文件是否打开。
{
cerr << "不能打开文件" << endl;//输出文件未打开的标志。
exit(0);
}
int G[3][7] = { { 1,0,0,1,1,1,0 },{ 0,1,0,0,1,1,1 },{ 0,0,1,1,1,0,1 } }; //(7,3)码的生成矩阵
int P[3][4], Q[4][3], HT[7][3], R2[7], C[3];
char  str[10000];
int i = 0;
while (!fp1.eof()) {
fp1 >> str[i];
i++;
}
i--;
int x = 0;
x = ((int)bitecount+1) % 3;
int f = 0, f1 = 0,x1=0;
for (int j = 0; j < i; j++) {
f++;
x1 = (j+1) / 7;
if ((i - j) >= 7) {
if (f == 7) {
c[0] = str[j - 6] - '0';
c[1] = str[j - 5] - '0';
c[2] = str[j - 4] - '0';
for (int e = 0; e < 3; e++) {
fp2 << c[e];
}
f = 0;
}
}
if ((i - j) < 7) {
if (f == 7) {
if (x == 1) {
c[0] = str[j -6] - '0';
fp2 << c[0];
}
if (x == 2) {
c[0] = str[j - 6] - '0';
c[1] = str[j - 5] - '0';
for (int e = 0; e < 2; e++) {
fp2 << c[e];
}
}
}
}
}
fp1.close();
fp2.close();

}

void jieya()

{
ifstream fp1;
ofstream fp2;
char inchar;
fp1.open("g://test5.txt");
if (!fp1) {
cerr << "不能打开文件!" << endl;
exit(0);
}
fp2.open("g://test6.txt");
if (!fp2)//检查文件是否打开。
{
cerr << "不能打开文件" << endl;//输出文件未打开的标志。
exit(0);
}
for (int ptr = sum; !fp1.eof();)//将编码转为字符输入的到文件中;从根结点开始搜索huffman树,直到找到叶结点为止
{

fp1 >> inchar;
if (inchar == '1')ptr = huffman[ptr].rightchild;//查找相应编码对应huffman树中的位置,
else ptr = huffman[ptr].leftchild;
if (huffman[ptr].rightchild == 0 && huffman[ptr].leftchild == 0)//判断是否为叶子结点;
{
fp2 << huff[ptr].data; ptr = sum;
}//是叶子结点,将该结点的对应字符输入到文件中;
}

}

int main()

{
char ch;
ifstream infile;
infile.open("G://test1.txt");
if (!infile) {
cout << "不能打开文件!" << endl;
exit(0);
}
while ((ch = infile.get()) != EOF) {
remfile[++filecount] = ch;
if (!charis_exist(ch)) {
char_new(ch);
}
}
creathuffman();
huffmancode();

ofstream fp;

fp.open("g://test2.txt");  //test2文件存取的为huffman编成的01码

for (int j = 1; j <= filecount; j++){
for (int i = 1; i <= Count; i++)
if (remfile[j] == hcode[i].c)
{
for (int k = hcode[i].Count; k>0; k--)
{
fp << hcode[i].bit[k];
bitecount++;
}
break;
}
}

fp.close();

yasuo();//huffman1.txt文件中的二进制编码7位7位的存成一个ascII值存入新的文件

float y1;
//将huffman1.txt文件中的二进制编码7位7位的存成一个ascII值存入新的文件,此时的压缩率为y1
y1 = bitecount / 7 / filecount * 100;
cout << "压缩比例是:" << y1 << "%" << endl;

cout << endl;

encode();
decode();
float y2;
y2 = 3.0 / 7.0;
cout << "信道传输率是:"<<y2 << endl;

jieya();

system("pause");
return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: