哈夫曼编译码器的实现 使用文件

两天做出的哈夫曼编译码器 还算稳定 只有一个字符的时候不能实现

//============================================================================
// Name : katherine
// Author : katherine
// Version : 1.0    2015-12-27 22:09:05
// Copyright : made by katherine
// Description : Ansi-style
// Last Modified time : 2015-12-30 12:07:32
//============================================================================
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <conio.h>

#define N 100
#define M 2*N-1
#define EOF (-1)

typedef struct Huffmantree
{
    char data;
    int weight;
    int parent;
    int lchild;
    int rchild;
}HuffmanTree[M];//哈夫曼树存储节点结构体

typedef struct Huffmancode
{
    char data;
    char bits[N];
}HuffmanCode[N];//哈夫曼编码的存储结构体

typedef struct  str
{
    char data;
    char num;
}str;//字符数组
int read(str s2[],char name[]);
void SelectMin(HuffmanTree ht,int i,int *p1,int *p2);
void CrtHuffmanTree(HuffmanTree ht,str s[],int n);
void CrtHuffmanCode(HuffmanTree ht,HuffmanCode hc,int k);
void WriteToFile(HuffmanCode hc,int n,char name[],char name1[]);
void DecodeHuffmanCode(HuffmanTree ht,int n,char name1[],char name2[]);
void compare(int n,char name[],char name2[]);
int main() {
    int k,;
    HuffmanTree ht;
    HuffmanCode hc;
    str s2[128];

    char name[30];
    char name1[30];
    char name2[30];
    printf("Please enter the filename you need coding:  \n");
    scanf("%s",name);
    k = read(s2,name);
    CrtHuffmanTree(ht,s2,k);
    CrtHuffmanCode(ht,hc,k);
    printf("Please enter the filename you need save:  \n");
    scanf("%s",name1);
    WriteToFile(hc,k,name,name1);
    printf("Please enter the filename you need save decoding:  \n");
    scanf("%s",name2);
    DecodeHuffmanCode(ht,k,name1,name2);

    compare(k,name,name2);
    getchar();
}
int read(str s2[],char name[])
{
    FILE *fp;//声明fp是指针,用来指向FILE类型的对象
    char ch;
    int i;
    int k;
    str s1[128];
    for (i = 0; i <128; i++)
    {
        s1[i].data =0;
        s1[i].num =0;
        s2[i].data =0;
        s1[i].num =0;

    }
    if((fp=fopen(name,"r"))==NULL)// fopen标准函数
    {
        printf("File open failed\n");
        getch();
        exit(1);
    }
    printf("The string to read is:\n");
    ch  = fgetc(fp);
    while(!feof(fp))
    {
        printf("%c",ch);
        s1[ch].num++;
        s1[ch].data = ch;
        ch  = fgetc(fp);//自动移动机制
    }
    fclose(fp);
    for (i=1,k=0;i<=128;i++)
    {
        if(s1[i].num!=0 )
        {   k++;
            s2[k].num = s1[i].num;
            s2[k].data = s1[i].data;
        }
    }
    printf("\nStatistical results are:\n");
    printf("\n<character   Code> \n");
    for(i=1;i<=k;i++)
    {
        printf("<%c            %d>\n",s2[i].data,s2[i].num);
    }
    printf("There are %d kinds of characters\n",k);
    return k ;
}

void SelectMin(HuffmanTree ht,int i,int *p1,int *p2)
{
    int j,min1,min2;
    min1 = min2 =-1;
    for (j=1;j<=i;j++)
    {
        if(ht[j].parent == 0)//找到还未加入到树里面的节点
        {
            if(ht[j].weight<min1||min1==-1)//找小的或者还没有赋给权值的
            {
                if(min1!=-1)
                {
                    min2=min1;//min1总是最小的那个
                    *p2=*p1;//p1总是指向最小的那个
                }
                min1 = ht[j].weight;//先赋给权值
                *p1=j;

            }
            else if(ht[j].weight<min2||min2==-1)
            {
                min2=ht[j].weight;
                *p2=j;
            }
        }
    }
}

