Formula 1, Gara singola - Soluzione

Soluzione

In questo tutorial non verrà presentata la possibile soluzione nella sua interezza, ma soltano le parti interessanti, che dovranno essere opportunamente integrate per fornire la soluzione completa e compilabile. Per ottenere un programma completo e funzionante, si tratta pertanto di scrivere la funzione main che dichiara le variabili necessarie e che chiama opportunamente le funzioni descritte.

Per cominciare, si assume che vengano effettuat le seguenti dichiarazioni:

#define N_SQUADRE (10)
#define N_PILOTI (20)
#define MAX_RIGA (50)

#define POS_A_PUNTI (10)        /* Posizioni a cui si assegnano punti */

int punti_per_pos[POS_A_PUNTI] = {
    25, 18, 15, 12, 10, 8, 6, 4, 2, 1
};

I dati saranno memorizzati in array di strutture. Piloti e squadre richiedono lo stesso tipo di informazioni (nome e punteggio). Pertanto conviene utilizzare lo stesso tipo, in questo modo si eviterà di replicare le funzioni che effettuano le elaborazioni:

struct classificato {
    char nome[MAX_RIGA + 1];
    int punti;
};

Le funzioni descritte di seguito dovranno essere oppotunamente richiamate nel main. Ad esse dovranno essere passati gli argomenti corretti.

1) Lettura e calcolo del punteggio

La funzione per la lettura può essere realizzata come segue:

void leggi_gara(FILE *fin, struct classificato *piloti)
{
    char buffer[MAX_RIGA + 1];
    int pos, punti;
    char nome_pilota[MAX_RIGA + 1];
    char nome_scuderia[MAX_RIGA + 1];

    pos = 0;
    while (pos < N_PILOTI && fgets(buffer, MAX_RIGA + 1, fin) != NULL) {
        sscanf(buffer, "%s %s", nome_pilota, nome_scuderia);

        if (pos < POS_A_PUNTI) {
            punti = punti_per_pos[pos];
        } else {
            punti = 0;
        }
        
        strcpy(piloti[pos].nome, nome_pilota);  /* Memorizza il nome */
        piloti[pos].punti += punti;             /* Assegna i punti */
        pos++;                                  /* Passaggio alla posizione successiva */
    }
}

La funzione richiede due argomenti:

  • il file da leggere, già aperto in lettura prima di chiamare leggi_gara (S8.2.1);
  • il vettore piloti di strutture di tipo struct classificato per memorizzare i punteggi dei piloti, passato per riferimento (S6.6).

Il ciclo while viene eseguito finché si registra il risultato di tutti i piloti attesi (pos < N_PILOTI) e, contemporaneamente, finché ci sono righe nel file. Ricorda che fgets restituisce NULL (quindi 0, quindi "falso") quando si è giunti alla fine del file e non ci sono più righe da leggere (S8.6).

Per scrivere il nome del pilota nel campo della struttura va usata la strcpy, perché l'assegnamento (operatore =) non funziona con le stringhe (S5.11).

ATTENZIONE: l'istruzione che memorizza i punti del pilota è un incremento, quindi questa funzione si aspetta che il valore dei punti sia correttamente inizializzato a zero!

Inizializzazione del vettore di strutture

Visto che la funzione per il calcolo dei punti si attende un vettore correttamente inizializzato, è possibile incapsulare le istruzioni per l'inizializzazione in una funzione come la seguente:

void inizializza_elenco(struct classificato *elenco, int size)
{
    int i;
    for (i = 0; i < size; i++) {
        elenco[i].nome[0] = '\0';
        elenco[i].punti = 0;
    }
}

Il campo stringa nome viene posto uguale alla stringa vuota, mettendo il terminatore come primo carattere del vettore. Il campo punti viene inizializzato a zero.