大二数据结构课写的,有一个问题是结束符ascii里也有,所以会提前终止,还有一些特殊字符的问题,所以只能实现文本文件的压缩,囧,不过至少是写出来了~压缩效果不错,一些bug也懒得改了
/******************************************************
* 本程序 *
* 核心完成时间 2011.06.03 *
* 程序开发环境:visual c++ *
* 压缩小工具 *
* 仅适用于文本文件 *
*******************************************************/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<conio.h>
#include<windows.h>
#include<malloc.h>
#include<math.h>
#define N 34
#define LEN sizeof(struct czq)
#define M 512
int iii;
struct haffman
{
unsigned char b;
long parent,lchild,rchild;
long count;
char bit[256];
}czqing[M],temp;
void compress()
{
unsigned char c;
FILE *fp,*fq;
char filename[255],outputfile[255],buf[512];
long flength;
int i,j;
long m,n,cz,k,f,kk;
int st;
printf("请输入需要压缩的文件名(必须是以txt结尾的文本文件):");
gets(filename);
fp=fopen(filename,"rb");
if(fp==NULL){
printf("文件打开失败\n");
return ;
}
printf("请输入压缩后的文件名: ");
gets(outputfile);
fq=fopen(strcat(outputfile,".czq"),"wb");
if(fq==NULL)
{
printf("压缩失败\n");
return ;
}
flength=0;
while(!feof(fp))
{
fread(&c,1,1,fp);
czqing[c].count++;
flength++;
}
printf("文件长度为:%ld\n",flength);
czqing[c].count--;
for(i=0;i<M;i++)
{
if(czqing[i].count!=0)
{
czqing[i].b=i;
}
else czqing[i].b=0;
czqing[i].parent=-1,czqing[i].lchild=-1,czqing[i].rchild=-1;
}
for(i=0;i<256;i++)
for(j=i+1;j<256;j++)
{
if(czqing[i].count<czqing[j].count)
{
temp=czqing[i];
czqing[i]=czqing[j];
czqing[j]=temp;
}
}
for(n=0;n<256;n++)
if(czqing[n].count==0)break;
m=2*n-1;
for(i=n;i<m;i++)
{
k=9999999;
for(j=0;j<i;j++)
{
if(czqing[j].parent!=-1)continue;
if(czqing[j].count<k)
{
cz=j;
k=czqing[cz].count;
}
}
czqing[i].lchild=cz;
czqing[cz].parent=i;
czqing[i].count=czqing[cz].count;
k=9999999;
for(j=0;j<i;j++)
{
if(czqing[j].parent!=-1)continue;
if(czqing[j].count<k)
{
cz=j;
k=czqing[cz].count;
}
}
czqing[i].count+=czqing[cz].count;
czqing[i].rchild=cz;
czqing[cz].parent=i;
}
for(i=0;i<n;i++)
{
f=i;k=0;
while(czqing[f].parent!=-1)
{
j=f;
f=czqing[f].parent;
if(czqing[f].lchild==j)
{
czqing[i].bit[k++]='0';
}
else
czqing[i].bit[k++]='1';
}
}
fseek(fp,0,SEEK_SET);
fprintf(fq,"%d ",n);
for(i=0;i<n;i++)
{
fprintf(fq,"%c %d ",czqing[i].b,czqing[i].count);
}
//压缩
kk=0;
fseek(fp,0,SEEK_SET);
k=0;kk=0;
while(!feof(fp))
{
c=fgetc(fp); //c为读取字符的AC
for(i=0;i<n;i++)
{
if(czqing[i].b==c)break;
}
for(j=strlen(czqing[i].bit)-1;j>=0;j--)
{
buf[k++]=czqing[i].bit[j];
kk++;
buf[k]='\0';
}
if(k>=8)
{
for(j=0;j<k;j=j+8)
{
if(k-j<8)break;
c=(buf[j]-'0')*2*2*2*2*2*2*2+(buf[j+1]-'0')*2*2*2*2*2*2+(buf[j+2]-'0')*2*2*2*2*2+(buf[j+3]-'0')*2*2*2*2
+(buf[j+4]-'0')*2*2*2+(buf[j+5]-'0')*2*2+(buf[j+6]-'0')*2+(buf[j+7]-'0');
}
k=k-j;
}
}
kk=0;
fseek(fp,0,SEEK_SET);
k=0;kk=0;
while(!feof(fp))
{
c=fgetc(fp); //c为读取字符的AC
for(i=0;i<n;i++)
{
if(czqing[i].b==c)break;
}
for(j=strlen(czqing[i].bit)-1;j>=0;j--)
{
buf[k++]=czqing[i].bit[j];
kk++;
buf[k]='\0';
}
// printf("%s ",buf);
if(k>=8)
{
for(j=0;j<k;j=j+8)
{
if(k-j<8)break;
c=(buf[j]-'0')*2*2*2*2*2*2*2+(buf[j+1]-'0')*2*2*2*2*2*2+(buf[j+2]-'0')*2*2*2*2*2+(buf[j+3]-'0')*2*2*2*2
+(buf[j+4]-'0')*2*2*2+(buf[j+5]-'0')*2*2+(buf[j+6]-'0')*2+(buf[j+7]-'0');
fprintf(fq,"%c",c);
}
k=k-j;
st=j;
for(iii=0;iii<k;iii++)
buf[iii]=buf[st++];
}
}
if(k!=0)
{
for(i=0;i<k;i++)
{
fprintf(fq,"%c",buf[i]-'0');
}
}
fclose(fp);
fclose(fq);
printf("压缩成功,压缩文件名为:%s\n",outputfile);
return;
}
void uncompress()
{
unsigned char c,cc;
FILE *fp,*fq;
char filename[255],outputfile[255];
char buf[512];
int i,j;
long m,n,cz,k,f,pn;
printf("请输入解压文件名(必须是以.czq结尾的文件): ");
gets(filename);
fp=fopen(filename,"rb");
if(fp==NULL){
return ;
}
printf("请输入解压后的文件名: ");
gets(outputfile);
fq=fopen(strcat(outputfile,".txt"),"wb");
if(fq==NULL)
{
printf("解压失败\n");
return ;
}
fseek(fp,0,SEEK_SET);
fscanf(fp,"%d%*c",&n);
for(i=0;i<M;i++)
{
czqing[i].b=0;
czqing[i].count=0;
czqing[i].parent=-1,czqing[i].lchild=-1,czqing[i].rchild=-1;
}
for(i=0;i<n;i++)
{
fscanf(fp,"%c%*c%d%*c",&c,&k);
// fread(&c,1,1,fp);
// fread(&k,1,1,fp);
czqing[i].count=k;
czqing[i].b=c;
}
for(i=0;i<M;i++)
{
czqing[i].parent=-1,czqing[i].lchild=-1,czqing[i].rchild=-1;
}
for(n=0;n<256;n++)
if(czqing[n].count==0)break;
m=2*n-1;
for(i=n;i<m;i++)
{
k=9999999;
for(j=0;j<i;j++)
{
if(czqing[j].parent!=-1)continue;
if(czqing[j].count<k)
{
cz=j;
k=czqing[cz].count;
}
}
czqing[i].lchild=cz;
czqing[cz].parent=i;
czqing[i].count=czqing[cz].count;
k=9999999;
for(j=0;j<i;j++)
{
if(czqing[j].parent!=-1)continue;
if(czqing[j].count<k)
{
cz=j;
k=czqing[cz].count;
}
}
czqing[i].count+=czqing[cz].count;
czqing[i].rchild=cz;
czqing[cz].parent=i;
}
for(i=0;i<n;i++)
{
f=i;k=0;
while(czqing[f].parent!=-1)
{
j=f;
f=czqing[f].parent;
if(czqing[f].lchild==j)
{
czqing[i].bit[k++]='0';
}
else
czqing[i].bit[k++]='1';
}
}
k=0;
for(n=0;n<256;n++)
if(czqing[n].count==0)break;
pn=n-1;
while(!feof(fp))
{
//fscanf(fp,"%c%*",&c);
fread(&c,1,1,fp);
cc=c;
if(cc==1||cc==0){
buf[7]=cc%2;i=6;}
else
for(i=7;i>=0;i--)
{
buf[i]=c%2;
c=c/2;
}
if(i!=0)
{
for(j=i+1;j<8;j++)
{
if(buf[j]==0){pn=czqing[pn].lchild;}
else if(buf[j]==1){pn=czqing[pn].rchild;}
if(czqing[pn].lchild==-1&&czqing[pn].rchild==-1)
{
//fprintf(fq,"%c",czqing[pn].b);
fwrite(&czqing[pn].b,1,1,fq);
pn=n-1;
}
}
}
else
for(j=0;j<8-i;j++)
{
if(buf[j]==0){pn=czqing[pn].lchild;}
else if(buf[j]==1){pn=czqing[pn].rchild;}
if(czqing[pn].lchild==-1&&czqing[pn].rchild==-1)
{
//fprintf(fq,"%c",czqing[pn].b);
fwrite(&czqing[pn].b,1,1,fq);
pn=n-1;
}
}
}
printf("解压成功,解压文件名为:%s\n",outputfile);
}
int main(int argv,char **argc)
{
char c;
system("color 3B");
printf("\n\n\n");
printf("\t╭──────────────────────────────╮ \n");
printf("\t│ 欢迎使用txt压缩工具 │ \n");
printf("\t│ │ \n");
printf("\t│ * * * * * * * * * * │ \n");
printf("\t│ * * * * │ \n");
printf("\t│ * * * * * │ \n");
printf("\t│* * * * * ** * * │ \n");
printf("\t│ * * * * * * * * * * │ \n");
printf("\t│ * * * * * * * * * │ \n");
printf("\t│ * * * * * * * * * * * * * * * * │ \n");
printf("\t│ * │ \n");
printf("\t│ * * │ \n");
printf("\t│ * * │ \n");
printf("\t│ ** │ \n");
printf("\t│1.压缩 │ \n");
printf("\t│2.解压 │ \n");
printf("\t│请输入要操作的序号(1 or 2): │ \n");
printf("\t│ │ \n");
printf("\t│ │ \n");
printf("\t╰──────────────────────────────╯ \n");
c=getch();
if(c=='\n')c=getchar();
if(c=='1')compress();
else if(c=='2')uncompress();
return 0;
}