Università degli Studi di Udine
Corsi di laurea in Ing. Elettronica e Ing. Gestionale Fondamenti di programmazione
25 novembre 2011 - Prova intermedia
Matricola __________________
Nome _____________________
Cognome __________________
Esercizio 1 (5 punti)
Un treno, identificato da un codice numerico, è formato da un numero massimo NCMAX di carrozze, di cui nc effettivemente presenti; ciascuna carrozza dispone di un numero massimo NPMAX di posti a sedere, di cui np effettivi. Ogni posto è identificato dalla sua posizione (da 0 a np-1) e contiene due informazioni: il tipo (‘c’ per corridoio, ‘f’ per finestrino) e un vettore di prenotazione. Il vettore di prenotazione è lungo MAXTRATTE e rappresenta tutte le tratte del treno (cioè i percorsi tra stazioni adiacenti). Per esempio, se tale vettore contiene uno nelle posizioni 0, 1 e 2 e zero in tutte le altre significa che il posto è prenotato nelle prime tre tratte (cioè fino alla quarta stazione, contando anche la stazione di partenza).
Si consideri il segmento di codice riportato a fianco, utilizzato per rappresentare tale treno.
Si completi la seguente funzione che cerca nel treno un posto libero del tipo specificato (corridoio o finestrino) dalla tratta tr_inizio alla tratta tr_fine e restituisce by reference il numero di carrozza e il numero di posto. Il codice di ritorno della funzione è uno se un posto con tali caratteristiche è disponibile e zero altrimenti.
Si consideri già disponibile la funzione
verifica_posto_libero (int tratte_prenotate[], int indice_prima_tratta, int indice_ultima_tratta)
che riceve un vettore di prenotazioni del posto a sedere e verifica se in esso non risultano prenotate tutte le tratte comprese tra i due indici passati come argomenti (estremi inclusi).
int cerca_posto_libero (struct tipo_treno treno, int tratta_inizio, char tipo, int tratta_fine, int *p_ncarrozza, int *p_nposto) {
int indice_carrozza, indice_posto;
indice_carrozza = 0;
while (_________________________________) {
indice_posto = 0;
while (___________________________________________) {
if (______________________________________________________
______________________________________________________
______________________________________________________) {
______________________________
______________________________
return 1;
}
indice_posto++;
}
indice_carrozza++;
}
return 0;
}
int cerca_posto_libero (struct tipo_treno treno, int tratta_inizio, char tipo, int tratta_fine, int *p_ncarrozza, int *p_nposto) {
int indice_carrozza, indice_posto;
struct tipo_posto {
char tipo;
int prenotazioni[MAXTRATTE];
};
struct tipo_carrozza {
int numero_carrozza;
int np;
struct tipo_posto posti[NPMAX];
};
struct tipo_treno {
int codice_treno;
int nc;
struct tipo_carrozza carrozze[NCMAX];
};
indice_carrozza = 0;
while (indice_carrozza < treno.nc) {
indice_posto = 0;
while (indice_posto < treno.carrozze[indice_carrozza].np) {
if (treno.carrozze[indice_carrozza].posti[indice_posto].tipo == tipo && verifica_posto_libero
(treno.carrozze[indice_carrozza].posti[indice_posto].prenotazioni, tratta_inizio, int tratta_fine))
{
*p_ncarrozza = indice_carrozza;
*p_nposto = indice_posto;
return 1;
}
indice_posto++;
}
indice_carrozza++;
}
return 0;
}
Esercizio 2 (3 punti)
Si consideri la seguente funzione:
int f (int a, int *p, char s[]) {
int *q = &a;
*p = *q + 1;
s[0] = a++ + '0';
s[1] = '\0';
return a;
}
Cosa stamperà il seguente frammento di codice?
int y, z, x = 1; /* oppure 2, 3 nelle diverse versioni */
char str[10];
z = f (x, &y, str);
printf ("%d %d %s", z, y, str);
2 2 1 (versione x = 1) 3 3 2 (versione x = 2) 4 4 3 (versione x = 3)
Esercizio 3 (4 punti)
In una gara motociclistica i tempi sono misurati in ore, minuti, secondi e millesimi di secondo, tutti interi. Si completi la seguente funzione , che calcola il tempo totale di gara sommando i tempi delle due prove parziali passati come parametri.
struct tempo somma_tempi (struct tempo tempo1, struct tempo tempo2) {
tempo1.h = _______________________;
tempo1.m = _______________________;
tempo1.s = _______________________;
tempo1.ms = ______________________;
return normalizza (tempo1);
}
struct tempo normalizza (struct tempo t) {
int riporto;
riporto = __________________;
t.ms = __________________;
t.s = __________________;
riporto = __________________;
t.s = __________________;
t.m = __________________;
riporto = __________________;
t.m = __________________;
t.h = __________________;
return t;
}
struct tempo somma_tempi (struct tempo tempo1, struct tempo tempo2) {
tempo1.h = tempo1.h + tempo2.h;
tempo1.m = tempo1.m + tempo2.m;
tempo1.s = tempo1.s + tempo2.s;
tempo1.ms = tempo1.ms + tempo2.ms;
return normalizza (tempo1);
}
struct tempo normalizza (struct tempo t) {
int riporto;
riporto = t.ms / 1000;
t.ms = t.ms % 1000;
t.s = t.s + riporto;
riporto = t.s / 60;
t.s = t.s % 60;
t.m = t.m + riporto;
riporto = t.m / 60;
t.m = t.m % 60;
t.h = t.h + riporto;
return t;
}
Esercizio 4 (7 punti)
Si scriva la funzione void specchia (char s[]) che raddoppia in modo speculare il contenuto della stringa s, aggiungendo al fondo i caratteri in essa contenuti in modo da renderne il contenuto palindromo. Si considerino spazi e simboli di interpunzione alla stregua delle lettere e si raddoppi anche il carattere centrale del risultato. Si assuma che la lunghezza massima della stringa s sia ignota, ma che sia comunque sufficiente a contenere tutti i caratteri necessari.
Esempio: “testo di prova!” → “testo di prova!!avorp id otset”
void specchia (char s[]) {
int i, j;
j = strlen (s); /* indice del '\0', dove inizio a copiare i caratteri */
i = j - 1; /* indice del primo carattere da copiare */
while (i >= 0) {
s[j] = s[i];
i--;
j++;
}
s[j] = '\0';
return;
}
Esercizio 5 (5 punti)
Un programma C legge una sequenza dati da un file di testo e li memorizza nel seguente vettore di strutture:
struct tipo_esame {
char nome_esame[64];
int voto;
char lode;
};
Il campo lode vale uno o zero.
Il formato dei dati di ingresso si evince dal seguente esempio:
Fondamenti di programmazione: 30L Algebra linare: 27
Le seguenti funzioni contengono diversi errori sintattici e semantici. Li si identifichino e li si correggano.
int carica_vettore_esami (FILE *fp, struct tipo_esame miei_esami[], int maxdim) {
char str[];
int i = 0;
while (i <= maxdim && fgets(str, 128, fp) != NULL) {
miei_esami[i] = estrai_dati (str[i]);
i++;
}
return i;
}
int estrai_dati (char s[]) {
struct esame;
char voto_in_cifre[8];
int i, j;
i = 0;
while (s[i] != ':') {
esame.nome_esame[i] = s[i];
i++;
} i++;
while (!isdigit(s[i])) i++;
j++;
while (isdigit(s[i])) {
voto_in_cifre[j] = s[i];
i++;
j++;
}
esame.voto = atoi (voto_in_cifre);
if (strcmp (s[i], 'L') == 0) esame.lode = 1;
else
esame.lode = 0;
return esame;
}
Soluzione:
int carica_vettore_esami (FILE *fp, struct tipo_esame miei_esami[], int maxdim) {
char str[];
int i = 0;
while (i <= maxdim && fgets(str, 128, fp) != NULL) {
miei_esami[i] = estrai_dati (str[i]);
i++;
}
return i;
}
int estrai_dati (char s[]) struct tipo_esame estrai_dati (...
{
struct esame; struct tipo_esame esame;
char voto_in_cifre[8];
int i, j;
i = 0;
while (s[i] != ':') {
esame.nome_esame[i] = s[i];
i++;
}
esame.nome_esame[i] = '\0';
i++;
while (!isdigit(s[i])) i++;
j++; j = 0;
while (isdigit(s[i])) {
voto_in_cifre[j] = s[i];
i++;
j++;
}
voto_in_cifre[j] = '\0';
esame.voto = atoi (voto_in_cifre);
if (strcmp (s[i], 'L') == 0) s[i] == 'L' esame.lode = 1;
else
esame.lode = 0;
return esame;
}
Esercizio 6 (3 punti)
Mettere in corrispondenza (tracciando delle linee) le dichiarazioni di variabili riportate a destra con le espressioni riportate a sinistra. Ogni elemento a sinistra deve avere una e una sola corrispondenza con un elemento a destra.
int b; "NO"
double z; -5
char k; 1000000000 / 3
char s[2] ""
char s[10] 1.0
int b; 1000000000 / 3
double z; 1.0
char k; -5
char s[2] ""
char s[10] "NO"
Esercizio 7 (3 punti)
Arrivati ad un certo punto della progettazione di un programma avete definito la rappresentazione dei dati mediante un vettore di strutture:
struct tipo_miei_dati {
char nome[16];
int numero;
};
struct tipo_miei_dati dati[100];
Ora iniziate a progettare una funzione che riempia l’elemento di indice i del vettore, leggendo i valori dalla tastiera ed eseguendo alcuni controlli di correttezza dei dati stessi. La funzione, oltre a riempire l’elemento del vettore, deve anche restituire uno se l’operazione è avvenuta correttamente e zero se i dati inseriti non erano corretti e quindi l’inserimento non è stato eseguito.
a) Si scriva la dichiarazione (non la definizione!) di tale funzione, tale da consentirne l’utilizzo sopra descritto.
int leggi_miei_dati (struct tipo_miei_dati *p_dati);
b) Assumendo che nel programma chiamante la variabile risultato dovrà contenere uno se la lettura è andata a buon fine e zero altrimenti, si scriva un esempio di chiamata di tale funzione.
risultato = leggi_miei_dati (&dati[i]);