Queremos saber si una cadena posee paréntesis, llaves y corchetes correctamente equilibrados. La regla clave es que cada apertura debe cerrarse en el orden inverso al que fue abierta, lo que convierte a la pila en la herramienta perfecta.
Consideraremos tres pares:
() para paréntesis.[] para corchetes.{} para llaves.Es sencillo ampliar la lista si la aplicación requiere otros delimitadores (por ejemplo, <> en lenguajes propios).
. ), se desapila.Usaremos una pila basada en arrays para simplicidad. El siguiente snippet funciona como utilidad general:
#include <stdio.h>
#include <string.h>
#define STACK_MAX 256
typedef struct {
char datos[STACK_MAX];
int top;
} StackChar;
void stack_init(StackChar *s) { s->top = 0; }
int stack_is_empty(const StackChar *s) { return s->top == 0; }
int stack_push(StackChar *s, char c) {
if (s->top == STACK_MAX) return 0;
s->datos[s->top++] = c;
return 1;
}
int stack_pop(StackChar *s, char *c) {
if (stack_is_empty(s)) return 0;
*c = s->datos[--s->top];
return 1;
}
static int coincide(char apertura, char cierre) {
return (apertura == '(' && cierre == ')') ||
(apertura == '[' && cierre == ']') ||
(apertura == '{' && cierre == '}');
}
int validar_parentesis(const char *texto) {
StackChar stack;
stack_init(&stack);
for (size_t i = 0; i < strlen(texto); ++i) {
char c = texto[i];
if (c == '(' || c == '[' || c == '{') {
if (!stack_push(&stack, c)) return 0;
} else if (c == ')' || c == ']' || c == '}') {
char apertura;
if (!stack_pop(&stack, &apertura) || !coincide(apertura, c)) {
return 0;
}
}
}
return stack_is_empty(&stack);
}
int main(void) {
const char *tests[] = {
"(a + b) * (c + d)",
"([{}])",
"( [ ) ]",
"funcion(x[2] + arr{1})"
};
for (size_t i = 0; i < sizeof(tests)/sizeof(tests[0]); ++i) {
printf("%s => %s\n", tests[i], validar_parentesis(tests[i]) ? "OK" : "ERROR");
}
return 0;
}
Al ejecutar el programa, las cadenas equilibradas imprimirán OK, mientras que las erróneas mostrarán ERROR.
Validar paréntesis es un clásico de entrevistas para medir:
Una extensión frecuente es soportar expresiones completas con operadores, distintos tipos de llaves o comentarios. Practicar este ejemplo permite dominar la pila antes de abordar ejercicios más complejos.