Huffman Algorithm - decoder

2

I'm doing the decoding part of the huffman algorithm, as such my program receives two files per console, one called "diccionariotxt" which contains the letters, the frequency with which they exit and the binary code of each letter and another one called "codificadotxt" which contains the binary code to decode

An example of the dictionary file: H (1): 000 O (1): 001 L (1): 010 A (1): 011

And an example of the encoded file will be: 000001010011 (Which should print HELLO)

My problem is that when the word is only 3 letters it does not decode it for any reason that I can not see, besides that, the character space ("") recognizes it at the moment of translation as a line break, I imagine that it must be some theoretical problem. Of the rest the algorithm works but if you could take a look at it I would be very grateful, I append the code:

#include <stdio.h>
#include <stdlib.h>

// MACRO PARA DECODIFICAR.
#define MAX_CARACTERES 255

// ESTRUCTURA PARA DECODIFICAR.
struct decod{
    int frecuencia;
    char letra;
    char codigo[10];
} nodo[MAX_CARACTERES];

// VARIABLES GLOBALES PARA DECODIFICAR.
int nro_elementos=0;                            // Cantidad de elementos que contiene el diccionario.
int elementos_diccionario[MAX_CARACTERES];      // Almacena la info del diccionario.

// FUNCIONES AUXILIARES PARA DECODIFICAR.
int longitud_codificado(char codificadotxt[20])
{
    int cont=0;
    char caracter;
    FILE * codificado;

    codificado = fopen(codificadotxt, "r");
    if(!codificado)
    {
        printf("Archivo invalido...\n");        //Devuelve la longitud del archivo codificado.
    return;
    }

    if(codificado!=NULL)
    {
        while(feof(codificado)==0)
        {
            caracter=fgetc(codificado);
            cont++;
        }
    }
    fclose(codificado);
    return cont;
}

int verifica_igualdad(char cadena1[], char cadena2[], int longitud)
{
    int i=0, bandera=0;

    for(i=0; i<longitud; i++)
    {
        if(cadena1[i]==cadena2[i])
        {
            bandera=1;                          // Verifica si el codigo leido es igual al codigo de la letra evaluada.
        }
        else
        {
            bandera=0;
            return bandera;
        }
    }
    return bandera;
}

