Università degli Studi di Udine
Corsi di laurea in Ingegneria Elettronica Fondamenti di programmazione
12 novembre 2010 - Prova intermedia
Matricola __________________
Nome _____________________
Cognome __________________
Esercizio 1 (3 punti)
Una piccola biblioteca dispone di 10 scaffalature, ciascuna con 8 scaffali, contenenti un massimo di 40 libri ciascuno. Si consideri il segmento di codice riportato a fianco, utilizzato per rappresentare tale biblioteca.
Si completi la seguente funzione che restituisce il numero di libri presenti in biblioteca pubblicati nell’anno passato come argomento.
int conta_libri_in_anno (____________________________________________________) {
int i, j, i_libro, somma = 0;
for (i = 0; i < 10; i++) for (j = 0; j < 8; j++)
for (i_libro = 0; __________________________________________; i_libro++)
if ( ___________________________________________ == anno) somma++;
return somma;
}
int conta_libri_in_anno (struct scaffale bib[][8], int anno) {
int i, j, i_libro, somma = 0;
for (i = 0; i < 10; i++) for (j = 0; j < 8; j++)
for (i_libro = 0; i_libro < bib[i][j].nlibri; i_libro++) if (bib[i][j].libro[i_libro].anno_pubblicazione == anno) somma++;
return somma;
}
Esercizio 2 (4 punti)
A) Si definisca una struttura dati adatta a rappresentare un angolo espresso in gradi, primi e secondi.
B) Si scriva la funzione confronta_angoli che riceva come argomenti due angoli alpha e beta e restituisca:
0 se alpha e beta differiscono per meno di 10-6 secondi;
-1 se alpha è minore di beta;
+1 se alpha è maggiore di beta.
Si assuma che entrambi gli angoli siano compresi nell’intervallo [0, 2π[.
struct tipo_libro {
char titolo[64];
char autori[64];
char casa_editrice[64];
int anno_pubblicazione;
};
struct scaffale {
int n_libri;
struct tipo_libro libro[40];
};
struct scaffale biblioteca[10][8];
struct angolo {
int gradi;
int primi;
double secondi;
};
int confronta_angoli (struct angolo alpha, struct angolo beta) {
/* assumiamo che i secondi e i primi siano inferiori a 60;
in caso contrario dovremmo scrivere e chiamare una funzione per eseguire i cicli per la normalizzazione visti a lezione */
if (alpha.gradi < beta.gradi) return -1;
else if (alpha.gradi > beta.gradi) return 1;
else
{ /* i gradi sono uguali */
if (alpha.primi < beta.primi) return -1;
else if (alpha.primi > beta.primi) return 1;
else
{ /* anche i primi sono uguali */
if (abs (alpha.secondi - beta.secondi) < 1e-6) return 0;
else if (alpha.secondi < beta.secondi) return -1;
else
return 1;
} } }
Esercizio 3 (6 punti)
Si scriva la funzione strtail (char s[], char t[], int n) che copia nella stringa s gli ultimi n caratteri della stringa t, oppure l’intera stringa t se n > strlen(t).
void strtail (char s[], char t[], int n) {
int inizio, lungh_t;
lungh_t = strlen(t);
if (lungh_t > n)
inizio = lungh_t - n;
else
inizio = 0;
strcpy (s, t + inizio);
return;
}
Esercizio 4 (7 punti)
Un file di testo contiene copia dei dati di un’agenda elettronica. Ogni appuntamento è memorizzato in una riga del file nel seguente formato:
gg-mm-aaaa hh:00-hh:00 <descrizione appuntamento>
Il giorno e il mese sono sempre rappresentati su due cifre. I due orari (nell’ordine, inizio e fine dell’appuntamento) hanno sempre il valore dei minuti a 00 perché l’agenda in questione gestisce solo appuntamenti a ore intere. La descrizione dell’appuntamento è delimitata dai caratteri '<' e '>'.
L’ordine degli appuntamenti nel file è quello con cui sono stati inseriti dall’utente nell’agenda.
Si scriva una funzione che riceva come argomenti il nome di un file siffatto e una struct data (definita come visto a lezione). La funzione deve verificare se nella data specificata ci sono appuntamenti che si sovrappongono, stampando a video le descrizioni degli appuntamenti che sono in orari già impegnati da appuntamenti inseriti in precedenza.
Suggerimento: si utilizzi un vettore che rappresenti le ore della giornata e in cui la funzione annoti se un’ora è impegnata da un appuntamento o se è libera.
struct data {
int giorno;
int mese;
int anno;
};
struct appuntamento {
struct data d;
int ora_inizio;
int ora_fine;
char descrizione[100];
};
void verifica_appuntamenti (char nomefile[], struct data d) {
FILE *fpin;
char riga[200], tmp[16];
struct appuntamento app;
int ore_impegnate[24] = {0};
int i, ora, stampa;
if ((fpin = fopen (nomefile, "r")) == NULL) {
printf ("errore apertura file di ingresso\n");
exit (EXIT_FAILURE);
}
/* metodo 1:
while (fscanf (fpin, "%d%*c%d%*c%d %d%*c%*d%*c%d%*c%*d", &app.d.giorno, &app.d.mese, &app.d.anno, &app.ora_inizio, &app.ora_fine) != EOF) {
fgets (app.descrizione, 100, fpin);
...
problema: bisogna togliere gli spazi all'inizio della descrizione e il \n alla fine. */
/* metodo 2: */
while (fgets (riga, 200, fpin) != NULL) {
i = estrai_stringa (riga, '/', tmp);
app.d.giorno = atoi(tmp);
i++;
i += estrai_stringa (riga + i, '/', tmp);
app.d.mese = atoi(tmp);
i++;
i += estrai_stringa (riga + i, ' ', tmp);
app.d.anno = atoi(tmp);
i++;
i += estrai_stringa (riga + i, ':', tmp);
app.ora_inizio = atoi(tmp);
i++;
i += estrai_stringa (riga + i, '-', tmp);
i++;
i += estrai_stringa (riga + i, ':', tmp);
app.ora_fine = atoi(tmp);
i++;
i += estrai_stringa (riga + i, ' ', tmp);
i++;
i = estrai_stringa (riga + i, '\n', app.descrizione);
stampa = 0;
if (app.d.giorno == d.giorno && app.d.mese == d.mese && app.d.anno == d.anno) {
for (ora = app.ora_inizio; ora <= app.ora_fine; ora++) {
if (ore_impegnate[ora] == 1) stampa = 1;
else
ore_impegnate[ora] = 1;
}
if (stampa)
printf ("%d/%d/%d %d-%d %s\n", app.d.giorno, app.d.mese, app.d.anno, app.ora_inizio, app.ora_fine, app.descrizione);
} }
fclose (fpin);
return;
}
/* funzione usata dal metodo 2 (vista a lezione): */
int estrai_stringa (char s[], char separatore, char out[]) {
int i_s, i_out;
i_s = 0;
i_out = 0;
while (s[i_s] != '\0' && s[i_s] == ' ') i_s++;
while (s[i_s] != '\0' && s[i_s] != separatore) {
out[i_out] = s[i_s];
i_s++;
i_out++;
}
out [i_out] = '\0';
return i_s;
}
Esercizio 5 (2 punti)
Osservando il contenuto della memoria in corrispondenza dell’indirizzo della variabile int x si trova (in esadecimale):
FFFFFFFFh. Di conseguenza, cosa stampa la seguente istruzione?
printf ("%d %X %d\n", x, x, x + 0xA);
-1 FFFFFFFF 9
Esercizio 6 (8 punti)
Sia data la funzione double f (double x) che calcola il valore di una funzione matematica f in corrispondenza del valore di x.
Si scriva una funzione che verifica se f è monotona, crescente o decrescente. La funzione riceve come parametri tre valori reali a, b e delta e verifica la monotonicità valutando f nell'intervallo [a,b] campionandolo con passo pari a delta (cioè calcolando i valori di f per x = a, x = a + delta, x = a + 2·delta, x = a·delta, ..., finché non si raggiunge o si supera b).
La funzione deve restituire 1 se f è monotona crescente, -1 se è monotona decrescente e 0 altrimenti.
int monotona (double a, double b, double delta) {
int cresce = 0, decresce = 0;
double x = a, precedente, corrente;
precedente = f(x);
x += delta;
while (x < b) {
corrente = f(x);
if (corrente > precedente) cresce = 1;
else if (corrente < precedente) decresce = 1;
x += delta;
}
if (cresce && !decresce) return 1;
else if (decresce && !cresce) return -1;
else
return 0;
}