📄 huffmantext.cpp
字号:
ch=(int)hft[a[j]].lchirld;
i++;
if(ch>127) //由于非叶子结点在128--128+sum-2之间
ch=64;
HuffmanTree1.Format("__%c(%3d)",ch,hft[a[j+1]].weight);//显示左孩子
HuffmanTree=HuffmanTree+HuffmanTree1;
j++;
}
HuffmanTree1.Format("\r\n");
HuffmanTree=HuffmanTree+HuffmanTree1;
for(k=0;k<flag;k++)
{
HuffmanTree1.Format(" "); //某行最前面输出的空格
HuffmanTree=HuffmanTree+HuffmanTree1;
}
for(k=0;k<i-1;k++)
{
HuffmanTree1.Format(" | ");
HuffmanTree=HuffmanTree+HuffmanTree1;
}
j=j-1;
i=i-1;
if(hft[a[j]].rchirld!=0)
{
for(k=0;k<(column[a[j]]-i-1-flag);k++)
{
HuffmanTree1.Format(" ");
HuffmanTree=HuffmanTree+HuffmanTree1;
}
ch=(int)hft[a[j]].rchirld;
if(ch>127)
ch=64;
HuffmanTree1.Format(" |__%c(%3d)",ch,hft[hft[a[j]].rchirld].weight);
HuffmanTree=HuffmanTree+HuffmanTree1;
}
if(j==0)
flag++; //下行最前面该输出的空格数
temp=a[j];
a[j]=hft[a[j]].rchirld; //
column[a[j]]=column[temp]+1;
}
SetDlgItemText(IDC_EDIT_HuffmanTree,HuffmanTree);
}
/*************************************************************************
函数名:Huffman_Information
返回值:void
说明:显示文本的信息,如压缩比,字符总数,字符种类数,各字符的频率
*************************************************************************/
void CHuffmanText::Huffman_Information()
{
int i;
float rate=0; //压缩比
float avglength=0; //平均代码长度
double entropy=0; //熵
int length[128]; //用于保存各字符编码的长度
for(i=0;i<=128;i++) //初始化length[128]
{
length[i]=0;
}
for(i=0;i<=127;i++)
{
if(w[i]!=0)
{
length[i]=127-hcd[i].start;
rate=rate+(length[i]*w[i]);
entropy=entropy-((log(w[i])-log(p))/log(2))*w[i]; //计算熵值
avglength=avglength+(((float)w[i]/p)*length[i]); //计算平均代码长度
}
}
rate=rate/(p*8); //计算压缩比
CString str1,str2,str3;
str1.Format("字符总数:%d\r\n 压缩比:%f\r\n 平均代码长度:%f\r\n 熵值:%f\r\n\r\n",p,rate,avglength,entropy);
str2.Format("各字符的权值如下:\r\n");
for(i=0;i<=127;i++)
{
if(w[i]!=0)
{
str3.Format("%c\t%d",i,w[i]);
str2=str2+str3+"\r\n";
}
}
str=str1+str2;
}
/****************************************************************************
函数名:OnBUTTONScan2
返回值:void
说明:单击浏览按钮弹出对话框,从中选择要解压的文件
****************************************************************************/
void CHuffmanText::OnBUTTONScan2()
{
// TODO: Add your control notification handler code here
CString fName;
char Filter[]="所有文件(*.*)|*.*||压缩文件(*.htc)|*.htc|";
CFileDialog dlg(TRUE,0,0,OFN_HIDEREADONLY|OFN_FILEMUSTEXIST,(LPCTSTR)Filter,NULL);
if(dlg.DoModal()==IDOK)
fName=dlg.GetPathName();
else
return;
sCompressText.Format("");
CFile file;
file.Open(fName,CFile::modeRead|CFile::typeBinary); //打开所选的文件,并按位只读
int length=file.GetLength(); //获取文件的长度
char *temp;
temp=new char[length+1]; //开辟length+1长的空间,其中length位置用于存'\0'
ZeroMemory(temp,length); //将temp清空
file.Read(temp,1); //从文件读一个字节存入temp
sum=(int)temp[0]; //文本字符的总数
int i;
//初始化w[128]
for(i=0;i<=127;i++)
{
w[i]=0;
}
unsigned int ascii;
for(i=0;i<sum;i++) //读出各字符的权值
{
file.Read(temp,1);
ascii=(unsigned int)temp[0]; //读出该字符
file.Read(temp,1);
w[ascii]=(int)temp[0]; //读出该字符的权值
}
p=0;
for(i=0;i<=127;i++) //p总字符数
p=p+w[i];
unsigned int binary;
int ss[8];
for(i=0;i<=7;i++)
ss[i]=0;
CString compresstext;
//把压缩的文件还原成二进制
for(i=0;i<(length-1)-2*sum;i++) //2*sum为字符种类及权值的和,减1为字符种类数
{
file.Read(temp,1);
ascii=(unsigned int)temp[0];
for(int j=0;j<=7;j++)
{
binary=(unsigned int)fmod(ascii,2);
ss[7-j]=(int)binary; //此时binary对应的是二进制的高位
ascii=ascii/2;
}
for(int k=0;k<=7;k++)
{
compresstext.Format("%d",ss[k]);
sCompressText=sCompressText+compresstext;
}
}
SetDlgItemText(IDC_EDIT_CompressText,sCompressText);
CButton *pBtn;
//屏蔽单选压缩按钮和Huffman树按钮
pBtn=(CButton*)GetDlgItem(IDC_RADIO_Compress);
pBtn->EnableWindow(FALSE);
pBtn=(CButton*)GetDlgItem(IDC_BUTTON_HuffmanTree);
pBtn->EnableWindow(FALSE);
//激活单选解压缩按钮
pBtn=(CButton*)GetDlgItem(IDC_RADIO_DeCompress);
pBtn->EnableWindow(TRUE);
}
/******************************************************************
函数名:OnRADIOCompress
返回值:void
说明:点击单选压缩按钮,使state=0
*******************************************************************/
void CHuffmanText::OnRADIOCompress()
{
// TODO: Add your control notification handler code here
if(IsDlgButtonChecked(IDC_RADIO_Compress))
state=0;
}
/******************************************************************
函数名:OnRADIODeCompress
返回值:void
说明:点击单选压缩按钮,使state=1
*******************************************************************/
void CHuffmanText::OnRADIODeCompress()
{
// TODO: Add your control notification handler code here
if(IsDlgButtonChecked(IDC_RADIO_DeCompress))
state=1;
}
/******************************************************************
函数名:OnButtonRun
返回值:void
说明:点击单选运行按钮,如果选中单选压缩按钮就对文本压缩,如果选中
单选解压缩按钮就对文本解压缩
*******************************************************************/
void CHuffmanText::OnButtonRun()
{
// TODO: Add your control notification handler code here
if(state==0)
{
GetDlgItemText(IDC_EDIT_OriginalText,sOriginalText); //把原文本编辑框内容赋给sOriginalText
Text_Measure(w); //计算文本的总字符的个数,各字符的权值及字符的种类
if(sum<=1)
{
str.Format("字符种类太少请重新输入");
::AfxMessageBox(str);
}
else
{
CString fname; //保存文件的路径
char Filter[]="所有文件(*.*)|*.*||压缩文件(*.htc)|*.htc|";
CFileDialog dlg(FALSE,"txt",NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,(LPCTSTR)Filter,NULL);
if(dlg.DoModal()==IDOK)
fname=dlg.GetPathName();
else
fname="";
Creat_Tree(w); //创建Huffman树
Huffman_Code(hcd); //根据创建的Huffman树,对每种字符进行编码
Huffman_Information(); //计算文本的信息
SetDlgItemText(IDC_EDIT_Information,str); //把计算的文本的信息赋给信息表编辑框
int Queue[136],b=136;
for(int i=0;i<=135;i++) //初始化Queue
{
Queue[i]=0;
}
int front=0,rear=0; //头尾指针
int *information;
information=new int[1];
char ch,m_cOriginalText[32767];
strcpy(m_cOriginalText,(LPSTR)(LPCTSTR)sOriginalText); //把原文本编辑框内容赋给m_sOriginalText
int C=0;
ch=m_cOriginalText[C];
CString code;
sCompressText.Format(""); //清空sCompressText
CFileException m_fException;
CStdioFile m_sFile;
m_sFile.Open(fname,CFile::modeCreate+CFile::modeWrite|CFile::typeBinary,&m_fException); //打开文件
if(fname!="")
{
information[0]=sum; //字符种类写入压缩文件中
m_sFile.Write(information,1);
CString saver;
for(int j=0;j<=127;j++) //把文本的字符及权值写入压缩文件中
{
if(w[j]!=0)
{
saver.Format("%c",j);
m_sFile.WriteString(saver); //将字符写入文件中
information[0]=w[j];
m_sFile.Write(information,1); //将字符的权值写入文件中
}
}
}
int surplus=0;
int aa=0;
while(ch!='\0') //当文本不是文本结束符
{
for(i=hcd[ch].start;i<=126;i++) //读取ch字符的编码
{
Queue[rear]=hcd[ch].Bits[i];
rear=(int)fmod(rear+1,b);
code.Format("%d",hcd[ch].Bits[i]);
sCompressText=sCompressText+code; //sCompressText用存入压缩编码
}
surplus=(int)fmod(rear-front+b,b);
while(surplus>=8)
{
for(int k=0;k<=7;k++) //将8位二进制数转化十进制
{
aa=aa+(int)(Queue[front]*pow(2,7-k));
front=(int)fmod(front+1,b);
}
information[0]=aa;
if(fname!="")
m_sFile.Write(information,1); //把转化的十进制写入文件中
aa=0;
surplus=surplus-8;
}
ch=m_cOriginalText[++C]; //读下一个字符
}
if(fname!="")
{
if(surplus!=0) //把剩余的不到8位二进制转化十进制
{
for(int x=0;x<=7;x++)
{
aa=aa+(int)(Queue[front]*pow(2,7-x));
front=(int)fmod(front+1,b);
}
information[0]=aa;
m_sFile.Write(information,1);
}
m_sFile.Close(); //关闭文件
}
SetDlgItemText(IDC_EDIT_CompressText,sCompressText); //在二进制编辑框中显示压缩编码
CString s;
s.Format("压缩完毕");
::AfxMessageBox(s);
CButton *pBtn;
//屏蔽单选压缩按钮
pBtn=(CButton*)GetDlgItem(IDC_RADIO_Compress);
pBtn->EnableWindow(FALSE);
//激活Huffman树按钮和单选解压按钮
pBtn=(CButton*)GetDlgItem(IDC_RADIO_DeCompress);
pBtn->EnableWindow(TRUE);
pBtn=(CButton*)GetDlgItem(IDC_BUTTON_HuffmanTree);
pBtn->EnableWindow(TRUE);
}
}
if(state==1)
{
CString fname; //保存文件的路径
char Filter[]="所有文件(*.*)|*.*||文本文件(*.txt)|*.txt|";
CFileDialog dlg(FALSE,"txt",NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,(LPCTSTR)Filter,NULL);
if(dlg.DoModal()==IDOK)
fname=dlg.GetPathName();
else
fname="";
GetDlgItemText(IDC_EDIT_CompressText,sCompressText); //把二进制压缩输出流赋给sCompressText
Creat_Tree(w);
DeCompress();
if(fname!="")
{
CFileException m_fException;
CStdioFile m_sFile;
m_sFile.Open(fname,CFile::modeCreate+CFile::modeWrite,&m_fException); //打开文件
m_sFile.WriteString(str);
m_sFile.Close();
}
SetDlgItemText(IDC_EDIT_DeCompressText,str); //把解压好的字符写入还原编辑框中
CString s;
s.Format("解压结束\n");
::AfxMessageBox(s);
CButton *pBtn;
//屏蔽单选解压缩按钮
pBtn=(CButton*)GetDlgItem(IDC_RADIO_DeCompress);
pBtn->EnableWindow(FALSE);
//激活单选压缩按钮和Huffman树按钮
pBtn=(CButton*)GetDlgItem(IDC_RADIO_Compress);
pBtn->EnableWindow(TRUE);
pBtn=(CButton*)GetDlgItem(IDC_BUTTON_HuffmanTree);
pBtn->EnableWindow(TRUE);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -