sexta-feira, 18 de setembro de 2015

Trabalhando com listas ligadas

     Neste projeto, o objetivo foi, sobretudo, trabalhar com listas ligadas, uma primeira estrutura de armazenamento de dados. O laboratório visava ler um Dicionário com expressões típicas do cotidiano iteano, para gravar as informações em um vetor de listas ligadas através de uma função de dispersão. A função em questão foi, no caso, dada pela soma, em ASCII, dos caracteres de cada expressão a ser gravada. Tendo essas informações já gravadas no vetor, foi possível consultar expressões (função 2), inserir significados ainda não contidos na estrutura (função 3), eliminar significados com a ressalva de que, no caso de tal significado ser único, a expressão referente também deveria ser desalocada (função 4), eliminar expressões em si (função 5) e gerar uma nova base de dados, atualizada (função 6). Para ver o código em execução, assista ao vídeo abaixo.


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


/********** DEFINEM-SE OS TYPEDEF'S E AS STRUCT'S **********/


typedef struct nodeSignificado nodeSignificado;
typedef struct nodeExpressao nodeExpressao;
typedef nodeExpressao *elementoVetor;
typedef nodeSignificado *acompanhanteSignificado;
typedef nodeExpressao *acompanhanteExpressao;
typedef int contador;

struct nodeSignificado
{
    char significado[50];
    nodeSignificado *prox;
};

struct nodeExpressao
{
    char expressao[50];
    nodeSignificado *listaSignificado;
    nodeExpressao *prox;
};


/********** DEFINEM-SE AS FUNCOES AUXILIARES **********/


void zerarStrings(char expr[50], char signif[50], char aux[101])
{
    /*** ZERA AS STRINGS AUXILIARES, I.E., AS CRIADAS NA MAIN ***/
    contador i;
    for(i=0; i<=49; i++)
    {
        expr[i] = '\0';
        signif[i] = '\0';
        aux[i] = '\0';
    }
    for(i=50; i<=100; i++)
        aux[i] = '\0';
}

int obterASCII(char expr[50], int N)
{
    /*** FAZ A SOMA, EM ASCII, DOS CARACTERES DAS EXPRESSOES ***/
    contador i;
    int ASCII = 0;
    for(i=0; expr[i] != '\0'; i++)
        ASCII += expr[i];
    return ASCII %= N;
}

