C语言实现Huffman的编码和解码( 三 )

< 8; ++index) {buffer <<= 1;if (!cursor->left || !cursor->right) {Byte data = http://www.kingceram.com/post/(Byte)cursor->data;fwrite(&data, sizeof(data), 1, output);if (--count == 0) {break;}cursor = root;}if (buffer & ~0xff) {cursor = setpHuffmanTree(cursor, NODE_FLAG_RIGHT);} else {cursor = setpHuffmanTree(cursor, NODE_FLAG_LEFT);}buffer &= 0xff;}}}}/*检测是否是可显示字符*/int canShowChar(char ch) {return (ch > 32 && ch < 127);}/*通过递归遍历方式打印Huffman树*/void outputHuffmanTree(FILE* output, pNode root, int flag) {if (root) {int index;char content[128] = { 0 };const char* flagname[] = { "ROOT", "LEFT", "RIGHT" };int offset = (int)strlen(root->code) - 1;for (index = 0; index < offset; ++index) {if (root->code[index] == '0') {fprintf(output, " │ ");} else {fprintf(output, "");}}switch (root->type) {case NODE_TYPE_DATA:sprintf(content, "> %-6s #%-4d 0xX : '%c'", flagname[flag], root->weight, root->data, canShowChar((char)root->data) ? root->data : ' ');break;case NODE_TYPE_BLANK:sprintf(content, "[+] %-6s #%-4d", flagname[flag], root->weight);break;}switch (flag) {case NODE_FLAG_ROOT:fprintf(output, "%s", content);break;case NODE_FLAG_LEFT:fprintf(output, " ├─%s", content);break;case NODE_FLAG_RIGHT:fprintf(output, " └─%s", content);break;}if (root->type == NODE_TYPE_DATA) {fprintf(output, " CODE : %s\n", root->code);} else {fprintf(output, "\n");}outputHuffmanTree(output, root->left, NODE_FLAG_LEFT);outputHuffmanTree(output, root->right, NODE_FLAG_RIGHT);}}/*打印Huffman树*/void printHuffmanTree(FILE* output, pNode root) {fprintf(output, "*******************************\n");fprintf(output, "Print Huffman Tree\n");fprintf(output, "\n");outputHuffmanTree(output, root, NODE_FLAG_ROOT);fprintf(output, "\n");}/*将Huffman表中的数据输出成编码和权重统计表*/void printHuffmanList(FILE* output, pNode root) {pNode nodelist[LIST_SIZE] = { NULL };int index;int listcount = 0;/*将Huffman树转换成Huffman表*/convertTreeToList(root, nodelist);listcount = trimNodeList(nodelist, LIST_SIZE);fprintf(output, "*******************************\n");fprintf(output, "# Print Huffman Code List #\n");fprintf(output, "\n");fprintf(output, "Total : %d\n", listcount);fprintf(output, "\n");fprintf(output, "%-7s%-10s%-10s%s\n", "ASCII", "Char", "Weight", "Code");for (index = 0; index < listcount; ++index) {pNode node = nodelist[index];Byte ch = (Byte)node->data;if (canShowChar((char)ch)) {/*可显示字符的输出*/fprintf(output, "%-7d%-10c%-10d%s\n", ch, ch, node->weight, node->code);} else {/*不可显示字符的输出*/fprintf(output, "%-7d%-10s%-10d%s\n", ch, "NOShow", node->weight, node->code);}}printf("\n");}/*统计输入的字符权重*/void contUserInputTimes(int times[]) {int index, count;printf("*******************************\n");printf("# Input data to test #\n");printf("\n");printf("Number of input nodes : ");scanf("%d", &count);printf("Enter the letters and weights for each node : \n");for (index = 0; index < count; ++index) {char str[128] = { 0 };int weight = 0;printf("Char: ");scanf("%s", str);printf("Weight : ");scanf("%d", &weight);times[(int)str[0]] = weight;}}/*输入数据构建Huffman树选项*/pNode inputDataToBuildHuffmanTreeOption() {int times[LIST_SIZE] = { 0 };contUserInputTimes(times);return buildHuffmanTree(times);}/*获取输入选项*/int inputOption(int begin, int end) {do {int opt;if (scanf("%d", &opt) == 1) {if (opt >= begin && opt <= end) {return opt;} else {printf("error : The input range should be between %d and %d.\n", begin, end);}} else {printf("error : Please enter integer type.\n");/*清空缓冲区*/setbuf(stdin, NULL);}} while (1);}/*检测文件类型*/int getFileType(const char filename[]) {int type = FILE_TYPE_NULL;FILE* input = fopen(filename, "rb");if (input) {char buffer[2] = { 0 };type = FILE_TYPE_ENCODE;if (fread(buffer, 2, 1, input) == 1) {if (buffer[0] == FILE_HEADER_FLAG[0] && buffer[1] == FILE_HEADER_FLAG[1]) {type = FILE_TYPE_DECODE;}}fclose(input);}return type;}/*写入文件头信息(文件头含文件头标识和字符权重集)*/int writeFileHeader(pNode root, FILE* output) {pNode nodelist[LIST_SIZE] = { NULL };Byte total = 0;int index;/*写入文件头标识*/fwrite(FILE_HEADER_FLAG, 2, 1, output);convertTreeToList(root, nodelist);/** 为节省空间字符集总量存储为1个字节* 总量1用0表示,总量256用255表示* 所以总量 - 1*/total = (Byte)(trimNodeList(nodelist, LIST_SIZE) - 1);/*写入字符集总数*/fwrite(&total, sizeof(total), 1, output);/*写入每个字符以及权重*/for (index = 0; index