Fondamenti di Informatica I / Fondamenti di Programmazione Prova scritta del 29 gennaio 2013
Esercizio 1 (10 punti)
Una gara di sci a staffetta è organizzata in modo tale che ogni concorrente di una squadra, all’arrivo, debba premere un pulsante per aprire il cancello di partenza del concorrente successivo della propria squadra (tranne l’ultimo, ovviamente). Ogni squadra è composta da tre concorrenti. Il sistema memorizza l’orario di partenza e di arrivo di ogni concorrente in un vettore di strutture di tipo struct concorrente, definito come riportato a lato.
Poiché gareggiano quattro squadre alla volta, il sistema registra orari di partenza e arrivo in ordine cronologico, senza raggrupparli per squadra.
Si scriva una funzione in linguaggio C che riceva come parametri il nome di una squadra, il vettore di strutture sopra descritto e un intero che ne rappresenti la lunghezza. La funzione deve restituire il tempo totale, in secondi (numero reale) impiegato da tale squadra. Se una squadra non ha
terminato la staffetta, cioè nel vettore non compaiono tutti e tre i concorrenti della squadra, la funzione deve restituire -1.0.
Si suggerisce di scrivere la funzione
double differenza_in_secondi (struct ora orario1, struct ora orario2)
che restituisce la differenza in seconti tra i due orari passati come argomenti (orario2 successivo a orario1).
struct ora {
int h;
int m;
double s;
};
struct concorrente {
char nome[64];
char squadra[32];
struct ora partenza;
struct ora arrivo;
};
double tempo_totale_squadra (char nome_squadra[], struct concorrente tempi[], int dim_tempi) {
int i, conteggio_arrivi;
double tempo_totale;
i = 0;
conteggio_arrivi = 0;
tempo_totale = 0.0;
while (i < dim_tempi && conteggio_arrivi < 3) {
if (strcmp (nome_squadra, tempi[i].squadra) == 0) {
tempo_totale += differenza_in_secondi (tempi[i].partenza, tempi[i].arrivo);
conteggio_arrivi++;
} i++;
}
if (conteggio_arrivi < 3) return -1;
else
return tempo_totale;
}
double differenza_in_secondi (struct ora orario1, struct ora orario2) {
return (orario2.h - orario1.h) * 3600 + (orario2.m - orario1.m) * 60 + orario2.s - orario1.s;
}
struct ora {
int h;
int m;
double s;
};
struct concorrente {
char nome[64];
char squadra[32];
struct ora partenza;
struct ore arrivo;
};
Esercizio 2 (15 punti)
Un file contiene le previsioni del tempo di una giornata, una previsione per riga. Ciascuna riga è formata da orario (ore e minuti nel formato hh:mm), temperatura prevista e previsione atmosferica (una stringa che può contenere anche spazi). La temperatura è un valore reale che può essere scritto sia in gradi Celsius che Fahrenheit (contraddistinti dalla lettera C oppure F). Come esempio, si consideri il seguente file.
01:30 0.8 C coperto con qualche pioggia 04:00 0.7 C pioggia debole
07:30 28.8 F pioggia debole 10:00 2.7 C pioggia debole 13:00 31.9 F pioggia debole 16:20 4.1 C pioggia debole 19:00 2.5 C pioggia e schiarite 21:15 -1.3 C sereno
22:10 0.2 C sereno
Si scriva una funzione in linguaggio C che riceva come parametro il nome di un file siffatto e restituisca, in una opportuna struttura dati, la temperatura minima della giornata (scritta in gradi Celsius), l'ora in cui è prevista e la relativa previsione atmosferica.
Si ricorda che la temperatura in gradi Celsius a partire da quella in gradi Fahrenheit si ottiene con la seguente formula:
oC = (
oF - 32) / 1,8.
Nell'esempio, la funzione dovrà restituire l'orario 7 e 30, la temperatura -1.778 (corrispondente a 28.8
oF) e la previsione “pioggia debole”.
struct previsione previsione_minima (char nomefile[]) {
FILE *fp;
char riga_file[128];
struct previsione p, pmin;
if ((fp = fopen (nomefile, "r")) == NULL) {
printf ("errore di apertura del file\n");
exit (EXIT_FAILURE);
}
/* inizializza la temperatura minima con il primo dato presente nel file */
if (fgets (riga_file, 128, fp) == NULL) {
printf ("il file e` vuoto\n");
fclose (fp);
exit (EXIT_FAILURE);
}
pmin = estrai_dati (riga_file);
while (fgets (riga_file, 128, fp) != NULL) {
p = estrai_dati (riga_file);
if (p.temperatura < pmin.temperatura) pmin = p;
}
fclose (fp);
return pmin;
}
struct previsione estrai_dati (char s[]) {
struct previsione p;
double temperatura;
char unita_di_misura[8];
int i, j;
/* estrai i valori numerici */
sscanf (s, "%d%*c%d %lf %s", &p.orario.h, &p.orario.m, &temperatura, unita_di_misura);
if (unita_di_misura[0] == 'F')
temperatura = converti_in_celsius (temperatura);
p.temperatura = temperatura;
/* cerca l'inizio del testo della previsione */
i = 0;
while (s[i] != 'C' && s[i] != 'F' && s[i] != '\0') i++;
i++;
/* salta gli spazi */
while (s[i] == ' ' && s[i] != 'F' && s[i] != '\0') i++;
/* copia il resto della stringa */
j = 0;
while (s[i] != '\0') {
p.testo_previsione[j] = s[i];
i++;
j++;
}
p.testo_previsione[j] = '\0';
return p;
}
double converti_in_celsius (double temperatura_in_fahrenheit) {
return (temperatura_in_fahrenheit - 32) / 1.8;
}
Esercizio 3 (5 punti)
Facendo riferimento all’esercizio precedente, il nome del file contenente le previsioni è così strutturato:
località_giorno_mese_anno.txt (esempio: udine_29_1_2012.txt ). Si scriva un programma in linguaggio C che
riceva come argomenti sulla riga di comando il nome della località e una data e chiami la funzione descritta
nell’esercizio precedente, stampando sul monitor i dati da essa restituiti.
#include <stdio.h>
#include <stdlib.h>
struct ora_minuti {
int h;
int m;
};
struct previsione {
struct ora_minuti orario;
double temperatura;
char testo_previsione[64];
};
struct previsione previsione_minima (char nomefile[]);
struct previsione estrai_dati (char s[]);
double converti_in_celsius (double temperatura_in_fahrenheit);
int main (int argc, char *argv[]) {
char nomefile[64];
struct previsione p;
if (argc != 5) {
printf ("servono 4 argomenti\n");
exit (EXIT_FAILURE);
}
sprintf (nomefile, "%s_%s_%s_%s.txt", argv[1], argv[2], argv[3], argv[4]);
p = previsione_minima (nomefile);
printf ("%d:%d, %f C, %s\n", p.orario.h, p.orario.m, p.temperatura, p.testo_previsione);
return EXIT_SUCCESS;
}