void inserirSignificado(elementoVetor *V, char expr[50], char signif[50], int N)
{
    int ASCII = obterASCII(expr, N);
    /*** CASO AINDA ESTEJA "NOVO", ALOCARA O nodeExpressao, o nodeSignificado E SALVA OS VALORES DE expr[50] e signif[50] ***/
    if(V[ASCII] == NULL)
    {
        V[ASCII] = (nodeExpressao*) malloc (sizeof(nodeExpressao));
        strcpy(V[ASCII]->expressao, expr);
        V[ASCII]->prox = NULL;
        V[ASCII]->listaSignificado = (nodeSignificado*) malloc (sizeof(nodeSignificado));
        strcpy(V[ASCII]->listaSignificado->significado, signif);
        V[ASCII]->listaSignificado->prox = NULL;
    }
    /*** CASO A PRIMEIRA EXPRESSAO SEJA A PROCURADA ***/
    else if(strcmp(V[ASCII]->expressao, expr) == 0)
    {
        bool encontrouSignificado = false;
        acompanhanteSignificado S;
        S = V[ASCII]->listaSignificado;
        ///TESTARA OS SIGNIFICADOS TENTANDO ENCONTRA-LO
        while(S->prox != NULL)
        {
            if(strcmp(S->significado, signif) == 0)
                encontrouSignificado = true;

            S = S->prox;
        }
        ///TESTARA UMA ULTIMA TENTATIVA, JA QUE O LIMITE VAI ATE S->PROX E, LOGO, AGORA ESTA EM S
        if(encontrouSignificado == false)
        {
            ///CASO AGORA TENHA ENCONTRADO, ENTAO O SIGNIFICADO ESTA LA, E NAO SERA PRECISO FAZER NADA
            if(strcmp(S->significado, signif) == 0)
            {}
            ///CASO NAO TENHA ENCONTRADO, PRECISARA ADICIONAR ESSE SIGNIFICADO
            else
            {
                S->prox = (nodeSignificado *) malloc (sizeof (nodeSignificado));
                strcpy(S->prox->significado, signif);
                S->prox->prox = NULL;
            }
        }
    }
    /*** CASO A PRIMEIRA EXPRESSAO NAO SEJA NECESSARIAMENTE, A PROCURADA ***/
    else
    {
        bool encontrouExpressao = false;
        acompanhanteExpressao E;
        E = V[ASCII];
        /*** PROCURA A EXPRESSAO ***/
        while(E->prox != NULL) ///alteracao feita aqui..., antes era E != NULL
        {
            if(strcmp(V[ASCII]->expressao, expr) == 0)
            {
                encontrouExpressao = true;
                bool encontrouSignificado = false;
                acompanhanteSignificado S;
                S = V[ASCII]->listaSignificado;
                while(S->prox != NULL)
                {
                    if(strcmp(S->significado, signif) == 0)
                        encontrouSignificado = true;

                    S = S->prox;
                }
                if(encontrouSignificado == false)
                {
                    S = (nodeSignificado *) malloc (sizeof (nodeSignificado));
                    strcpy(S->significado, signif);
                    S->prox = NULL;
                }
            }
            E = E->prox;
        }
        /*** CASO NAO A TENHA ENCONTRADO, TESTARA UMA ULTIMA VEZ ***/
        if(encontrouExpressao == false)
        {
            if(strcmp(V[ASCII]->expressao, expr) == 0)
            {
                bool encontrouSignificado = false;
                acompanhanteSignificado S;
                S = V[ASCII]->listaSignificado;
                while(S->prox != NULL)
                {
                    if(strcmp(S->significado, signif) == 0)
                        encontrouSignificado = true;

                    S = S->prox;
                }
                if(encontrouSignificado == false)
                {
                    S = (nodeSignificado *) malloc (sizeof (nodeSignificado));
                    strcpy(S->significado, signif);
                    S->prox = NULL;
                }
            }
            else
            {
                E = (nodeExpressao*)malloc(sizeof(nodeExpressao));
                strcpy(E->expressao, expr);
                E->listaSignificado = (nodeSignificado*)malloc(sizeof(nodeSignificado));
                strcpy(E->listaSignificado->significado, signif);
                E->prox = NULL;
                E->listaSignificado->prox = NULL;
            }
        }
    }
}

