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);