9 PAC6
9.1 Exemple: llistaCartes
El plantejament és el següent: imaginem que tenim una llista de cartes de tipus DIAMANTS
, CORS
, TREVOLS
i PIQUES
; el que volem aconseguir és filtrar aquesta llista per un tipus determinat de carta, DIAMANTS
, i afegir totes aquestes cartes de DIAMANTS
a una altra llista.
Una possible implementació seria:
/* Exemple CA0901 */
#include <stdio.h>
#include <stdbool.h>
/* Definició del model de cartes segons l'enllaç:
* https://ca.wikipedia.org/wiki/Joc_de_cartes#Baralla_francesa
*/
#define MAX_CARTES 54+1
/* El terme "coll" equival a "baraja". */
typedef enum {DIAMANTS, PIQUES, TREVOLS, CORS} tColl;
typedef struct {
char valor;
tColl coll;
} tCarta;
typedef struct {
tCarta cartes[MAX_CARTES];
int nCartes;
} tCartesList;
/* Predeclaració de les accions i les funcions. */
void initList();
void insert(tCartesList *llista, tCarta carta, int index);
void delete(tCartesList *llista, int index);
void get(tCartesList llista, int index, tCarta *carta);
bool isEnd(tCartesList llista, int pos);
bool isEmptyList(tCartesList llista);
bool isFullList(tCartesList llista);
void printList(tCartesList llista);
void getCartesByColl(tCartesList llista, tColl coll, tCartesList *llistaByColl);
void copiarCarta(tCarta *desti, tCarta origen);
/* Programa principal. */
int main(int argc, char **argv) {
tCarta carta1, carta2, carta3, carta4, carta5;
tCartesList llistaCartes, llistaCartesDiamants;
/* Creem les dues llistes. */
initList(&llistaCartes);
initList(&llistaCartesDiamants);
/* Definim una sèrie de cartes. */
carta1.valor = '3';
carta1.coll = CORS;
carta2.valor = 'A';
carta2.coll = DIAMANTS;
carta3.valor = 'J';
carta3.coll = TREVOLS;
carta4.valor = '5';
carta4.coll = DIAMANTS;
carta5.valor = 'Q';
carta5.coll = PIQUES;
/* I les afegim a la llista genèrica de cartes. */
insert(&llistaCartes, carta1, 0);
insert(&llistaCartes, carta2, 1);
insert(&llistaCartes, carta3, 2);
insert(&llistaCartes, carta4, 3);
insert(&llistaCartes, carta5, 4);
/* Mostrem el contingut de la llista de cartes
* per pantalla, amb l'acció printList.
*/
printf("Contingut de la llista 'llistaCartes' :\n");
printList(llistaCartes);
/* Ara volem filtrar la llista genèrica de cartes amb
* un dels colls possibles. Concretament volem separar
* de la llista genèrica de cartes aquelles que siguin
* del coll DIAMANTS; ho fem mitjançant la crida a
* l'acció getCartesByColl. Per veure el seu funcionament,
* reviseu el comentari fet en la implementació d'aquesta
* acció.
*/
getCartesByColl(llistaCartes, DIAMANTS, &llistaCartesDiamants);
/* I mostrem ara el contingut de la llista que conté
* únicament les cartes del coll DIAMANTS.
*/
printf("Contingut de la llista 'llistaCartesDiamants' :\n");
printList(llistaCartesDiamants);
return 0;
}
/* Implementació dels mètodes de la llista: he fet un copy/paste
* de la codificació C de l'exemple 19_12 de la xWiki, canviant
* el genèric "elem" per "tCarta", i el genèric "list" per "tCartesList",
* ja que aquests seran els elements amb els que treballarem
* en aquest exemple.
*/
void initList(tCartesList *llista) {
llista->nCartes = 0;
}
void insert(tCartesList *llista, tCarta carta, int index) {
int i;
if (llista->nCartes == MAX_CARTES) {
printf("\n Full list \n");
} else {
for (i=llista->nCartes-1; i>=index; i--) {
llista->cartes[i+1] = llista->cartes[i];
}
llista->nCartes++;
llista->cartes[index]=carta;
}
}
void delete(tCartesList *llista, int index) {
int i;
if (llista->nCartes == 0) {
printf("\n Empty list\n");
} else {
for (i=index; i<llista->nCartes-1; i++) {
llista->cartes[i] = llista->cartes[i+1];
}
llista->nCartes--;
}
}
void get(tCartesList llista, int index, tCarta *carta) {
if (llista.nCartes == 0) {
printf("\n Empty list \n");
} else {
copiarCarta(carta, llista.cartes[index]);
}
}
bool isEnd(tCartesList llista, int pos) {
return (pos >= llista.nCartes);
}
bool isEmptyList(tCartesList llista) {
return (llista.nCartes == 0);
}
bool isFullList(tCartesList llista) {
return (llista.nCartes == MAX_CARTES);
}
/* A continuació s'implementaran dues noves accions que
* no surten ja a l'exemple 19_12. La primera acció,
* printList, imprimeix per pantalla una llista. La segona
* acció, getCartesByColl, permet fer un filtratge de
* cartes sobre una llista.
*/
void printList(tCartesList llista) {
int i;
tCarta cartaAux;
i = 0;
while (!isEnd(llista, i)) {
get(llista, i, &cartaAux);
if (cartaAux.coll == DIAMANTS) {
printf(" [%c] de DIAMANTS\n", cartaAux.valor);
} else if (cartaAux.coll == PIQUES) {
printf(" [%c] de PIQUES\n", cartaAux.valor);
} else if (cartaAux.coll == TREVOLS) {
printf(" [%c] de TREVOLS\n", cartaAux.valor);
} else if (cartaAux.coll == CORS) {
printf(" [%c] de CORS\n", cartaAux.valor);
}
i = i + 1;
}
}
/* La següent acció, getCartesByColl, rep tres paràmetres:
* - tCartesList llista (in): llista sobre la qual aplicarem el filtre.
* - tColl tipus (in): correspon al tipus de coll que utilitzarem per
* fer el filtratge; per exemple, si com a coll indiquem
* DIAMANTS significa que el filtratge el farem
* sobre les cartes de tipus DIAMANTS.
* - tCartesList llistaByColl (out): llista de sortida en la qual
* s'hi inclouran aquelles cartes de la llista d'entrada que
* són del coll tipus.
*/
void getCartesByColl(tCartesList llista, tColl tipus, tCartesList *llistaByColl) {
int i, j;
tCarta carta;
initList(llistaByColl);
i = 0;
j = 0;
/* Amb un bucle i la funció end(), controlem que no
* hem arribat al final de la llista
*/
while (!isEnd(llista, i)) {
/* Obtenim la carta de la posició i */
get(llista, i, &carta);
/* Si la carta és del coll indicat per tipus,
* s'afegeix a la llista de sortida .
*/
if (carta.coll == tipus) {
insert(llistaByColl, carta, j);
j = j + 1;
}
i = i + 1;
}
}
/* Acció que permet copiar el contingut d'una tupla
* tCarta a una altra tupla.
*/
void copiarCarta(tCarta *desti, tCarta origen) {
desti->valor = origen.valor;
desti->coll = origen.coll;
}