Sandor Ferreira da Silva 22 de Julho de 2014 Resumo Fundamentando-se na teoria das estruturas de dados pilha e arvore, este trabalho tem como arquivo nal um interpretador de fun c oes aritmeticas em p os-ordem. Com auxlio de um dicion ario contendo os principais ope- radores matematicos, o programa le operando por operando e realiza a operac ao correspondente quando encontra um operador. Alem de exibir o resultado da opera c ao, o interpretador tambem e capaz de converter a express ao para as chamadas Pre-Ordeme InOrdemcom auxlio de uma arvore bin aria. 1 1 Introducao O conhecimento de linguagens de programa cao por si so nao capacita progra- madores e necessario saber usa-las de maneira eciente. O projeto de um programa engloba a fase de identicacao das propriedades dos dados e carac- tersticas funcionais. Uma representacao adequada dos dados, tendo em vista as funcionalidades que devem ser atendidas, constitui uma etapa fundamental para a obten cao de programas ecientes e conaveis. A linguagem C e dita uma linguagens convencional, projetad a partir dos elementos fundamentais da arquitetura de von Neuman, que serve como base para praticamente todos os computadores em uso. Para programar em uma linguagem convencional, precisamos de alguma maneira especicar as areas de memoria em que os dados com que queremos trabalhar estao armazenados e, frequentemente, considerar os enderecos de memoria em que os dados se situam, o que faz com que o processo de programacao envolva detalhes adicionais, que podem ser ignorados quando se programa em uma linguagem como Scheme. Em compensa cao, temos um maior controle da maquina quando utilizamos uma lin- guagem convencional, e podemos fazer programas melhores, ou seja, menores e mais rapidos. 2 Objetivos Este trabalho tem como objetivo primario a utiliza cao das estruturas de dados Pilhae
Arvorena elaboracao de programas de complexidade superior aos
elaborados em sala. Como objetivos secundarios, o trabalho procura incentivar boas praticas de programacao, como a utiliza cao correta do comando free();e da ferramenta valgrind, permitindo que nao haja extrapolacao de memoria por parte do pro- grama. Por m, mas nao menos importante, e objetivo deste trabalho, tambem, com- plementar o conte udo ministrado em sala, levando os alunos a aplicarem os conhecimentos ali obtidos. 2 3 Metodologia Durante as etapas iniciais do trabalho, a ideia era de implementar um programa que lesse o arquivo de entrada expressao por expressao - fosse ela um operando ou um operador - e colocando-as em uma pilha ate que se chegasse ao m do arquivo. ` A medida que o codigo come cou a ser elaborado, percebemos que este realizaria esfor co repetitivo para a analise da parte 1 e da parte 2 do trabalho. Com isso, chegamos `a conclusao de que poderamos agrupar ambas as partes em apenas um raciocnio, reduzindo o tamanho da codigo e aumentando a sua eciencia. 3.1 Parte 1: Bibliotecas Para o programa, utilizamos apenas 4 bilbiotecas: STDIO.H: Utilizada para ler as informacoes contidas no arquivo de entrada e para printar na tela os resultados. STDLIB.H: Utilizada para conversar strings em n umeros pelo comando atof() e para permitir a aloca cao e a liberacao de memoria dinamicamente. STRING.H: Utilizada na copia de strings e na comparacoes entre strings. MINIPS.H: Biblioteca contendo as deni coes das structs e o prototipo de todas as fun coes que foram utilizadas no programa. 3.2 Parte 2: Programa Principal Embora curto, o programa principal do codigo apresenta relativa complexidade, principalemente devido `as funcoes auxiliares do qual ele depende. Inicialmente, inicializa-se o dicionario, inserindo nele todas as fun coes que serao utilizadas para o programa, o que inclui a funcao de soma, subtra cao, multi- placao, divisao, oposicao e resultado. Feito isso, abre-se o arquivo de entrada e, a partir dele, le-se termo a termo ate que se chegue ao m do arquivo. Ao ler uma expressao, o programa varre o dicionario ate encontrar a expressao correspondente, executando entao a operacao correspondente com os operandos abaixo dela na pilha. Com isso, os operandos e operadores sao retirados da pilha um a um ate que se tenha o resultado nal da opera cao, quando a mesma sera mostrada na tela. Paralelamente a isso, o programa vai inserindo os elementos da expressao em uma arvore binaria, na qual cada no corresponde a um operador e seus lhos correspondem aos operandos. 3 3.3 Parte 3: Func oes Auxiliares Buscamos modularizar nosso codigo o maximo possvel a m de facilitar a com- preensao do mesmo, alem de deixar o codigo mais limpo e mais pratico na hora de modica-lo. Para isso, foram criadas diversas fun coes. PUSH DICTIONARY: Insere um elemento na ultima posi cao na pilha do dicionario. FUNC ADD: Realiza a soma de dois elementos. Neste caso, dos dois elementos antecessores na pilha. FUNC MUL: Realiza a multiplicacao de dois elementos. Neste caso, dos dois elementos antecessores na pilha. FUNC SUB: Realiza a subtracao de dois elementos. Neste caso, dos dois elementos antecessores na pilha. FUNC NEG: Retorna o oposto do n umero. Neste caso, do elemento an- tecessor na pilha. FUNC DIV: Realiza a divisao entre dois n umeros. Neste caso, dos dois elementos antecessores na pilha. FUNC RESULT: Imprime na tela o resultado da operacao, assim como as expressoes correspondentes em Pre-Ordem, In-Ordem e Pos-Ordem. PUSHEXPRESSION: Insere uma expressao na ultima posi cao da pilha. POPEXPRESSION: Retira o ultimo elemento da pilha. OPENFILE: Abre o arquivo de entrada de dados. PUSHBANKN: Insere um n umero (operando) na arvore. PUSHBANKD: Insere um elemento qualquer na arvore, podendo este ser um operando ou um operador. PUSHBANKO: Insere um operador na arvore. POPBANK: Remove um no da arvore. PRINTFTREEIN: Imprime a arvore em questao em In-Ordem (operando- operador-operando). PRINTFTREEPRE: Imprime a arvore em questao em Pre-Ordem (operador- operando-operando). PRINTFTREEPOS: Imprime a arvore em questao em Pos-Ordem (operando- operando-operador). 4 4 Analise e Resultados Finais Utilizando o novo raciocnio (de unir ambas as partes do trabalho em uma so), obteve-se um resultado muito melhor do que o esperado anteri- ormente. De incio, o codigo contou com, aproximadamente, 200 linhas, o que e um n umero razoavel considerando o nvel de complexidade do tra- balho. Alem disso, a utiliza cao tanto da pilha como da arvore permitiu uma com- preensao ampla a respeito das estruturas de dados, de sua utilizacao na pratica e das facilidades que cada uma traz para cada problema. Ao utilizarmos a pilha para as expressoes, notou-se a praticidade em sua utilizacao para situacoes lineares - em que cada elemento depende do an- terior de alguma forma. Com a pilha, e possvel inserir, remover e analisar elementos sem maior diculdade. Utilizando a arvore para as notacoes pre, in e pos-xadas, vericou a pra- ticidade ao se utilizar esta estrutura de dados para grupos que possuem elementos com um mesmo nvel/grau de parentesco. Separando os operan- dos e os operadores em seus respectivos nveis e nos, foi possvel gera-las nos tres tipos de notacoes sem maiores problemas. Por m, mas nao menos importante, nota-se a importancia da aloca cao e libera cao dinamica da memoria. Utilizando a ferramenta do VALGRIND, vericou-se que nenhum bloco de memoria continuou preenchido apos a execucao do programa, o que o classica como um programa de qualidade. 5 5 Referencias Bibliogracas Autor Desconhecido.
Arvores Binarias. Disponvel em: http://www. inf.puc-rio.br/ ~ inf1007/material/slides/arvoresbinarias.pdf. Acesso em 15/07/2014. Autor Desconhecido. Estrutura de Dados -
Arvores. Disponvel em: http://www.ic.unicamp.br/ ~ ra069320/PED/MC102/1s2008/Apostilas/ Cap11.pdf. Acesso em 15/07/2014. W. CELES, R. CERQUEIRA, J. L. RANGEL. Introducao a Estru- turas de Dados. Editora Campus Elsevier, 2004. 6