当前位置:   article > 正文

【数据结构】实验十:哈夫曼编码_哈夫曼编码实验

哈夫曼编码实验

实验十 哈夫曼编码

一、实验目的与要求

1)掌握树、森林与二叉树的转换;

2)掌握哈夫曼树和哈夫曼编码算法的实现;

二、 实验内容

1. 请编程实现如图所示的树转化为二叉树。

2. 编程实现一个哈夫曼编码系统,系统功能包括:

(1) 字符信息统计:读取待编码的源文件SourceFile.txt,统计出现的字符及其频率。

  附:SourceFile.txt文件内容为

 

(2) 建立哈夫曼树:根据统计结果建立哈夫曼树。

(3) 建立哈夫曼码表:利用得到的哈夫曼树,将各字符对应的编码表保存在文件Code.txt中。

(4) 对源文件进行编码:根据哈夫曼码表,将SourceFile.txt中的字符转换成相应的编码文件ResultFile.txt。

实现提示:

(1) 字符信息统计:假设源文件SourceFile.txt中的字符只有大小写英文字母(同一个字母的大小写看作一个字符),则字符统计算法的实现过程可以归纳为:先定义一个含有26个元素的整形数组,用来存储各个字母出现的次数,最后还要排除其中出现次数为0的数组元素。

(2) 建立哈夫曼树:可参考教材算法。

(3) 建立哈夫曼码表:可参考教材算法。

(4) 对源文件进行编码:依次读入文件SourceFile.txt中的字符 c,在编码表 HC 中找到此字符,将字符c转换为编码表中存放的编码串,写入编码文件ResultFile.txt中,直到所有的字符处理完毕为止。

三、实验结果

1)请将调试通过的运行结果截图粘贴在下面,并说明测试用例和运行过程。

2)请将源代码cpp文件压缩上传。


题目1:

测试用例及运行结果:

测试用例输入的树为:

树通过孩子兄弟表示法转化的二叉树为:

测试用例实验结果为:

根据最后三行输出(即二叉树的先序遍历和中序遍历,以及树的层序遍历)可知,输入的树可以转化为二叉树,且存储效果均良好。

运行过程:

首先通过主函数调用的函数顺序可知,运行过程为初始化树->通过输入创建树->preorder输出树->midorder输出树->floororder输出树->销毁树。

初始化树时,不需要做额外操作。

通过输入创建树时,主要使用队列实现。首先初始化每个结点的左孩子和右兄弟均为空,然后把当前结点加入队列。如果当前结点为根结点,则树从当前结点开始。否则,获取队列的队首结点,依次存储其左孩子和右兄弟。

 

preorder输出树时,通过if条件判断当前结点是否为空,然后采用根结点——左孩子——右兄弟的方法递归输出。

midorder输出树时,通过if条件判断当前结点是否为空,然后采用左孩子——根结点——右兄弟的方法递归输出。

floororder输出树时,主要通过队列输出。通过if条件判断当前结点是否为空,输出当前根结点的值,然后进行根结点排队。当队列非空时,先输出根结点e的左孩子p,再输出p的右兄弟,此时容易知道p和p的右兄弟在同一层。

销毁树时,通过if条件判断当前结点是否为空,然后采用左孩子——右兄弟——根结点的方法递归销毁,并依次将结点置为空。

