Esercizio: Calcolo dell'orario a partire dal numero di secondi

Esercizio

Vogliamo realizzare una funzione chiamata calcolo_orario.

Questa funzione ha come tipo di ritorno void e prende in ingresso il numero di secondi totali trascorsi dalla mezzanotte. Deve restituire l'orario corrispondente in termini di ore, minuti e secondi corrispondenti.

Ad esempio, fornendo in ingresso il valore 41130 la funzione deve restituire tre valori corrispondenti a:

  • Numero di ore: 11;
  • Numero di minuti: 25;
  • Numero di secondi: 30.

Implementazione

Leggendo il testo di questo esercizio, la prima cosa che dobbiamo notare è che la funzione calcolo_orario prende in ingresso un parametro, il numero di secondi, e restituisce ben tre valori: il numero di ore, il numero di minuti e il numero di secondi.

Per questo motivo dobbiamo usare i puntatori come argomenti della funzione. Una possibile firma della funzione è la seguente:

void calcolo_orario(tipo numero_secondi, tipo *ore, tipo *minuti, tipo *secondi);

Quindi l'argomento numero_secondi sarà passato per copia, mentre gli argomenti ore, minuti e secondi saranno passati sotto forma di puntatori.

Ciò che rimane da capire è il tipo di questi argomenti.

Per il tipo numero_secondi possiamo usare un long int, o semplicemente long, in quanto rappresenta il numero di secondi trascorso ma il testo dell'esercizio non ci fornisce un limite superiore al suo valore. Motivo per cui scegliamo un long rendendo la funzione abbastanza robusta per gestire numeri elevati. Dal momento che il numero di secondi trascorso non può essere negativo possiamo usare un unsigned long.

Per quanto riguarda ore, minuti e secondi possiamo banalmente usare un unsigned int, o semplicemente unsigned. Infatti, le ore sono comprese tra 0 e 23 mentre minuti e secondi sono compresi tra 0 e 59.

Per tal motivo la signature della funzione diventa:

void calcolo_orario(unsigned long numero_secondi,
                    unsigned int *ore,
                    unsigned int *minuti,
                    unsigned int *secondi);

Proviamo adesso ad implementare la funzione.

La prima operazione da effettuare è quella di riportare il numero di secondi totale in un intervallo compreso tra 0 e il numero massimo di secondi che trascorrono in un giorno. Infatti il numero di secondi in un giorno è pari a:

\mbox{secondi} = 24 \cdot 60 \cdot 60 = 86400

Se il parametro numero_secondi dovesse sforare questo valore dobbiamo riportarlo nell'intervallo [0, 86400]. Per cui:

void calcolo_orario(unsigned long numero_secondi,
                    unsigned int *ore,
                    unsigned int *minuti,
                    unsigned int *secondi) {

    const long numero_secondi_in_un_giorno = 86400;

    /*
     * Riportiamo il numero totale di secondi
     * nell'intervallo [0, 86400]
     */
    numero_secondi %= numero_secondi_in_un_giorno;

    /* ... */

}

Abbiamo usato l'operazione di modulo. In questo modo scartiamo eventualmente il numero di secondi corrispondenti ad uno o più giorni completi.

Adesso dobbiamo calcolare il numero di ore. Per far questo basta dividere il numero di secondi totale per il numero di secondi che trascorrono in un'ora. Prima di ciò ci conviene però memorizzare il numero di secondi in eccedenza attraverso un'operazione di modulo. Per cui:

void calcolo_orario(unsigned long numero_secondi,
                    unsigned int *ore,
                    unsigned int *minuti,
                    unsigned int *secondi) {

    const long numero_secondi_in_un_giorno = 86400;
    const long numero_secondi_in_un_ora = 3600;

    /* Variabile di supporto */
    unsigned long secondi_rimanenti = 0;

    /*
     * Riportiamo il numero totale di secondi
     * nell'intervallo [0, 86400]
     */
    numero_secondi %= numero_secondi_in_un_giorno;

    /*
     * Calcoliamo il numero di ore e salviamo il numero
     * di secondi in eccedenza
     */
    secondi_rimanenti = numero_secondi % numero_secondi_in_un_ora;
    *ore = (numero_secondi - secondi_rimanenti) / numero_secondi_in_un_ora;

    /* ... */

}

