版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、<p> 文件加密-赫夫曼算法</p><p><b> 一 目的</b></p><p> 通過(guò)課程設(shè)計(jì),鞏固和加深對(duì)線(xiàn)性表、棧、隊(duì)列、字符串、樹(shù)、圖、查找、排序等理論知識(shí)的理解;掌握現(xiàn)實(shí)復(fù)雜問(wèn)題的分析建模和解決方法(包括問(wèn)題描述、系統(tǒng)分析、設(shè)計(jì)建模、代碼實(shí)現(xiàn)、結(jié)果分析等);提高利用計(jì)算機(jī)分析解決綜合性實(shí)際問(wèn)題的基本能力。</p>&
2、lt;p><b> 二 需求分析</b></p><p> 1、文件加密核心算法(赫夫曼編碼)設(shè)計(jì)</p><p> 文件加密的核心算法是赫夫曼編碼,赫夫曼編碼的完成首先建立在赫夫曼樹(shù)的創(chuàng)建,在此之前要完成編碼字符的權(quán)值計(jì)算,依照題意:</p><p> 1、將26個(gè)字符的權(quán)值存入weight結(jié)構(gòu)體中。</p>&
3、lt;p> 2、將各個(gè)結(jié)點(diǎn)HTNode補(bǔ)充數(shù)值,創(chuàng)建赫夫曼樹(shù)HuffmanTree。</p><p> 3、赫夫曼樹(shù)創(chuàng)建完畢,即可進(jìn)行字符串的編碼和解碼工作。核心算法即完成。</p><p><b> 2、功能要求和說(shuō)明</b></p><p> 使用菜單操作,提示用戶(hù)相應(yīng)的操作,用戶(hù)指定文件對(duì)其進(jìn)行加密或解密,在屏幕上可以看到文
4、件內(nèi)容。</p><p> 用戶(hù)指定文件,默認(rèn)在D:\,為了便于測(cè)試編碼和解碼的正確性??梢杂捎脩?hù)輸入字符串進(jìn)行編碼和解碼。</p><p><b> 三 概要設(shè)計(jì)</b></p><p> 1、可滿(mǎn)足輸入輸出的形式及限制</p><p> 本程序只支持26字符編碼解碼,程序運(yùn)行中間會(huì)產(chǎn)生一個(gè)outfile.t
5、xt文件,用于存儲(chǔ)加密或解密內(nèi)容。支持用戶(hù)在屏幕查看文件內(nèi)容。</p><p> 程序在用戶(hù)輸入數(shù)據(jù)前,會(huì)輸出相應(yīng)的提示,在用戶(hù)輸入超出范圍或者輸入錯(cuò)誤時(shí),會(huì)提示重新輸入或者提示錯(cuò)誤并退出。</p><p> 2、所用數(shù)據(jù)類(lèi)型的定義及含義</p><p> 此程序運(yùn)用了整形、實(shí)型、字符型、指針、數(shù)組、結(jié)構(gòu)體。下面是全局(舉例):</p><
6、p> typedef struct{</p><p> int weight;</p><p> int parent,lchild,rchild;</p><p> }HTNode; //構(gòu)造赫夫曼樹(shù)結(jié)點(diǎn)的結(jié)構(gòu)體</p><p> typedef struct{</p><p
7、> HTNode *HTN; //存儲(chǔ)編碼的各個(gè)字符</p><p> int length; //需編碼字符個(gè)數(shù)</p><p> int size; //赫夫曼編碼總?cè)萘?lt;/p><p> }HuffmanTree; //構(gòu)造赫夫曼樹(shù)的結(jié)構(gòu)體</p>&
8、lt;p> typedef struct{</p><p> char *ch; //存放需要編碼的原始字碼</p><p> int *in; //存放各個(gè)字碼的權(quán)值</p><p><b> }Weight; </b></p><p> cha
9、r Code[27][26]; //存放各個(gè)字符的赫夫曼編碼01</p><p> int Code_N[30]; //存放各個(gè)字符對(duì)應(yīng)編碼01的個(gè)數(shù),用于輸出控制</p><p><b> 3、各模塊的劃分</b></p><p><b> 簡(jiǎn)化圖:</b></p><
10、p> 4、各模塊的功能描述</p><p> 1、赫夫曼編碼部分:題意規(guī)定字符頻率或用戶(hù)輸入字符串,計(jì)算出字符權(quán)值,創(chuàng)建赫夫曼樹(shù),進(jìn)行赫夫曼編碼,將其存入全局變量,用于字符串編碼解碼,文件加密及解密。</p><p> 2、文件加密部分:由用戶(hù)輸入加密的文件名稱(chēng)(filename.txt),加密過(guò)程中將加密后內(nèi)容暫時(shí)存入outfile.txt中,此時(shí)已經(jīng)將filename.tx
11、t中內(nèi)容加密,但內(nèi)容在outfile.txt中,重新將outfile.txt內(nèi)容存入到filename.txt中,則文件加密過(guò)程完成。</p><p> 3、文件解密部分:文件解密過(guò)程同加密過(guò)程,只是內(nèi)容處理只是由加密變?yōu)榻饷苓^(guò)程。其余過(guò)程不改變,解密過(guò)程也用到了outfile.txt文件。</p><p> 4、文件查看部分:用戶(hù)輸入文件名稱(chēng),文件內(nèi)容輸出到屏幕,用于查看文件加密或解
12、密的結(jié)果。</p><p> 5、各函數(shù)的定義及描述</p><p> void showMenu(); //輸出菜單列表</p><p> 操作結(jié)果:在屏幕上打印出菜單</p><p> void Init_Huf
13、fmanTree(HuffmanTree &H,Weight S); //對(duì)赫夫曼樹(shù)結(jié)構(gòu)初始化</p><p> H是初始化的赫夫曼樹(shù)的結(jié)構(gòu)體,S是字符及權(quán)值的結(jié)構(gòu)體</p><p> 操作結(jié)果:對(duì)H和S進(jìn)行了初始化</p><p> void Init_Weight(Weight &S,int msize,int msize1);
14、//對(duì)編碼個(gè)數(shù)和權(quán)值的結(jié)構(gòu)初始化</p><p> S是傳入函數(shù)的字符及權(quán)值的結(jié)構(gòu)體</p><p> msize和msize1是初始化S.ch和S.in的整形數(shù)據(jù)</p><p> 操作結(jié)果:將Weight結(jié)果體初始化</p><p> void WeightNumber(Weight &S);
15、 //求出輸入字符串各個(gè)字符的權(quán)值</p><p> S是傳入的的Weight結(jié)構(gòu)體</p><p> 操作結(jié)果:S的數(shù)值按照程序重新計(jì)算字符權(quán)值</p><p> void select(HuffmanTree H,int j,int a[]); //選擇parent=0且權(quán)值較小的兩個(gè)HTn
16、ode</p><p> H是HuffmanTree結(jié)構(gòu)體傳入數(shù)值,a[]用來(lái)返回兩個(gè)較小權(quán)值的下標(biāo)</p><p> 操作結(jié)果:a[]存入了在j個(gè)數(shù)據(jù)中較小權(quán)值的結(jié)點(diǎn)下標(biāo)</p><p> void creat_HuffmanTree(HuffmanTree &H); //創(chuàng)建赫夫曼樹(shù)</p><p>
17、 H是HuffmanTree結(jié)構(gòu)體。</p><p> 操作結(jié)果:H構(gòu)建好了赫夫曼樹(shù)</p><p> void creat_HTCode(HuffmanTree H,Weight S); //赫夫曼編碼</p><p> 操作結(jié)果:輸出各個(gè)字符編碼并存入code[][]中。</p><p> void explain_H
18、TCode(HuffmanTree H,Weight S); //用戶(hù)輸入01字符串進(jìn)行赫夫曼解碼</p><p> 輸入內(nèi)容:輸入01字符串</p><p> 操作結(jié)果:輸出對(duì)01字符串按照赫夫曼編碼對(duì)應(yīng)的字符串</p><p> void encryptFile(Weight S);
19、 //對(duì)指定文件進(jìn)行加密</p><p> 操作結(jié)果:文件內(nèi)容變?yōu)榘凑蘸辗蚵幋a規(guī)則的01字符內(nèi)容</p><p> void deencryptFile(HuffmanTree H,Weight S); //對(duì)指定文件進(jìn)行解密</p><p> 操作結(jié)果:加密內(nèi)容變?yōu)榘凑蘸辗蚵幋a規(guī)則對(duì)應(yīng)的字符內(nèi)容</p><p>
20、; void my_readFile(); //用于讀出文件中所儲(chǔ)存的全部信息</p><p> 操作結(jié)果:在屏幕上輸出指定文件內(nèi)容</p><p> 6、各函數(shù)之間的調(diào)用關(guān)系</p><p> 主函數(shù)中是菜單打?。╯howmenu ())和switch()
21、,各模塊套用和調(diào)用關(guān)系如下:</p><p> 主函數(shù)中調(diào)用Init_HuffmanTree(h,s); creat_HuffmanTree(h); creat_HTCode(h,s);</p><p> explain_HTCode(h,s); encryptFile(s); deencryptFile(h,s); WeightNumber(s);</p><p
22、> 子函數(shù)creat_HuffmanTree(h);中調(diào)用了select(HuffmanTree H,int j,int a[]);</p><p><b> 四 詳細(xì)設(shè)計(jì)</b></p><p><b> 1、流程圖</b></p><p><b> 2、數(shù)據(jù)類(lèi)型及定義</b><
23、;/p><p> 1、此程序運(yùn)用了整形、實(shí)型、字符型、指針、文件指針、數(shù)組、結(jié)構(gòu)體。</p><p> 2、全局變量的數(shù)據(jù)類(lèi)型</p><p> typedef struct{</p><p> int weight;</p><p> int parent,lchild,rchild;</p>&
24、lt;p> }HTNode; //構(gòu)造赫夫曼樹(shù)結(jié)點(diǎn)的結(jié)構(gòu)體</p><p> typedef struct{</p><p> HTNode *HTN; //存儲(chǔ)編碼的各個(gè)字符</p><p> int length; //需編碼字符個(gè)數(shù)</p><p> int si
25、ze; //赫夫曼編碼總?cè)萘?lt;/p><p> }HuffmanTree; //構(gòu)造赫夫曼樹(shù)的結(jié)構(gòu)體</p><p> typedef struct{</p><p> char *ch; //存放需要編碼的原始字碼</p><p> int *in;
26、 //存放各個(gè)字碼的權(quán)值</p><p><b> }Weight; </b></p><p> char Code[27][26]; //存放各個(gè)字符的赫夫曼編碼01</p><p> int Code_N[30]; //存放各個(gè)字符對(duì)應(yīng)編碼01的個(gè)數(shù),用于輸出控制</p>
27、;<p><b> 3、數(shù)據(jù)的定義聲明</b></p><p> 主函數(shù)中定義了:HuffmanTree h; //用于構(gòu)建赫夫曼樹(shù)</p><p> Weight s; //用于存放各個(gè)字符的權(quán)值</p><p> 3、主要程序的源代碼(部分)及注釋</p><p> //
28、對(duì)赫夫曼樹(shù)結(jié)構(gòu)初始化</p><p> void Init_HuffmanTree(HuffmanTree &H,Weight S){</p><p> H.HTN=new HTNode[S.in[0]*2-1];</p><p> for(int i=1;i<=S.in[0]*2-1;i++){ //將H.HTN[i]權(quán)值、父親節(jié)點(diǎn)、左右孩
29、子都設(shè)置為0</p><p> H.HTN[i].weight=0;</p><p> H.HTN[i].parent=0;</p><p> H.HTN[i].lchild=0;</p><p> H.HTN[i].rchild=0; </p><p><b> }<
30、;/b></p><p> for(int j=1;j<=S.in[0];j++){</p><p> H.HTN[j].weight=S.in[j];</p><p> } </p><p> H.length=S.in[0];
31、 //需要編碼的字符個(gè)數(shù)</p><p> H.size=S.in[0]*2-1; //赫夫曼編碼容量為2*n-1,n為編碼字符個(gè)數(shù)</p><p><b> }</b></p><p> //對(duì)編碼個(gè)數(shù)和權(quán)值的結(jié)構(gòu)初始化</p><p> void Init_Weig
32、ht(Weight &S,int msize,int msize1){</p><p> S.ch=new char[msize];</p><p> S.in=new int[msize1];</p><p> if(!S.ch&&!S.in){</p><p> cout<<"未能分配
33、空間!"<<endl;</p><p> getchar();</p><p><b> exit(0);</b></p><p><b> }</b></p><p><b> }</b></p><p> //求出輸入
34、字符串各個(gè)字符的權(quán)值</p><p> void WeightNumber(Weight &S){</p><p> char s[50];</p><p> int i=0,j=1,k=1;</p><p> for(i=0;i<50;i++)</p><p> S.in[i]=0;</
35、p><p> printf("請(qǐng)輸入要編碼的字符串(0-50):\n");</p><p> gets(s); //輸入字符串</p><p> while(s[i]!='\0'){</p><p><
36、b> j=1;</b></p><p> while(S.ch[j]!='\0'){ //統(tǒng)計(jì)字符串中各字符存入S.ch中</p><p> if(S.ch[j]==s[i]){ </p><p><b> j=1;</b></p><p><b
37、> i++;</b></p><p><b> continue;</b></p><p> }else j++;</p><p><b> }</b></p><p> S.ch[k]=s[i];</p><p><b> k++;&
38、lt;/b></p><p><b> i++;</b></p><p><b> }</b></p><p> S.ch[k]='\0';</p><p><b> i=1;</b></p><p> while(S.c
39、h[i]!='\0') </p><p><b> i++;</b></p><p> S.in[0]=i-1; </p><p> for(i=1;S.ch[i]!='\0';){
40、 //統(tǒng)計(jì)字符串中各字符的個(gè)數(shù)</p><p> for(j=0;s[j]!='\0';){</p><p> if(S.ch[i]==s[j]){</p><p> S.in[i]++;</p><p><b> }</b></p><p><b>
41、 j++;</b></p><p><b> }</b></p><p><b> i++;</b></p><p><b> }</b></p><p><b> }</b></p><p> //選擇par
42、ent=0且權(quán)值較小的兩個(gè)HTnode</p><p> void select(HuffmanTree H,int j,int a[]){</p><p> a[1]=a[2]=0;</p><p> H.HTN[0].weight=1000;</p><p> for(int i=1;i<=j;i++){</p>
43、<p> if(H.HTN[i].parent==0){ //parent為0,則為未插入樹(shù)的結(jié)點(diǎn)</p><p> if(H.HTN[i].weight<H.HTN[a[1]].weight){</p><p> a[2]=a[1];</p><p><b> a[1]=i;</b></
44、p><p><b> }</b></p><p> else if(H.HTN[i].weight<H.HTN[a[2]].weight){</p><p><b> a[2]=i;</b></p><p><b> }</b></p><p>
45、;<b> }</b></p><p><b> }</b></p><p><b> }</b></p><p><b> //創(chuàng)建赫夫曼樹(shù)</b></p><p> void creat_HuffmanTree(HuffmanTree &am
46、p;H){</p><p> int i=H.length;</p><p> int node[3];</p><p> node[1]=i;node[2]=i;</p><p> HTNode h1,h2;</p><p> h1.weight=h2.weight=H.HTN[0].weight;<
47、/p><p> for(int k=i+1;k<=H.size;k++){</p><p> select(H,k-1,node); </p><p> //選擇出兩個(gè)權(quán)值較小的兩個(gè)結(jié)點(diǎn),node存有兩個(gè)結(jié)點(diǎn)的值</p><p> H.HTN[node[1]].parent=k; //構(gòu)造
48、出父親結(jié)點(diǎn)</p><p> H.HTN[node[2]].parent=k;</p><p> H.HTN[k].lchild=node[1];</p><p> H.HTN[k].rchild=node[2];</p><p> H.HTN[k].weight=H.HTN[node[1]].weight+H.HTN[node[2]
49、].weight;</p><p><b> }</b></p><p><b> }</b></p><p><b> //赫夫曼編碼</b></p><p> void creat_HTCode(HuffmanTree H,Weight S){ </p>
50、;<p> int i,j,n,k=25;</p><p> for(i=0;i<30;i++) //Code_N用于計(jì)數(shù),初始化為0,為計(jì)數(shù)準(zhǔn)備</p><p> Code_N[i]=0;</p><p> for(i=1;i<=H.length;i++){
51、 //對(duì)每個(gè)字符進(jìn)行編碼</p><p> k=25; //編碼不會(huì)超過(guò)25個(gè)字符</p><p> //將各個(gè)字符編碼存入到Code中</p><p> for(j=i,n=H.HTN[i].parent;j!=0;j=n,n=H.HTN[n].parent){ </p>
52、<p> if(H.HTN[n].lchild==j){ </p><p> Code[i][k--]='0';</p><p> Code_N[i]++;</p><p><b> }else{</b></p><p> Code[i][k--]='1
53、9;;</p><p> Code_N[i]++;</p><p><b> }</b></p><p> if(H.HTN[n].parent==0)</p><p><b> break;</b></p><p><b> }</b><
54、;/p><p><b> }</b></p><p> for(i=1;i<=H.length;i++) //循環(huán)輸出各個(gè)字符的編碼</p><p><b> {</b></p><p> printf("%c編碼為:",S
55、.ch[i]);</p><p> for(k=25-Code_N[i]+1;k<=25;k++){</p><p> printf("%c",Code[i][k]);</p><p><b> }</b></p><p> printf("\n");</p&g
56、t;<p><b> }</b></p><p><b> }</b></p><p><b> //赫夫曼解碼</b></p><p> void explain_HTCode(HuffmanTree H,Weight S){</p><p> cha
57、r a[50],b[30];</p><p> int n=0,i,j,l=0,k=0;</p><p> printf("請(qǐng)輸入需要解碼的字符串(0—49例子:01010)\n");</p><p> gets(a); </p><p> while(a[
58、n]!='\0')</p><p><b> n++;</b></p><p> for(j=H.size,i=0;i<n;){ //結(jié)束控制為01字符個(gè)數(shù)的限制</p><p> j=H.size; </p><p> while(H.
59、HTN[j].lchild!=0&&H.HTN[j].rchild!=0&&a[i]!='\0'){</p><p> if(a[i]=='0'){ </p><p> j=H.HTN[j].lchild; i++;</p><p><b> }</b></p
60、><p><b> else{</b></p><p> j=H.HTN[j].rchild; i++;</p><p><b> }</b></p><p><b> }</b></p><p> if(j<=H.length){
61、 //控制當(dāng)剩余一部分01卻無(wú)法解碼</p><p> b[l++]=S.ch[j]; //將對(duì)應(yīng)解碼的字符存放到b中用于輸出</p><p> k=i; //記錄無(wú)法解碼01的個(gè)數(shù)用于輸出</p><p><b> }</b></p><p
62、> if(a[i]=='\0') </p><p><b> break;</b></p><p><b> }</b></p><p> for(i=0;i<k;i++)</p><p> printf("%c",a[i])
63、;</p><p> printf("序列解碼后代碼為:");</p><p> for(i=0;i<l;i++)</p><p> printf("%c",b[i]);</p><p> printf("\n無(wú)法解碼序列為:");</p><p&g
64、t; for(i=k;i<n;i++)</p><p> printf("%c",a[i]);</p><p><b> }</b></p><p> /*對(duì)指定文件進(jìn)行加密*/</p><p> void encryptFile(Weight S){</p><p
65、> FILE *fp1,*fp2;</p><p><b> char ch;</b></p><p> int k=25,i;</p><p> char ming[]="D:\\",wen[20];</p><p> char fileName[]="";<
66、;/p><p> printf("\n請(qǐng)輸入讀取的文件的名稱(chēng)(例:outfile1.txt): ");</p><p><b> do</b></p><p><b> {</b></p><p> scanf("%s",wen);</p>
67、<p> if(strlen(wen)>20)</p><p> printf("文件字符過(guò)長(zhǎng),(0~20)");</p><p> }while(strlen(wen)>20);</p><p> strcat(ming,wen);</p><p> strcpy(fileName,min
68、g);</p><p> if((fp1=fopen(ming,"r"))==NULL){ //打開(kāi)方式為讀取方式</p><p> printf("%s文件無(wú)法打開(kāi)!",fileName);</p><p><b> exit(1);</b><
69、/p><p><b> }</b></p><p> if((fp2=fopen("D:\\outFile.txt","w+"))==NULL){ //打開(kāi)方式為寫(xiě)入方式</p><p> printf("D:\\outFile.txt%s文件無(wú)法打開(kāi)!");</p>
70、<p><b> exit(1);</b></p><p><b> }</b></p><p> while((ch=fgetc(fp1))!=EOF){</p><p> for(i=1;i<=S.in[0];i++){</p><p> if(ch==S.ch[i
71、]){</p><p> for(k=25-Code_N[i]+1;k<=25;k++){ //原理同赫夫曼編碼</p><p> printf("%c",Code[i][k]);</p><p> fputc(Code[i][k],fp2);</p><p><b> }</b>
72、;</p><p><b> }</b></p><p><b> }</b></p><p><b> }</b></p><p> fclose(fp1); </p><p> fclose(fp2);
73、 //關(guān)閉文件,對(duì)文件進(jìn)行保存</p><p> fp1=fopen(fileName,"w"); //打開(kāi)方式為寫(xiě)入方式</p><p> fp2=fopen("D:\\outFile.txt","r");
74、//打開(kāi)方式為讀取方式</p><p> while((ch=getc(fp2))!=EOF){</p><p> fputc(ch,fp1);</p><p><b> }</b></p><p> fclose(fp1); </p><p> fclose(fp2); //
75、關(guān)閉文件</p><p><b> }</b></p><p> /*對(duì)指定文件進(jìn)行解密*/</p><p> void deencryptFile(HuffmanTree H,Weight S){</p><p> FILE *fp1,*fp2;</p><p><b> c
76、har ch;</b></p><p> char ming[]="D:\\",wen[20]; </p><p> char fileName[]="";</p><p><b> int i;</b></p><p> printf("\n請(qǐng)輸入讀
77、取的文件的名稱(chēng)(例:outfile1.txt): ");</p><p><b> do</b></p><p><b> {</b></p><p> scanf("%s",wen);</p><p> if(strlen(wen)>20)</p&
78、gt;<p> printf("文件字符過(guò)長(zhǎng),(0~20)");</p><p> }while(strlen(wen)>20);</p><p> strcat(ming,wen);</p><p> strcpy(fileName,wen);</p><p> if((fp1=fopen(
79、ming,"r"))==NULL){ //打開(kāi)方式為讀取方式</p><p> printf("%s文件無(wú)法打開(kāi)!",ming);</p><p><b> exit(1);</b></p><p><b> }</b></
80、p><p> if((fp2=fopen("D:\\outFile.txt","w+"))==NULL){ //打開(kāi)方式為寫(xiě)入方式</p><p> printf("D:\\outFile.txt%s文件無(wú)法打開(kāi)!");</p><p><b> exit(1);</b><
81、/p><p><b> }</b></p><p> ch=getc(fp1);</p><p> while(ch!=EOF){ //原理同赫夫曼解碼</p><p><b> i=H.size;&l
82、t;/b></p><p> while(H.HTN[i].lchild!=0&&H.HTN[i].rchild!=0&&ch!=EOF){</p><p> if(ch=='0'){</p><p> i=H.HTN[i].lchild; ch=getc(fp1);</p><p>
83、;<b> }</b></p><p><b> else{</b></p><p> i=H.HTN[i].rchild; ch=getc(fp1);</p><p><b> }</b></p><p><b> }</b></p&g
84、t;<p> if(i<=H.length){</p><p> printf("%c",S.ch[i]);</p><p> fputc(S.ch[i],fp2);</p><p><b> }</b></p><p> if(ch==EOF)</p>&
85、lt;p><b> break;</b></p><p><b> }</b></p><p> fclose(fp1); </p><p> fclose(fp2); //關(guān)閉文件,對(duì)文件進(jìn)行保存</p>
86、;<p> fp1=fopen(fileName,"w"); //打開(kāi)方式為寫(xiě)入方式</p><p> fp2=fopen("D:\\outFile.txt","r"); //打開(kāi)方式為讀取方式</p><p> while((ch=getc(fp2
87、))!=EOF){</p><p> fputc(ch,fp1);</p><p><b> }</b></p><p> fclose(fp1); </p><p> fclose(fp2); //關(guān)閉文件</p><p><b> }</b></
88、p><p> /*用于讀出文件中所儲(chǔ)存的全部信息*/</p><p> void my_readFile(){</p><p><b> FILE *fp;</b></p><p><b> char ch; </b></p><p> char ming[]=&quo
89、t;D:\\",wen[20]; </p><p> printf("\n請(qǐng)輸入讀取的文件的名稱(chēng)(例:outfile1.txt): ");</p><p><b> do</b></p><p><b> {</b></p><p> scanf("%
90、s",wen);</p><p> if(strlen(wen)>20)</p><p> printf("文件字符過(guò)長(zhǎng),(0~20)");</p><p> }while(strlen(wen)>20);</p><p> strcat(ming,wen);
91、 //將路徑和文件名稱(chēng)連接形成一個(gè)字符串</p><p> if((fp=fopen(ming,"r"))==NULL){ //打開(kāi)方式為追加方式</p><p> printf("%s文件無(wú)法打開(kāi)!",ming);</p><p><b> exit(
92、1);</b></p><p><b> }</b></p><p> printf("文件內(nèi)容為:\n");</p><p> while((ch=fgetc(fp))!=EOF)</p><p> fputc(ch,stdout);</p><p>
93、fclose(fp);</p><p><b> }</b></p><p><b> 五 調(diào)試分析</b></p><p> 1、程序問(wèn)題解決及優(yōu)化</p><p> 1、核心問(wèn)題是創(chuàng)建赫夫曼樹(shù)并進(jìn)行編碼,但是在編碼問(wèn)題中出現(xiàn)了問(wèn)題,由于01編碼的長(zhǎng)度無(wú)法確定,我現(xiàn)在用的方法是用數(shù)組存放
94、,用計(jì)數(shù)來(lái)控制數(shù)組輸出,這樣會(huì)使空間浪費(fèi),改進(jìn)的想法是用指針來(lái)存儲(chǔ),這樣就可以節(jié)省空間,鑒于空間的使用和實(shí)現(xiàn)復(fù)雜程度就使用了數(shù)組存放。</p><p> 2、文件加密和解密部分,一開(kāi)始是使用讀取文件的內(nèi)容加密后保存到另一個(gè)文件中,但是對(duì)文件加密,應(yīng)該更好的是對(duì)加密文件本身加密。所以使用過(guò)渡文件即臨時(shí)文件,將要加密文件加密后內(nèi)容存入到這個(gè)臨時(shí)文件中,結(jié)束后再將臨時(shí)文件內(nèi)容轉(zhuǎn)存到要加密的文件。這樣就真正完成了對(duì)指定
95、文件本身的加密或者解密。</p><p> 3、對(duì)文件的操作,此程序主要是為了實(shí)現(xiàn)赫夫曼編碼及其應(yīng)用,只是把文件都默認(rèn)放到了D盤(pán)符下,可以加以改進(jìn)使用戶(hù)選擇盤(pán)符等,增加靈活性。</p><p><b> 六 測(cè)試結(jié)果</b></p><p><b> 1、屏幕輸出</b></p><p>&
96、lt;b> 1、輸出菜單顯示</b></p><p> 2、順序輸入帶有*號(hào)0、2、3:輸出字符赫夫曼編碼顯示</p><p> 3、輸入5 :輸入文件名稱(chēng)得到文件加密結(jié)果</p><p> 4、輸入6 :輸入解密文件名稱(chēng)得到解密結(jié)果</p><p> 5、輸入7:輸入文件名稱(chēng)查看文件內(nèi)容</p>&
97、lt;p><b> 2、文件加密效果</b></p><p> 經(jīng)過(guò)對(duì)比文件加密和解密后的內(nèi)容一致,文件加密成功。</p><p><b> 七 用戶(hù)使用說(shuō)明</b></p><p> 1、運(yùn)行環(huán)境及用戶(hù)操作說(shuō)明</p><p> 1、源代碼可在VC等編譯器下連接編譯運(yùn)行,huff
98、man.exe運(yùn)行環(huán)境要求低。</p><p><b> 下面是菜單頁(yè)面:</b></p><p> 2、運(yùn)行程序首先順序輸入帶有*號(hào)項(xiàng)0、2、3進(jìn)行赫夫曼編碼,然后就可以進(jìn)行4、赫夫曼解碼5、文件加密6、文件解密功能。</p><p> 3、在有關(guān)文件操作的選項(xiàng)中,都是輸入文件的名稱(chēng)包括文件的后綴。在六中結(jié)果演示中操作說(shuō)明已經(jīng)詳細(xì),并且
99、屏幕的提示輸出可以引導(dǎo)用戶(hù)簡(jiǎn)單操作此程序。</p><p><b> 八 課程設(shè)計(jì)總結(jié)</b></p><p><b> 1、學(xué)習(xí)心得</b></p><p> 1、通過(guò)這個(gè)課程設(shè)計(jì)可以知道,有關(guān)于利用赫夫曼樹(shù)求字符串的最優(yōu)編碼的基本方法有兩類(lèi),而在此程序中用到的是從葉子節(jié)點(diǎn)到根節(jié)點(diǎn)求編碼的方法,還有一種是從根到葉
100、子節(jié)點(diǎn)的方法,不過(guò)相對(duì)而言,這里運(yùn)用到的程序?qū)崿F(xiàn)代碼更容易讓人理解。</p><p> 2、通過(guò)此次程序編寫(xiě),對(duì)算法的空間和時(shí)間,還有實(shí)現(xiàn)難度上有了自己的理解,通過(guò)數(shù)據(jù)結(jié)構(gòu)的選取可以使得空間得到有效利用,并且應(yīng)該考慮到效率問(wèn)題,現(xiàn)在小程序可能體現(xiàn)不出什么問(wèn)題,并且這次對(duì)文件的操作又熟悉了,之前淺學(xué)了下數(shù)據(jù)庫(kù),通過(guò)學(xué)習(xí)的深入和對(duì)比,明白了在學(xué)習(xí)中要勤于思考,對(duì)知識(shí)間的聯(lián)系要善于發(fā)現(xiàn)和總結(jié),從而真正掌握。</
101、p><p> 3、在這個(gè)實(shí)驗(yàn)過(guò)程中實(shí)現(xiàn)赫夫曼編碼的過(guò)程中,對(duì)赫夫曼編碼的應(yīng)用自己有了更深入一步的了解。在這里只是用這個(gè)編碼用作加密作用。赫夫曼編碼可以起到壓縮的作用,要是把編碼后的字符串看做8bits為一字節(jié)的話(huà),在字符串中字符的頻率都較高的情況下,加密后的編碼轉(zhuǎn)換為8bits為一字節(jié)的話(huà),就起到了壓縮文件的內(nèi)容,要是根據(jù)文件確定字符的權(quán)值,再把權(quán)值信息放到另一個(gè)文件中,這樣既起到了壓縮文件作用又起到了加密文件的內(nèi)
102、容,要是不知道權(quán)值信息是無(wú)法解壓的。經(jīng)過(guò)查詢(xún)資料,了解到赫夫曼編碼是一種統(tǒng)計(jì)編碼。屬于無(wú)損壓縮編碼等等信息。所以實(shí)驗(yàn)中應(yīng)該不斷學(xué)習(xí)新的知識(shí)并且應(yīng)該用于實(shí)踐,這樣收獲會(huì)更多。</p><p><b> 源代碼: </b></p><p> 注: 編輯器:vc 6.0 </p><p> #include <stdio.h><
103、;/p><p> #include <stdlib.h></p><p> #include <iostream.h></p><p> #include <string.h></p><p> typedef struct{</p><p> int weight;</
104、p><p> int parent,lchild,rchild;</p><p> }HTNode; //構(gòu)造赫夫曼樹(shù)結(jié)點(diǎn)的結(jié)構(gòu)體</p><p> typedef struct{</p><p> HTNode *HTN; //存儲(chǔ)編碼的各個(gè)字符</p><p> int l
105、ength; //需編碼字符個(gè)數(shù)</p><p> int size; //赫夫曼編碼總?cè)萘?lt;/p><p> }HuffmanTree; //構(gòu)造赫夫曼樹(shù)的結(jié)構(gòu)體</p><p> typedef struct{</p><p> char *ch; //存放需要編碼的原始字碼<
106、;/p><p> int *in; //存放各個(gè)字碼的權(quán)值</p><p><b> }Weight; </b></p><p> char Code[27][26]; //存放各個(gè)字符的赫夫曼編碼01</p><p> int Code_N[30]; //存放各個(gè)字符對(duì)應(yīng)編碼01的
107、個(gè)數(shù),用于輸出控制</p><p><b> //輸出菜單列表</b></p><p> void showMenu();</p><p> //對(duì)赫夫曼樹(shù)結(jié)構(gòu)初始化</p><p> void Init_HuffmanTree(HuffmanTree &H,Weight S);</p>&
108、lt;p> //對(duì)編碼個(gè)數(shù)和權(quán)值的結(jié)構(gòu)初始化</p><p> void Init_Weight(Weight &S,int msize,int msize1);</p><p> //求出輸入字符串各個(gè)字符的權(quán)值</p><p> void WeightNumber(Weight &S);</p><p>
109、//選擇parent=0且權(quán)值較小的兩個(gè)HTnode</p><p> void select(HuffmanTree H,int j,int a[]);</p><p><b> //創(chuàng)建赫夫曼樹(shù)</b></p><p> void creat_HuffmanTree(HuffmanTree &H);</p>&l
110、t;p><b> //赫夫曼編碼</b></p><p> void creat_HTCode(HuffmanTree H,Weight S);</p><p><b> //赫夫曼解碼</b></p><p> void explain_HTCode(HuffmanTree H,Weight S);<
111、/p><p> /*對(duì)指定文件進(jìn)行加密*/</p><p> void encryptFile(Weight S);</p><p> /*對(duì)指定文件進(jìn)行解密*/</p><p> void deencryptFile(HuffmanTree H,Weight S);</p><p> /*用于讀出文件中所儲(chǔ)存的
112、全部信息*/</p><p> void my_readFile();</p><p> //主函數(shù)實(shí)現(xiàn)赫夫曼樹(shù)</p><p> void main()</p><p><b> {</b></p><p> HuffmanTree h;</p><p><
113、;b> Weight s;</b></p><p> Init_Weight(s,50,50);</p><p> char choose='\0',yes_no='\0',ch;</p><p><b> do</b></p><p><b> {&
114、lt;/b></p><p> showMenu();</p><p> printf(" 選擇: ");</p><p> cin>>choose;</p><p> switch(choos
115、e)</p><p><b> {</b></p><p> case'1': {WeightNumber(s);</p><p><b> }break;</b></p><p> case'2': {Init_HuffmanTree(h,s);</p
116、><p> creat_HuffmanTree(h);</p><p><b> }break;</b></p><p> case'3': {creat_HTCode(h,s);</p><p><b> }break;</b></p><p> ca
117、se'4': {explain_HTCode(h,s);</p><p><b> }break;</b></p><p> case'5': {encryptFile(s);</p><p><b> }break;</b></p><p> case
118、9;6': {deencryptFile(h,s);</p><p><b> }break;</b></p><p> case'7':{my_readFile();</p><p><b> }break;</b></p><p> case'8'
119、: {exit(0);</p><p><b> }break;</b></p><p> case'0': { </p><p> //對(duì)26個(gè)字符設(shè)置給定的權(quán)值</p><p> s.ch[1]='e';s.ch[2]='a';s.ch[3]='r
120、39;;s.ch[4]='i';s.ch[5]='o';</p><p> s.ch[6]='t';s.ch[7]='n';s.ch[8]='s';s.ch[9]='l';s.ch[10]='c';</p><p> s.ch[11]='u';s.ch[12]
121、='d';s.ch[13]='p';s.ch[14]='m';s.ch[15]='h';</p><p> s.ch[16]='g';s.ch[17]='b';s.ch[18]='f';s.ch[19]='y';s.ch[20]='w';</p><
122、p> s.ch[21]='k';s.ch[22]='v';s.ch[23]='x';s.ch[24]='z';s.ch[25]='j';</p><p> s.ch[26]='q';</p><p> s.in[1]=57;s.in[2]=43;s.in[3]=39;s.in[4]=
123、38;s.in[5]=37;</p><p> s.in[6]=35;s.in[7]=34;s.in[8]=29;s.in[9]=28;s.in[10]=23;</p><p> s.in[11]=19;s.in[12]=17;s.in[13]=16;s.in[14]=15;s.in[15]=15;</p><p> s.in[16]=13;s.in[17]=
124、11;s.in[18]=9;s.in[19]=9;s.in[20]=7;</p><p> s.in[21]=6;s.in[22]=5;s.in[23]=1;s.in[24]=1;s.in[25]=1;</p><p> s.in[26]=1;s.in[0]=26; </p><p><b
125、> FILE *fp;</b></p><p> if((fp=fopen("original.txt","w"))==NULL){ //打開(kāi)文件</p><p> printf("文件不能打開(kāi)");</p><p><b> exit(1);<
126、/b></p><p><b> }</b></p><p> for(int i=1;i<=26;i++){</p><p> fprintf(fp,"%c %d ",s.ch[i],s.in[i]);</p><p><b> }</b></p>
127、;<p> fclose(fp);</p><p><b> }break;</b></p><p> cout<<"\n\n\n\t\t\t確定退出(Y||N)";</p><p><b> cin>>ch;</b></p><p>
128、; if(ch=='Y'||ch=='y')</p><p><b> exit(0);</b></p><p> default:printf("\n %c 沒(méi)有此選項(xiàng)! 錯(cuò)誤! \n ",choose);</p><p><b> }</b></p
129、><p> printf("\n\n 繼續(xù)? 回到主菜單 (Y&y||N&n) \t請(qǐng)選擇:");</p><p><b> do</b></p><p><b> {</b></p><p> cin>>yes_no;</p>
130、<p> } while(yes_no!='Y'&&yes_no!='y'&&yes_no!='N'&&yes_no!='n');</p><p> } while(yes_no=='Y'||yes_no=='y');</p><p>
131、;<b> exit(0);</b></p><p><b> }</b></p><p><b> //輸出菜單列表</b></p><p> void showMenu(){</p><p> cout<<"\t\t-------------
132、-----文件加密------------------"<<"\n"</p><p> <<"\t\t\t* 0、根據(jù)給定的字符權(quán)值"<<"\n"</p><p> <<"\t\t\t 1、輸入需要編碼的字符串"<<"\n&q
133、uot;</p><p> <<"\t\t\t* 2、創(chuàng)建赫夫曼樹(shù)"<<"\n"</p><p> <<"\t\t\t* 3、對(duì)各字符進(jìn)行赫夫曼編碼"<<"\n"</p><p> <<"\t\t\t 4、輸入
134、01串進(jìn)行赫夫曼解碼"<<"\n"</p><p> <<"\t\t\t* 5、對(duì)文件進(jìn)行加密"<<"\n"</p><p> <<"\t\t\t* 6、對(duì)文件進(jìn)行解密"<<"\n"</p><p&
135、gt; <<"\t\t\t 7、讀取文件內(nèi)容"<<"\n"</p><p> <<"\t\t\t 8、退出"<<"\n"</p><p> <<"\t\t---------------------------------------
136、------"<<endl;</p><p><b> }</b></p><p> //對(duì)赫夫曼樹(shù)結(jié)構(gòu)初始化</p><p> void Init_HuffmanTree(HuffmanTree &H,Weight S){</p><p> H.HTN=new HTNode[S.i
137、n[0]*2-1];</p><p> for(int i=1;i<=S.in[0]*2-1;i++){ //將H.HTN[i]權(quán)值、父親節(jié)點(diǎn)、左右孩子都設(shè)置為0</p><p> H.HTN[i].weight=0;</p><p> H.HTN[i].parent=0;</p><p> H.HTN[i].lchild=
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 眾賞文庫(kù)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 數(shù)據(jù)結(jié)構(gòu)課程設(shè)計(jì)----赫夫曼樹(shù)
- 數(shù)據(jù)結(jié)構(gòu)-赫夫曼樹(shù)-課程設(shè)計(jì)
- 數(shù)據(jù)結(jié)構(gòu)課程設(shè)計(jì)(赫夫曼樹(shù)的建立)
- 赫夫曼編譯碼器數(shù)據(jù)結(jié)構(gòu)課程設(shè)計(jì)
- 數(shù)據(jù)結(jié)構(gòu)課程設(shè)計(jì)報(bào)告----哈夫曼
- 赫夫曼編譯碼器的實(shí)現(xiàn)數(shù)據(jù)結(jié)構(gòu)課程設(shè)計(jì)報(bào)告
- 課程設(shè)計(jì)-赫夫曼編譯碼器數(shù)據(jù)結(jié)構(gòu)設(shè)計(jì)
- 數(shù)據(jù)結(jié)構(gòu)赫夫曼樹(shù)2
- 數(shù)據(jù)結(jié)構(gòu)課程設(shè)計(jì)---哈夫曼編碼
- 哈夫曼樹(shù)_數(shù)據(jù)結(jié)構(gòu)課程設(shè)計(jì)
- 數(shù)據(jù)結(jié)構(gòu)課程設(shè)計(jì)----哈夫曼編碼
- 數(shù)據(jù)結(jié)構(gòu)課程設(shè)計(jì)哈夫曼編碼
- 哈夫曼樹(shù)_數(shù)據(jù)結(jié)構(gòu)課程設(shè)計(jì)
- 數(shù)據(jù)結(jié)構(gòu)課程設(shè)計(jì)--哈夫曼編碼
- 數(shù)據(jù)結(jié)構(gòu)課程設(shè)計(jì)---哈夫曼編碼
- 數(shù)據(jù)結(jié)構(gòu)課程設(shè)計(jì)哈夫曼編碼
- 數(shù)據(jù)結(jié)構(gòu)課程設(shè)計(jì)報(bào)告——哈夫曼編譯器
- 數(shù)據(jù)結(jié)構(gòu) 課程設(shè)計(jì)之哈夫曼編碼
- 數(shù)據(jù)結(jié)構(gòu)課程設(shè)計(jì)報(bào)告---基于哈夫曼樹(shù)的文件壓縮解壓程序
- 數(shù)據(jù)結(jié)構(gòu)課程設(shè)計(jì)報(bào)告---哈夫曼編碼器
評(píng)論
0/150
提交評(píng)論