I vettori - Soluzione

Un esempio di soluzione per l'esercizio sui vettori è il seguente:

#include <stdlib.h>
#include <stdio.h>

#define MINVOTO 18
#define MAXVOTO 30
#define NVOTI   (MAXVOTO - MINVOTO + 1)
#define NMAX    100

int main() {
    char s[80];
    int n;
    int voti[NMAX];
    int i, voto;

    /* input dei dati */
    fgets(s, sizeof(s), stdin);
    n = atoi(s);

    /* se n <= 0 stampo una stringa di errore ed esco */
    if (n <= 0 || n > NMAX) {
        printf("[RISULTATO]\nerrore\n");
        /* NOTA: sarebbe bene restituire un numero != 0, ma pvcheck da errore */
        return 0;
    }

    /* ciclo di lettura dei voti validi */
    i = 0;
    do {
        fgets(s, sizeof(s), stdin);
        voto = atoi(s);

    /* memorizzo il voto e incremento i solo se il voto è valido */
        if (voto >= MINVOTO && voto <= MAXVOTO) {
            voti[i] = voto;
            i++;
        }
    } while (i < n);

    /* stampa valori */
    printf("[VALORI]\n");
    for (i = 0; i < n; i++)
        printf("%d\n", voti[i]);

    /* minimo */
    int min = voti[0];
    for (i = 1; i < n; i++)
        if (voti[i] < min)
            min = voti[i];
    printf("[MINIMO]\n");
    printf("%d\n", min);

    /* frequenze */
    int freq[NVOTI] = {0};
    for (i = 0; i < n; i++)
        freq[voti[i] - MINVOTO]++;
    printf("[FREQUENZE]\n");
    for (i = 0; i < NVOTI; i++)
        printf("%d\n", freq[i]);

    /* indice del voto piu` frequente */
    int maxIndice = 0;
    for (i = 1; i < NVOTI; i++)
        if (freq[i] > freq[maxIndice])
            maxIndice = i;

    /* devo sommare MINVOTO a maxIndice per ottenere il voto */
    printf("[MAXFREQ]\n");
    printf("%d\n", maxIndice + MINVOTO);

    return 0;
}

Commenti

Il funzionamento del programma è molto lineare:

  • all'inizio sono dichiarate una serie di macro, con le direttive #define, che definiscono le costanti relative ai limiti dei valori necessari
    • le macro sono utili per evitare di inserire direttamente nel codice i cosiddetti numeri magici, che rendono problematica la comprensione del codice e eventuali successive modifiche
  • il valore di n viene letto da testiera, e il costrutto if successivo serve a terminare il programma qualora il valore non sia compreso nell'intervallo [1,NMAX]
    • il controllo è necessario in quanto il vettore voti viene dimensionato per memorizzare NMAX elementi
  • il ciclo do-while permette di leggere i valori dei voti
    • si noti che l'indice i che conteggia il numero di voti validi letti viene incrementato solo nel caso in cui il voto letto sia corretto (quindi all'interno del costrutto if annidato nel do-while)
  • la stampa dei valori (marcatore [VALORI]) è un semplice ciclo for da 0 a n-1 che stampa tutti i valori nel vettore voti

Per cercare il minimo

  • viene assegnato alla variabile min il valore del primo elemento del vettore voti[0]
  • con un ciclo for si controllano tutti i voti successivi al primo
  • se si trova un valore inferiore a min ne si aggiorna il valore
  • alla fine si stampa il valore min

Il calcolo della frequenza dei voti è interessante:

  • l'istruzione freq[voti[i] - MINVOTO]++ incrementa di 1 l'elemento del vettore freq di indice voti[i]-MINVOTO
  • voti[i] è il valore del voto corrente, mentre MINVOTO è il valore minimo (18)
  • pertanto e il voto vale 18 verrà incrementato il valore di indice 0, se vale 19 quello di indice 1, ... e se vale 30 il valore di indice 13

Infine, per il calcolo del massimo delle frequenze:

  • si opera come per il minimo, ma invertendo il test per cercare il massimo, e analizzando il vettore freq invece che voti
  • da notare che in questo caso non si tiene traccia del valore massimo, ma dell'indice del valore massimo
  • tale indice viene poi utilizzato alla fine per recuperare il valore massimo dal vettore

Hands-on

La soluzione che include anche il calcolo richiesto dai due seguenti hands-on è vettori-completo.test.

Il programma completo si può testare con

pvcheck -f vettori-completo.test ./a.out

prova-tu Modifica la soluzione dell'esercizio per calcolare anche il massimo dei voti.

Stampi a video il massimo calcolato usando il formato:

[MASSIMO]
28

Suggerimenti

Si proceda come per il minimo, modificando opportunamente i test necessari.

Scopri un esempio di soluzione »

prova-tu Modifica la soluzione dell'esercizio per calcolare anche il voto medio.

Stampa a video la media dei voti usando il formato:

[MEDIA]
23.7

Suggerimenti

Come si vede nell'esempio di output, viene richiesto di stampare un numero con una sola cifra dopo la virgola; per farlo utilizzare lo specificatore di formato %.1f nella printf (gli specificatori di formato sono trattati in S2.12).

Il calcolo della media richiede la somma di tutti i valori, che viene divisa per il numero di valori sommati. Presta attenzione ai seguenti aspetti:

  • la divisione non deve essere fatta tra interi, in quanto il risultato verrebbe arrotondato
  • si può utilizzare un totale di tipo double, oppure fare il cast da intero a double in modo opportuno

Per calcolare la somma si usi un ciclo for (S4.6) e una variabile (es. totale) nella quale sommare il valore di tutti i numeri nel vettore.

Scopri un esempio di soluzione »

ATTENZIONE: non dimenticare di inizializzare la variabile totale assegnando il valore 0 (zero). Cosa succederebbe altrimenti?

Scopri un esempio di soluzione »