9 PEC6
9.1 Ejemplo: listaCartas
El planteamiento es el siguiente: imaginemos que tenemos una lista de cartas de tipo DIAMANTES
, CORAZONES
, TREVOLES
y PICAS
; lo que queremos conseguir es filtrar esta lista para un tipo determinado de carta, DIAMANTES
, y añadir todas estas cartas de DIAMANTES
a otra lista.
Una posible implementación sería:
/* Ejemplo ES0901 */
#include <stdio.h>
#include <stdbool.h>
/* Definición del modelo de cartas según el enlace:
* https://es.wikipedia.org/wiki/Baraja_francesa
*/
#define MAX_CARTAS 54+1
#define MAX_DIAMANTES_CARTAS 13+1
/* El término "palo" equivale a "baraja". */
typedef enum {DIAMANTES, PICAS, TREVOLES, CORAZONES} tPalo;
typedef struct {
char valor;
tPalo palo;
} tCarta;
typedef struct {
tCarta cartas[MAX_CARTAS];
int nCartas;
} tCartasList;
/* Predeclaración de las funciones y acciones. */
void initList();
void insert(tCartasList *lista, tCarta carta, int indice);
void delete(tCartasList *lista, int indice);
void get(tCartasList lista, int indice, tCarta *carta);
bool isEnd(tCartasList lista, int pos);
bool isEmptyList(tCartasList lista);
bool isFullList(tCartasList lista);
void printList(tCartasList lista);
void getCartasByPalo(tCartasList lista, tPalo palo, tCartasList *listaByPalo);
void copiarCarta(tCarta *destino, tCarta origen);
/* Programa principal. */
int main(int argc, char **argv) {
tCarta carta1, carta2, carta3, carta4, carta5;
tCartasList listaCartas, listaCartasDiamantes;
/* Creamos las dos listas. */
initList(&listaCartas);
initList(&listaCartasDiamantes);
/* Definimos una serie de cartas. */
carta1.valor = '3';
carta1.palo = CORAZONES;
carta2.valor = 'A';
carta2.palo = DIAMANTES;
carta3.valor = 'J';
carta3.palo = TREVOLES;
carta4.valor = '5';
carta4.palo = DIAMANTES;
carta5.valor = 'Q';
carta5.palo = PICAS;
/* Y las añadimos a la lista genérica de cartas. */
insert(&listaCartas, carta1, 0);
insert(&listaCartas, carta2, 1);
insert(&listaCartas, carta3, 2);
insert(&listaCartas, carta4, 3);
insert(&listaCartas, carta5, 4);
/* Mostramos el contenido de la lista de cartas
* por pantalla mediante la acción printList.
*/
printf("Contenido de la lista 'listaCartas' :\n");
printList(listaCartas);
/* Ahora queremos filtrar la lista genérica de cartas con
* uno de los palos posibles. Concretamente queremos separar
* de la lista genérica de cartas aquellas que sean
* del palo DIAMANTES; lo hacemos mediante la llamada a
* la acción getCartasByPalo. Para ver su funcionamiento,
* revisad el comentario hecho en la implementación de esta
* acción.
*/
getCartasByPalo(listaCartas, DIAMANTES, &listaCartasDiamantes);
/* Y mostramos el contenido de la lista que contiene
* únicamente las cartas del palo DIAMANTES.
*/
printf("Contenido de la lista 'listaCartasDiamantes' :\n");
printList(listaCartasDiamantes);
return 0;
}
/* Implementación de los métodos de la lista: se ha hecho un copy/paste
* de la codificación C del ejemplo 19_12 de la xWiki, cambiando
* el genérico "elem" por "tCarta", y el genérico "list" por "tCartesList",
* ya que estos serán los elementos con los que trabajaremos
* en este ejemplo.
*/
void initList(tCartasList *lista) {
lista->nCartas = 0;
}
void insert(tCartasList *lista, tCarta carta, int indice) {
int i;
if (lista->nCartas == MAX_CARTAS) {
printf("\n Full list \n");
} else {
for (i=lista->nCartas-1; i>=indice; i--) {
lista->cartas[i+1] = lista->cartas[i];
}
lista->nCartas++;
lista->cartas[indice]=carta;
}
}
void delete(tCartasList *lista, int indice) {
int i;
if (lista->nCartas == 0) {
printf("\n Empty list\n");
} else {
for (i=indice; i<lista->nCartas-1; i++) {
lista->cartas[i] = lista->cartas[i+1];
}
lista->nCartas--;
}
}
void get(tCartasList lista, int indice, tCarta *carta) {
if (lista.nCartas == 0) {
printf("\n Empty list \n");
} else {
copiarCarta(carta, lista.cartas[indice]);
}
}
bool isEnd(tCartasList lista, int pos) {
return (pos >= lista.nCartas);
}
bool isEmptyList(tCartasList lista) {
return (lista.nCartas == 0);
}
bool isFullList(tCartasList lista) {
return (lista.nCartas == MAX_CARTAS);
}
/* A continuación se implementarán dos nuevas acciones que
* no salen en el ejemplo 19_12. La primera acción,
* printList(), imprime por pantalla una lista. la segunda
* acción, getCartesByPalo(), permite hacer un filtrado de
* cartas sobre una lista.
*/
void printList(tCartasList lista) {
int i;
tCarta cartaAux;
i = 0;
while (!isEnd(lista, i)) {
get(lista, i, &cartaAux);
if (cartaAux.palo == DIAMANTES) {
printf(" [%c] de DIAMANTES\n", cartaAux.valor);
} else if (cartaAux.palo == PICAS) {
printf(" [%c] de PICAS\n", cartaAux.valor);
} else if (cartaAux.palo == TREVOLES) {
printf(" [%c] de TREVOLES\n", cartaAux.valor);
} else if (cartaAux.palo == CORAZONES) {
printf(" [%c] de CORAZONES\n", cartaAux.valor);
}
i = i + 1;
}
}
/* La siguiente acción, getCartesByPalo, recibe tres parámetros:
* - tCartasList lista (in): lista sobre la que aplicaremos el filtro.
* - tPalo tipo (in): corresponde al tipo de palo que utilizaremos
* para hacer el filtrado; por ejemplo, si como palo indicamos
* DIAMANTES significa que el filtrado lo haremos
* sobre las cartas de tipo DIAMANTES.
* - tCartasList listaByPalo (out): lista de salida en la
* que se incluirán aquellas cartas de la lista de entrada que
* son del palo tipo.
*/
void getCartasByPalo(tCartasList lista, tPalo tipo, tCartasList *listaByPalo) {
int i, j;
tCarta carta;
initList(listaByPalo);
i = 0;
j = 0;
/* Con un bucle y la función end(), controlamos que no
* hayamos llegado al final de la lista.
*/
while (!isEnd(lista, i)) {
/* Obtenemos la carta de la posición i */
get(lista, i, &carta);
/* Si la carta es del palo indicado por tipo,
* se añade a la lista de salida.
*/
if (carta.palo == tipo) {
insert(listaByPalo, carta, j);
j = j + 1;
}
i = i + 1;
}
}
/* Acción que permite copiar el contenido de una tupla
* tCarta a otra tupla del mismo tipo.
*/
void copiarCarta(tCarta *destino, tCarta origen) {
destino->valor = origen.valor;
destino->palo = origen.palo;
}