void eliminarSignificado(elementoVetor *V, char expr[50], char signif[50], int N)
{
    int ASCII = obterASCII(expr, N);
    acompanhanteExpressao E;
    E = V[ASCII];
    /*** CASO A EXPRESSAO QUE CONTEM O SIGNIFICADO A SER ELIMINADO SEJA (A EXPRESSAO) LOGO A PRIMEIRA ***/
    if(strcmp(E->expressao, expr) == 0)
    {
        acompanhanteSignificado S;
        S = E->listaSignificado;
        ///CASO O SIGNIFICADO A SER ELIMINADO SEJA LOGO O PRIMEIRO
        if(strcmp(S->significado, signif) == 0)
        {
            /// CASO ESSE SIGNIFICADO SEJA UNICO
            if(S->prox == NULL)
            {
                if(V[ASCII]->prox == NULL)
                    V[ASCII] = NULL;
                else
                {
                    V[ASCII] = V[ASCII]->prox;
                    free(E);
                }
            }
            /// CASO ESSE SIGNIFICADO SEJA O PRIMEIRO, MAS NAO SEJA O UNICO QUE A EXPRESSAO APRESENTA
            else
            {
                E->listaSignificado = E->listaSignificado->prox;
                S->prox = NULL;
                free(S);
            }
        }
        /// CASO O SIGNIFICADO DA EXPRESSAO NAO SEJA O PRIMEIRO
        while(S->prox->prox != NULL)
        {
            if(strcmp(S->significado, signif) == 0)
            {
                acompanhanteSignificado T;
                T = S;
                S = S->prox;
                free(T);
            }
            else
                S = S->prox;
        }
        /// SE ESSE SIGNIFICADO FOR O PENULTIMO
        if(strcmp(S->significado, signif) == 0)
        {
            acompanhanteSignificado T;
            T = S;
            S = S->prox;
            free(T);
        }
        /// SE ESSE SIGNIFICADO FOR O ULTIMO
        else if(strcmp(S->prox->significado, signif) == 0)
        {
            acompanhanteSignificado T;
            T = S->prox;
            S->prox = S->prox->prox; //NULL
            free(T);
        }
    }
    /*** CASO A EXPRESSAO NAO SEJA, NECESSARIAMENTE, A PRIMEIRA ***/
    else
    {
        bool encontrouExpressao = false;
        while((E->prox != NULL) && (encontrouExpressao == false))
        {
            if(strcmp(E->expressao, expr) == 0)
                encontrouExpressao = true;
            else
                E = E->prox;
        }
        if(encontrouExpressao == true)
        {
            acompanhanteExpressao F;
            F = E;
            acompanhanteSignificado S;
            S = E->listaSignificado;
            if(strcmp(S->significado, signif) == 0)
            {
                ///CASO SEJA O PRIMEIRO E UNICO SIGNIFICADO, PRECISARA DESALOCAR A EXPRESSAO, TAMBEM
                if(S->prox == NULL)
                {
                    E = E->prox;
                    free(F->listaSignificado);
                    free(F);
                }
                else
                {
                    E->listaSignificado = E->listaSignificado->prox;
                    free(S);
                }
            }
            while(S->prox != NULL)
            {
                if(strcmp(S->significado, signif) == 0)
                {
                    acompanhanteSignificado T;
                    T = S;
                    S = S->prox;
                    free(T);
                }
                else
                    S = S->prox;
            }
            if(strcmp(S->significado, signif) == 0)
            {
                acompanhanteSignificado T;
                T = S;
                S = S->prox;
                free(T);
            }
            else if(strcmp(S->prox->significado, signif) == 0)
            {
                acompanhanteSignificado T;
                T = S->prox;
                S->prox = S->prox->prox;
                free(T);
            }
        }
    }
}

void eliminarExpressao(elementoVetor *V, char expr[50], int N)
{
    int ASCII = obterASCII(expr, N);
    acompanhanteExpressao E, F;
    E = F = V[ASCII];
    /*** CASO A EXPRESSAO A SER ELIMINADA FOR A PRIMEIRA ***/
    if(strcmp(E->expressao, expr) == 0)
    {
        if(E->prox == NULL)
        {
            if(V[ASCII]->prox == NULL)
                V[ASCII] = NULL;
            else
            {
                V[ASCII] = V[ASCII]->prox;
                free(E);
            }
        }
        else
        {
            E = E->prox;
            F->prox = NULL;
            free(F);
        }
    }
    else
    {
        bool encontrouExpressao = false;
        while((E->prox != NULL)&&(encontrouExpressao == false))
        {
            if(strcmp(E->expressao, expr) == 0)
                encontrouExpressao = true;
            else
                E = E->prox;
        }
        if(encontrouExpressao == false)
        {
            if(strcmp(E->expressao, expr) == 0)
                encontrouExpressao = true;
        }
        if(encontrouExpressao == true)
        {
            acompanhanteSignificado S, T;
            S = T = E->listaSignificado;
            while(S != NULL)
            {
                T = S;
                S = S->prox;
                free(T);
            }
            F = E;
            E = E->prox;
            free(F);
        }
    }
}

