#include "in2pos.h" /* Funções que não estão na libdados */ char *LeExpressao(){ /* Lê expressao em notação entre-fixa com parênteses. */ char *e; e = (char *) calloc(TAMEXP,sizeof(char )); fscanf(stdin,"%s",e); return(e); } void GravaExpressao(char *e){/* Grava expressão em notação pós-fixa. */ fprintf(stdout,"%s\n",e); } bool Balanceada(char *e) { Pilha *p; bool stat = false; int i; if (e == NULL) comAviso(AVS1,"Balanceada"); else { p = pilCria(); i=0; stat=true; while ((e[i] != '\0') && (stat==true)) { switch(e[i]) { case '(': { pilEmpilha(&p,(int)'('); }break; case ')': { if (! pilVazia(p)) if (pilTopo(p) == '(') pilDesempilha(&p); else stat=false; else stat=false; } break; } i++; } if (! pilVazia(p)) stat = false; } pilDestroi(&p); return stat; } /* Recebe uma sequencia de caracteres contendo uma expressao em infixa, e retorna uma sequencia contendo uma expressao posfixa. A sequencia infixa eh composta de letras minusculas e os simbolos (,),+,-,*,/ e ^. Serao usados apenas operadores binarios, e todas as expressoes dos testes estarao cercadas por parenteses (com a possivel excessao da mais externa). Ainda assim, eh um exercicio interessante tentar implementar esta funcao para que crie a expressao pos-fixa por regras de prioridade e com operadores unarios tambem. */ char *EntreParaPosFixa(char *e){ Pilha *p, *bal=NULL; char *ne = NULL; int i; if (e == NULL) comAviso(AVS1,"EntreParaPosFixa"); else { if (! Balanceada(e)) comAviso("Expressao 'e' nao balanceada","EntreParaPosFixa"); else { if ((ne = (char *) calloc(TAMEXP,sizeof(char ))) == NULL) comTrataErro(MSG1,"EntreParaPosFixa"); p = pilCria(); bal = pilCria(); for (i=0; e[i] != '\0'; i++) { switch (e[i]) { case '(': case '+': case '-': case '*': case '/': case '^': { pilEmpilha(&bal,(int) e[i]); } break; case ')': { while (pilTopo(bal) != '(') pilEmpilha(&p, pilDesempilha(&bal)); /* Acrescenta o operador apos os operarandos */ pilDesempilha(&bal); /* Desempilha o '(' */ } break; default: { pilEmpilha(&p, (int) e[i]); } break; } } if (!pilVazia(bal)) /* Sobrou um operador. Caso que nao comecou com parenteses*/ pilEmpilha(&p, pilDesempilha(&bal)); /* Agora desempilha e grava em string. MAS ATENCAO, tudo esta na ordem INVERSA! Portanto vamos desempilhar e empilhar em outra pilha para colocarmos na ordem certa. */ while (!pilVazia(p)) pilEmpilha(&bal, pilDesempilha(&p)); for (i=0; ! pilVazia(bal); i++) ne[i] = (char) pilDesempilha(&bal); pilDestroi(&bal); pilDestroi(&p); } } return (ne); } /* Funcao recursiva para executar operacoes numa pilha com sequencia pos fixa invertida */ int OperaPilha(Pilha **p, int vars[]) { int total=0; int operador, operando[2]; operador = pilDesempilha(p); switch (operador) { case '+': case '-': case '*': case '/': case '^': break; default: return vars[0]; /* caso soh for 1 elemento, sem operacao */ break; } /* operando[0] */ operando[0] = pilDesempilha(p); switch(operando[0]) { case '+': case '-': case '*': case '/': case '^': pilEmpilha(p,operando[0]); operando[0] = OperaPilha(p, vars); break; default: operando[0] = vars[operando[0]-'a']; /* Substitui pelo valor */ break; } /* operando[1] */ operando[1] = pilDesempilha(p); switch(operando[1]) { case '+': case '-': case '*': case '/': case '^': pilEmpilha(p,operando[1]); operando[1] = OperaPilha(p, vars); break; default: operando[1] = vars[operando[1]-'a']; /* Substitui pelo valor */ break; } /* Faz a operacao */ switch(operador) { case '+': total = operando[1]+operando[0]; break; case '-': total = operando[1]-operando[0]; break; case '*': total = operando[1]*operando[0]; break; case '/': /* Supoe que operando[0] != 0 */ total = operando[1]/operando[0]; break; case '^': total = pow(operando[1],operando[0]); break; } return total; } /* recebe uma sequencia de caracteres representando uma expressao em posfixa, contendo letras minusculas e os sinais +,-,*,/,^. Deve ler um valor inteiro da entrada padrao para cada letra minuscula, e calcular o valor da expressao posfixa, usando esse resultado como valor de retorno. A divisao (/) eh a divisao inteira. */ int AvaliaExpressao(char *e) { int vars[27]; bool vars_mask[27]; int i; int total=0; Pilha *p; p = pilCria(); for (i=0; i < 27; i++, vars_mask[i]=false); for (i=0; e[i]!='\0'; i++) { switch (e[i]) { case '+': case '-': case '*': case '/': case '^': break; default: if ( ! vars_mask[e[i] -'a']) { vars_mask[e[i] - 'a'] = true; scanf("%i", &vars[e[i] - 'a']); } break; } pilEmpilha(&p, (int)e[i]); } total = OperaPilha(&p, vars); pilDestroi(&p); return total; }