实验代码:

  1. //孩子兄弟表示法存储
  2. #include <iostream>
  3. #include <cstdio>
  4. #include <malloc.h>
  5. using namespace std;
  6. typedef int ElemType;
  7. typedef struct CSNode{
  8. ElemType data;
  9. struct CSNode *firstchild,*rightsib;
  10. }CSNode,*CSTree;
  11. #define OK 1
  12. #define ERROR 0
  13. #define TRUE 1
  14. #define FALSE 0
  15. typedef struct QNode{
  16. CSTree data;
  17. struct QNode *next;
  18. }QNode;
  19. typedef struct LinkQueue{
  20. QNode *front,*rear;
  21. }LinkQueue;
  22. //构造空队列
  23. void InitQueue_Sq(LinkQueue &Q){
  24. Q.front = Q.rear = NULL;
  25. }
  26. //判断是否为空
  27. int QueueEmpty(const LinkQueue &Q){
  28. return (Q.rear == NULL && Q.front == NULL);
  29. }
  30. //插入元素进队尾
  31. void EnQueue_Sq(LinkQueue &Q,CSTree &e){
  32. QNode *p=(QNode*)malloc(sizeof(QNode));
  33. if(!p){
  34. exit(0);
  35. }
  36. p->data =e;
  37. p->next =NULL;
  38. if (QueueEmpty(Q)){
  39. Q.front =Q.rear =p;
  40. }
  41. else{
  42. Q.rear->next =p;
  43. Q.rear=p;
  44. }
  45. }
  46. //删除元素从队头
  47. CSTree DeQueue_Sq(LinkQueue &Q,CSTree &s){
  48. if(QueueEmpty(Q)){
  49. return ERROR;
  50. }
  51. QNode *p=Q.front ;
  52. s=p->data;//队头存的数据
  53. if(Q.front==Q.rear){
  54. Q.front=Q.rear=NULL;
  55. }
  56. else{
  57. Q.front =p->next;
  58. }
  59. free(p);
  60. return s;
  61. }
  62. //取队头元素
  63. void GetHead_Sq(LinkQueue Q,CSTree &p){
  64. if(QueueEmpty(Q)){
  65. exit(0);
  66. }
  67. p=Q.front->data ;
  68. }
  69. //初始化树
  70. void InitTree_CST(CSTree &T){
  71. }
  72. //构造树
  73. void CreateTree_CST(CSTree &T){
  74. T=NULL;
  75. LinkQueue Q;
  76. InitQueue_Sq(Q);
  77. ElemType parent,child;
  78. CSTree p,q,r=new CSNode;
  79. for(cin>>parent>>child;child!=0;cin>>parent>>child){
  80. p=(CSTree)malloc(sizeof(CSNode));
  81. p->data=child;
  82. p->firstchild =p->rightsib =NULL;
  83. EnQueue_Sq(Q,p);//append p to Q
  84. if(parent==-1){
  85. T=p;//root node
  86. }
  87. else{
  88. GetHead_Sq(Q,q);
  89. while(q->data != parent){
  90. DeQueue_Sq(Q,q);
  91. GetHead_Sq(Q,q);
  92. }
  93. if(!(q->firstchild )){
  94. q->firstchild =p;
  95. r=p;
  96. }
  97. else{
  98. r->rightsib =p;
  99. r=p;
  100. }
  101. }
  102. }
  103. }
  104. //pre-order output
  105. void PreOrderTraverse_CST(CSTree &T){
  106. if(T){
  107. cout<<T->data<<" ";
  108. PreOrderTraverse_CST(T->firstchild );
  109. PreOrderTraverse_CST(T->rightsib );
  110. }
  111. }
  112. //mid-order output
  113. void MidOrderTraverse_CST(CSTree &T){
  114. if(T){
  115. MidOrderTraverse_CST(T->firstchild );
  116. cout<<T->data<<" ";
  117. MidOrderTraverse_CST(T->rightsib );
  118. }
  119. }
  120. //layer-order output
  121. void FloorTraverse_CST(CSTree &T){
  122. LinkQueue Q;
  123. InitQueue_Sq(Q);
  124. if(T){
  125. cout<<T->data <<" ";
  126. EnQueue_Sq(Q,T);//根结点排队
  127. while(!QueueEmpty(Q)){
  128. CSTree e,p;
  129. e=(CSTree)malloc(sizeof(CSNode));
  130. p=(CSTree)malloc(sizeof(CSNode));
  131. DeQueue_Sq(Q,e);
  132. p=e->firstchild ;
  133. while(p){
  134. cout<<p->data<<" ";
  135. EnQueue_Sq(Q,p);
  136. p=p->rightsib ;
  137. }
  138. }
  139. }
  140. }
  141. //销毁CST
  142. void DestroyTree_CST(CSTree &T){
  143. if(T){
  144. DestroyTree_CST(T->firstchild );
  145. DestroyTree_CST(T->rightsib );
  146. free(T);
  147. T=NULL;
  148. }
  149. }
  150. //主函数
  151. int main(){
  152. CSTree T;
  153. InitTree_CST(T);
  154. cout<<"Input tree:"<<endl;
  155. CreateTree_CST(T);
  156. cout<<endl<<"Preordered sequence: ";
  157. PreOrderTraverse_CST(T);
  158. cout<<endl<<"Midordered sequence: ";
  159. MidOrderTraverse_CST(T);
  160. cout<<"Floorordered sequence: ";
  161. FloorTraverse_CST(T);
  162. cout<<endl;
  163. DestroyTree_CST(T);
  164. return 0;
  165. }

