Nesta aula vamos ver uma aplicação da estrutura de dados pilha aqui no nosso Curso de Programação C. Vamos ver como verificar se uma expressão matemática está mal formada com o auxilio de uma estrutura PILHA.
Normalmente uma expressão matemática pode ser composta por caracteres como parênteses ( () ), colchetes ( [] ) e chaves ( {} ). Estes caracteres ajudam a determinar a ordem em que as operações podem ser realizadas. Para cada caracter de abertura é necessário um de fechamento formando o par.
A ideia aqui é elaborar um pequeno programa em C que, dada uma expressão digitada no teclado, ele seja capaz de dizer se a expressão está bem formada ou não.
No início pode parecer complicado, mas não é, desde claro que você tenha entendido como trabalhar com a estrutura pilha. A ideia básica aqui é, percorrer a expressão procurando pelos caracteres mencionados acima. Ao encontrar qualquer um dos três, vamos avaliar se é de abertura ou de fechamento. Se for de abertura, então ele será inserido na pilha. Se for de fechamento, então iremos remover o elemento do topo da pilha, que precisa obrigatoriamente fazer par com o elemento de fechamento, caso contrário a expressão está mal formada. Observe a expressão a seguir:
3 * [(5 – 2) / 5]
Será empilhado um [ e, sem seguida um (. Ao encontrarmos o ), será desempilhado o topo da pilha, formando o par (), e ao encontrar o ], será desempilhado novamente o topo da pilha, formando o par []. Como ao terminar a expressão a pilha estará vazia, então podemos afirmar que a expressão está bem formada.
Este processo descrito acima é realizado pela função a seguir:
int identifica_formacao(char x[]){ int i = 0; No *remover, *pilha = NULL; // percorre a string (expressão digitada) até o fim while(x[i] != '\0'){ // se for um caracter de abertura, empilha if(x[i] == '[' || x[i] == '(' || x[i] == '{'){ pilha = empilhar(pilha, x[i]); imprimir(pilha); } // se for um caracter de fechamento, desempilha e verifica se formam par else if(x[i] == ']' || x[i] == ')' || x[i] == '}'){ remover = desempilhar(&pilha); // se não formar um par, então a expressão está mal formada if(forma_par(x[i], remover->caracter) == 0){ printf("\tEXPRESSAO MAL FORMADA!\n"); return 1; // expressao está mal formada } free(remover); } i++; } imprimir(pilha); // ao final, se a pilha não estiver vazia significa que a expressão está mal formada if(pilha){ printf("\tExpressao mal formada!\n"); return 1; } else{ printf("\tEXPRESSAO BEM FORMADA!\n"); return 0; } }
* Esta função tem um problema. Teste ela com esta expressão 3 * (5 – 2) / 5] e tende descobrir qual o problema. Nas aulas seguintes trarei a solução.
A função a seguir, utilizada na função anterior, recebe dois caracteres e verifica se formam um par ou não.
int forma_par(char f, char d){ switch(f){ case ')': if(d == '(') return 1; // bem formada else return 0; // mal formada break; case ']': if(d == '[') return 1; // bem formada else return 0; // mal formada break; case '}': if(d == '{') return 1; // bem formada else return 0; // mal formada break; } }
Código completo em C para verificar se uma expressão está bem formada ou não com uma estrutura de dados pilha
/* Aula 231: Como descobrir se uma expressão matemática está mal formada? Código escrito por Wagner Gaspar Julho de 2021 */ typedef struct no{ char caracter; struct no *proximo; }No; No* empilhar(No *pilha, char valor){ No *novo = malloc(sizeof(No)); if(novo){ novo->caracter = valor; novo->proximo = pilha; return novo; } else printf("\tErro ao alocar memoria!\n"); return NULL; } No* desempilhar(No **pilha){ No *remover = NULL; if(*pilha){ remover = *pilha; *pilha = remover->proximo; } else printf("\tPilha vazia\n"); return remover; } void imprimir(No *pilha){ printf("\n\tPILHA\n"); while(pilha){ printf("\t%c\n", pilha->caracter); pilha = pilha->proximo; } printf("\tFIM PILHA\n\n"); } int forma_par(char f, char d){ switch(f){ case ')': if(d == '(') return 1; // bem formada else return 0; // mal formada break; case ']': if(d == '[') return 1; // bem formada else return 0; // mal formada break; case '}': if(d == '{') return 1; // bem formada else return 0; // mal formada break; } } int identifica_formacao(char x[]){ int i = 0; No *remover, *pilha = NULL; while(x[i] != '\0'){ if(x[i] == '[' || x[i] == '(' || x[i] == '{'){ pilha = empilhar(pilha, x[i]); imprimir(pilha); } else if(x[i] == ']' || x[i] == ')' || x[i] == '}'){ remover = desempilhar(&pilha); if(forma_par(x[i], remover->caracter) == 0){ printf("\tEXPRESSAO MAL FORMADA!\n"); return 1; // expressao está mal formada } free(remover); } i++; } imprimir(pilha); if(pilha){ printf("\tExpressao mal formada!\n"); return 1; } else{ printf("\tEXPRESSAO BEM FORMADA!\n"); return 0; } } int main(){ char exp[50]; printf("\tDigite um expressao: "); scanf("%49[^\n]", exp); printf("\nExpressao: %s\nRetorno: %d\n", exp, identifica_formacao(exp)); }