/*** MAIN ***/
int main()
{
    /*** ABRE OS ARQUIVOS DE ENTRADA E SAIDA ***/
    FILE *arqEntrada, *arqSaida;
    arqEntrada = fopen("entrada.txt", "r");
    arqSaida = fopen("saida.txt", "w");

    /*** VARIAVEIS DO PROGRAMA ***/
    char expr[50], signif[50], aux[101], *pch, lixo;
    int N, qtdOperac, codOperac;
    contador i, j;

    /*** ALOCAR VETOR ***/
    fscanf(arqEntrada, "%d", &N);
    nodeExpressao **V;
    V = (elementoVetor*) malloc (N * sizeof (elementoVetor*));

    /*** APONTAR OS ELEMENTOS DO VETOR PARA NULL ***/
    for(i=0; i<=N-1; i++)
        V[i] = NULL;

    /*** LOOP PRINCIPAL ***/
    fscanf(arqEntrada, "%d", &qtdOperac);
    for(i=1; i<=qtdOperac; i++)
    {
        zerarStrings(expr, signif, aux);
        fscanf(arqEntrada, "%d%c", &codOperac, &lixo);
        switch(codOperac)
        {
        /*** ABRE A ESTRUTURA DE DADOS E INSERE OS DADOS NO VETOR ***/
        case 1:
        {
            FILE *arqLeitura;
            arqLeitura = fopen("DicionITA.txt", "r");
            while(fgets(aux, 101, arqLeitura) != NULL)
            {
                aux[strlen(aux)-1] = '\0';
                pch = strtok(aux, "|");
                strcpy(expr, pch);
                pch = strtok(NULL, "|");
                strcpy(signif, pch);
                inserirSignificado(V, expr, signif, N);
                zerarStrings(expr, signif, aux);
            }
            fclose(arqLeitura);
        }
        break;
        /*** CONSULTA UMA EXPRESSAO PELOS SEUS SIGNIFICADOS ***/
        case 2:
        {
            fgets(expr, 50, arqEntrada);
            expr[strlen(expr)-1] = '\0';
            int ASCII = obterASCII(expr, N);
            acompanhanteExpressao E;
            E = V[ASCII];
            bool encontrouExpressao = false;
            while((E != NULL) && (encontrouExpressao == false))
            {
                if(strcmp(E->expressao, expr) == 0)
                    encontrouExpressao = true;
                else
                    E = E->prox;
            }
            if(encontrouExpressao == true)
            {
                acompanhanteSignificado S;
                S = V[ASCII]->listaSignificado;
                while(S != NULL)
                {
                    fprintf(arqSaida, "%s\n", S->significado);
                    S = S->prox;
                }
                fprintf(arqSaida, "\n");
            }
            else
                fprintf(arqSaida, "nada consta\n\n");
        }
        break;
        /*** ACRESCENTA, CASO AINDA NAO ESTEJA PRESENTE, UM SIGNIFICADO A ALGUMA EXPRESSAO ***/
        case 3:
        {
            fgets(aux, 101, arqEntrada);
            aux[strlen(aux)-1] = '\0';
            pch = strtok(aux, "|");
            strcpy(expr, pch);
            pch = strtok(NULL, "|");
            strcpy(signif, pch);
            inserirSignificado(V, expr, signif, N);
        }
        break;
        /*** ELIMINA UM SIGNIFICADO, CASO ESTEJA PRESENTE ***/
        case 4:
        {
            fgets(aux, 101, arqEntrada);
            aux[strlen(aux)-1] = '\0';
            char *pch;
            pch = strtok(aux, "|");
            strcpy(expr, pch);
            pch = strtok(NULL, "|");
            strcpy(signif, pch);
            eliminarSignificado(V, expr, signif, N);
        }
        break;
        /*** ELIMINA UMA EXPRESSAO, CASO ESTEJA PRESENTE ***/
        case 5:
        {
            fgets(expr, 50, arqEntrada);
            expr[strlen(expr)-1] = '\0';
            eliminarExpressao(V, expr, N);
        }
        break;
        /*** PRODUZ A NOVA ESTRUTURA DE DADOS ***/
        case 6:
        {
            FILE *DicionITA;
            DicionITA = fopen("Dicionario.txt", "w");
            acompanhanteExpressao E = V[0];
            acompanhanteSignificado S = V[0]->listaSignificado;

            for(j=0; j <= N-1; j++)
            {
                if(V[j] != NULL)
                {
                    E = V[j];
                    S = V[j]->listaSignificado;
                    while(E != NULL)
                    {
                        while(S != NULL)
                        {
                            fprintf(DicionITA, "%s|%s\n", E->expressao, S->significado);
                            S = S->prox;
                        }
                        E = E->prox;
                    }
                }
            }
            fprintf(DicionITA, "\n");
            fclose(DicionITA);
        }
        break;
        default:
        {
            fprintf(arqSaida,"ERRO\n\n");
            return 0;
        }
        break;
        }
    }
    fclose(arqEntrada);
    fclose(arqSaida);
    return 0;
}