大二数据结构课写的,有一个问题是结束符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; }