Formula 1, Campionato

Si adatti il programma che risolve il problema della singola gara al fine di leggere da un file l'ordine d'arrivo di un intero campionato di Formula 1 composto da più gare. Le prime 20 righe sono relative alla prima gara. Seguono 20 righe relative alla seconda gara, e così via.

Il programma dovrà essere in grado di svolgere le seguenti elaborazioni.

Suggerimenti generali

Ricorda che le righe nel file rispecchiano l'ordine di arrivo nella gara! Puoi memorizzare il punteggio assegnato per ciascuna posizione di classifica in un vettore, in modo che l'indice del vettore, legato alla posizione in classifica, permetta di recuperare con una istruzione il punteggio del pilota; per esempio:

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

dove POS_A_PUNTI è una costante definita con una #define (vedi S3.1) che indica il numero di posizioni che permettono di ottenere dei punti.

Puoi utilizzare una struttura dati per memorizzare l'associazione tra pilota e punteggio, per esempio:

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

dove MAX_RIGA è una costante definita con una #define (vedi S3.1) che indica la dimensione massima della riga di testo.

Sarà necessario un vettore di tali strutture per memorizzare i punteggi dei piloti (nel main):

struct classificato piloti[N_PILOTI];

dove N_PILOTI è una costante definita con una #define (vedi S3.1) che indica il numero di piloti che gareggiano.

Il nome del file da leggere sarà l'argomento argv[1] del main (vedi S6.9), mentre per aprire il file in lettura si usa fopen (S8.2.1).

Funzione di lettura

Creare una funzione di lettura dichiarata come la segue:

int leggi_gara(FILE * fin,
        struct classificato *piloti,
        struct classificato *scuderie);

La funzione richiede tre 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 vettore scuderie di strutture di tipo struct classificato per memorizzare i punteggi delle squadre, passato per riferimento (S6.6)

La funzione leggi_gara restituirà il numero di piloti caricati per la gara corrente. Quando restituisce 0, significa che è stata raggiunta la fine del file.

Nella funzione leggi_gara:

  • leggere il file con un ciclo attraverso fgets (S8.6)
  • da ogni riga, estrarre il nome del pilota tramite sscanf, determinare il punteggio e memorizzare questi valori in un elemento del vettore piloti
    • si ricorda che per estrarre una stringa con sscanf si usa lo specificatore %s
    • nella sscanf, la variabile stringa nella quale memorizzare il nome estratto va passato per riferimento (se si tratta di un vettore di char non serve la &)
    • il nome va copiato tramite strcpy nel campo della struttura giusta del vettore piloti

Nel main:

  • chiamare la funzione leggi_gara in un ciclo come segue (piloti e scuderie sono vettori opportunamente dichiarati nel main):
    while (leggi_gara(fin, piloti, scuderie) != 0) {
        /* quando leggi_gara ritorna, una gara intera e` stata letta */
        .....
    }
  • elaborare opportunamente il contenuto dei vettori piloti e scuderie

Per poter funzionare, la leggi_gara deve poter cercare un elemento dentro un vettore di strutture struct classificato il cui campo nome corrisponde ad un nome specificato. La funzione di ricerca può essere dichiarata come segue:

struct classificato *cerca_classificato(struct classificato
        *elenco, int size,
        char *nome);

I parametri sono i seguenti:

  • elenco è il vettore di strutture sul quale fare la ricerca
  • size è il numero di strutture presenti nel vettore
  • nome è la stringa che specifica il nome da ricercare

La funzione restituisce l'indirizzo dell'elemento all'interno di elenco che abbia il campo nome uguale alla stringa nome passata come argomento. La funzione deve considerare due casi:

  1. un elemento con il nome desiderato è già presente in elenco, nel qual caso si ritorna l'indirizzo di quell'elemento
  2. un elemento con il nome desiderato non è già presente in elenco (questo si verifica durante la lettura della prima gara nel file); quindi la funzione cerca_classificato dovrà:
  • restituire l'indirizzo del primo elemento del vettore che non contiene alcun nome
  • inizializzare tale elemento inserendo il nome (con strcpy) e inizializzando a 0 il valore dei punti

La funzione cerca_classificato potrà essere chiamata all'interno di leggi_gara sia per cercare il nome di un pilota all'interno del vettore piloti che per cercare il nome di una squadra all'interno del vettore scuderie.

Per capire meglio come operano le funzioni leggi_gara e cerca_classificato si veda l'esempio di soluzione qui.

1) Numero di gare

Determinare il numero di gare presenti nel file, stampandone il valore usando il formato:

[NUMERO_GARE]
2

Suggerimenti

La funzione leggi_gara dovrà leggere al massimo un numero di righe pari al numero di piloti che gareggiano in ciascuna gara, in questo modo la funzione può essere chiamata più volte in un ciclo while nel main per sommare i punteggi delle varie gare.

Si può contare il numero di volte che la funzione leggi_gara viene chiamata per sapere il numero di gare memorizzate nel file.

2) Pilota vincitore

Determinare il pilota vincitore del campionato Il punteggio di un pilota è la somma dei punti ottenuti nelle singole gare. A parità di punteggio vince il pilota che viene prima in ordine alfabetico.

Stampare il nome del pilota usando il seguente formato:

[PILOTA_VINCITORE]
pilota punteggio

3) Squadra vincitrice

Determinare la squadra vincitrice del campionato. Considerando che il punteggio di una squadra consiste nella somma dei punti ottenuti dai suoi piloti, determinare la squadra vincitrice.

Stampare il nome della squadra usando il seguente formato:

[SQUADRA_VINCITRICE]
squadra punteggio

A parità di punteggio vince la squadra che viene prima in ordine alfabetico.

Verifica automatica

Si utilizzi il tool pvcheck di verifica automatica per testare il corretto funzionamento del programma. Il file contenente i test è formula1_2.test. Per poter eseguire i test con pvcheck è necessario scaricare anche i seguenti file di dati, da salvare nella medesima directory del file di test:

Il comando da eseguire per il test è il seguente:

pvcheck -f formula1_2.test ./a.out

Nella prossima pagina potrai esaminare un esempio di soluzione dell'esercizio.