通信系统传输模型仿真实现
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;
}
#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;
}
相关文章推荐
- jQuery选择器之表单选择器
- 利用Matlab Image Processing Toolbox中的图像配准工具
- Java 没有MPI
- Object-C,NSArraySortTest,数组排序3种方式
- Object-C,NSArraySortTest,数组排序3种方式
- Object-C,NSArraySortTest,数组排序3种方式
- Spring容器注解详解<四>
- Profiling 性能分析
- 2015-12-02 计划任务维护数据库
- java web module of login
- 学自慕课网:Java常用集合框架(理论篇)
- HTTP相关知识
- 纯技术之外的产品工作经验
- 非对称加密解密与签名验签的关系
- 本地音乐播放
- 【Python】用zip函数求欧氏距离、余弦相似度
- hdu 5540 Secrete Master Plan(水)
- jQuery选择器之过滤选择器
- linux0.11 内核启动代码分析(二)
- UIControl整理笔记