10 PR4

10.1 Mode menu vs mode test

El workspace de la PR4 té habilitats dos modes de funcionament/execució. Per activar un mode o un altre fem el següent, amb el workspace de la PR1 obert: CodeLite –> Build –> Configuration manager…

Aquí es mostra un desplegable amb dues opcions:

  • Menu: és el mode estàndard de funcionament del programa, que mostra el menú per pantalla amb les accions que permet realitzar.
  • Test: s’executen una sèrie de tests per validar que les accions que hem codificat al nostre programa funcionin com s’espera que ho facin.

Tant si s’escull l’opció Menu com l’opció Test, després hem de fer l’habitual CodeLite –> Build –> Build and Run Project per executar el programa en el mode que hem escollit.

10.2 strncpy()

L’acció strncpy(desti, origen, numero) copia la cadena de caràcters de la variable origen a la variable desti. Únicament copia els primers n-caràcters, indicats pel valor numero. Així, si origen = "Hello World!" i numero = 5, el contingut de la variable desti serà "Hello" (limitat als 5 primers caràcters).

Exemple: imaginem que ens demanen que les entregues de les PAC han de seguir una nomenclatura concreta. El nom de l’arxiu ha d’estar compost per:

  1. La inicial del nom.
  2. Les tres primeres lletres del primer cognom.
  3. Les tres primeres lletres del segon cognom.
  4. El literal _pacN.zip, sent N el número de la PAC.

Per exemple, si l’alunme es diu David Rives Ingles i vol entregar la PAC6, el nom de l’arxiu serà DRivIng_pac6.zip.

Volem un programa que mostri per pantalla el nom de l’arxiu a partir del nom, els cognoms i el número de PAC de l’alumne.

Una possible solució és la següent:

/* Exemple CA1101 */
#include <stdio.h>
#include <string.h>

#define MAX_NOM 20+1
#define MAX_COGNOM 15+1
#define MAX_PART_NOM 1+1
#define MAX_PART_COGNOM 3+1
#define CARACTERS_PART_NOM 1
#define CARACTERS_PART_COGNOM 3

int main(int argc, char **argv)
{
    char nom[MAX_NOM];
    char cognom1[MAX_COGNOM];
    char cognom2[MAX_COGNOM];
    int numPac;

    char part1[MAX_PART_NOM];
    char part2[MAX_PART_COGNOM];
    char part3[MAX_PART_COGNOM];

    printf("Nom: ");
    scanf("%s", nom);
    printf("Primer cognom: ");
    scanf("%s", cognom1);
    printf("Segon cognom: ");
    scanf("%s", cognom2);
    printf("Número de PAC: ");
    scanf("%d", &numPac);

    strncpy(part1, nom, CARACTERS_PART_NOM);
    part1[CARACTERS_PART_NOM] = '\0';

    strncpy(part2, cognom1, CARACTERS_PART_COGNOM);
    part2[CARACTERS_PART_COGNOM] = '\0';

    strncpy(part3, cognom2, CARACTERS_PART_COGNOM);
    part3[CARACTERS_PART_COGNOM] = '\0';

    printf("\n>> Nom de l'entregable: %s%s%s_pac%d.zip \n",
        part1, part2, part3, numPac);

    return 0;
}

Un exemple d’execució:

Nom: David
Primer cognom: Rives
Segon cognom: Ingles
Número de PAC: 6

>> Nom de l'entregable: DRivIng_pac6.zip

10.3 Exemple: tupla dins de tupla

De vegades pot costar veure com treballar amb atributs d’una tupla que al seu torn és a dins d’una altra tupla, si s’hi accedeix per valor, per referència (punter), etc. Per aquest motiu, s’adjunta el següent exemple inventat, en el qual s’han afegit comentaris per tal que es vegi clarament com treballar amb atributs d’una tupla continguda dins d’una altra tupla:

llenguatge C

/* Exemple CA1102 */
#include <stdio.h>
#include <string.h>

