zoukankan      html  css  js  c++  java
  • Huffman编码

    PS:这篇博客的发表已经快一两年了,以我现在的知识水平来看这个程序写的太烂了,什么函数的定义写在h里面啊,h文件没有预编译宏之类的问题,关键是这个程序的效率太低了,主要原因还是编码的时候不断左移的问题,整个程序的复杂度都是O(c*m^2)了,m是一个很大很大的数,c是最大的编码长度,这个东西当是一个怀念吧。

      上次我在http://www.cnblogs.com/Philip-Tell-Truth/p/4787067.html这里,稍微讲了一下一种很普通的贪婪的算法,其实这个算法一开始是用来做压缩程序的,就是最著名的Huffman压缩算法

      那么这个算法是怎么样的呢,我们知道,我们的字符如果以ASCII的形式表示的话(只算英文和数字),其实就是一堆二进制代码,一个char型字符占一个字节。那么我们想到怎么压缩呢?

      因为我们的文档不可能打印那一些不可能出现在屏幕的字符,那么我们完全可以把这些字符去掉,然后制一套我们自己的字符表(二进制对应),不一定是1个字节对应一个字符,我们可以6个位对应一个字符这个样子,这样会对文档有一定的压缩。

      然后我们再想,在一篇文档中,每一个字符出现的概率不是相等的,有一些字母会出现很多次,比如a,b,s,这些,而有一些会出现的相对较少比如z,q这些,那么我们可不可以根据这个来压缩文件呢?答案是肯定的,既然我们已经确定了我们要根据概率来压缩文件,我们很自然地就会想到贪婪算法。

      我们先来看Fence Repair这一道题,这一道题最后我们是把最小的板占据树的最低空间,同样的,对于出现概率不一的字母,我们也可以给他构建一个这样的生成树(不同深度,分叉不同,对应的二进位的位数和状态(0,1)也会不同)。

           比如有一个这样的文档,里面的字符出现的概率对应如下:

    a 000 10 30
    e 001 15 45
    i 010 12 36
    s 011 3 9
    t 100 4 12
    space 101 13 19
    newline 110 1 3
    总和     174

      我们在不考虑其出现的概率进行压缩的情况下,我们重新制了一个对应表,那么最后出来的比特率就会降低很多

    现在我们尝试用概率结合贪婪算法继续进行压缩,我们知道,如果我们要构建一棵生成树的话,我们可以这样办,出现概率较高的字母,我们给他二进制的位比较少,出现概率比较低的字母,我们给他二进制位比较高,然后这样定义以后我们就会有一个很直观的结论,就是因为出现概率比较高的字母占的比特率会比较低,那么我们的整体占的比特数就会相应的低。这是一种贪婪的思想。

    然后我们来想,怎么构建这样的字母表呢?我们知道,由于我们最后写到文件上肯定不能直接写ASCII码,不然我们做这些就没意义了,我们最后是要写比特到上面去的,也就是一堆01010101,那么我们既然只有0,1两种状态,我们就可以想到我们可以用二叉树的形式去构建,我们把字母放在节点上,然后结合成一棵二叉树,我们可以这样规定,如果字母在节点的左边,那么这个字母的下一个二进位就是0,在右边就是1。

    那么我们最后就会得到一个二叉树,由于我们是要把出现概率较低的字母放在深度比较低的地方,我们可以先把概率较低的字母先结合起来,然后结合成一个新的节点,然后和其他节点继续结合,有点像修篱笆那题。大概就像下图那样

    然后我们就得到了一棵生成树,现在我们就可以给所有的字母重新编码了,那么怎么编码呢?刚才我们说了,出现在比较高的字母他的编码会比较长,在深度比较低的字母编码会比较短(节点往左走相应的二进位就代表0,往右走就代表1)我们很容易就可以得到下面的编码表

    a 001 10 30
    e 01 15 30
    i 10 12 24
    s 00000 3 15
    t 0001 4 16
    space 11 13 26
    newline 00001 1 5
    总和     146

    可以看到,最后编码占的总空间更小了,达到了我们压缩的目的。

    最后的问题就很简单了,怎么实现这个生成最优编码树呢?我们维护一个堆就可以了,建立完树以后就可以根据字母在树的位置给文件写编码拉!

    下面是代码,全实现,有点长

      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <string.h>
      4 #define MAX 255//可读字符类型最多为255(相当于散列了)
      5 #define UNSIGNED_LONG_32_MAX 4294967296ULL
      6 #define SUFFIX ".hfc"
      7 
      8 typedef int Position;
      9 typedef struct node
     10 {
     11     char symbol;
     12     int sum;
     13     struct node *left, *right;
     14 }NODE, *Heap;
     15 typedef struct node_list
     16 {
     17     int weight;
     18     int code_gragh[MAX];
     19 }LIST;
     20 typedef struct _tree
     21 {
     22     int sum;
     23     char symbol;
     24 }Hf_Store;
     25 
     26 //局部函数定义
     27 Heap *Read_TextFile(int *,FILE **,Hf_Store **,char []);
     28 Heap *Read_PackagedFile(int *, FILE **, Hf_Store **,int *,int *);
     29 void Inivilzie_store(int[]);
     30 void BulidHeap(Heap *, int);
     31 void Percolate_Up(Heap *, int, Position);
     32 NODE *DeleteMin(Heap *, int *);
     33 NODE *Bulid_Tree(Heap *,const int);
     34 void Push_in(NODE *, Heap *, int *);
     35 void Unpackged_File_to_File(NODE *, FILE *,const int,const int,char[]);
     36 void Write_In_Code_List(NODE *, int *, int[],const int,LIST[]);
     37 void Write_in_file(NODE *,FILE *,Hf_Store *,const int,char []);
     38 void *Allocate_In_Memory(const int, int *, int *, FILE *, LIST[]);
     39 void Destory_Node(NODE *);
     40 void Binary_to_ANSCII(NODE *,FILE *, FILE *,const int,const int);
     41 void Op_OverFlow(unsigned long[], const int);
     42 void Op_LackFlow(unsigned long[], const int);
     43 Heap *Put_Array_To_Heap(Hf_Store *, const int);
     44 inline void Put_size_to_array(const int, const int,const int, int[]);
     45 inline void Put_arrary_to_size(int[],int *,int *,int *,int *);
     46 inline void Destroy_Heap_node_and_HfTree(Heap **, Hf_Store **,NODE *);
     47 
     48 void Inivilzie_store(int store[])
     49 {
     50     for (int i = 0; i < MAX; i++) store[i] = 0;
     51 }
     52 
     53 Heap *Read_TextFile(int *length, FILE **fp, Hf_Store **Hf_Tree, char file_name[261])
     54 {
     55     int i, word_sum = 0, tmp, j = 1,_store[MAX];
     56     NODE *tmp_node = NULL;
     57 
     58     Inivilzie_store(_store);//初始化读取数组
     59     while (1)
     60     {
     61         fflush(stdin);
     62         printf("请输入文件名   ");
     63         scanf("%s", file_name);
     64         if ((*fp = fopen(file_name, "r")) == NULL)
     65             printf("a文件不存在,请重新输入
    
    ");
     66         else break;
     67     }
     68     for (;;)
     69     {
     70         tmp = fgetc(*fp);
     71         if (feof(*fp)) break;
     72         if (!_store[tmp]) word_sum++;
     73         _store[tmp]++;
     74     }
     75     *length = word_sum;
     76     Heap *word_arrary = (Heap *)malloc(sizeof(Heap)*(word_sum + 1));//堆从1位置开始
     77     *Hf_Tree = (Hf_Store *)malloc(sizeof(Hf_Store)*word_sum);
     78     for (i = 0; i < MAX; i++)
     79         if (_store[i]){ 
     80             tmp_node = (NODE *)malloc(sizeof(NODE));
     81             tmp_node->sum = _store[i];
     82             tmp_node->right = tmp_node->left = NULL;
     83             tmp_node->symbol = i;
     84             word_arrary[j] = tmp_node;
     85             j++; 
     86         }
     87     BulidHeap(word_arrary, *length);
     88     for (int i = 0; i < word_sum; i++)
     89     {
     90         (*Hf_Tree)[i].symbol = (word_arrary[i + 1])->symbol;
     91         (*Hf_Tree)[i].sum = (word_arrary[i + 1])->sum;
     92     }
     93     return word_arrary;
     94 }
     95 
     96 Heap *Read_PackagedFile(int *length, FILE **fp, Hf_Store **Hf_Tree,int *sum_byte,int *sum_bit_left,char source_file_name[])
     97 {
     98     char file_name[261], *suffix = SUFFIX;
     99     int inform[3];//文件头的三个信息
    100     int sum_bit, scr_size;
    101 
    102     while (1)
    103     {
    104         fflush(stdin);
    105         printf("请输入你要解压文件的文件名(自动添加后缀.hfc)   ");
    106         scanf("%s", file_name);
    107         strcat(file_name, suffix);
    108         if ((*fp = fopen(file_name, "rb")) == NULL)//直接用二进制模式读取
    109             printf("a文件不存在,请重新输入
    
    ");
    110         else break;
    111     }
    112 
    113     fread(&scr_size, sizeof(int), 1, *fp);
    114     fread(source_file_name, sizeof(char), scr_size, *fp);
    115     source_file_name[scr_size] = '';//补一个斜杠0
    116     printf("
    源文件名字为%s", source_file_name);
    117 
    118     fread(inform, sizeof(int), 3, *fp);
    119     Put_arrary_to_size(inform, &sum_bit, sum_byte, sum_bit_left, length);
    120     *Hf_Tree = (Hf_Store *)malloc(sizeof(Hf_Store) * (*length));
    121     fread(*Hf_Tree, sizeof(Hf_Store), (*length), *fp);
    122 
    123     Heap *word_arrary = Put_Array_To_Heap(*Hf_Tree, *length);
    124 
    125     return word_arrary;
    126 }
    127 
    128 void BulidHeap(Heap *word_arrary, int size)//线性建堆法,不多说
    129 {
    130     Position i;
    131     if (size % 2) for (i = size - 1; i > 1; i -= 2)  Percolate_Up(word_arrary, size, i / 2);//如果是奇数
    132     else for (i = size; i > 1; i -= 2) Percolate_Up(word_arrary, size, i / 2);
    133 }
    134 
    135 void Percolate_Up(Heap *heap, int size, Position i)
    136 {
    137     Position s1, s2;
    138     NODE *tmp = heap[i];
    139     for (; i <= size;)
    140     {
    141         s1 = 2 * i; s2 = s1 + 1;
    142         if (s2 <= size)
    143         {
    144             if ((*heap[s1]).sum <= (*heap[s2]).sum)
    145             {
    146                 if (tmp->sum > (heap[s1])->sum) { heap[i] = heap[s1]; i = s1; }
    147                 else break;
    148             }
    149             else
    150             {
    151                 if (tmp->sum > (heap[s2])->sum){ heap[i] = heap[s2]; i = s2; }
    152                 else break;
    153             }
    154         }
    155         else
    156         {
    157             if (s1 <= size)
    158             {
    159                 if (tmp->sum > (heap[s1])->sum) { heap[i] = heap[s1]; i = s1; break; }
    160                 else break;
    161             }
    162             else break;
    163         }
    164     }
    165     heap[i] = tmp;
    166 }
    167 
    168 NODE *DeleteMin(Heap *heap, int *size)//Floyd算法
    169 {
    170     Position i = 1, s1, s2, s;
    171     NODE *out = heap[1];
    172     NODE *tmp = heap[(*size)--];
    173     for (; i <= *size;)
    174     {
    175         s1 = 2 * i; s2 = s1 + 1;
    176         if (s2 <= *size)
    177         {
    178             if ((heap[s1])->sum <= (heap[s2])->sum) { heap[i] = heap[s1]; i = s1; }
    179             else { heap[i] = heap[s2]; i = s2; }
    180         }
    181         else
    182         {
    183             if (s1 <= *size) { heap[i] = heap[s1]; i = s1; break; }
    184             else break;
    185         }
    186     }
    187     for (; i > 1;)
    188     {
    189         if (i % 2 == 1)//注意是这里判断奇偶性
    190         {
    191             s = (i - 1) / 2;
    192             if ((heap[s])->sum > tmp->sum) { heap[i]= heap[s]; i = s; }
    193             else break;
    194         }
    195         else
    196         {
    197             s = i / 2;
    198             if ((heap[s])->sum > tmp->sum) { heap[i] = heap[s]; i = s; }
    199             else break;
    200         }
    201     }
    202     heap[i] = tmp; return out;
    203 }
    204 
    205 void Push_in(NODE *tmp_new, Heap *heap, int *size)
    206 {
    207     Position i, s;
    208     for (i = ++(*size); i > 1;)
    209     {
    210         if (i % 2 == 1)//注意是这里判断奇偶性
    211         {
    212             s = (i - 1) / 2;
    213             if ((heap[s])->sum > tmp_new->sum) { heap[i] = heap[s]; i = s; }
    214             else break;
    215         }
    216         else
    217         {
    218             s = i / 2;
    219             if ((heap[s])->sum > tmp_new->sum) { heap[i] = heap[s]; i = s; }
    220             else break;
    221         }
    222     }
    223     heap[i] = tmp_new;
    224 }
    225 
    226 inline void Put_size_to_array(const int sum_bit, const int sum_byte,const int length,int inform[])
    227 {
    228     inform[0] = sum_byte;//文件字节数
    229     inform[1] = sum_bit;//文件实际比特数
    230     inform[2] = length;//文件堆的大小
    231 }
    232 
    233 inline void Destroy_Heap_node_and_HfTree(Heap **Heap, Hf_Store **Hf_Tree,NODE *Thead)
    234 {
    235     free(*Heap); *Heap = NULL;
    236     free(*Hf_Tree); *Hf_Tree = NULL;
    237     Destory_Node(Thead);
    238 }
    239 
    240 inline void Put_arrary_to_size(int inform[], int *sum_bit, int *sum_byte, int *sum_bit_left, int *length)
    241 {
    242     *sum_byte = inform[0];//文件字节数
    243     *sum_bit = inform[1];//文件实际比特数
    244     *length = inform[2];//文件堆的大小
    245     *sum_bit_left = (*sum_byte * 32) - (*sum_bit);
    246 }
    247 
    248 void Destory_Node(NODE *T)
    249 {
    250     if (T == NULL) return;
    251 
    252     Destory_Node(T->left);
    253     Destory_Node(T->right);
    254     free(T);
    255 }
    256 
    257 void Op_OverFlow(unsigned long M[],const int length)
    258 {
    259     int overflow = 0;
    260     unsigned long long out_flow;
    261 
    262     for (int i = 0; i < length; i++)
    263     {
    264         out_flow = (unsigned long long)M[i] << 1;
    265 
    266         if (overflow) {
    267             out_flow += 1UL; overflow = 0;//一定要记得归零
    268         }
    269         if (out_flow >= UNSIGNED_LONG_32_MAX){
    270             out_flow -= UNSIGNED_LONG_32_MAX;
    271             M[i] = (unsigned long)out_flow;
    272             overflow = 1;
    273         }
    274         else M[i] = (unsigned long)out_flow;
    275     }
    276 }
    277 
    278 void Op_LackFlow(unsigned long M[], const int length)//TODO:完成这个函数
    279 {
    280     unsigned long long lack_flow;
    281 
    282     for (int i = length - 1; i >= 0; i--)
    283     {
    284         lack_flow = (unsigned long long)M[i] << 1;
    285 
    286         if (lack_flow >= UNSIGNED_LONG_32_MAX)
    287         {
    288             lack_flow -= UNSIGNED_LONG_32_MAX;
    289             M[i] = (unsigned long)lack_flow;
    290             if (i != length - 1)
    291                 M[i + 1] += 1UL;
    292         }
    293         else M[i] = (unsigned long)lack_flow;
    294     }
    295 }
    296 
    297 Heap *Put_Array_To_Heap(Hf_Store *Hf_Tree, const int length)
    298 {
    299     Heap *word_arrary = (Heap *)malloc(sizeof(Heap)*(length + 1));//堆从1位置开始
    300     NODE *tmp = NULL;;
    301 
    302     for (int i = 0; i < length; i++)
    303     {
    304         tmp = (NODE *)malloc(sizeof(NODE));
    305         tmp->left = tmp->right = NULL;
    306         tmp->symbol = Hf_Tree[i].symbol;
    307         tmp->sum = Hf_Tree[i].sum;
    308         word_arrary[i + 1] = tmp;
    309     }
    310     return word_arrary;
    311 }
      1 #include "plug.h"
      2 
      3 int main()//Huffman压缩程序
      4 {
      5     Heap *heap = NULL; NODE *Tree_Heap = NULL; FILE *fp = NULL; Hf_Store *Hf_Tree = NULL;
      6     int length; char choice;
      7     char source_file_name[261];//文件名长度最多为260
      8 
      9     while (1)
     10     {
     11         printf("Huffman无损压缩程序-----By Philip 2015.7.20----Version 1.0
    ");
     12         printf("====================================================
    ");
     13         printf("请输入选项
    Y(压缩某文件)	J(解压某文件)	Q(退出程序)   ");
     14         while (1)
     15         {
     16             fflush(stdin);
     17             scanf("%c", &choice);
     18             if (choice == 'Y' || choice == 'J' || choice == 'Q') break;
     19             printf("
    a错误的输入,请重新输入   ");
     20         }
     21         if (choice == 'Y')
     22         {
     23             heap = Read_TextFile(&length, &fp, &Hf_Tree, source_file_name);
     24             Tree_Heap = Bulid_Tree(heap, length);
     25             Write_in_file(Tree_Heap,fp,Hf_Tree,length,source_file_name);
     26             Destroy_Heap_node_and_HfTree(&heap, &Hf_Tree, Tree_Heap);
     27             system("pause");
     28         }
     29         else if (choice == 'J')
     30         {
     31             int sum_bit_left, sum_byte;
     32 
     33             heap = Read_PackagedFile(&length, &fp, &Hf_Tree, &sum_byte, &sum_bit_left,source_file_name);
     34             Tree_Heap = Bulid_Tree(heap, length);
     35             Unpackged_File_to_File(Tree_Heap, fp, sum_byte, sum_bit_left,source_file_name);
     36             Destroy_Heap_node_and_HfTree(&heap, &Hf_Tree, Tree_Heap);
     37             system("pause");
     38         }
     39         else break;
     40         printf("
    
    
    "); system("cls");
     41     }
     42     printf("
    ");system("pause");return 0;
     43 }
     44 
     45 NODE *Bulid_Tree(Heap *heap,const int size)
     46 {
     47     int size_tmp = size, i = 0;
     48     NODE *tmp1 = NULL, *tmp2 = NULL, *tmp_new = NULL;
     49 
     50     for (; size_tmp > 1;)//不断deleteMin
     51     {
     52         tmp1 = DeleteMin(heap, &size_tmp); 
     53         tmp2 = DeleteMin(heap, &size_tmp); 
     54 
     55         tmp_new = (NODE *)malloc(sizeof(NODE));
     56         tmp_new->left = tmp1; tmp_new->right = tmp2; tmp_new->symbol = '';
     57         tmp_new->sum = tmp1->sum + tmp2->sum;
     58 
     59         Push_in(tmp_new, heap, &size_tmp);
     60     }
     61     return heap[1];
     62 }
     63 
     64 void Write_in_file(NODE *Thead, FILE *fp, Hf_Store *Hf_Tree, const int length,char source_file_name[])
     65 {
     66     int sum_bit = 0, Depth = 0, sum_byte, sum_left, inform[3], code_List[MAX], scr_size = strlen(source_file_name);
     67     char *suffix = SUFFIX, out_name[MAX + 1], choice = 'N';
     68     FILE *out_fp = NULL;
     69     LIST code_Hash[MAX];
     70 
     71     Write_In_Code_List(Thead, &sum_bit, code_List, Depth, code_Hash);
     72 
     73     void *Memory_Pool = Allocate_In_Memory(sum_bit, &sum_byte, &sum_left, fp, code_Hash);
     74     Put_size_to_array(sum_bit, sum_byte, length, inform);
     75 
     76     fclose(fp); fp = NULL;//这个时候可以关闭文件流了
     77 
     78     printf("请输入你要输出的压缩文件的文件名(自动添加后缀.hfc)   ");
     79     while (choice == 'N')
     80     {
     81         fflush(stdin);
     82         scanf("%s", out_name);
     83         strcat(out_name, suffix);
     84 
     85         if ((out_fp = fopen(out_name, "r")) != NULL)
     86         {
     87             printf("文件已存在,是否覆盖?(Y or N)   ");
     88             while (1)
     89             {
     90                 fflush(stdin);
     91                 scanf("%c", &choice);
     92                 if (choice == 'Y') break;
     93                 else if (choice == 'N') { printf("请重新指定文件名   "); break; }
     94                 else printf("你的输入有误,请重新输入  ");
     95                 fclose(out_fp);//先关掉out_fp
     96             }
     97         }
     98         else break;
     99     }
    100     printf("%s文件即将被写入
    ", out_name);
    101 
    102     if ((out_fp = fopen(out_name, "wb+")) == NULL){
    103         printf("文件写入失败
    "); 
    104         system("pause"); return;
    105     }
    106 
    107     fwrite(&scr_size, sizeof(int), 1, out_fp);
    108     fwrite(source_file_name, sizeof(char), scr_size, out_fp);
    109     fwrite(inform, sizeof(int), 3, out_fp);
    110     fwrite(Hf_Tree, sizeof(Hf_Store), length, out_fp);
    111     fwrite(Memory_Pool,sizeof(unsigned long), sum_byte, out_fp);
    112 
    113     printf("对%s写入成功!
    ", out_name);
    114 
    115     fclose(out_fp); out_fp = NULL;//记得关文件
    116     free(Memory_Pool);//记得释放这个
    117 }
    118 
    119 void Write_In_Code_List(NODE *T, int *sum_bit, int code_List[],const int Depth,LIST code_Hash[])
    120 {
    121     if (T->symbol != '')
    122     {
    123         *sum_bit += Depth*T->sum;
    124         code_Hash[T->symbol].weight = Depth;
    125         for (int i = 0; i < Depth; i++) (code_Hash[T->symbol]).code_gragh[i] = code_List[i];
    126     }
    127     else//这里如果不是那么一定存在左右节点
    128     {
    129         code_List[Depth] = 0;
    130         Write_In_Code_List(T->left, sum_bit, code_List, Depth + 1,code_Hash);
    131         code_List[Depth] = 1;
    132         Write_In_Code_List(T->right, sum_bit, code_List, Depth + 1,code_Hash);
    133     }
    134 }
    135 
    136 void *Allocate_In_Memory(const int sum_bit, int *sum_byte, int *sum_bit_left, FILE *fp, LIST code_Hash[])
    137 {
    138     int tmp, i;
    139 
    140     if (!(sum_bit % 32)) *sum_byte = sum_bit / 32;
    141     else *sum_byte = sum_bit / 32 + 1;//一个字节等于八位(unsigned long是32个字节-1)
    142     *sum_bit_left = (*sum_byte) * 32 - sum_bit;
    143 
    144     unsigned long *Memory_Pool = (unsigned long *)malloc(*sum_byte*sizeof(unsigned long));
    145     memset(Memory_Pool, 0, *sum_byte*sizeof(unsigned long));
    146     Memory_Pool[0] = 1;///记住要把第一个弄成1,不然0放不进去
    147 
    148     fseek(fp, 0L, SEEK_SET);//将指针定位到开头
    149     for (; ;)
    150     {
    151         tmp = fgetc(fp);
    152         if (feof(fp)) break;
    153 
    154         for (i = 0; i < code_Hash[tmp].weight; i++)
    155         {
    156             Op_OverFlow(Memory_Pool,*sum_byte);
    157             if ((code_Hash[tmp]).code_gragh[i] == 0) Memory_Pool[0]= Memory_Pool[0] | 0X00;//0的时候就按0
    158             else Memory_Pool[0] = Memory_Pool[0] | 0X01;                                   //1的时候按1
    159         }
    160     }
    161     return (void *)Memory_Pool;
    162 }
    163 
    164 void Binary_to_ANSCII(NODE *T_head, FILE *fp_source, FILE *fp_out, const int sum_byte, const int sum_bit_left)
    165 {
    166     int i;
    167     NODE *tmp;
    168     unsigned long *M = (unsigned long *)malloc(sizeof(unsigned long)*sum_byte);//拿一块大的区域
    169     fread(M, sizeof(unsigned long), sum_byte, fp_source);//把数据录入这个区域
    170 
    171     for (i = 0; i < sum_bit_left; i++)//首先去掉最后一个区域的空位数字
    172         Op_LackFlow(M, sum_byte);
    173     for (i = 0; i < T_head->sum; i++)
    174     {
    175         for (tmp = T_head; tmp->symbol == '';)
    176         {
    177             if ((M[sum_byte - 1] & 2147483648UL) == 2147483648UL) tmp = tmp->right;//如果是1那么往左走
    178             else tmp = tmp->left;                                                   //如果是0往右走
    179             Op_LackFlow(M, sum_byte);
    180         }
    181         fputc(tmp->symbol, fp_out);
    182     }
    183     free(M);
    184 }
    185 
    186 void Unpackged_File_to_File(NODE *T_head, FILE *fp, const int sum_byte, int sum_bit_left,char source_file_name[])
    187 {
    188     FILE *out_fp = NULL;
    189     char choice = 'N', position[268] = "hfc.";
    190 
    191     printf("输出文件的位置将在本程序所在目录的创建,名称为%s%s
    ", position, source_file_name);
    192     while (choice == 'N')
    193     {
    194         strcat(position, source_file_name);
    195         if ((out_fp = fopen(position, "r")) != NULL)
    196         {
    197             printf("文件已存在,是否覆盖?(Y or N)   ");
    198             while (1)
    199             {
    200                 fflush(stdin);
    201                 scanf("%c", &choice);
    202                 if (choice == 'Y') break;
    203                 else if (choice == 'N') { printf("请重新指定文件名   "); break; }
    204                 else printf("你的输入有误,请重新输入  ");
    205                 fclose(out_fp);//先关掉out_fp
    206             }
    207             if (choice == 'N')
    208             {
    209                 scanf("%s", source_file_name);
    210                 strcat(position, source_file_name);
    211             }
    212         }
    213         else break;
    214     }
    215     printf("%s文件即将被写入
    ", position);
    216 
    217     if ((out_fp = fopen(position, "w")) == NULL){
    218         printf("文件写入失败
    ");
    219         system("pause"); return;
    220     }
    221     Binary_to_ANSCII(T_head, fp, out_fp,sum_byte,sum_bit_left);
    222 
    223     printf("
    成功写入%s文件!
    
    ", position);
    224 
    225     fclose(out_fp); out_fp = NULL;
    226     fclose(fp); fp = NULL;//记得关源文件
    227 }
  • 相关阅读:
    第四节:前端自动化准备和详细配置(NVM、NPM/CNPM、NodeJs、NRM、WebPack、Gulp/Grunt、Git/SVN)
    第二十三节: EF性能篇(三)之基于开源组件 Z.EntityFrameWork.Plus.EF6解决EF性能问题
    第三节:一些指令总结(Nuget、)
    第十七节:易混淆的概念(静态和非静态、拆箱和装箱)
    Java使用Log4记录日志
    Java读取xml
    C# int.ToString() 常用参数说明
    WebAPI获取客户端请求数据
    Zend Studio获取永久使用权
    template.js 模版内调用外部JS方法
  • 原文地址:https://www.cnblogs.com/Philip-Tell-Truth/p/4787186.html
Copyright © 2011-2022 走看看