domingo, 25 de outubro de 2015

LAB 3 - CES 11

          Olá! Agora apresento o meu código para o LAB 3 de CES 11. Nele, o objetivo era o de criar um contador de palavras, a partir da implementação da estrutura de dados árvore. Para auxiliar nesse trabalho, também foi implementada uma pilha de caracteres alocada dinamicamente, facilitando a impressão das palavras. Acompanhe o vídeo abaixo e, a seguir, veja o código comentado:


 /***     ALUNO: GUSTAVO NAHUM ALVAREZ FERREIRA      ***/  
 /***     TURMA: 19.3                   ***/  
 /***     LAB 3 - CES 11                 ***/  
 #include <stdio.h>  
 #include <stdlib.h>  
 #include <string.h>  
 #include <stdbool.h>  
 #include <ctype.h>  
 /**   O MÁXIMO É REFERENTE À QUANTIDADE DE ELEMENTOS DA STRING QUE RECEBERÁ AS LINHAS DE "entrada.txt"   **/  
 #define max 100  
 /**   AS DUAS ESTRUTURAS DE DADOS USADAS NO CÓDIGO FORAM A árvore, A PARTIR DE células, E A pilha, A PARTIR DE nodes. A árvore SERÁ NECESSÁRIA AO LONGO DE TODO O CÓDIGO   **/  
 typedef struct celula celula;  
 struct celula  
 {  
   char letra;  
   int cont;  
   celula *filhos[26];  
 };  
 typedef celula *arvore;  
 typedef celula *posicao;  
 /**   A pilha SERÁ IMPORTANTE PARA AUXILIAR NA IMPRESSÃO DAS PALAVRAS CONTIDAS NA árvore   **/  
 typedef struct node node;  
 struct node  
 {  
   char elem;  
   node *prox;  
 };  
 typedef node *pilha;  
 /**   A FUNÇÃO "alocaArvore" CRIA O "NÓ-LÍDER" DA árvore, E APONTA PARA AS LETRAS INICIAIS DAS PALAVRAS. ELA SERÁ USADA NA "main", PARA ALOCAR A árvore USADA EM TODO O PROGRAMA   **/  
 void alocaArvore (arvore *A)  
 {  
   (*A) = (celula *)malloc(sizeof(celula));  
   (*A)->letra = '#';  
   (*A)->cont = 0;  
   int i;  
   for(i = 0; i <= 25; i++)  
     (*A)->filhos[i] = NULL;  
 }  
 /**   A FUNÇÃO "alocaCelula" CRIA UMA NOVA célula E INSERE A LETRA CORRESPONDENTE. ELA SERÁ USADA EM "lerArquivo", NA HORA DE INSERIR AS LETRAS DAS PALAVRAS   **/  
 void alocaCelula (celula **P, char c)  
 {  
   (*P) = (celula *)malloc(sizeof(celula));  
   (*P)->letra = c;  
   (*P)->cont = 0;  
   int i;  
   for(i = 0; i <= 25; i++)  
     (*P)->filhos[i] = NULL;  
 }  
 /**   A FUNÇÃO "numFilhos" RETORNA O VALOR NUMÉRICO CORRESPONDENTE A UMA LETRA DADA: "a" E "A" CORRESPONDEM AO "0", "b" E "B" CORRESPONDEM AO "1", ETC. ELA SERÁ IMPORTANTE PARA FACILITAR A CONVERSÃO DE MAIÚSCULAS EM MINÚSCULAS EM "lerArquivo"   **/  
 int numFilhos(char carac)  
 {  
   if(islower(carac))  
     return carac - 'a';  
   else  
     return carac - 'A';  
 }  
 /**   A FUNÇÃO "lerArquivo" DEVERÁ LER O ARQUIVO "entrada.txt" E GERAR A árvore CORRESPONDENTE. COM ESSA árvore, A FUNÇÃO "imprimirArquivo" PODERÁ IMPRIMIR AS PALAVRAS E SUAS QUANTIDADES DE APARIÇÃO EM "entrada.txt"   **/  
 void lerArquivo(FILE *f_entrada, arvore *A)  
 {  
   char string[max];  
   int i, aux;  
   posicao P;  
   P = *A;  
   while(fgets(string, max, f_entrada) != NULL)  /* RECEBE, LINHA A LINHA, O CONTEÚDO DE "entrada.txt" */  
   {  
     for(i = 0; i <= strlen(string)-1; i++)   /* ANALISA, LETRA A LETRA, O CONTEÚDO DAS LINHAS: */  
     {  
       if(isalpha(string[i]))         /* 1. SE FOR ALFA-NUMÉRICO, A LETRA VAI PARA A PRÓXIMA CÉLULA */  
       {  
         if(P->filhos[numFilhos(string[i])] == NULL)  
           alocaCelula(&P->filhos[numFilhos(string[i])], numFilhos(string[i])+'a');  
         P = P->filhos[numFilhos(string[i])];  
       }  
       else                  /* 2. SE NÃO FOR ALFA-NUMÉRICO, A CÉLULA INCREMENTA O CONTADOR... */  
       {                    /* ...E RETORNA AO TOPO DA ÁRVORE, PARA INICIAR A LEITURA DE UMA NOVA PALAVRA */  
         P->cont++;  
         P = *A;  
       }  
     }  
   }  
 }  
 /**   A FUNÇÃO "tamanhoPilha" RETORNA A QUANTIDADE DE nodes DA pilha. ELA SERÁ USADA PARA AUXILIAR A FUNÇÃO "imprimePilhaReversa"   **/  
 int tamanhoPilha(pilha P)  
 {  
   int i;  
   node *Q;  
   Q = P;  
   for (i = 0; Q != NULL; Q = Q->prox)  
     i++;  
   return i;  
 }  
 /**   A FUNÇÃO "imprimePilhaReversa" IMPRIME OS VALORES DA pilha, DO ÚLTIMO PARA O PRIMEIRO ELEMENTO. ELA SERÁ USADA NA FUNÇÃO "imprimeArquivo"   **/  
 void imprimePilhaReversa(FILE *f_saida, pilha P)  
 {  
   int i, j;  
   node *Q;  
   for(j = tamanhoPilha(P); j>= 1; j--)  
   {  
     Q = P;  
     for(i = 1; i < j; i++)  
       Q = Q->prox;  
     fprintf(f_saida, "%c", Q->elem);  
   }  
   fprintf(f_saida, "\n");  
 }  
 /**   A FUNÇÃO RECURSIVA "imprimeArquivo" TOMA A árvore PRODUZIDA EM "lerArquivo" E USA UMA PILHA QUE É ALTERADA CONTINUAMENTE. ESSA pilha SERVE PARA GUARDAR AS PALAVRAS QUE SERÃO IMPRESSAS EM "saida.txt"   **/  
 void imprimeArquivo (FILE *f_saida, posicao A, pilha *P)  
 {  
   int i;  
   for(i = 0; i <= 25; i++)    /* PERCORRERÁ OS CAMPOS filhos[i], PARA ENCONTRAR POSSÍVEIS CONTINUAÇÕES PARA AS PALAVRAS */  
   {  
     if(A->filhos[i] != NULL)  /* SE HOUVER CONTINUAÇÃO, ELA É INSERIDA NA pilha */  
     {  
       node *Q;  
       Q = (node *)malloc(sizeof(node));  
       Q->elem = A->filhos[i]->letra;  
       Q->prox = *P;  
       *P = Q;  
       if(A->filhos[i]->cont != 0) /* SE HOUVER UMA PALAVRA ATÉ ALI, ELA SERÁ IMPRESSA EM "saida.txt" */  
       {  
         fprintf(f_saida, "%d ", A->filhos[i]->cont);  
         imprimePilhaReversa(f_saida, *P);  
       }  
       imprimeArquivo(f_saida, A->filhos[i], P);  /* E, RECURSIVAMENTE, ELA FARÁ ISSO COM TODOS OS SEUS FILHOS "NÃO-NULLOS" */  
     }  
   }  
   if(*P != NULL) /* AO FINAL, DESALOCA-SE O node CORRESPONDENTE À LETRA CORRESPONDENTE A ESTE ESCOPO DA FUNÇÃO */  
   {  
     node *D;  
     D = (*P)->prox;  
     free(*P);  
     *P = D;  
   }  
 }  
 int main()  
 {  
   arvore A;  A = NULL;  alocaArvore(&A);  
   pilha P;  P = NULL;  
   FILE *f_entrada, *f_saida;  
   f_entrada = fopen("entrada.txt", "r");  
   f_saida = fopen("saida.txt", "w");  
   lerArquivo(f_entrada, &A);  
   imprimeArquivo(f_saida, A, &P);  
   fclose(f_entrada);  
   fclose(f_saida);  
   return 0;  
 }  

Nenhum comentário:

Postar um comentário