/* Un parking d'un centre comercial ens ha 
 * encarregat una app que faciliti els seus
 * clients a localitzar on ha aparcat el seu
 * vehicle.
 * 
 * El parking ja disposa de tres tipus de 
 * càmeres, independents entre elles:
 * 
 * - d'entrada: càmera posicionada a l'entrada
 *   del pàrking que, a més de llegir la matrícula,
 *   permet saber el tipus de vehicle.
 * 
 * - d'accés: càmeres que ens permeten
 *   saber si un vehicle ha pujat o ha baixat
 *   una planta.
 * 
 * - de planta: càmeres que ens permeten saber
 *   la fila i eĺ número de plaça on s'ha 
 *   aparcat un vehicle.
 * 
 * L'identificador de vehicle és la seva 
 * matrícula.
 * 
 * A partir de la informació obtinguda pels
 * tres conjunts de càmeres, caldrà indicar
 * a l'usuari on ha aparcat el seu vehicle.
 */

#define MAX_MATRICULA 7+1

typedef enum {COTXE, MOTO, FURGONETA} tTipus;

/* El lloc on aparca un vehicle ve donat
 * per tres valors: la planta, la fila i el 
 * número de la plaça.
 */
typedef struct {
    int planta;
    char fila;
    int numero;
} tAparcament;

/* El tipus tVehicle conté la seva matrícula
 * (identificador únic), el tipus de vehicle
 * detectat en la primera càmera (COTXE, MOTO,
 * FURGONETA), i el lloc on ha aparcat (tAparcament).
 */
typedef struct {
    char matricula[MAX_MATRICULA];
    tTipus tipus;
    tAparcament aparcament;
} tVehicle;

/* Predeclaració d'accions */
void inicialitzar(tVehicle *vehicle, tTipus tipus, char *matricula);
void pujarPlanta(tVehicle *vehicle);
void baixarPlanta(tVehicle *vehicle);
void aparcar(tVehicle *vehicle, char fila, int numero);
void obtenirPosicio(tVehicle);

/* Programa principal */
int main(int argc, char **argv){
    
    tVehicle vehicle;
    
    /* Es llegeix la matrícula del vehicle amb la 
     * càmera d'entrada del pàrking i s'assigna
     * a l'element de tipus tVehicle del nostre
     * pàrking.
     */
    printf("\n>> Entrada al pàrking \n");
    inicialitzar(&vehicle, COTXE, "7472GZZ");
    
    printf("\n>> Baixar una planta\n");
    baixarPlanta(&vehicle);
    
    printf("\n>> Baixar una planta\n");
    baixarPlanta(&vehicle);
    
    printf("\n>> Pujar una planta\n");
    pujarPlanta(&vehicle);
    
    printf("\n>> Baixar una planta\n");
    baixarPlanta(&vehicle);
    
    printf("\n>> Baixar una planta\n");
    baixarPlanta(&vehicle);
    
    printf("\n>> Aparcar\n");
    aparcar(&vehicle, 'C', 23);
    
    printf("\nAnem a comprar ...");
    printf("\n... hi passem més de 3 hores ...");
    printf("\n... i ens oblidem d'on hem aparcat el vehicle! \n");
    
    printf("\nSolució: consultem la posició del nostre vehicle");
    printf("\na l'app del pàrquing : \n");
    obtenirPosicio(vehicle);
    return 0;
}

/* Com que la posició ve donada pels atributs planta, fila i
 * numero de tAparcament, és molt important que inicialitzem
 * els valors (sobretot per la planta). La planta inicial del
 * pàrking és la 0, i la resta de plantes són soterrades.
 */
void inicialitzar(tVehicle *vehicle, tTipus tipus, char *matricula) {
    strcpy(vehicle->matricula, matricula);
    vehicle->tipus = tipus;
    /* L'accés a l'atribut aparcament (tupla) el fem amb '->'
     * ja que es tracta d'un punter, i accedim
     * als atributs de la tupla aparcament amb '.'
     */
    vehicle->aparcament.planta = 0;
    vehicle->aparcament.fila = '-';
    vehicle->aparcament.numero = 0;
}

/* Quan pugem una planta, incrementem en 1 l'atribut
 * planta de la tupla tAparcament que conté la tupla tVehicle. 
 */
void pujarPlanta(tVehicle *vehicle) {
    vehicle->aparcament.planta = vehicle->aparcament.planta + 1;
}

/* Quan baixem una planta, decrementem en 1 l'atribut
 * planta de la tupla tAparcament que conté la tupla tVehicle.
 */
void baixarPlanta(tVehicle *vehicle) {
    vehicle->aparcament.planta = vehicle->aparcament.planta - 1;
}

/* Quan aparquem el vehicle, donem valor als atributs
 * fila i numero de la tupla tAparcament que conté la 
 * tupla tVehicle.
 */
void aparcar(tVehicle *vehicle, char fila, int numero) {
    vehicle->aparcament.fila = fila;
    vehicle->aparcament.numero = numero;
}

/* Mostrem per pantalla la posició del tVehicle. */ 
void obtenirPosicio(tVehicle vehicle) {
    if (vehicle.tipus == COTXE) {
        printf("\nCotxe %s : ", vehicle.matricula);
    } else {
        if (vehicle.tipus == MOTO) {
            printf("\nMoto %s : ", vehicle.matricula);
        } else {
            printf("\nFurgoneta %s : ", vehicle.matricula);
        }
    }
    
    /* En aquest cas l'accés a l'atribut aparcament (tupla)
     * es fa amb '.' ja que s'ha passat per valor (no és un punter)
     * i accedim als atributs de la tupla aparcament amb '.' 
     */
    printf("planta %d, ", vehicle.aparcament.planta);
    printf("fila %c, ", vehicle.aparcament.fila);
    printf("número %d \n", vehicle.aparcament.numero);
}

El resultat de l’execució d’aquest programa és:

>> Entrada al pàrking 

>> Baixar una planta

>> Baixar una planta

>> Pujar una planta

>> Baixar una planta

>> Baixar una planta

>> Aparcar

Anem a comprar ...
... hi passem més de 3 hores ...
... i ens oblidem d'on hem aparcat el vehicle!

Solució: consultem la posició del nostre vehicle 
a l'app del parking : 

Cotxe 7472GZZ : planta -3, fila C, número 23

10.4 Desplaçament d’elements en un vector

Els desplaçaments en un vector es poden produir quan s’afegeix o s’elimina un element d’un vector.

10.4.1 Afegir un element

Volem afegir un element dins del vector de la taula en una posició que no és l’última. Per exemple, si volem que els elements que afegim a un vector vagin a la posició inicial, caldrà abans desplaçar la resta d’elements una posició a la dreta:

Contingut inicial del vector:

[element2] [element5] [element1] [element7]

Abans d’afegir el nou element6, caldrà moure tots els elements una posició cap a la dreta, per tal de fer un buit a l’inici:

[........] [element2] [element5] [element1] [element7]

Ara ja es pot afegir l’element6 a la primera posició del vector:

[element6] [element2] [element5] [element1] [element7]

Important: com a darrer pas, incrementar en 1 l’atribut que conté la mida de la taula.

10.4.2 Esborrar un element

Quan volem eliminar un element d’un vector també es pot produir un desplaçament d’elements. Per exemple:

Contingut inicial del vector:

[element2] [element5] [element1] [element7]

Per eliminar l’element5 simplement desplacem la resta d’elements que van a continuació una posició cap a l’esquerra:

[element2] [element1] [element7]

Important: com a darrer pas, decrementar en 1 l’atribut que conté la mida de la taula.

10.5 Exemple: diesSetmana

A continuació s’adjunta un exemple inventat per consolidar l’explicació anterior: la idea és que pugueu comparar la inserció d’elements a una taula com hem fet habitualment fins ara (afegits al final de tot), amb una altra acció que permet afegir de forma ordenada els elements a la taula. En aquesta segona inserció caldrà anar realitzant desplaçaments cap a la dreta dels elements del vector de la taula per tal que vagin quedant ordenats.

/* Exemple CA1103 */
#include <stdio.h>
#include <string.h>
#include <stdbool.h>

/* Definició de constants. */
#define MAX_DIES 7
#define MAX_NOM 9+1

/* Definició de la tupla tDia. */
typedef struct {
    char nom[MAX_NOM];
    int id;
} tDia;

/* Definició de la taula tSetmana. */
typedef struct {
    tDia dies[MAX_DIES];
    int numDies;
} tSetmana;

/* Predeclaració de les accions. */

/* Acció que inicialitza la taula tSetmana,
 * tot posant l'atribut numDies a 0.
 */
void inicialitzar(tSetmana *setmana);

/* Acció que afegeix un element de tipus tDia
 * a la taula tSetmana.
 */
void afegirDia(tSetmana *setmana, tDia dia);

/* Acció que afegeix un element de tipus tDia
 * a la taula tSetmana de forma ordenada. 
 */
void afegirDiaOrdenat(tSetmana *setmana, tDia dia);

/* Acció que copia el contingut d'un tDia origen (src)
 * a un tDia destí (dst). 
 */
void copiarDia(tDia *dst, tDia src);

/* Acció que mostra per pantalla el contingut
 * de la taula tSetmana. 
 */
void mostrar(tSetmana setmana);

/* Programa principal */
int main(int argc, char **argv) {
    /* Definim les variables. */
    tSetmana setmana, setmanaOrdenada;
    tDia dl, dm, dc, dj, dv, ds, dg; 
    
    /* Inicialitzem les variables de tipus tDia. */
    strcpy(dl.nom, "dilluns");
    dl.id = 1;
    strcpy(dm.nom, "dimarts");
    dm.id = 2;
    strcpy(dc.nom, "dimecres");
    dc.id = 3;
    strcpy(dj.nom, "dijous");
    dj.id = 4;
    strcpy(dv.nom, "divendres");
    dv.id = 5;
    strcpy(ds.nom, "dissabte");
    ds.id = 6;
    strcpy(dg.nom, "diumenge");
    dg.id = 7;
    
    /* Inicialitzem les variables de tipus
     * tSetmana. 
     */
    inicialitzar(&setmana);
    inicialitzar(&setmanaOrdenada);
    
    /* Afegim sense ordre les variables
     * tDia dins de les taules setmana
     * i setmanaOrdenada. La diferència
     * entre elles serà el mètode utilitzat
     * per inserir els tDia: mentre que 
     * la inserció per setmana serà 
     * l'habitual d'afegir com a darrer
     * element de la taula, per la 
     * setmanaOrdenada utilitzarem l'acció
     * afegirDiaOrdenat().
     */
    afegirDia(&setmana, dj);
    afegirDia(&setmana, dl);
    afegirDia(&setmana, dc);
    afegirDia(&setmana, dg);
    afegirDia(&setmana, ds);
    afegirDia(&setmana, dm);
    afegirDia(&setmana, dv);
    afegirDiaOrdenat(&setmanaOrdenada, dj);
    afegirDiaOrdenat(&setmanaOrdenada, dl);    
    afegirDiaOrdenat(&setmanaOrdenada, dc);
    afegirDiaOrdenat(&setmanaOrdenada, dg);
    afegirDiaOrdenat(&setmanaOrdenada, ds);
    afegirDiaOrdenat(&setmanaOrdenada, dm);
    afegirDiaOrdenat(&setmanaOrdenada, dv);

    printf("\nSetmana sense ordenar : \n");
    mostrar(setmana);
    printf("\nSetmana ordenada : \n");
    mostrar(setmanaOrdenada);
    return 0;
}

/* Implementació de les accions. */

void inicialitzar(tSetmana *setmana) {
    setmana->numDies = 0;
}

void afegirDia(tSetmana *setmana, tDia dia) {
    /* numDies conté el número d'elements 
     * de tipus tDia que conté la taula 
     * tSetmana en cada moment. 
     */
    copiarDia(&setmana->dies[setmana->numDies], dia);

    /* Una vegada assignat un element nou 
     * tDia a la taula, incrementem el valor 
     * de numDies. 
     */
    setmana->numDies = setmana->numDies + 1;
}

/* Acció que afegeix un element de tipus tDia
 * a la taula tSetmana de forma ordenada.
 */
void afegirDiaOrdenat(tSetmana *setmana, tDia dia) {
    
    int i, j;
    bool isAfegit;
    
    isAfegit = false;
    i = 0;
    
    /* Per fer l'ordenació s'utilitzarà el camp
     * id de tDia. 
     */
    for (i = 0; i < setmana->numDies && !isAfegit; i++) {
        
        /* Si l'id del tDia de la tSetmana > id del
         * paràmetre dia, a partir d'aquest punt 
         * caldrà desplaçar les tuples tDia cap 
         * a la dreta. L'objectiu és aconseguir un
         * lloc lliure, on s'afegirà el tDia dia 
         * passat com a paràmetre a l'acció.
         */
        if (setmana->dies[i].id > dia.id) {
            
            /* Desplaçament dels tDia cap a la dreta, a
             * partir de la posició on caldrà afegir 
             * el paràmetre dia passat per valor. 
             */
            for (j = setmana->numDies; j > i; j--) {
                copiarDia(&setmana->dies[j], setmana->dies[j-1]);    
            }
            
            /* S'afegeix el paràmetre dia a la 
             * posició que li correspon, una vegada
             * desplaçats la resta de tuples tDia 
             * cap a dreta.
             */
            copiarDia(&setmana->dies[j], dia);
            setmana->numDies = setmana->numDies + 1;
            isAfegit = true;
        }
    }

    /* Si en aquest punt encara no s'ha 
     * afegit el tDia, significa que ha d'anar
     * al final de tot de la taula tSetmana.
     */
    if (!isAfegit) {
        copiarDia(&setmana->dies[i], dia);
        setmana->numDies = setmana->numDies + 1;
    }
}

void copiarDia(tDia *dst, tDia src) {    
    dst->id = src.id; 
    strcpy(dst->nom, src.nom);
}

void mostrar(tSetmana setmana) {
    int i;
    for (i = 0; i < setmana.numDies; i++) {
        printf("%s\n", setmana.dies[i].nom);
    }
}

L’execució del programa genera la següent sortida:

Setmana sense ordenar : 
dijous
dilluns
dimecres
diumenge
dissabte
dimarts
divendres

Setmana ordenada : 
dilluns
dimarts
dimecres
dijous
divendres
dissabte
diumenge

10.6 Exemple: pilaCartes

A continuació s’exposa un exemple on, donada una pila de cartes inicial, el que volem és codificar l’acció separarDiamants que ens permeti separar de la pila totes aquelles que són DIAMANTS, afegint-les a una nova pila de cartes DIAMANTS.

Exemple: si inicialment tenim la pila1:

[Q] de PIQUES
[5] de DIAMANTS
[J] de TRÈVOLS
[A] de DIAMANTS
[3] de CORS

Volem que, d’una banda, la pila1 contingui totes les cartes que no són DIAMANTS:

[3] de CORS
[J] de TRÈVOLS
[Q] de PIQUES

I, de l’altra banda, una nova pila2 amb totes les cartes DIAMANTS:

[A] de DIAMANTS
[5] de DIAMANTS

S’han afegit comentaris dins el codi per facilitar-ne la comprensió:

/* Exemple CA1104 */
#include <stdio.h>
#include <stdbool.h>

/* Definició del model de cartes segons l'enllaç:
   https://ca.wikipedia.org/wiki/Joc_de_cartes#Joc_de_cartes_francès */

#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 A[MAX_CARTES];
    int nelem;
} tStack;

/* Predeclaració de les accions i les funcions */
void initStack(tStack *s);
void push(tStack *s, tCarta e);
void pop(tStack *s);
void top(tStack s, tCarta *carta);
bool isEmptyStack(tStack s);
bool isFullStack(tStack s);
void printStack(tStack s);
void copiarCarta(tCarta *desti, tCarta origen);
void separarDiamants(tStack *pilaCartes, tStack *pilaDiamants);

/* Programa principal */

int main(int argc, char **argv) {
    tCarta carta1, carta2, carta3, carta4, carta5;
    tStack pilaCartes, pilaCartesDiamants;
    
    /* Creem dues piles (reviseu el comentari inicial del bloc
     * d'implementació de les accions/funcions de la pila). 
     */
    initStack(&pilaCartes);
    initStack(&pilaCartesDiamants);
    
    /* 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 totes a pilaCartes */
    push(&pilaCartes, carta1);
    push(&pilaCartes, carta2);
    push(&pilaCartes, carta3);
    push(&pilaCartes, carta4);
    push(&pilaCartes, carta5);
    
    /* Mostrem el contingut de pilaCartes per
     * pantalla, amb l'acció addicional printStack. 
     */
    printf("\nContingut de la pila 'pilaCartes' :\n");
    printStack(pilaCartes);
    
    /* Ara volem separar de pilaCartes totes 
     * aquelles cartes que són DIAMANTS, les quals
     * formaran part d'una nova pila de cartes. 
     */
    printf("\nSeparem les cartes en dues piles!\n");
    
    /* Explicació detallada dins de la implementació
     * de l'acció. 
     */
    separarDiamants(&pilaCartes, &pilaCartesDiamants);
    
    printf("\nContingut de la pila 'pilaCartes' sense DIAMANTS :\n");
    printStack(pilaCartes);
    printf("\nContingut de la pila 'pilaCartesDiamants' :\n");
    printStack(pilaCartesDiamants);
    return 0;
}

