Expressões algébricas são combinações legais de operandos e operadores. Operandos são quantidades nas quais as operações matemáticas são realizadas. Os operandos podem ser variáveis, como x, y, z ou constantes como 5, 1.99, 3.1415926535. Um operador é um símbolo que indica a aplicação de uma operação entre os operandos. Alguns operadores familiares: +, -, *, /, ^.
Expressões algébricas podem ser representadas usando três notações diferentes:
Uma árvore é uma forma natural de representar a estrutura de uma expressão. Abaixo, temos a expressão infixa 1 + 2 * 3 representada através de uma árvore de forma não ambígua:
+ / \ 1 * / \ 2 3
Os nós de uma árvore de expressão podem ser operandos, como constantes ou variáveis, ou operadores. Operandos são sempre folhas, e operadores nós intermediários. (Neste laboratório todos os operadores são binários, isto é, aceitam exatamente dois operandos).
O objetivo deste laboratório é implementar funções para manipular e avaliar expressões algébricas. Um programa principal irá testar as funções implementadas através de um interpretador simples na linha de comando, e poderá armazenar até 5 árvores de expressões.
Os comandos disponibilizados pelo interpretador serão:
Os comandos do interpretador já vêm implementados e fazem uso da biblioteca de manipulação de expressões. Apenas será necessário implementar as funções da biblioteca, no arquivo expressoes.c.
As funções, juntamente com suas descrições se encontram no arquivo expressoes.c. Além das funções fornecidas é encorajado o uso de funções auxiliares extras para melhorar a organização do código.
Para ler cada um dos elementos que compõem uma expressão será fornecida uma função auxiliar que fornece separadamente e em ordem cada um dos elementos de uma cadeia contendo uma expressão. Essa função encontra-se nos arquivos atomos.h e atomos.c juntamente com um exemplo de uso.
O programa principal (interpretador de comandos) lê os dados da entrada padrão, portanto para executar os testes a partir de um arquivo de entrada é necessário redirecionar o arquivo para a entrada padrão do programa e eventualmente redirecionar a saída padrão do programa para um arquivo. Assim:
./principal < arqN.in > arqN.out
O arquivo de saída arqN.out pode ser posteriormente comparado com o arquivo de resposta esperado (arqN.res) visualmente ou através do comando diff:
diff arqN.out arqN.res
Será fornecido também um arquivo Makefile para facilitar a compilação do programa e execução dos testes.
Por exemplo, a seguinte entrada:
inpos a*(b+2) arv 0 a b 2 + * in 0 pre 0 pos 0 avalia 0 a=10 b=5.55 libera 0 sair
Gera a seguinte saída:
Posfixa: a b 2 + * Árvore de: a b 2 + * a * b + 2 Infixa: a * ( b + 2 ) Prefixa: * a + b 2 Posfixa: a b 2 + * Resultado: 75.5
Os testes estarão classificados em 4 grupos, que testam as funções em ordem crescente de dificuldade.