#ifndef _PILAGENERICA_HPP #define _PILAGENERICA_HPP // Constantes y tipos previos const unsigned TAM_MAX = 1000; // Interfaz del TAD Pila. Pre-declaraciones: /* Los valores del TAD Pila representan una pila de elementos, * que sigue un comportamiento LIFO (Last In, First Out). Los * valores de Pila disponen de operaciones que permiten apilar * elementos, desapilar el último elemento, consultar el tope * de la pila y verificar si la pila está vacía. * * El tipo Elemento requerirá tener el operador habitual de * copia =, que se utilizará en las operaciones de apilar, * desapilar y cima. Elemento& operator=(const Elemento& origen) */ template struct Pila; /* Crea una pila vacía (es decir, no contiene ningún elemento) */ template void inicializar(Pila& p); /* Si p no está llena, devuelve en el mismo parámetro p la pila * resultante de añadir e a p y error = falso. En caso contrario, * la pila p no se modifica y error = verdad */ template void apilar(Pila& p, Elemento e, bool& error); /* Si p no es vacía, devuelve la pila resultante de eliminar * el último elemento que fue apilado, dejándolo en c, y error = falso. * Si la pila es vacía, error = verdad */ template void desapilar(Pila& p, Elemento& e, bool& error); /* Si p no es vacía, devuelve en e el último elemento apilado en p y * error = falso. En caso contrario, error = verdad y e queda indefinido */ template void cima(const Pila& p, Elemento& e, bool& error); /* Devuelve verdad si y sólo si p no tiene ningún elemento */ template bool estaVacia(const Pila& p); /* Devuelve verdad si y sólo si p ha alcanzado su máximo de capacidad */ template bool estaLlena(const Pila& p); // Al hacer la pila genérica, el uso de template nos obliga a declarar // esta función como pública :( /* Operaciones del iterador */ /* Prepara el iterador para que el siguiente elemento a visitar * sea la cima de la pila p, si existe (situación de no haber * visitado ningún elemento) */ template void iniciarIterador(Pila& p); /* Devuelve falso si ya se han visitado todos los elementos * contenidos en p, verdad en caso contrario */ template bool existeSiguiente(const Pila& p); /* Implementa las ops. siguiente y avanza de la especificación. * Si existeSiguiente(p), error = falso y e toma el valor del * siguiente elemento de la pila, y se avanza el iterador al * siguiente elemento de la pila. En caso contrario, * error = verdad, e queda indefinido y p queda como estaba */ template void siguiente(Pila& p, Elemento& e, bool& error); // Declaración template struct Pila { friend void inicializar(Pila& p); friend void apilar(Pila& p, char c, bool& error); friend void desapilar(Pila& p, char& c, bool& error); friend void cima(const Pila& p, char& c, bool& error); friend bool estaVacia(const Pila& p); friend bool estaLlena(const Pila& p); friend void iniciarIterador(Pila& p); friend bool existeSiguiente(const Pila& p); friend void siguiente(Pila& p, Elemento& e, bool& error); private: // Representación interna de los valores del TAD Elemento datos[TAM_MAX]; int tope; int iter; // iterador }; // Implementación de las operaciones: al ser un TAD genérico, // el código ha de estar en el archivo HPP (una guarrada, pero OBLIGATORIO) /* Crea una pila vacía (es decir, no contiene ningún elemento) */ template void inicializar(Pila& p) { p.tope = -1; // necesidades de C: los vectores se indexan empezando en 0 } /* Devuelve verdad si y sólo si p ha alcanzado su máximo de capacidad */ template bool estaLlena(const Pila& p) { return p.tope == (TAM_MAX - 1); } /* Si p no está llena, devuelve en el mismo parámetro p la pila * resultante de añadir e a p y error = falso. En caso contrario, * la pila p no se modifica y error = verdad */ template void apilar(Pila& p, Elemento e, bool& error) { error = true; if (!estaLlena(p)) { p.tope = p.tope + 1; p.datos[p.tope] = e; error = false; } } /* Si p no es vacía, devuelve la pila resultante de eliminar * el último elemento que fue apilado, dejándolo en c, y error = falso. * Si la pila es vacía, error = verdad */ template void desapilar(Pila& p, Elemento& e, bool& error) { error = true; if (!estaVacia(p)) { e = p.datos[p.tope]; p.tope = p.tope - 1; error = false; } } /* Si p no es vacía, devuelve en e el último elemento apilado en p y * error = falso. En caso contrario, error = verdad y e queda indefinido */ template void cima(const Pila& p, Elemento& e, bool& error) { error = true; if (!estaVacia(p)) { e = p.datos[p.tope]; error = false; } } /* Devuelve verdad si y sólo si p no tiene ningún elemento */ template bool estaVacia(const Pila& p) { return (p.tope == -1); } /* Operaciones del iterador */ /* Prepara el iterador para que el siguiente elemento a visitar * sea la cima de la pila p, si existe (situación de no haber * visitado ningún elemento) */ template void iniciarIterador(Pila& p) { p.iter = p.tope; } /* Devuelve falso si ya se han visitado todos los elementos * contenidos en p, verdad en caso contrario */ template bool existeSiguiente(const Pila& p) { return p.iter != -1; } /* Implementa las ops. siguiente y avanza de la especificación. * Si existeSiguiente(p), error = falso y e toma el valor del * siguiente elemento de la pila, y se avanza el iterador al * siguiente elemento de la pila. En caso contrario, * error = verdad, e queda indefinido y p queda como estaba */ template void siguiente(Pila& p, Elemento& e, bool& error) { error = true; if(existeSiguiente(p)) { e = p.datos[p.iter]; p.iter--; error = false; } } #endif