Queremos recrear el comportamiento de un navegador: visitar URLs, volver atrás y adelante, y registrar el historial sin perder contexto. La solución emplea dos pilas para representar los movimientos de navegación.
Mantenemos dos estructuras:
Visitar una nueva URL limpia la pila Forward (como en un navegador real) y apila la URL en Back.
Utilizaremos pilas dinámicas para no restringir el tamaño. A continuación un prototipo sencillo:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Nodo {
char *url;
struct Nodo *sig;
} Nodo;
typedef struct {
Nodo *top;
} PilaURL;
static void pila_init(PilaURL *p) { p->top = NULL; }
static int pila_is_empty(const PilaURL *p) { return p->top == NULL; }
static void pila_push(PilaURL *p, const char *url) {
Nodo *n = malloc(sizeof(Nodo));
if (!n) return;
n->url = strdup(url);
n->sig = p->top;
p->top = n;
}
static char *pila_pop(PilaURL *p) {
if (pila_is_empty(p)) return NULL;
Nodo *tmp = p->top;
char *valor = tmp->url;
p->top = tmp->sig;
free(tmp);
return valor;
}
static void pila_clear(PilaURL *p) {
while (!pila_is_empty(p)) {
free(pila_pop(p));
}
}
static void pila_print(const PilaURL *p, const char *nombre) {
printf("%s:\n", nombre);
for (Nodo *n = p->top; n; n = n->sig) {
printf(" %s%s\n", n->url, n == p->top ? " <- top" : "");
}
}
typedef struct {
PilaURL back;
PilaURL forward;
char *actual;
} Historial;
void historial_init(Historial *h, const char *home) {
pila_init(&h->back);
pila_init(&h->forward);
h->actual = strdup(home);
pila_push(&h->back, home);
}
void historial_visit(Historial *h, const char *url) {
pila_push(&h->back, url);
pila_clear(&h->forward);
free(h->actual);
h->actual = strdup(url);
}
const char *historial_back(Historial *h) {
if (!h->back.top || !h->back.top->sig) return h->actual;
char *prev = pila_pop(&h->back);
pila_push(&h->forward, prev);
free(prev);
free(h->actual);
h->actual = strdup(h->back.top->url);
return h->actual;
}
const char *historial_forward(Historial *h) {
if (pila_is_empty(&h->forward)) return h->actual;
char *next = pila_pop(&h->forward);
pila_push(&h->back, next);
free(h->actual);
h->actual = strdup(next);
free(next);
return h->actual;
}
void historial_print(const Historial *h) {
printf("Pagina actual: %s\n", h->actual);
pila_print(&h->back, "BACK");
pila_print(&h->forward, "FORWARD");
}
void historial_clear(Historial *h) {
pila_clear(&h->back);
pila_clear(&h->forward);
free(h->actual);
}
int main(void) {
Historial hist;
historial_init(&hist, "https://inicio.com");
historial_visit(&hist, "https://noticias.com");
historial_visit(&hist, "https://docs.com");
historial_back(&hist);
historial_forward(&hist);
historial_visit(&hist, "https://foros.com");
historial_print(&hist);
historial_clear(&hist);
return 0;
}
El programa permite probar visitas, retrocesos y avances, mostrando cómo se actualizan ambas pilas.
Este ejemplo combina pilas, manejo de cadenas y estructuras auxiliares, todo muy frecuente en preguntas de diseño de sistemas. Extensiones comunes: