Corsi di laurea in Ingegnera Elettronica e Ingegneria Gestionale Fondamenti di Programmazione / Fondamenti di Informatica I
Prova scritta del 2 febbraio 2016
Esercizio 1 (16 punti)
Un file di testo contiene le equivalenze tra unità di misura, nel formato che si evince dall’esempio a lato.
Le unità di misura sono sempre formate da una sola parola, il secondo elemento di ogni riga è sempre la freccia rappresentata con i caratteri “-->” e il quarto elemento è sempre un asterisco, ad indicare l’operazione di moltiplicazione necessaria per la conversione. Il file contiene al massimo 100 regole di traduzione.
Un secondo file, di lunghezza ignota, contiene delle grandezze che devono essere convertite, nel formato deducibile dall’esempio del riquadro a lato.
Si scriva una funzione che riceva come argomenti il nome del file di equivalenze sopra descritto, il nome di un file di grandezze (con i punti interrogativi) e il nome di un file di uscita. La funzione deve copiare le righe del file di ingresso in quello di uscita sostituendo ai punti interrogativi i valori corretti.
Si assuma che per tutte le coppie di unità di misura utilizzate in ogni riga del file delle grandezze sia presente una regola di conversione nel file delle equivalenze (eventualmente da utilizzare invertita, come nei casi “9782 cmq
= ? mq” e “7 mm = ? m” dell’esempio). Quindi è sempre sufficiente cercare ed applicare una e una sola regola di conversione.
Relativamente agli esempi sopra riportati, al termine dell’esecuzione della funzione il file di uscita dovrà contenere quanto riportato a lato.
NOTA: è accettabile che il formato numerico dei dati di ingresso cambi nel file di uscita. Per esempio, “9782 cmq
= ? mq” può anche diventare “9.782e3 cmq = 0.9782 mq” o “7 km = ? m” può diventare “7.0 km = 7000.0 m”, ecc.
#include <stdio.h>
#include <stdlib.h>
#define MAXDIM 100 struct equivalenza {
char nome_da[32];
char nome_a[32];
double fattore_di_conversione;
};
struct conversione {
char nome_da[32];
char valore_da_str[32]; /* opzionale, serve per mantenere il formato */
double valore_da;
char nome_a[32];
double valore_a;
};
void esegui_conversioni (char nomefile_equivalenze[],
char nomefile_in[], char nomefile_out[]);
int carica_equivalenze (FILE *fp, struct equivalenza equivalenze[], int maxdim);
double fattore_conversione (char da[], char a[],
struct equivalenza equivalenze[], int dim);
m --> cm * 100 m --> mm * 1000 km --> m * 1000 mq --> cmq * 10000
7 km = ? m 123.56 m = ? cm 9782 cmq = ? mq 7 mm = ? m
7 km = 7000 m
123.56 m = 12356 cm
9782 cmq = 0.9782 mq
7 mm = 0.007 m
int main (int argc, char *argv[]) /* non richiesto nella prova scritta */
{
if (argc != 4) {
printf ("numero di argomenti sbagliato: "
"<file equivalenze> <file ingresso> <file uscita>\n");
exit (EXIT_FAILURE);
}
esegui_conversioni (argv[1], argv[2], argv[3]);
return EXIT_SUCCESS;
}
void esegui_conversioni (char nomefile_equivalenze[],
char nomefile_in[], char nomefile_out[]) {
struct conversione c;
struct equivalenza equivalenze[MAXDIM];
double fattore_di_conversione;
int dim;
FILE *fpeq, *fpin, *fpout;
if ((fpeq = fopen (nomefile_equivalenze, "r")) == NULL) {
printf ("errore apertura tabella equivalenze\n");
exit (EXIT_FAILURE);
}
dim = carica_equivalenze (fpeq, equivalenze, MAXDIM);
fclose (fpeq);
if ((fpin = fopen (nomefile_in, "r")) == NULL) {
printf ("errore apertura file di ingresso\n");
exit (EXIT_FAILURE);
}
if ((fpout = fopen (nomefile_out, "w")) == NULL) {
printf ("errore apertura file di uscita\n");
exit (EXIT_FAILURE);
}
while (fscanf (fpin, "%s %s %*s %*s %s",
c.valore_da_str, c.nome_da, c.nome_a) != EOF) {
c.valore_da = atof (c.valore_da_str);
fattore_di_conversione = fattore_conversione
(c.nome_da, c.nome_a, equivalenze, dim);
if (fattore_di_conversione < 0) {
printf ("errore: conversione da %s a %s non presente in tabella\n", c.nome_da, c.nome_a);
} else {
fprintf (fpout, "%s %s = %g %s\n", c.valore_da_str, c.nome_da,
c.valore_da * fattore_di_conversione, c.nome_a);
} }
fclose (fpin);
fclose (fpout);
return;
}
int carica_equivalenze (FILE *fp, struct equivalenza equivalenze[], int maxdim) {
int cnt = 0;
while (cnt < maxdim && fscanf (fp, "%s %*s %s %*s %lf",
equivalenze[cnt].nome_da, equivalenze[cnt].nome_a, &equivalenze[cnt].fattore_di_conversione) != EOF) {
cnt++;
}
return cnt;
}
double fattore_conversione (char da[], char a[],
struct equivalenza equivalenze[], int dim) {
int i;
/* cerca conversione diretta */
i = 0;
while (i < dim) {
if (strcmp (da, equivalenze[i].nome_da) == 0 &&
strcmp (a, equivalenze[i].nome_a) == 0) return equivalenze[i].fattore_di_conversione;
i++;
}
/* cerca conversione diretta */
i = 0;
while (i < dim) {
if (strcmp (da, equivalenze[i].nome_a) == 0 &&
strcmp (a, equivalenze[i].nome_da) == 0)
return 1.0 / equivalenze[i].fattore_di_conversione;
i++;
}
return -1;
}
Esercizio 2 (14 punti)
Due file di testo contengono due elenchi di nomi di lunghezza ignota. Ogni riga di ciascun file contiene uno e un solo nome, che può essere composto da più parole separate da spazi. I nomi in entrambi i file sono ordinati in ordine alfabetico e il formato in cui sono scritti
(spaziature, ecc.) è identico.
Si scriva un programma che riceva sulla riga di comando i nomi dei due file e stampi sul monitor i nomi che compaiono in entrambi i file.
Per esempio, se il contenuto dei due file è quello riportato nei riquadri a lato, il programma deve stampare il risultato che segue:
# nomi_in_entrambi_i_file autori_1.dat autori_2.dat Alessandro Baricco
Andy Weir Dan Brown
Herbert George Wells Matilde Asensi
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int stampa_nomi_in_comune (FILE *fp1, FILE *fp2);
int main (int argc, char *argv[]) {
FILE *fp1, *fp2;
if (argc != 3) {
printf ("servono i nomi di due file come argomenti\n");
exit (EXIT_FAILURE);
}
if ((fp1 = fopen (argv[1], "r")) == NULL) {
printf ("errore apertura file 1\n");
exit (EXIT_FAILURE);
}
if ((fp2 = fopen (argv[2], "r")) == NULL) {
printf ("errore apertura file 1\n");
exit (EXIT_FAILURE);
}
stampa_nomi_in_comune (fp1, fp2);
fclose (fp1);
fclose (fp2);
return EXIT_SUCCESS;
}
File autori_1.dat:
Alessandro Baricco Andrea Camilleri Andy Weir
Dan Brown
Herbert George Wells J. K. Rowling
Matilde Asensi
File autori_2.dat:
Alessandro Baricco Andy Weir
Dan Brown
Frank Schatzing Herbert George Wells Matilde Asensi
Umberto Eco
int leggi_nome (FILE *fp, char s[]) {
if (fgets (s, 64, fp) == NULL) return 0;
s[strlen(s)-1] = '\0'; /* rimuovi il '\n' */
return 1;
}
int stampa_nomi_in_comune (FILE *fp1, FILE *fp2) {
char s1[64], s2[64];
int confronto, fine = 0;
if (leggi_nome (fp1, s1) == 0) return;
if (leggi_nome (fp2, s2) == 0) return;
fine = 0;
while (!fine) {
confronto = strcmp (s1, s2);
if (confronto == 0) /* se uguali stampa e avanza in entrambi i file */
{
puts (s1);
if (leggi_nome (fp1, s1) == 0) fine = 1;
if (leggi_nome (fp2, s2) == 0) fine = 1;
} else {
/* avanza nel file la cui parola corrente viene prima in ordine alfabetico */
if (confronto < 0) {
if (leggi_nome (fp1, s1) == 0) fine = 1;
} else {
if (leggi_nome (fp2, s2) == 0) fine = 1;
} } } return;
}