⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 huffmantext.cpp

📁 在VC环境下
💻 CPP
📖 第 1 页 / 共 2 页
字号:
			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 + -