题目2

测试用例及运行结果:

测试用例1:AAABBC

运行结果截图:

 

 

 

 SourceFile.txt内容:

 Code.txt内容:

ResultFile.txt内容:

 

测试用例2:U ARE THE BEST IN MY HEART

运行结果截图:

 

 

 

 

 

 

 

 

SourceFile.txt内容:

Code.txt内容:

 

 ResultFile.txt内容:

 

运行过程:

读取SourceFile.txt文件->统计各个字符出现的频数->基于频数构建Huffman树->基于Huffman树建立Huffman表,即Code.txt文件->基于Huffman表对SourceFile.txt文件进行编码,结果为ResultFile.txt文件。

主要通过终端提示的字母信息进行相应操作。

实验代码:

  1. #include<stdio.h>
  2. #include <malloc.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #define TRUE 1
  6. #define FALSE 0
  7. #define OK 1
  8. #define ERROR 0
  9. #define INFEASIBLE -1
  10. #define OVERFLOW -2
  11. typedef int Status;
  12. typedef struct HTNode
  13. {
  14. char leaf;
  15. unsigned int weight;
  16. unsigned int parent, lchild, rchild;
  17. }HTNode, *HuffmanTree;
  18. typedef char **HuffmanCode; //动态分配数组存储哈夫曼编码表
  19. typedef struct Node
  20. {
  21. char leaf;
  22. unsigned int weight;
  23. struct Node * next;
  24. }LeafNode, *LeafLink;
  25. typedef struct
  26. {
  27. LeafLink head;
  28. unsigned len;
  29. }LeafLinkList;
  30. int min1(HuffmanTree t, int i)
  31. { /* 函数void select()调用 */
  32. int j, flag;
  33. unsigned int k = UINT_MAX; /* 取k为不小于可能的值 */
  34. for (j = 1; j <= i; j++)
  35. if (t[j].weight<k&&t[j].parent == 0)
  36. k = t[j].weight, flag = j;
  37. t[flag].parent = 1;
  38. return flag;
  39. }
  40. void select(HuffmanTree t, int i, int *s1, int *s2)
  41. { /* s1为最小的两个值中序号小的那个 */
  42. int j;
  43. *s1 = min1(t, i);
  44. *s2 = min1(t, i);
  45. if (*s1>*s2)
  46. {
  47. j = *s1;
  48. *s1 = *s2;
  49. *s2 = j;
  50. }
  51. }
  52. void HuffmanCoding(HuffmanTree &HT, HuffmanCode &HC, LeafLinkList L)
  53. { /* w存放n个字符的权值(权值均需大于0),构造哈夫曼树HT,并求出n个字符的哈夫曼编码HC*/
  54. int m, i, s1, s2, start;
  55. int n = L.len;
  56. unsigned c, f;
  57. LeafLink ptr;
  58. HuffmanTree p;
  59. char *cd;
  60. if (n <= 1)
  61. return;
  62. m = 2 * n - 1;
  63. printf("表长为%d\t哈夫曼树含节点数为%d\n", n, m);
  64. HT = (HuffmanTree)malloc((m + 1)*sizeof(HTNode)); /* 0号单元未用 */
  65. ptr = L.head->next;
  66. for (p = HT + 1, i = 1; i <= n; ++i, ++p, ptr = ptr->next)
  67. {
  68. (*p).leaf = ptr->leaf;
  69. printf("%d\t", (*p).leaf);
  70. (*p).weight = ptr->weight;
  71. printf("%d\n", (*p).weight);
  72. (*p).parent = 0;
  73. (*p).lchild = 0;
  74. (*p).rchild = 0;
  75. }
  76. for (; i <= m; ++i, ++p)
  77. {
  78. (*p).parent = 0;
  79. (*p).leaf = 0;
  80. }
  81. for (i = n + 1; i <= m; ++i) /* 建哈夫曼树 */
  82. { /* 在HT[1~i-1]中选择parent为0且weight最小的两个结点,其序号分别为s1和s2 */
  83. select(HT, i - 1, &s1, &s2);
  84. HT[s1].parent = HT[s2].parent = i;
  85. HT[i].lchild = s1;
  86. HT[i].rchild = s2;
  87. HT[i].weight = HT[s1].weight + HT[s2].weight;
  88. }
  89. /* 从叶子到根逆向求每个字符的哈夫曼编码 */
  90. HC = (HuffmanCode)malloc((n + 1)*sizeof(char*));
  91. /* 分配n个字符编码的头指针向量([0]不用) */
  92. cd = (char*)malloc(n*sizeof(char)); /* 分配求编码的工作空间 */
  93. cd[n - 1] = '\0'; /* 编码结束符 */
  94. for (i = 1; i <= n; i++)
  95. { /* 逐个字符求哈夫曼编码 */
  96. start = n - 1; /* 编码结束符位置 */
  97. for (c = i, f = HT[i].parent; f != 0; c = f, f = HT[f].parent)
  98. /* 从叶子到根逆向求编码 */
  99. if (HT[f].lchild == c)
  100. cd[--start] = '0';
  101. else
  102. cd[--start] = '1';
  103. HC[i] = (char*)malloc((n - start)*sizeof(char));
  104. /* 为第i个字符编码分配空间 */
  105. strcpy(HC[i], &cd[start]); /* 从cd复制编码(串)到HC */
  106. }
  107. free(cd); /* 释放工作空间 */
  108. for (i = 1; i <= n; i++)
  109. {
  110. printf("%c编码为%s:\n", HT[i].leaf, HC[i]);
  111. }
  112. }
  113. void InitLeafList(LeafLinkList &L)
  114. {
  115. L.head = (LeafLink)malloc(sizeof(LeafLink));
  116. L.head->next = NULL;
  117. L.len = 0;
  118. }
  119. void PrintList(LeafLinkList L)
  120. {
  121. LeafLink p;
  122. p = L.head->next;
  123. printf("打印链表\n");
  124. printf("表长为%d\n", L.len);
  125. while (p != NULL)
  126. {
  127. printf("%c or %d,%u\t", p->leaf, p->leaf, p->weight);
  128. printf("打印一个节点\n");
  129. p = p->next;
  130. }
  131. printf("打印结束\n");
  132. printf("\n");
  133. }
  134. void EnLeafList(LeafLinkList &L, char ch)
  135. {
  136. LeafLink p, pre, temp;
  137. int flag = 0;
  138. pre = p = L.head;
  139. printf("%d即为%c******\n\n", ch, ch);
  140. if (p->next == NULL) //p->next=NULL则为第一次插入操作
  141. {
  142. printf("第一次插入\n");
  143. temp = (LeafLink)malloc(sizeof(LeafNode));
  144. temp->leaf = ch;
  145. temp->weight = 1;
  146. temp->next = NULL;
  147. p->next = temp;
  148. L.len++;
  149. }
  150. else
  151. {
  152. p = p->next;
  153. while (p != NULL)
  154. {
  155. if (ch == p->leaf)
  156. {
  157. p->weight++;
  158. printf("加权\n");
  159. p = NULL;
  160. flag = 1;
  161. } //权重加一
  162. else if (ch<p->leaf) //插入
  163. {
  164. printf("插入A\n");
  165. temp = (LeafLink)malloc(sizeof(LeafNode));
  166. temp->leaf = ch;
  167. temp->weight = 1;
  168. temp->next = p;
  169. pre->next = temp;
  170. L.len++;
  171. flag = 1;
  172. p = NULL;
  173. }
  174. else //继续寻找插入点
  175. {
  176. pre = p;
  177. p = p->next;
  178. }
  179. }
  180. if (p == NULL&&flag != 1) //若p=NULL则插到链尾
  181. {
  182. printf("插入B\n");
  183. temp = (LeafLink)malloc(sizeof(LeafNode));
  184. temp->leaf = ch;
  185. temp->weight = 1;
  186. temp->next = NULL;
  187. pre->next = temp;
  188. L.len++;
  189. }
  190. }
  191. }
  192. void EnCoding()
  193. {
  194. FILE *fp, *fr, *fc;
  195. HuffmanTree HT;
  196. HuffmanCode HC;
  197. int i, n;
  198. LeafLinkList L;
  199. InitLeafList(L);
  200. char filename[15];
  201. char ch;
  202. printf("请输入文件名:\n ");
  203. scanf("%s", filename);
  204. if (!(fp = fopen(filename, "r")))
  205. {
  206. printf("打开文件失败,请输入正确的文件名!! ");
  207. exit(0);
  208. }
  209. ch = getchar(); //接收执行scanf语句时最后输入的回车符
  210. printf("文件已经打开\n");
  211. while (!feof(fp))
  212. {
  213. ch = fgetc(fp);
  214. if (ch == -1)
  215. {
  216. printf("结束统计\n");
  217. }
  218. else
  219. {
  220. EnLeafList(L, ch);
  221. }
  222. }
  223. PrintList(L);
  224. HuffmanCoding(HT, HC, L);
  225. n = L.len;
  226. for (i = 1; i <= n; i++)
  227. {
  228. puts(HC[i]);
  229. }
  230. char TreeName[15];
  231. printf("把哈夫曼树存入文件,请输入文件名:\n ");
  232. scanf("%s", TreeName);
  233. if (!(fr = fopen(TreeName, "wb")))
  234. {
  235. printf("打开文件失败,请输入正确的文件名!! ");
  236. exit(0);
  237. }
  238. ch = getchar(); //接收执行scanf语句时最后输入的回车符
  239. printf("文件已经打开\n");
  240. //把哈夫曼树存入文件
  241. printf("%d\n", n);
  242. printf("把树的长度先存入\n");
  243. _putw(n, fr); //把树的长度先存入
  244. for (i = 1; i <= 2 * n - 1; i++)
  245. if (fwrite(&HT[i], sizeof(struct HTNode), 1, fr) != 1)
  246. printf("文件写入出错\n");
  247. fclose(fr);
  248. printf("打印原来的树\n");
  249. for (i = 1; i <= 2 * n - 1; i++)
  250. printf("%c %u %u %u %u\n", HT[i].leaf, HT[i].weight, HT[i].parent, HT[i].lchild, HT[i].rchild);
  251. fclose(fr);
  252. printf("把编码结果存入文件,请输入文件名:\n ");
  253. char CodeFileName[15];
  254. scanf("%s", CodeFileName);
  255. if (!(fc = fopen(CodeFileName, "wb")))
  256. {
  257. printf("打开文件失败,请输入正确的文件名!! ");
  258. exit(0);
  259. }
  260. ch = getchar(); //接收执行scanf语句时最后输入的回车符
  261. printf("待编码的文件位置指针重新指向开始位置\n");
  262. printf("对待编码文件进行编码,编码同步显示,并将结果存入指定的文件\n");
  263. rewind(fp);
  264. while (!feof(fp))
  265. {
  266. ch = fgetc(fp);
  267. printf("%c\n", ch);
  268. if (ch == -1)
  269. {
  270. printf("结束编码\n");
  271. }
  272. else
  273. {
  274. for (int tap = 0, i = 1; tap == 0 && i <= n;) //查找,该叶子对应的编码串
  275. {
  276. if (ch == HT[i].leaf) //找到,打印出对应的编码,并存入文件
  277. {
  278. printf("%s\n", HC[i]);
  279. fputs(HC[i], fc); //将编码字符串存入文件
  280. tap = 1;
  281. }
  282. else
  283. {
  284. i++;
  285. }
  286. }
  287. }
  288. }
  289. fclose(fp); //关闭文件
  290. fclose(fc); //关闭文件
  291. }
  292. int decode(FILE *fc, HuffmanTree HT, int n)
  293. {
  294. while (!feof(fc))
  295. {
  296. char ch = fgetc(fc);
  297. if (ch == '0')
  298. {
  299. n = HT[n].lchild;
  300. if (HT[n].leaf != 0)
  301. {
  302. printf("%c", HT[n].leaf);
  303. return OK;
  304. }
  305. else
  306. {
  307. decode(fc, HT, n);
  308. return OK;
  309. }
  310. }
  311. else if (ch == '1')
  312. {
  313. n = HT[n].rchild;
  314. if (HT[n].leaf != 0)
  315. {
  316. printf("%c", HT[n].leaf);
  317. return OK;
  318. }
  319. else
  320. {
  321. decode(fc, HT, n);
  322. return OK;
  323. }
  324. }
  325. else return OK;
  326. }
  327. return ERROR;
  328. }
  329. //解码文件
  330. void Decoding()
  331. {
  332. FILE *fc, *fr;
  333. char CodeFileName[15], ch, TreeName[15];
  334. int i;
  335. printf("解码文件,请输入文件名(如*.dat):\n ");
  336. scanf("%s", CodeFileName);
  337. if (!(fc = fopen(CodeFileName, "r")))
  338. {
  339. printf("打开文件失败,请输入正确的文件名!! ");
  340. exit(0);
  341. }
  342. ch = getchar(); //接收执行scanf语句时最后输入的回车符
  343. printf("存放编码结果文件已经打开\n");
  344. //读入哈夫曼树
  345. HuffmanTree HT;
  346. printf("取出对应的哈夫曼树文件,请输入文件名,\n");
  347. scanf("%s", TreeName);
  348. if (!(fr = fopen(TreeName, "rb"))) //打开存放哈夫曼树的文件
  349. {
  350. printf("打开文件失败,请输入正确的文件名!! ");
  351. exit(0);
  352. }
  353. int n = _getw(fr); //将叶子数目取出
  354. printf("叶子数目%d\n", n);
  355. HT = (HuffmanTree)malloc((2 * n)*sizeof(HTNode)); /* 然后分配空间,0号单元未用 */
  356. for (i = 1; i <= 2 * n - 1; i++)
  357. if (fread(&HT[i], sizeof(struct HTNode), 1, fr) != 1)
  358. printf("文件读出出错\n");
  359. int length = 2 * n - 1; //总长度
  360. printf("总结点数目为:%d\n", n);
  361. printf("该文件译码后得到的源文件为:\n");
  362. printf("**************************************\n");
  363. while (!feof(fc))
  364. {
  365. decode(fc, HT, length);
  366. }
  367. printf("**************************************\n");
  368. printf("\n\n");
  369. }
  370. int PreOrderPrint(HuffmanTree HT, int n, int count)
  371. {
  372. if (HT[n].lchild)
  373. {
  374. for (int i = 0; i<count; i++)
  375. printf(" ");
  376. printf("%u\n", HT[n].weight);
  377. if (PreOrderPrint(HT, HT[n].lchild, ++count))
  378. if (PreOrderPrint(HT, HT[n].rchild, ++count))
  379. return OK;
  380. return ERROR;
  381. }
  382. else return OK;
  383. }
  384. void PrintTree()
  385. {
  386. //读入哈夫曼树
  387. FILE *fr;
  388. char TreeName[15];
  389. HuffmanTree HT;
  390. printf("取出对应的哈夫曼树文件(如*.dat),请输入文件名,\n");
  391. scanf("%s", TreeName);
  392. if (!(fr = fopen(TreeName, "rb"))) //打开存放哈夫曼树的文件
  393. {
  394. printf("打开文件失败,请输入正确的文件名!! ");
  395. exit(0);
  396. }
  397. int n = _getw(fr); //将叶子数目取出
  398. printf("含叶子数%d\n", n);
  399. HT = (HuffmanTree)malloc((2 * n)*sizeof(HTNode)); /* 然后分配空间,0号单元未用 */
  400. for (int i = 1; i <= 2 * n - 1; i++)
  401. if (fread(&HT[i], sizeof(struct HTNode), 1, fr) != 1)
  402. printf("文件读出出错\n");
  403. int count = 0;
  404. n = 2 * n - 1;
  405. printf("总结点数目为;%d\n", n);
  406. printf("哈夫曼树的存储形式为:\n");
  407. for (int i = 1; i <= n; i++)
  408. {
  409. printf("%c,%u,%u,%u,%u\n", HT[i].leaf, HT[i].weight, HT[i].parent, HT[i].lchild, HT[i].rchild);
  410. }
  411. printf("哈夫曼树的凹入表形式为:\n");
  412. PreOrderPrint(HT, n, count);
  413. }
  414. void PrintCodeFile()
  415. {
  416. FILE *fc;
  417. printf("打印编码后的文件,请输入文件名(如*.dat):\n ");
  418. char CodeFileName[15];
  419. scanf("%s", CodeFileName);
  420. if (!(fc = fopen(CodeFileName, "r")))
  421. {
  422. printf("打开文件失败,请输入正确的文件名!! ");
  423. exit(0);
  424. }
  425. char ch = getchar(); //接收执行scanf语句时最后输入的回车符
  426. printf("打印编码后的文件,打印方法一\n");
  427. int flag = 1;
  428. while (!feof(fc))
  429. {
  430. ch = fgetc(fc);
  431. if (ch == -1)
  432. {
  433. printf("结束打印\n");
  434. }
  435. else
  436. {
  437. printf("%c", ch);
  438. if (flag <= 49)
  439. flag++;
  440. else
  441. {
  442. flag = 1;
  443. printf("\n");
  444. }
  445. }
  446. }
  447. printf("打印编码后的文件,打印方法二\n");
  448. rewind(fc);
  449. char str[50];
  450. while (!feof(fc))
  451. {
  452. fgets(str, 51, fc);
  453. puts(str);
  454. }
  455. fclose(fc); //关闭文件
  456. }
  457. //系统初始化
  458. void Initialization()
  459. {
  460. printf("**************************************\n");
  461. printf("*编码文件请输入e\n*译码文件请输入d\n*打印编码后的文件请输入p\n*打印哈夫曼树请输入t\n*结束请输入q \n");
  462. printf("**************************************\n");
  463. printf("\n\n\t\t字符:\n\n\n");
  464. printf("**************************************\n");
  465. printf("* 输入一个字符:e,d,p,t or q *\n");
  466. printf("**************************************\n");
  467. }
  468. int read(char cmd)
  469. {
  470. int i, flag = 0;
  471. char choice[10] = { 'e', 'E', 'd', 'D', 'p', 'P', 'T', 't', 'Q', 'q' };
  472. for (i = 0; i<10; i++){
  473. if (cmd == choice[i]) flag++;
  474. }
  475. if (flag == 1) return FALSE;
  476. else return TRUE;
  477. }
  478. // 读入操作命令符
  479. void ReadCommand(char &cmd)
  480. {
  481. do{
  482. cmd = getchar();
  483. } while (read(cmd));
  484. }
  485. //解释执行操作命令
  486. void Interpret(char cmd)
  487. {
  488. switch (cmd)
  489. {
  490. case 'e':
  491. case'E':
  492. EnCoding();
  493. Initialization();
  494. break;
  495. case 'd':
  496. case'D':
  497. Decoding();
  498. Initialization();
  499. break;
  500. case 'p':
  501. case'P':
  502. PrintCodeFile();
  503. Initialization();
  504. break;
  505. case't':
  506. case'T':
  507. PrintTree();
  508. Initialization();
  509. break;
  510. case 'q':
  511. case'Q':
  512. exit(0);
  513. break;
  514. default:
  515. printf("Error\n");
  516. break;
  517. }
  518. }
  519. //主程序
  520. int main()
  521. {
  522. char cmd;
  523. Initialization(); //初始化
  524. do{
  525. ReadCommand(cmd); //读入一个操作命令符
  526. Interpret(cmd); //解释执行操作命令符
  527. }while(cmd != 'q'&&cmd != 'Q');
  528. EnCoding();
  529. Decoding();
  530. return 0;
  531. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/运维做开发/article/detail/859272
推荐阅读
相关标签
  

闽ICP备14008679号