Linha | Codigo |
001 | // Prof. Leo^nidas - http://www.matematica.br http://line.ime.usp.br |
002 | // MAC0122 - 2017/10/08 |
003 | |
004 | // Descricao: Transforma uma expressao aritmetica em outra equivalente em notacao pos-fixada |
005 | // notacao in-fixa : EXP op EXP |
006 | // notacao pos-fixa : EXP EXP op |
007 | // Interessante: a notacao pos-fixa dispensa parenteses! E.g. "(2+3)*4" fica como "2 3 + 4 *" |
008 | |
009 | // Ideia: Usar uma pilha apenas para operadores, a cada operando anotar na "pilha final" |
010 | // 1. Para cada caractere da expressao de entrada (notacao in-fixa e usando uma unica letra) - lendo da esquerda para a direita a "string" |
011 | // 2. Se caractere e' operando, insira na expressao pos-fixada |
012 | // 3. Senao |
013 | // 4. Se caractere e' '(', entao empilhe-o |
014 | // 5. Senao |
015 | // 6. Se caractere e' ')', entao desempilhe e insira-o na expressao pos-fixada, ate' encontrar '(' |
016 | // 7. Senao |
017 | // 8. Enquanto a pilha nao vazia e precedencia do operador atual <= precedencia do operador no topo da pilha, |
018 | // 9. desempilhe e insira-o na expressao pos-fixada |
019 | // 10. empilhe operador atual |
020 | // 11. Desempilhe os operadores que restaram na pilha de operadores, inserindo cada um na expressao pos-fixada e na "pilha final" |
021 | |
022 | #include <stdio.h> |
023 | #include <string.h> |
024 | #include <stdlib.h> |
025 | |
026 | #define MAX 256 |
027 | #define DEBUG 0 |
028 | |
029 | // Construtor do tipo "pilha" |
030 | typedef struct { |
031 | int topo; |
032 | unsigned comprimentoPilha; |
033 | int * dadosPilha; |
034 | } tipoPilha; |
035 | |
036 | // Estrutura registrando a pilha (usar uma para operadores e uma para a expressao em notacao pos-fixa) |
037 | tipoPilha * criarPilha (unsigned comprimento) { |
038 | tipoPilha * pilha = (tipoPilha*) malloc(sizeof(tipoPilha)); |
039 | if (!pilha) |
040 | return NULL; |
041 | pilha->topo = -1; |
042 | pilha->comprimentoPilha = comprimento; |
043 | pilha->dadosPilha = (int*) malloc(comprimento * sizeof(int)); |
044 | if (!pilha->dadosPilha) |
045 | return NULL; |
046 | return pilha; |
047 | } |
048 | |
049 | // Verifica se caractere e' operando (simplificacao: aceito apenas 'a' ate 'z' ou 'A' ate 'Z' |
050 | int ehOperando (char ch) { |
051 | return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'); |
052 | } |
053 | |
054 | // Devolve a precedencia de operador (se operador, senao -1): ^ => 2; * / => 1; + 0 => 0 |
055 | int ordemPrecedencia (char ch) { |
056 | switch (ch) { |
057 | case '+': case '-': return 0; |
058 | case '*': case '/': return 1; |
059 | case '^': return 2; |
060 | } |
061 | return -1; |
062 | } |
063 | |
064 | void examinaPilha (int *vetor, int comp) { // examine pilha de 0 ate o topo = 'comp' |
065 | int i; |
066 | if (DEBUG) printf("Examina pilha de operadores: #pilha = %d\n ", comp); |
067 | for (i=0; i<=comp; i++) { |
068 | printf("%c, ", vetor[i]); |
069 | } |
070 | printf("\n"); |
071 | } |
072 | |
073 | int pilhaVazia (tipoPilha* pilha) { // create |
074 | return (pilha->topo == -1); |
075 | } |
076 | char examinaTopoPilha (tipoPilha* pilha) { // examina |
077 | //S if (pilha==NULL || pilha->topo==-1) { printf("examinaTopoPilha: pilha vazia! topo=%d\n", pilha->topo); return 255; } // pilha vazia => devolva maior ASCII |
078 | return pilha->dadosPilha[pilha->topo]; |
079 | } |
080 | char desempilha (tipoPilha* pilha) { // desempilha |
081 | if (!pilhaVazia(pilha)) |
082 | return pilha->dadosPilha[pilha->topo--] ; |
083 | return '$'; |
084 | } |
085 | void empilha (tipoPilha *pilha, char c, int aux) { // empilhe |
086 | if (c == ' ') { printf("empilha: ERRO branco! topo=%d\n", pilha->topo); return; } |
087 | pilha->dadosPilha[++pilha->topo] = c; |
088 | if (DEBUG) printf(" (%d: %d) c=%c ", aux, pilha->topo, c); |
089 | } |
090 | |
091 | // Insere operando ou operador para compor uma pilha completa em notacao pos-fixada |
092 | void insereItemExp (char *str, char c, int *k, tipoPilha *pilha) { |
093 | if (c == ' ') return; |
094 | str[++*k] = c; |
095 | empilha(pilha, c, 3); |
096 | } |
097 | |
098 | // Converte um expressao composta por operadores com uma unica letra (em notacao in-fixa) em equivalente pos-fixa |
099 | int infixa2PosFixada (char* strExpIn, char* strExpPos, tipoPilha **pilhaOriginal, tipoPilha **pilhaFinal) { |
100 | tipoPilha *pilha, *pilhaAux; // apenas para eliminar um apontamento '*' |
101 | int i, k; char c; |
102 | |
103 | // Cria pilha usando vetor, de tamanho comprimentoPilha igual ao tamanho da expressao |
104 | pilha = criarPilha(strlen(strExpIn)); // esta sera' a "pilha de operadores" |
105 | pilhaAux = criarPilha(strlen(strExpIn)); // esta sera' a "pilha final" (com elementos na ordem da notacao pos-fixa) |
106 | *pilhaOriginal = pilha; |
107 | if (DEBUG) printf("infixa2PosFixada: pilhaOriginal->comprimentoPilha=%d\n", (*pilhaOriginal)->comprimentoPilha); |
108 | |
109 | for (i = 0, k = -1; strExpIn[i]; i++) { // Examina cada caractere (item lexico) |
110 | c = strExpIn[i]; |
111 | if (ehOperando(c)) { // Caractere atual e' operando: solte-o |
112 | insereItemExp(strExpPos, c, &k, pilhaAux); // Insere na "pilha final" e na expressao pos-fixa |
113 | } |
114 | else |
115 | if (c == '(') { // Caractere atual e' '(': empilhe-o |
116 | empilha(pilha, c, 1); |
117 | if (DEBUG) { printf("empilha: "); examinaPilha(pilha->dadosPilha, pilha->topo); } |
118 | } |
119 | else |
120 | if (c == ')') { // Caractere atual e' ')': desempilha e desempilhe ate encontrar um '(' |
121 | while (!pilhaVazia(pilha) && examinaTopoPilha(pilha) != '(') { |
122 | insereItemExp(strExpPos, desempilha(pilha), &k, pilhaAux); // Insere na "pilha final" e na expressao pos-fixa |
123 | if (DEBUG) { printf("desempilha: "); examinaPilha(pilha->dadosPilha, pilha->topo); } |
124 | } |
125 | if (!pilhaVazia(pilha) && examinaTopoPilha(pilha) != '(') |
126 | return -1; // expressao invalida!? |
127 | else { |
128 | desempilha(pilha); |
129 | if (DEBUG) { printf("desempilha: "); examinaPilha(pilha->dadosPilha, pilha->topo); } |
130 | } |
131 | } // if (c == ')') |
132 | else { // Caractere atual e' operador: desempilhe enquanto precedencia dele for menor que do topo da pilha |
133 | while (!pilhaVazia(pilha) && ordemPrecedencia(c) <= ordemPrecedencia(examinaTopoPilha(pilha))) { |
134 | insereItemExp(strExpPos, desempilha(pilha), &k, pilhaAux); // Insere na "pilha final" e na expressao pos-fixa |
135 | if (DEBUG) { printf("desempilha: "); examinaPilha(pilha->dadosPilha, pilha->topo); } |
136 | } |
137 | empilha(pilha, c, 2); |
138 | if (DEBUG) { printf("empilha: "); examinaPilha(pilha->dadosPilha, pilha->topo); } |
139 | } |
140 | } // for (i = 0, k = -1; strExpIn[i]; i++) |
141 | |
142 | if (DEBUG) { printf("O que sobou na pilha k=%d: ", k); examinaPilha(pilha->dadosPilha, pilha->topo); } |
143 | |
144 | // desempilha todos os operadores que sobraram na pilha |
145 | while (!pilhaVazia(pilha)) { |
146 | insereItemExp(strExpPos, c = desempilha(pilha), &k, pilhaAux); // Insere na "pilha final" e na expressao pos-fixa |
147 | if (DEBUG) { printf(" insere %d, k=%d: %c\n", pilha->topo, k, c); } |
148 | } |
149 | strExpPos[++k] = '\0'; // Finaliza "string" da expressao em notacao pos-fixa |
150 | pilhaAux->comprimentoPilha = k; // Agora temos o tamanho da expressao em 'pos-fixa' (sem os parenteses) |
151 | |
152 | *pilhaFinal = pilhaAux; // Pilha final |
153 | |
154 | } // int infixa2PosFixada(char* strExpIn, char* strExpPos, tipoPilha **pilhaOriginal, tipoPilha **pilhaFinal) |
155 | |
156 | // Programa principal |
157 | int main () { |
158 | tipoPilha *pilha, *pilhaFinal; |
159 | char strExpPos[MAX]; // Para a expressao final em notacao pos-fixa |
160 | int i; |
161 | char *strExp, |
162 | strExpressao[][MAX] = { // Exemplos fixos |
163 | "a+b*c", |
164 | "(a+b)*c", |
165 | "a+b*c^d", |
166 | "a+b*c^d-e", |
167 | "a+b*c^d-e*f", |
168 | "a+b*c^d-e*f+g", |
169 | "a+b*c^d-e*f+g-h", |
170 | "a+b*c^d-e*f+g-h/i", |
171 | "a+(b*c)^d-e*f+g-h/i", |
172 | "a+(b*c)^(d-e)*f+g-h/i" |
173 | }; |
174 | |
175 | for (i=0; i<10; i++) { |
176 | //printf("Digite uma expressao em notacao in-fixa: "); //D Se desejar digitar... |
177 | //scanf("%s", strExp); |
178 | strExp = strExpressao[i]; |
179 | infixa2PosFixada(strExp, strExpPos, &pilha, &pilhaFinal); |
180 | |
181 | printf("Expressao original: %s\n", strExp); |
182 | printf("Expressao final : %s\n", strExpPos); |
183 | |
184 | printf(" : "); |
185 | examinaPilha(pilhaFinal->dadosPilha, pilhaFinal->topo); |
186 | } |
187 | printf("\n"); |
188 | |
189 | return 0; |
190 | } |