void CrtHuffmanTree(HuffmanTree ht,str s[],int n)
{
    int i,m,p1,p2;
    for (i=1;i<=n;i++)
    {

        //strcpy(ht[i].data,&s[i].data);
        ht[i].data = s[i].data;
        printf("%c ",ht[i].data);
        ht[i].weight= s[i].num;
        ht[i].parent=0;
        ht[i].lchild=0;
        ht[i].rchild = 0;
    }
    m = 2*n-1;
    for (i = n+1;i<=m;i++)
    {
        //strcpy(ht[i].data,NULL);
        ht[i].data=0;
        ht[i].weight=0;
        ht[i].parent = 0;
        ht[i].lchild=0;
        ht[i].rchild=0;
    }
    for (i = n+1;i<=m;i++)
    {
        SelectMin(ht,i-1,&p1,&p2);
        ht[i].weight=ht[p1].weight+ht[p2].weight;
        ht[p1].parent=i;
        ht[p2].parent=i;
        ht[i].lchild=p1;
        ht[i].rchild=p2;
    }
    printf("\nThe establishment of the Huffman tree for:\n");
    printf("number\tdata\tweight\tlchild\trchild\tparent\n");
    for(i=1;i<=n;i++)
    {
        printf("%d:\t%c\t%d\t%d\t%d\t%d\n",i,ht[i].data,ht[i].weight,ht[i].lchild,ht[i].rchild,ht[i].parent);
    }

}

void CrtHuffmanCode(HuffmanTree ht,HuffmanCode hc,int k)
{
    int c,p,i;
    char cd[N+1];
    int start;
    for(i=1;i<=k;i++)
    {
        //strcpy(hc[i].data,&ht[i].data);
        hc[i].data = ht[i].data;
        start = k-1;//深度
        cd[start] = '\0';
        c=i;
        while((p=ht[c].parent)!=NULL)
        {
            cd[--start] = (ht[p].lchild==c)?'0':'1';
            c=p;
        }
        strcpy(hc[i].bits,&cd[start]);

    }
    printf("\n\nEach character corresponds to the encoding:\n");
    for(i=1;i<=k;i++)
        printf("<%d     %c     %s>   \n",i,hc[i].data,hc[i].bits);
}

