通过写这个程序让我更正了一个错误的认识,,, -1不一定是文件的结束符!!!!(害我调了两天..::>_<::) #include<iostream> #include<fstream> #include<conio.h> #include<math.h> #include<time.h> using namespace std; long P[600],HEAD,FILESIZE=0; char INPATH[255],OUTPATH[255],W[8]={0}; struct tree { int weight,left,right,data; }; tree T[600]; void cal() /*统计字符出现频率*/ { FILE *in=fopen(INPATH,"rb"); memset(P,0,sizeof(P)); char a=fgetc(in); while(!feof(in)) { P[a+300]++; FILESIZE++; a=fgetc(in); } fclose(in); } char code[600][600]; void getbianma(int left,int now,char c,int deep) { if(deep>0) { strcpy(code[T[now].data+300],code[T[left].data+300]); code[T[now].data+300][deep-1]=c; code[T[now].data+300][deep]='/0'; } if(T[now].left!=-1) getbianma(now,T[now].left,'0',deep+1); if(T[now].right!=-1) getbianma(now,T[now].right,'1',deep+1); } void creatHoffman() /*创建哈弗曼树*/ { int i,j,n=0,k,s; for(i=0;i<600;i++) if(P[i]>0) { T[n].data=char(i-300); T[n].weight=P[i]; T[n].left=T[n].right=-1; n++; } char lock[600]; memset(lock,0,sizeof(lock)); for(k=0,s=n;k<s-1;k++) /*开始生成哈弗曼树*/ { int min1,min2=-1; for(i=0;i<n;i++) if(!lock[i]) { min1=i; break;} for(j=i;j<n;j++) /*找到权值第一小的节点*/ if(!lock[j]&&T[j].weight<T[min1].weight) min1=j; for(j=i;j<n;j++) /*找到权值第一小的节点*/ if(!lock[j]&&j!=min1&&((min2==-1||T[j].weight<T[min2].weight))) min2=j; /*找到两个节点后开始合并*/ T[n].weight=T[min1].weight+T[min2].weight; T[n].data=-300; T[n].right=min1; T[n].left=min2; code[T[n].data+300][0]='/0'; lock[min1]=lock[min2]=1; n++; } HEAD=n-1; getbianma(-1,n-1,'0',0); } void savenote() /*保存密码本*/ { ofstream out(OUTPATH,ios::binary); out.write((char *)&FILESIZE,sizeof(long)); out.write((char *)&HEAD,sizeof(int)); for(int i=0;i<=HEAD;i++) out.write((char *)&T[i],sizeof(tree)); out.close(); } void readnote() { ifstream in(INPATH,ios::binary); in.read((char *)&FILESIZE,sizeof(long)); in.read((char *)&HEAD,sizeof(int)); for(int i=0;i<=HEAD;i++) in.read((char *)&T[i],sizeof(tree)); in.close(); } void passed() { FILE *in=fopen(INPATH,"rb"),*out=fopen(OUTPATH,"wb"); char a=fgetc(in); char temp=0; int th=0; while(!feof(in)) { for(int i=0;i<strlen(code[a+300]);i++) { if(code[a+300][i]-48) { temp=temp|W[th]; } th++; if(th>7) { th=0; fputc(temp,out); temp=0; } } a=fgetc(in); } if(th>0) fputc(temp,out); fclose(in); fclose(out); } void huanyuan() { FILE *in=fopen(INPATH,"rb"),*out=fopen(OUTPATH,"wb"); char a=fgetc(in); int p=HEAD; while(!feof(in)&&FILESIZE) { for(int i=0;i<8&&FILESIZE;i++) { if(a&W[i]) { if(T[p].right!=-1) p=T[p].right; else { fputc(T[p].data,out); p=HEAD; FILESIZE--; i--; } } else { if(T[p].left!=-1) p=T[p].left; else { fputc(T[p].data,out); p=HEAD; FILESIZE--; i--; } } } a=fgetc(in); } while(FILESIZE--) fputc(T[p].data,out); fclose(in); fclose(out); } int main() { int t1,t2; for(int i=0;i<8;i++) W[i]|=(char)pow(2,7-i); while(1) { system("cls"); cout<<"您正在使用的是哈夫曼压缩程序!/n1:加密 /n2:解密 /n0:退出"<<endl; char a=getch(); FILESIZE=0; if(a=='1') { cout<<"输入待压缩文件路径!(也可以直接将待压缩文件拖到本程序窗口中)/n"; cin>>INPATH; strcpy(OUTPATH,INPATH); strcat(OUTPATH,".passnote"); t1=clock(); cal(); creatHoffman(); savenote(); strcpy(strrchr(OUTPATH,'.'),".passed"); passed(); t2=clock(); cout<<"压缩完毕,用时"<<double(t2-t1)/1000<<"s,请保管好压缩后的文件和编码本文件!./n"; } else if(a=='2') { cout<<"输入待解压文件路径!(也可以直接将待解压文件拖到本程序窗口中)/n"; cin>>INPATH; strcpy(strrchr(INPATH,'.'),".passnote"); strcpy(OUTPATH,INPATH); *strrchr(OUTPATH,'.')='/0'; t1=clock(); readnote(); getbianma(-1,HEAD,'0',0); strcpy(strrchr(INPATH,'.'),".passed"); huanyuan(); t2=clock(); cout<<"文件已经解压!,用时"<<double(t2-t1)/1000<<"s./n"; } else break; system("pause"); } return 0; }