Applichiamo lo stesso ragionamento anche al calcolo dei minuti:

void calcolo_orario(unsigned long numero_secondi,
                    unsigned int *ore,
                    unsigned int *minuti,
                    unsigned int *secondi) {

    const long numero_secondi_in_un_giorno = 86400;
    const long numero_secondi_in_un_ora = 3600;

    /* Variabile di supporto */
    unsigned long secondi_rimanenti = 0;

    /*
     * Riportiamo il numero totale di secondi
     * nell'intervallo [0, 86400]
     */
    numero_secondi %= numero_secondi_in_un_giorno;

    /*
     * Calcoliamo il numero di ore e salviamo il numero
     * di secondi in eccedenza
     */
    secondi_rimanenti = numero_secondi % numero_secondi_in_un_ora;
    *ore = (numero_secondi - secondi_rimanenti) / numero_secondi_in_un_ora;

    /*
     * Calcoliamo il numero di minuti e salviamo il numero
     * di secondi in eccedenza
     */
    *secondi = secondi_rimanenti % 60;
    *minuti = (secondi_rimanenti - *secondi) / 60;
}

Programma completo

Scriviamo, adesso, un programma completo che richiede un numero di secondi all'utente e stampa il numero di ore, minuti e secondi corrispondente:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include <stdio.h>

void calcolo_orario(unsigned long numero_secondi,
                    unsigned int *ore,
                    unsigned int *minuti,
                    unsigned int *secondi);

int main() {
    unsigned long numero_secondi = 0;

    /* Variabili per il calcolo dell'orario */
    unsigned int ore = 0;
    unsigned int minuti = 0;
    unsigned int secondi = 0;

    /* Chiede all'utente di inserire un numero di secondi */
    printf("Inserisci un numero di secondi: ");
    scanf("%lu", &numero_secondi);

    /* Calcola l'orario */
    calcolo_orario(numero_secondi, &ore, &minuti, &secondi);

    /* Stampa l'orario */
    printf("%lu secondi corrispondono a %u ore, %u minuti e %u secondi\n",
           numero_secondi, ore, minuti, secondi);

    return 0;
}

void calcolo_orario(unsigned long numero_secondi,
                    unsigned int *ore,
                    unsigned int *minuti,
                    unsigned int *secondi) {

    const long numero_secondi_in_un_giorno = 86400;
    const long numero_secondi_in_un_ora = 3600;

    /* Variabile di supporto */
    unsigned long secondi_rimanenti = 0;

    /*
     * Riportiamo il numero totale di secondi
     * nell'intervallo [0, 86400]
     */
    numero_secondi %= numero_secondi_in_un_giorno;

    /*
     * Calcoliamo il numero di ore e salviamo il numero
     * di secondi in eccedenza
     */
    secondi_rimanenti = numero_secondi % numero_secondi_in_un_ora;
    *ore = (numero_secondi - secondi_rimanenti) / numero_secondi_in_un_ora;

    /*
     * Calcoliamo il numero di minuti e salviamo il numero
     * di secondi in eccedenza
     */
    *secondi = secondi_rimanenti % 60;
    *minuti = (secondi_rimanenti - *secondi) / 60;
}

Compilando ed eseguendo il programma, proviamo a passare il numero 41130 che corrisponde ad 11 ore, 30 minuti e 25 secondi:

Inserisci un numero di secondi: 41130
41130 secondi corrispondono a 11 ore, 25 minuti e 30 secondi

Provando a inserire un numero maggiore di 86400, ad esempio 192441, otteniamo il seguente risultato:

Inserisci un numero di secondi: 192441
192441 secondi corrispondono a 5 ore, 27 minuti e 21 secondi

Il risultato è corretto in quanto 192441 secondi corrispondono a 2 giorni, 5 ore, 27 minuti e 21 secondi. Se sottraiamo a questo numero il numero di secondi che corrispondono a 2 giorni otteniamo:

192441 - (86400 \cdot 2) = 19641

Provando a passare questo valore al nostro programma otteniamo:

Inserisci un numero di secondi: 19641
19641 secondi corrispondono a 5 ore, 27 minuti e 21 secondi

Ossia il risultato che abbiamo ottenuto prima.