void vaciar_arreglo(char *comparar, int tamano)
{
    int i=0;

    // Vacia el arreglo para leer una letra nueva.
    for(i=0;i<=tamano;i++)
        comparar[i]='
#include <stdio.h>
#include <stdlib.h>

// MACRO PARA DECODIFICAR.
#define MAX_CARACTERES 255

// ESTRUCTURA PARA DECODIFICAR.
struct decod{
    int frecuencia;
    char letra;
    char codigo[10];
} nodo[MAX_CARACTERES];

// VARIABLES GLOBALES PARA DECODIFICAR.
int nro_elementos=0;                            // Cantidad de elementos que contiene el diccionario.
int elementos_diccionario[MAX_CARACTERES];      // Almacena la info del diccionario.

// FUNCIONES AUXILIARES PARA DECODIFICAR.
int longitud_codificado(char codificadotxt[20])
{
    int cont=0;
    char caracter;
    FILE * codificado;

    codificado = fopen(codificadotxt, "r");
    if(!codificado)
    {
        printf("Archivo invalido...\n");        //Devuelve la longitud del archivo codificado.
    return;
    }

    if(codificado!=NULL)
    {
        while(feof(codificado)==0)
        {
            caracter=fgetc(codificado);
            cont++;
        }
    }
    fclose(codificado);
    return cont;
}

int verifica_igualdad(char cadena1[], char cadena2[], int longitud)
{
    int i=0, bandera=0;

    for(i=0; i<longitud; i++)
    {
        if(cadena1[i]==cadena2[i])
        {
            bandera=1;                          // Verifica si el codigo leido es igual al codigo de la letra evaluada.
        }
        else
        {
            bandera=0;
            return bandera;
        }
    }
    return bandera;
}

void vaciar_arreglo(char *comparar, int tamano)
{
    int i=0;

    // Vacia el arreglo para leer una letra nueva.
    for(i=0;i<=tamano;i++)
        comparar[i]='%pre%';
}

void guarda_diccionario(char diccionariotxt[20])
{
    int i=0;
    FILE * diccionario;

    diccionario = fopen(diccionariotxt, "r");       //Abrimos el diccionario para asignar cada campo a la estructura.
    if(!diccionario)
    {
        printf("Archivo invalido...\n");
        return;
    }
    if(diccionario != NULL)
    {
        while(!feof(diccionario)){          //Empieza a guardar cada campo.
            fscanf(diccionario, "%c (%d): %s", &nodo[nro_elementos].letra,&nodo[nro_elementos].frecuencia,&nodo[nro_elementos].codigo);
            nro_elementos++;
        }
        fclose(diccionario);
    }
}

void decodifica(char codificadotxt[20])
{
    int cont1=0, cont2=0, longitud=0;
    char caracter;
    FILE *codificado;

    codificado = fopen(codificadotxt, "r");     //Abrimos el archivo codificado para empezar a decodificar.
    if(!codificado)
    {
        printf("Archivo invalido...\n");
        return;
    }
    longitud=longitud_codificado(codificadotxt);
    char comparar[10];
    if(codificado != NULL)
    {
        while(feof(codificado) == 0)
        {
            caracter=fgetc(codificado);
            comparar[cont1]=caracter;
            for(cont2=0;cont2<nro_elementos;cont2++)
            {
                if(strncmp(comparar,nodo[cont2].codigo, 10) == 0)
                {
                    printf("%c", nodo[cont2].letra);
                    vaciar_arreglo(comparar, cont1);
                    cont1=-1;
                    goto salir;
                }
            }
            salir:
            cont1++;
        }
        fclose(codificado);
    }
    printf("\n");
}

void imprime_dicc()
{
    int i=0;
    for(i=0;i<nro_elementos;i++)
        printf("Caracter: %c Frecuencia:(%d): Codigo:%s\n", nodo[i].letra,nodo[i].frecuencia,nodo[i].codigo);
}


void main()
{
    char diccionariotxt[20], codificadotxt[20];
    printf("         |HUFFMAN|      \n");
    printf("Ingrese el nombre del archivo diccionario: ");
    scanf("%s", &diccionariotxt);
    printf("Ingrese el nombre del archivo codificado: ");
    scanf("%s", &codificadotxt);
    guarda_diccionario(diccionariotxt);
    decodifica(codificadotxt);
}
'; } void guarda_diccionario(char diccionariotxt[20]) { int i=0; FILE * diccionario; diccionario = fopen(diccionariotxt, "r"); //Abrimos el diccionario para asignar cada campo a la estructura. if(!diccionario) { printf("Archivo invalido...\n"); return; } if(diccionario != NULL) { while(!feof(diccionario)){ //Empieza a guardar cada campo. fscanf(diccionario, "%c (%d): %s", &nodo[nro_elementos].letra,&nodo[nro_elementos].frecuencia,&nodo[nro_elementos].codigo); nro_elementos++; } fclose(diccionario); } } void decodifica(char codificadotxt[20]) { int cont1=0, cont2=0, longitud=0; char caracter; FILE *codificado; codificado = fopen(codificadotxt, "r"); //Abrimos el archivo codificado para empezar a decodificar. if(!codificado) { printf("Archivo invalido...\n"); return; } longitud=longitud_codificado(codificadotxt); char comparar[10]; if(codificado != NULL) { while(feof(codificado) == 0) { caracter=fgetc(codificado); comparar[cont1]=caracter; for(cont2=0;cont2<nro_elementos;cont2++) { if(strncmp(comparar,nodo[cont2].codigo, 10) == 0) { printf("%c", nodo[cont2].letra); vaciar_arreglo(comparar, cont1); cont1=-1; goto salir; } } salir: cont1++; } fclose(codificado); } printf("\n"); } void imprime_dicc() { int i=0; for(i=0;i<nro_elementos;i++) printf("Caracter: %c Frecuencia:(%d): Codigo:%s\n", nodo[i].letra,nodo[i].frecuencia,nodo[i].codigo); } void main() { char diccionariotxt[20], codificadotxt[20]; printf(" |HUFFMAN| \n"); printf("Ingrese el nombre del archivo diccionario: "); scanf("%s", &diccionariotxt); printf("Ingrese el nombre del archivo codificado: "); scanf("%s", &codificadotxt); guarda_diccionario(diccionariotxt); decodifica(codificadotxt); }
    
asked by Marshal 25.06.2016 в 04:55
source

1 answer

4
char diccionariotxt[20];
scanf("%s", &diccionariotxt);

diccionariotxt is an array of characters, that is, a pointer. On the other hand, scanf needs to be passed pointers to store the values it retrieves from the keyboard. In your case you are passing a reference to a pointer or, what is the same, a double pointer. The correct thing would be the following:

char diccionariotxt[20];
scanf("%s", diccionariotxt);

This error is replicated in many other readings of your code.

You should also monitor the compiler's messages, including the warning, since some of them may have undesirable effects on your application. In this case it is an empty return when the function expects the return of an integer:

int longitud_codificado(char codificadotxt[20])
{
    if(!codificado)
    {
        printf("Archivo invalido...\n");        //Devuelve la longitud del archivo codificado.
        return; // <<--- AQUI!!!!
    }
}

Greetings.

    
answered by 27.06.2016 в 09:09