void WriteToFile(HuffmanCode hc,int n,char name[],char name1[]){
    FILE *fp1,*fp2;
    char ch;
    int i;

    if((fp1=fopen(name,"r"))==NULL)
    {
        printf("File open failed");
        getch();
        exit(1);
    }
    if((fp2=fopen(name1,"w"))==NULL)
    {
        printf("File open failed");
        getch();
        exit(1);
    }
    ch = fgetc(fp1);
    while(ch!=EOF)
    {
        for(i=1;i<=n;i++)
        if(ch==hc[i].data)
        {
        fputs(hc[i].bits,fp2);
        }
        ch = fgetc(fp1);
    }
    fclose(fp1);
    fclose(fp2);

    printf("File save Success\n");

}
void DecodeHuffmanCode(HuffmanTree ht,int n,char name1[],char name2[])
{
    FILE *fp1,*fp2;
    char ch;
    int p,k;

    if((fp1 = fopen(name1,"r"))==NULL)
    {
        printf("File open failed");
        getch();
        exit(1);
    }
    if((fp2= fopen(name2,"w"))==NULL)
    {
        printf("File open failed");
        getch();
        exit(1);
    }
    p = k = 2*n-1;
    ch = fgetc(fp1);

    while(!feof(fp1))
    {  if(ch=='0')
        {
            p = ht[p].lchild;
        }
        if(ch=='1')
        {
            p = ht[p].rchild;
        }
        if(ht[p].data!=0)
        {
            printf("%c",ht[p].data);
            fprintf(fp2,"%c",ht[p].data);
            p = k;
        }
        ch = fgetc(fp1);
    }
    printf("\n");
    fclose(fp1);
    fclose(fp2);
}
void compare(int n,char name[],char name2[])
{
    FILE *fp1,*fp2;
    char s1[N], s2[N];
    int i = 1,j = 1;
    if((fp1 = fopen(name,"rt"))==NULL)
    {
        printf("File open failed");
        getch();
        exit(1);
    }
    if((fp2= fopen(name2,"rt"))==NULL)
    {
        printf("File open failed");
        getch();
        exit(1);
    }
    printf("Source file is:");
    for(i=1;(s1[i]=fgetc(fp1))!=EOF;i++)
    {
        printf("%c",s1[i]);
    }
    printf("\nDeCode file is:");
    for(i=1;(s2[i]=fgetc(fp2))!=EOF;i++)
    {
        printf("%c",s1[i]);
    }
    printf("\n");
    fclose(fp1);
    fclose(fp2);
    while(j<n)
    {
        if(s1[j]==s2[j])
        {
           j++;
        }
        else
        {
            printf("Sorry compiler failed\n");
            break;
        }
    }
    if(j==n)
    {
        printf("*****Congratulations to compile successfully*****");
    }
    getch();
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
[ 问题描述 ] 利用哈夫曼码进行信息通讯可以大大提高信道利用率, 缩短信息传输时间,降低传输成本。但是, 这要求在发送端通过一个码系统对待传数据预先码; 在接收端将传来的数据进行译码( 复原 )。对于双工信道( 即可以双向传输信息的信道 ), 每端都需要一个完整的/译码系统。试为这样的信息收发站写一个哈夫曼码的译码系统。 [ 基本要求 ] 一个完整的系统应具有以下功能: (1) I:初始化(Initialization)。从终端读入字符集大小 n,及 n 个字符和 n 个权值,建立哈夫曼树, 并将它存于文件 hfmtree 中。 (2) C:码(Coding)。利用已建好的哈夫曼树(如不在内存, 则从文件 hfmtree 中读入), 对文件 tobetrans 中的正文进行码, 然后将结果存入 codefile 中。 (3) D:译码(Decoding)。利用已建好的哈夫曼树将文件 codefile 中的代码进行译码, 结果存入文件 textfile 中。 (4) P:印代码文件(Print)。将文件 codefile 以紧凑格式显示在终端上, 每行 50 个代码。同时将此字符形式的文件写入文件 codeprint 中。 (5) T:印哈夫曼树(Tree print)。将已在内存中的哈夫曼树以直观的方式( 树或凹入表行式 )显示在终端上, 同时将此字符形式的哈夫曼树写入文件 treeprint 中。 [ 测试数据 ] (1)利用教科书 6-2 中的数据调试程序。 (2)用下表中给出的字符集和频度的实际统计数据建立哈夫曼树, 并实现以下报 文的码和译码: "THIS PROGRAM IS MY FAVORITE". 字符 A B C D E F G H I J 频度 186 64 13 22 32 103 21 15 47 57 1 字符 K L M N O P Q R S T U 频度 5 32 20 57 63 15 1 48 51 80 23 字符 V W X Y Z 频度 8 18 1 16 1 [ 实现提示 ] (1) 文件 codefile 的基类型可以设为子界型 bit=0..1。 (2) 用户界面可以设计为"菜单"方式: 显示上述功能符号, 再加上"E",表示结束运行 End, 请用户键入一个选择功能符。此功能执行完毕后再显示此菜单, 直至某次用户选择了 "E"为止。 (3) 在程序的一次执行过程中, 第一次执行 I,D 或 C 命令之后, 哈符曼树已经在内存了, 不必再读入。每次执行中不一定执行 I 命令, 因为文件 hfmtree 可能早己建好。 [ 选作内容 ] (1) 上述 codefile 的基类型实际上占用了存放一个整数的空间, 只起到示意或模拟的作用。现使 codefile 的基类型 package=integer, 把哈夫曼码紧缩到一个整型变量中去, 最大限度地利用码点存储能力, 试改写你的系统。 (2) 修改你的系统, 实现对你的系统的源程序的码和译码。( 主要是将行尾符/译码问题 ) (3) 实现各个转换操作的源/目文件, 均由用户在选择此操作时指定。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值