Pilhas em C: Uma Abordagem Prática com Duas Pilhas de Caracteres: Exemplo De Programa Em C Com 2 Pilhas Em Char
Exemplo De Programa Em C Com 2 Pilhas Em Char – Este artigo apresenta uma implementação em C de duas pilhas utilizando arrays, abordando desde conceitos básicos de estruturas de dados até o tratamento de erros e considerações de eficiência. Exploraremos a aplicação prática dessas pilhas na verificação de palíndromos, demonstrando a versatilidade e utilidade dessa estrutura de dados fundamental em programação.
Introdução à Estrutura de Dados Pilha

Uma pilha é uma estrutura de dados linear que segue o princípio LIFO (Last-In, First-Out), ou seja, o último elemento inserido é o primeiro a ser removido. Imagine uma pilha de pratos: você só pode adicionar um prato no topo e remover o prato do topo. As pilhas são amplamente utilizadas em diversas aplicações, como gerenciamento de memória, avaliação de expressões aritméticas, e controle de fluxo em programas, entre outras.
A principal diferença entre pilhas e filas reside no mecanismo de acesso aos elementos. Enquanto as pilhas seguem o princípio LIFO, as filas seguem o princípio FIFO (First-In, First-Out), similar a uma fila de espera: o primeiro elemento inserido é o primeiro a ser removido.
Em C, uma pilha pode ser implementada utilizando arrays. Um array é alocado para armazenar os elementos da pilha, e um índice acompanha o topo da pilha, indicando a posição do último elemento inserido. Operações como inserção (push) e remoção (pop) são realizadas nesse array, mantendo a ordem LIFO.
Implementação de Duas Pilhas em Char
O programa a seguir demonstra a criação e manipulação de duas pilhas de caracteres utilizando um único array. Um índice controla o topo de cada pilha, permitindo que ambas compartilhem o mesmo espaço de memória sem sobreposição. O limite de tamanho do array é definido, garantindo a prevenção de estouro de pilha (stack overflow).
A tabela a seguir ilustra o estado das pilhas após cada operação. Observe que o tamanho máximo do array é considerado, e mensagens de erro são exibidas caso ocorra estouro ou vazamento de pilha.
Operação | Pilha 1 | Pilha 2 | Status |
---|---|---|---|
Push ‘A’ na Pilha 1 | A | Pilha 1: Não Cheia, Pilha 2: Vazia | |
Push ‘B’ na Pilha 1 | AB | Pilha 1: Não Cheia, Pilha 2: Vazia | |
Push ‘X’ na Pilha 2 | AB | X | Pilha 1: Não Cheia, Pilha 2: Não Vazia |
Pop da Pilha 1 | A | X | Pilha 1: Não Vazia, Pilha 2: Não Vazia |
Pop da Pilha 2 | A | Pilha 1: Não Vazia, Pilha 2: Vazia | |
Push ‘C’ na Pilha 1 (limite próximo) | AC | Pilha 1: Não Cheia, Pilha 2: Vazia | |
Push ‘D’ na Pilha 1 (pilha cheia!) | AC | Erro: Pilha 1 Cheia |
Operações com as Pilhas: Push e Pop
As funções push
e pop
são fundamentais para a manipulação das pilhas. A função push
adiciona um elemento ao topo da pilha, enquanto a função pop
remove e retorna o elemento do topo. Ambas as funções incluem tratamento de erros para situações de pilha cheia ( push
) e pilha vazia ( pop
).
Funções auxiliares, pilha_cheia
e pilha_vazia
, verificam o estado das pilhas, facilitando o gerenciamento de erros.
Exemplo de Uso: Verificação de Palíndromo
Um palíndromo é uma sequência que pode ser lida da mesma forma de trás para frente, como “arara” ou “ovo”. Este exemplo demonstra como usar duas pilhas para verificar se uma string é um palíndromo. A string é inserida pelo usuário, e cada caractere é empilhado em uma das pilhas. Em seguida, os caracteres são desempilhados e comparados, verificando se são iguais.
Se todos os caracteres corresponderem, a string é um palíndromo.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAX_TAM 100
// ... (implementação das funções push, pop, pilha_cheia, pilha_vazia) ...
int main()
char str[MAX_TAM];
char pilha1[MAX_TAM], pilha2[MAX_TAM];
int topo1 = -1, topo2 = -1;
printf("Digite uma string: ");
fgets(str, MAX_TAM, stdin);
str[strcspn(str, "\n")] = 0; // remove o \n do fgets
int len = strlen(str);
for (int i = 0; i < len; i++)
char c = tolower(str[i]); //ignora maiúsculas/minúsculas
if (isalpha(c)) // considera apenas letras
push(pilha1, &topo1, c);
push(pilha2, &topo2, c);
int palindromo = 1;
while (topo1 != -1)
if (pop(pilha1, &topo1) != pop(pilha2, &topo2))
palindromo = 0;
break;
if (palindromo)
printf("'%s' é um palíndromo.\n", str);
else
printf("'%s' não é um palíndromo.\n", str);
return 0;
Tratamento de Erros e Exceções, Exemplo De Programa Em C Com 2 Pilhas Em Char
O tratamento de erros é crucial para a robustez do programa. Situações como estouro de pilha ( stack overflow
), quando se tenta adicionar um elemento a uma pilha cheia, e vazamento de pilha ( stack underflow
), quando se tenta remover um elemento de uma pilha vazia, devem ser tratadas adequadamente. Mensagens de erro claras e informativas devem ser exibidas ao usuário, indicando o tipo de erro e a ação necessária.
Diferentes estratégias de tratamento de erros podem ser empregadas, como o uso de códigos de retorno, exceções (se a linguagem o permitir), ou a verificação explícita das condições de erro antes de cada operação.
Considerações sobre Eficiência
A complexidade de tempo das operações push
e pop
em uma pilha implementada com arrays é O(1), ou seja, constante. Isso significa que o tempo de execução dessas operações não depende do tamanho da pilha. A complexidade de espaço é O(n), onde n é o tamanho máximo da pilha, pois o array precisa alocar espaço para todos os elementos.
Comparando com outras implementações, como listas encadeadas, a implementação com arrays oferece melhor desempenho para operações de acesso aleatório, mas a lista encadeada permite um tamanho dinâmico, enquanto o array tem tamanho fixo.
Utilizar arrays para implementar pilhas apresenta vantagens como simplicidade e eficiência para operações de push e pop. No entanto, a desvantagem principal é a alocação de memória estática, o que limita o tamanho da pilha.
Extensões e Melhorias

Para tornar o programa mais robusto, a adição de funcionalidades como a verificação de tamanho de entrada antes da alocação de memória e a implementação de uma pilha com tamanho dinâmico utilizando alocação de memória dinâmica ( malloc
e realloc
) são recomendadas. Uma função para visualizar o conteúdo das pilhas a qualquer momento também aumentaria a utilidade do programa.
A implementação de uma pilha com tamanho dinâmico permite que a pilha cresça ou diminua conforme necessário, eliminando a restrição de tamanho fixo dos arrays.
Dominar a arte de manipular pilhas em C é um passo importante na jornada de qualquer programador. Neste guia, percorremos a construção de um programa que utiliza duas pilhas de caracteres, abordando desde a implementação básica até o tratamento de erros e a otimização do código. Aprendemos a lidar com situações de pilha cheia e vazia, garantindo a robustez da aplicação.
A utilização prática na verificação de palíndromos serviu como um exemplo concreto da utilidade das pilhas. Esperamos que este tutorial tenha sido útil e que você possa agora aplicar esses conhecimentos para criar programas mais eficientes e robustos. Lembre-se: a prática leva à perfeição! Continue explorando o mundo da programação e aperfeiçoe suas habilidades.