Cap 11. Apartado 11.5.1, página 358-362 EJERCICIO 11.2 La salida a pista de las avionetas de un aeródromo está organizada en forma de fila(línea), con una capacidad máxima de aparatos en espera de 13 avionetas. Las avionetas llegan por el extremo izquierdo y salen por el extremo derecho. Un piloto puede decidir retirarse de la fila por razones técnicas, en ese caso todas las avionetas a su derecha han de ser retiradas, retirar el aparato y las avionetas desplazadas colocarlas de nuevo en el mismo orden relativo en que estaban. La salida de una avioneta de la fila supone que las demás son movidas hacia adelante, de tal forma que los espacios libres del estacionamiento estén en la parte izquierda. El programa para emular este estacionamiento tiene como entrada un carácter que indica una acción sobre la avioneta, y la matrícula de la avioneta. La acción puede ser llegada(E), salida(S) de la avioneta que ocupa la primera posición y retirada (T) de una avioneta de la fila . En la llegada puede ocurrir que el estacionamiento esté lleno, si esto ocurre la avioneta espera hasta que se quede una plaza libre. El estacionamiento va a estar representado por una bicola de salida restringida. ¿Por qué esta elección?, la salida siempre se hace por el mismo extremo, sin embargo la entrada se puede hacer por los dos extremos, y así contemplar dos acciones: que llegue una avioneta nueva; y que tenga que entrar una avioneta que ha sido movida para que salga una intermedia. Las avionetas que se mueven para poder retirar del estacionamiento una intermedia, se disponen en una lista LIFO, así la ultima en entrar será la primera en añadirse en el extremo salida del estacionamiento (bicola) y seguir en el mismo orden relativo. Las avionetas se pueden representar mediante una cadena para almacenar el número de matrícula (tipo avioneta). Los elementos de la pila y de la bicola son del tipo avioneta. La lista LIFO es en realidad una pila. La codificación de las operaciones sobre pilas se encuentran el el capítulo 10, ahora simplemente se incluye el archivo pila.h . Las operaciones del TAD Bicola se realizan considerando el almacenamiento de los elementos en un array circular. La restricción de salida se refleja en que no es válida la operación quitarIzqda. Los extremos de la estructura se denominan entrada y salida, de tal forma que son índices de las avionetas que menos tiempo lleva en la fila y que mas tiempo lleva respectivamente. En el archivo bicolacircular.h se encuentran los tipos de datos y los prototipos de las operaciones. Los tipos y constantes: #define MAXTAMQ 14 typedef struct { TipoDato listaBicola[MAXTAMQ]; int salida, entrada; }Bicola; A continuación se presenta el archivo con la implementación de las operaciones mas importantes. Para mover circularmente los índices hacia delante y hacia atrás se codifican las funciones siguiente() y anterior() respectivamente. Codificación del TAD Bicola typedef struct { char matricula[51]; } Avioneta; typedef Avioneta TipoDato; #include “bicolacircular.h” int siguiente(int n) { return (n + 1) % MAXTAMQ; } int anterior(int n) { /* anterior de 0 es el índice mas alto */ return ((n-1) < 0) ? MAXTAMQ-1 : n-1; } void crearBicola(Bicola* bicola) { bicola -> salida = 0; bicola -> entrada = MAXTAMQ-1; } void inserIzqda(Bicola* bicola, TipoDato avta) { if (!bicolaLlena(*bicola)) { bicola -> entrada = siguiente(bicola->entrada); bicola -> listaBicola[bicola->entrada] = avta; } } void inserDrcha(Bicola* bicola, TipoDato avta) { if (!bicolaLlena(*bicola)) { bicola -> salida = anterior(bicola->salida); bicola -> listaBicola[bicola->salida] = avta; } } TipoDato quitarIzqda(Bicola* bicola) { TipoDato tmp; if (bicolaVacia(*bicola)) { puts(" Extracción por entrada en bicola vacía "); exit (1); } tmp = bicola -> listaBicola[bicola->entrada]; /* retrocede el índice entrada */ bicola -> entrada = anterior(bicola->entrada); return tmp; } TipoDato quitarDrcha(Bicola* bicola) { TipoDato tmp; if (bicolaVacia(*bicola)) { puts(" Extracción en bicola vacía "); exit (1); } tmp = bicola -> listaBicola[bicola->salida]; /* avanza el índice salida */ bicola -> salida = siguiente(bicola->salida); return tmp; } int bicolaVacia(Bicola bicola) { return bicola.salida == siguiente(bicola.entrada); } int bicolaLlena(Bicola bicola) { return bicola.salida siguiente(siguiente(bicola.entrada)); } == Codificación de la función principal En el archivo fuente con la función principal se codifica la simulación a realizar. Se incorpora la función posicion() que determina la posición que ocupa una avioneta en la fila. También, la operación retirar() que simula el hecho de que una avioneta que se encuentra en cualquier posición de la bicola decide salir de la fila; esta función hace uso del TAD Pila para guardar las avionetas que temporalmente tienen que apartarse de la fila para que pueda salir la avioneta en cuestión. typedef struct { char matricula[51]; } Avioneta; typedef Avioneta TipoDato; #include “bicolacircular.h” #include "pila.h" #include <ctype.h> #include <stdio.h> int posicion(Bicola bicola, Avioneta av); int retirar(Bicola* bicola, Avioneta av); void main() { Avioneta u; char ch; Bicola fila; int esta, mas = 1; crearBicola(&fila); while (mas) { puts(“\n Entrada de datos: [acción: matrícula.”); puts(“ Para terminar la simulación: X.”); E/S/T] do { scanf(“%c%*c”,&ch); ch = tolower(ch); } while(ch != ‘e’ && ch != ‘s’ && ch != ‘t’ && ch != ‘x’); if (ch == ‘s’) { if (!bicolaVacia(fila)) { u = quitarDrcha(&fila); printf(“Salida de la avioneta: %s”, u.matricula); } } else if (ch == ‘e’) { if (!bicolaLlena(fila)) { gets(u.matricula); inserIzqda(&fila, u); } } else if (ch == ‘t’) { if (!bicolaLlena(fila)) { gets(u.matricula); esta = retirar(&fila, u); if (!esta) puts(“Error de datos, avioneta no encontrada”); } } mas = !(ch == ‘x’); } } int posicion(Bicola bicola, Avioneta a) { int p, encontrada; p = anterior(bicola.salida); encontrada = 0; while (!encontrada && p != bicola.entrada) { p = siguiente(p); encontrada = strcmp(bicola.listaBicola[p].matricula, a.matricula) == 0; } if (encontrada) return p; else return –1; } int retirar(Bicola* bicola, Avioneta av) { int p; p = posicion(*bicola, av); if (p == -1) error no está la avioneta */ return 0; else { Pila pila /* if (p == bicola->salida) /* está en el extremo de salida */ quitarDrcha(bicola); else { /* se meten en la pila los elementos siguientes a p */ crearPila(&pila); do { insertar(&pila, quitarDrcha(bicola)); } while (bicola->salida != p); printf(“Avioneta %s es retirada \n”, quitarDrcha(bicola).matricula); /* elementos de la pila se meten de nuevo en la fila */ while (!pilaVacia(pila)) { inserDrcha(bicola,quitar(&pila)); } } return 1; } } /* operación realizada */