/* Implementació de les accions/funcions de la pila: s'ha fet un copy/paste
 * de la codificació C de l'exemple 19_04 de la xWiki, canviant
 * el genèric "elem" per "tCarta". 
 */

void initStack(tStack *s) {
    s->nelem=0;
}

void push(tStack *s, tCarta e) {
    if (s->nelem == MAX_CARTES) {
        printf("\n Full stack \n");
    } else {
        s->A[s->nelem]=e; /* first position in C is 0 */
        s->nelem++;
    }
}

void pop(tStack *s) {
    if (s->nelem == 0) {
        printf("\n Empty stack\n");
    } else {
        s->nelem--;
    }
}

void top(tStack s, tCarta *carta) {
    if (s.nelem == 0) {
        printf("\n Empty stack \n");
    } else {
        copiarCarta(carta, s.A[s.nelem-1]);
    }
}

bool isEmptyStack(tStack s) {
    return (s.nelem == 0);
}

bool isFullStack(tStack s) {
    return (s.nelem == MAX_CARTES);
}

/* Acció addicional que mostra per pantalla tots 
 * els elements d'una pila. 
 */
void printStack(tStack s) {
    tCarta cartaAux;
    while (!isEmptyStack(s)) {
        top(s, &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 TRÈVOLS\n", cartaAux.valor);
        } else if (cartaAux.coll == CORS) {
            printf("  [%c] de CORS\n", cartaAux.valor);
        }
        pop(&s);
    }
}

/* Acció que permet copiar el contingut
 * d'una tupla tCarta a una altra
 */
void copiarCarta(tCarta *desti, tCarta origen) {
    /* Recordem: 
     * - si el paràmetre és un punter, s'accedeix 
     *   als atributs amb '->'
     * - si el paràmetre és un valor, s'accedeix
     *   als atributs amb '.'
     */
    desti->valor = origen.valor;
    desti->coll = origen.coll;
}

/* Acció que rep dos paràmetres:
 * - pilaCartes (inout)
 * - pilaDiamants (out)
 * Aquesta acció separa de pilaCartes (inout) aquelles
 * cartes amb coll DIAMANTS, i les afegeix a
 * pilaDiamants (out). Així una vegada executada l'acció, tindrem:
 * - pilaCartes: contindrà totes les cartes que no són DIAMANTS.
 * - pilaDiamants: contindrà tots els DIAMANTS. 
 */
void separarDiamants(tStack *pilaCartes, tStack *pilaDiamants) {
    tCarta cartaAux;
    tStack pilaNoDiamants;
    
    /* Totes les cartes inicialment estan a pilaCartes.
     * Es tracta d'anar afegint els DIAMANTS a la pilaDiamants,
     * i els que no són DIAMANTS a la pila temporal pilaNoDiamants.
     * Posteriorment assignarem pilaNoDiamants a pilaCartes (inout).
     */
    
    /* Inicialitzem la pila auxiliar. */
    initStack(&pilaNoDiamants);
    
    /* Hem de tractar tots els elements de la pila. */
    while (!isEmptyStack(*pilaCartes)) {
        top(*pilaCartes, &cartaAux);
        if (cartaAux.coll == DIAMANTS) {
            push(pilaDiamants, cartaAux);
        } else {
            push(&pilaNoDiamants, cartaAux);
        }
        pop(pilaCartes);
    }

    /* Es traspassa el contingut de la pila auxiliar 
     * pilaNoDiamants a pilaCartes, que correspon
     * al paràmetre de classe inout de l'acció.
     */
    while (!isEmptyStack(pilaNoDiamants)) {
        top(pilaNoDiamants, &cartaAux);
        push(pilaCartes, cartaAux);
        pop(&pilaNoDiamants);
    }
}