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

📄 main.cpp

📁 著名的LZW压缩和解压的C++实现
💻 CPP
字号:
////////////////////////////////////////////////////////////////////////////
////////                                                            ////////
////////                  利用哈希表完成LZW压缩与解压               ////////
////////                                               by 施玮喆    ////////
////////                                               5060309818   ////////
////////                                               2007--11-5   ////////
////////                                                            ////////
////////////////////////////////////////////////////////////////////////////


#include<iostream.h>
#include<stdio.h> 
#include<stdlib.h> 
#include<malloc.h> 
#include<string.h> 
#include<math.h> 
#include"hash.h"



int mark=0;
int status=0;
int LeftOver;



void Output(unsigned long pcode,FILE* file,int& out)
{
   unsigned char a,b;
   if(mark)                                      //有上次剩余的4位
   {
	   b=pcode & 255;
	   a=(LeftOver << 4) | (pcode >> 8);
	   fprintf(file,"%c",a);
	   fprintf(file,"%c",b);
	   out=out+2;
	   mark=0;
   }
   else                                         //没有剩余
   {
	   LeftOver=pcode & 15; 
	   a=pcode >> 4;
	   fprintf(file,"%c",a);
	   out++;
	   mark=1;
   }
}



bool Getcode(int& code,FILE* file)
{                                           
	char a,b;
	int c,d;
	a=fgetc(file);
	if(feof(file)) return false; 
	if(status)
	{
		c=a & 255;
		code=(LeftOver << 8) | c;
	}
	else 
	{
		b=fgetc(file);
		c=a & 255;
		d=b & 255;
		code=(c << 4) | (d >> 4);
		LeftOver=d & 15;
	}
	status=1-status;
	return true;
}



void Print(int code,int& n,unsigned char s[4096],element ht[4096],FILE* file)
{
   n=-1;
   while(code>=256)
   {
	   s[++n]=ht[code].suffix;
	   code=ht[code].prefix;
   }
   s[++n]=code;
   for(int i=n;i>=0;i--)
	   fprintf(file,"%c",s[i]);
}



void Compress(char fori[30],char fcom[30])       //LZW压缩器
{
   FILE* forigin=fopen(fori,"rb");
   FILE* fcompress=fopen(fcom,"wb");

   hashnode* P=new hashnode[D];                    //定义并初始化代码字典
   hashnode* T;
   for(int i=0;i<D;i++) P[i].link=NULL;
   part e;
   char ch;
   int temp,in=1,out=0;
   int s;
   
   for(i=0;i<256;i++)
   {
	   e.key=i;
	   e.code=i;
	   insert(P,e);
   }
   int used=256;                                 //记录当前code用到的数

   ch=fgetc(forigin);                            //输入文件中的第一个字符
   unsigned long pcode=ch; 
   if (!feof(forigin))
   {
	   do{
		   ch=fgetc(forigin);
		   in++;
		   if(feof(forigin)) 
			   break; 
		   s=ch & 255;
		   unsigned long k=(pcode << 8) | s;
		   if(search(P,k,temp))
			   pcode=temp;
		   else
		   {
			   Output(pcode,fcompress,out);
			   if(used>=4096)                              //刷新字典
			   {
				   T=P;
				   delete T;
				   P=new hashnode[D];
				   for(int i=0;i<D;i++) P[i].link=NULL;
				   for(i=0;i<256;i++)
				   {
					   e.key=i;
					   e.code=i;
					   insert(P,e);
				   }
				   used=256;         
			   }
			   e.code=used++;
			   s=ch & 255;
			   e.key=(pcode << 8) | s;
			   insert(P,e);
			   pcode=ch;
		   }
	   }while(1);
	   Output(pcode,fcompress,out);
	   if(mark)
	   {
		   ch=LeftOver << 4;
		   fprintf(fcompress,"%c",ch);
		   out++;
	   }
   }
   fclose(forigin);
   fclose(fcompress);
   cout<<"压缩成功,压缩比为:"<<out*100/in<<"%\n";
}


void Decompress(char fcom[30],char fori[30])     //LZW解压器
{
	FILE* fcompress=fopen(fcom,"rb");
	FILE* forigin=fopen(fori,"wb");
	
	int n=0;
	int used = 256;                              // 迄今所使用的代码
	int pcode,ccode;                             // 前一代码与当前代码
	element ht[4096];
	unsigned char s[4096];
	
	if(Getcode(pcode,fcompress))
	{
		s[0]=pcode;  
		fprintf(forigin,"%c",s[0]);
		
		while(Getcode(ccode,fcompress))
		{
			if(ccode<used)                    // ccode已在字典中
			{
				Print(ccode,n,s,ht,forigin);
				if(used>=4096) used=256;
				
				ht[used].prefix=pcode;
				ht[used++].suffix=s[n];
				
			}                                    
			else
			{
				ht[used].prefix=pcode;
				ht[used++].suffix=s[n];
				Print(ccode,n,s,ht,forigin);
			}
			pcode=ccode;
		}
	}
	fclose(fcompress);
	fclose(forigin);
	cout<<"解压成功\n";
}



int main() 
{ 
    cout<<"//////////////////////////////////////////////////////////////"<<endl;
    cout<<"////                                                      ////"<<endl;
    cout<<"////      利用哈希表完成LZW压缩与解压                     ////"<<endl;
    cout<<"////                                   姓名: 施玮喆      ////"<<endl;
    cout<<"////                                   学号: 5060309818  ////"<<endl;
    cout<<"////                                   班级: F0603031    ////"<<endl;
    cout<<"////                               完成时间: 2007-11-5   ////"<<endl;
    cout<<"////                                                      ////"<<endl;
    cout<<"//////////////////////////////////////////////////////////////"<<endl<<endl;

	char choice,fori[30],fcom[30];

	while(1)
	{
		cout<<"****************************************************************\n";
		cout<<" 1   --   Compress\n";
		cout<<" 2   --   Decompress\n";
		cout<<" 3   --   Quit\n";
		cout<<"****************************************************************\n";
		cout<<" what to do : ";
		cin>>choice;
		switch(choice){
		case '1':
			{
				cout<<"请输入要压缩的文件名: "; 
				cin>>fori; 
				cout<<"请输入压缩后的保存文件名: "; 
				cin>>fcom; 
				Compress(fori,fcom);
			}
			break;
		case '2':
			{
				cout<<"请输入要解压缩的文件名: "; 
				cin>>fcom; 
				cout<<"请输入解压缩后的保存文件名: "; 
				cin>>fori; 
				Decompress(fcom,fori);
			}
			break;
		case '3':
			return 0;
		default:
			cout<<"Wrong input!";
		}
	}

	return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -