matricola, nome, cognome - diegm - Università degli Studi di Udine
Transcript
matricola, nome, cognome - diegm - Università degli Studi di Udine
Università degli Studi di Udine Corsi di laurea in Ing. Gestionale FONDAMENTI DI INFORMATICA (NUOVO ORDINAMENTO) 6 settembre 2006 – Prova scritta DA RIPORTARE SUL FOGLIO CHE VERRÀ CONSEGNATO: matricola, nome, cognome ISTRUZIONI (da leggere attentamente) 1) Lo studente è tenuto a scrivere, correggere, compilare ed eseguire su computer (a casa o in laboratorio) gli esercizi di programmazione prima della prova orale. Alla prova orale lo studente deve portare un floppy disk contenente i sorgenti dei programmi corretti e le stampe dei relativi file. 2) Non è consentito l’uso di libri, appunti, calcolatrici programmabili, telefoni cellulari. 1. (16 punti) Compilazione di un calendario lunare. Il mese lunare, cioè il periodo di tempo necessario perché la Luna si ripresenti nella stessa fase, dura 29 giorni, 12 ore, 44 minuti e 3 secondi, pari a 2551443 secondi. La luna entra quindi in una nuova fase (primo quarto, luna piena, ultimo quarto, luna nuova – nell’ordine) ogni 2551443/4 = 637860.75 secondi. Noto che la durata di un giorno di 24 ore è pari a di 86400 secondi, e noto che il giorno 20 dicembre 2006 sarà un mercoledì e inizierà la fase di luna nuova, si scriva un programma che riceva come argomento sulla linea di comando il nome di un file di testo e vi scriva un calendario che parta dal giorno 20 dicembre 2006 e arrivi fino al giorno 31 gennaio 2008 nel formato riportato a fianco, comprendente anno, mese, giorno della settimana e fasi lunari. (NOTA: per ragioni di spazio è stato riportato soltaqnto l’inizio del file di uscita). Si assuma che siano disponibili le funzioni struct data DataSuccessiva (struct data d) che restituisce in un’opportuna struct data la data successiva a quella passata nell’argomento d e int ConfrontaDate (struct data d1, struct data d2) che restituisce -1 se d1 viene prima di d2, 1 se d1 viene dopo d2 e zero se d1 == d2. 20 21 22 23 24 25 26 27 28 29 30 31 mercoledi` giovedi` venerdi` sabato domenica lunedi` martedi` mercoledi` giovedi` venerdi` sabato domenica 2007 gennaio 1 lunedi` 2 martedi` 3 mercoledi` 4 giovedi` 5 venerdi` 6 sabato 7 domenica 8 lunedi` 9 martedi` 10 mercoledi` 11 giovedi` 12 venerdi` 13 sabato 14 domenica 15 lunedi` 16 martedi` 17 mercoledi` 18 giovedi` 19 venerdi` 20 sabato 21 domenica ... #include <stdio.h> #include <stdlib.h> struct { int int int }; data giorno; mese; anno; /* NOTA: sono riportate soltanto le dichiarazioni delle funzioni richieste dal compito */ void CalendarioLunare (struct data inizio, int giorno_della_settimana, int fase, struct data fine, FILE *fp); char *GiornoInLettere (int giorno_della_settimana); char *MeseInLettere (int mese); char *FaseInLettere (int fase); int main(int argc, char *argv[]) { struct data inizio = { 20, 12, 2006 }; int giorno_della_settimana = 3; int fase = 4; struct data fine = { 31, 1, 2008 }; FILE *fp; if (argc != 2) { printf ("argomento: nome del file\n"); exit (EXIT_FAILURE); } if ((fp = fopen (argv[1], "w")) == NULL) { luna nuova primo quarto luna piena ultimo quarto luna nuova printf ("errore di apertura del file\n"); exit (EXIT_FAILURE); } CalendarioLunare (inizio, giorno_della_settimana, fase, fine, fp); fclose (fp); return EXIT_SUCCESS; } char *GiornoInLettere (int giorno_della_settimana) { static char nome_giorno[8][16] = { "", "lunedi` ", "martedi` ", "mercoledi`", "giovedi` "venerdi` ", "sabato ", "domenica " }; ", return nome_giorno[giorno_della_settimana]; } char *MeseInLettere (int mese) { static char nome_mese[13][16] = { "", "gennaio", "febbraio", "marzo", "aprile", "maggio", "giugno", "luglio", "agosto", "settembre", "ottobre", "novembre", "dicembre" }; return nome_mese[mese]; } char *FaseInLettere (int fase) { static char nome_fase[5][16] = { "", "primo quarto", "luna piena", "ultimo quarto", "luna nuova" }; return nome_fase[fase]; } void CalendarioLunare (struct data inizio, int giorno_della_settimana, int fase, struct data fine, FILE *fp) { struct data data_corrente; double secondi_residui_in_fase_corrente; /* NOTA: per semplicita` si assume che tutti gli argomenti siano corretti e si omettono quindi i possibili controlli */ data_corrente = inizio; secondi_residui_in_fase_corrente = 0; do { if (data_corrente.mese == 1 && data_corrente.giorno == 1) { /* stampa l'anno */ fprintf (fp, "\n%d\n", data_corrente.anno); } if (data_corrente.giorno == 1) { /* stampa il nome del mese */ fprintf (fp, " %s\n", MeseInLettere (data_corrente.mese)); } /* stampa il giorno */ fprintf (fp, " %2d %s", data_corrente.giorno, GiornoInLettere (giorno_della_settimana)); /* stampa la fase lunare */ if (secondi_residui_in_fase_corrente <= 0) { fprintf (fp, " %s", FaseInLettere (fase)); /* in realta` fase rappresenta la prossima fase da stampare */ if (++fase > 4) fase = 1; secondi_residui_in_fase_corrente += 637860.75; } fprintf (fp, "\n"); data_corrente = DataSuccessiva (data_corrente); if (++giorno_della_settimana > 7) giorno_della_settimana = 1; secondi_residui_in_fase_corrente -= 86400; } while (ConfrontaDate (data_corrente, fine) != 1); return; } 2. (16 punti) Alcuni credono che le fasi della luna influenzino le nascite. È facile dimostrare che non è così, avendo a disposizione un elenco anagrafico contenente le date di nascita di un numero sufficientemente elevato di persone. Scopo del seguente esercizio è scrivere un programma per effettuare in modo automatico tale verifica. Si assuma di disporre di un elenco anagrafico nel seguente formato: nome, cognome, luogo di nascita, data di nascita (in formato giorno – mese in lettere – anno) Nome, cognome e luogo di nascita possono essere composti di più parole. La lunghezza dell’elenco non è nota. Esempio: Mario, Rossi, Udine, 10 luglio 2005 Pier Giulio, De Martino, Forni di Sopra (UD), 27 settembre 2002 Francesco, Di Francesco, Tavagnacco (UD), 1 gennaio 2000 Si assuma inoltre che un calendario lunare, dal 1° gennaio 2000 al 31 dicembre 2005 sia stato memorizzato in un vettore tridimensionale int calendario [6][13][32] in cui è possibile indirizzare un giorno utilizzando direttamente i valori numerici della data in formato gg/mm/aa. Per esempio, calendario [10][2][3] rappresenta il giorno 10 febbraio 2003. È evidente che non tutti gli elementi del vettore sono utilizzati). Il vettore contiene, in corrispondenza di ogni giorno, il corrispondente giorno del mese lunare (da 1 a 30). Si scriva una funzione C che riceva come parametro il nome di un file contenente un elenco anagrafico come sopra descritto, il vettore calendario, e un vettore di 30 interi, rappresentante i 30 giorni del mese lunare. La funzione deve leggere l’elenco anagrafico e restituire nel vettore di 30 interi i contatori dei nati in ciascun giorno del mese lunare. #define #define #define #define #define struct { int int int }; ANNOINIZIO ANNOFINE ANNICALENDARIO SECONDIMESELUNARE SECONDIGIORNO 2000 2005 (ANNOFINE-ANNOINIZIO+1) 2551443 86400 data giorno; mese; anno; void DistribuzioneNascite (FILE *fp, int calendario_lunare[ANNICALENDARIO][13][31], int mese_lunare[31]); char NumeroMese (char *mese); struct data EstraiDataDiNascita (char *s); char NumeroMese (char *mese) { char nome_mese[13][16] = { "", "gennaio", "febbraio", "marzo", "aprile", "maggio", "giugno", "luglio", "agosto", "settembre", "ottobre", "novembre", "dicembre" }; int i; for (i = 1; i <= 12; i++) { if (!strcmp (mese, nome_mese[i])) return i; } printf ("mese %s non riconosciuto\n", mese); exit (EXIT_FAILURE); } void DistribuzioneNascite (FILE *fp, int calendario_lunare[ANNICALENDARIO][13][31], int mese_lunare[31]) { char s[128]; struct data d; while (fgets (s, 128, fp) != NULL) { d = EstraiDataDiNascita (s); mese_lunare[calendario_lunare[d.anno-ANNOINIZIO][d.mese][d.giorno]]++; } return; } struct data EstraiDataDiNascita (char *s) { int i; struct data d; char m[16]; i = 0; while (s[i++] != ','); /* while (s[i++] != ','); /* while (s[i++] != ','); /* sscanf (s + i, "%d %s %d", d.mese = NumeroMese (m); return d; } salta il nome */ salta il cognome */ salta il comune di nascita */ &d.giorno, m, &d.anno);