logo
  • userLoginStatus

Welcome

Our website is made possible by displaying online advertisements to our visitors.
Please disable your ad blocker to continue.

Current View

Management Engineering - Informatica A

Full exam

CORSO DI LAUREA IN INGEGNERIA GESTIONALE Prof. Florian Daniel Prof. Gerardo Pelosi Prof. Giuseppe Pozzi Informatica A – a.a. 2019/2020 – 2 o Appello – Parte B – 04/02/2020 Cognome _____________________________ Matricola o Cod. Persona _______________ Nome _______________________________ Firma ________________________ Istruzioni  Non separate questi fogli. Scrivete la soluzione solo sui fogli distribuiti, utilizzando il retro delle pagine se necessario. Cancellate le parti di brutta (o ripudiate) con un tratto di penna.  Ogni parte non cancellata a penna sarà considerata parte integrante della soluzione.  È possibile scrivere a matita e non occorre ricalcare al momento della consegna.  È vietato utilizzare calcolatrici e qualsiasi dispositivo elettronico. Chi tenti di farlo vedrà annullata la sua prova.  È vietato consultare libri o appunti. Chi tenti di farlo vedrà annullata la sua prova.  Qualsiasi tentativo di comunicare con altri studenti comporta l’espulsione dall’aula.  Non è possibile lasciare l’aula conservando il tema della prova in corso.  È possibile ritirarsi senza penalità.  Tempo a disposizione: 2h Valore indicativo degli esercizi, voti parziali e voto finale: Esercizio 1 ( 8 punti ) ____________ Esercizio 2 ( 8 punti ) ____________ Esercizio 3 ( 8 punti ) ____________ Esercizio 4 ( 5 punti ) ____________ Totale ( 29 punti ) ____________ Parte A ( 4 punti ) ____________ Voto finale __________ Se si continua sul retro di qualche foglio, indicare quale Informatica A – a.a. 2019/2020 – 2do Appello, Parte B – 04/02/2020 foglio 2 di 8 Esercizio 1 (8 punti) Un file contenente le informazioni sui movimenti di un conto corrente bancario (in Euro) ha il seguente formato:  la prima riga contiene una stringa con l’IBAN del conto corrente;  la seconda riga contiene il saldo iniziale (sempre positivo);  le righe seguenti formano una sequenza (di lunghezza ignota) di movimenti. Ogni movimento è descritto dalla data del movimento nel formato aaaa-mm-gg, l’importo del movimento espresso in Euro (che è un numero sempre con due decimali) e un carattere che può essere il segno ꞌ+ꞌ (entrata) oppure ꞌ-ꞌ (uscita). Ciascun movimento è posto su di una singola riga del file, con un carattere di spazio, ꞌ ꞌ, usato come separatore dei valori sulla riga. I movimenti sono riportati nel file in ordine cronologico crescente: NON esistono due movimenti effettuati nel medesimo giorno. Un esempio di tracciato del file è il seguente: IT12T1234512345123456789012 2000.00 2019-10-01 1200.00 + 2019-10-20 100.50 - 2019-10-28 523.10 + 2019-11-10 3000.00 - 2019-11-14 1430.23 - 2019-12-20 1555.55 + 2020-01-07 56.00 + Scrivere in C la funzione char* dataLimite(char nomefile[], float limCredito); che prende come parametri il nome di un file contenente le informazioni di un conto corrente nel formato sopra descritto e un limite di credito limCredito (con limCredito < 0), e restituisce la data in cui il saldo è sceso sotto il valore limite passato come parametro (come stringa dinamica). Nel caso in cui il saldo non scenda mai sotto tale valore, la funzione deve restituire NULL. Per esempio, nel tracciato del file precedentemente mostrato se limCredito = −500.00, la funzione restituisce la data 2019-11-14. Se invece limCredito = −1000.00, la funzione restituisce NULL. Se si continua sul retro di qualche foglio, indicare quale Informatica A – a.a. 2019/2020 – 2do Appello, Parte B – 04/02/2020 foglio 3 di 8 Soluzione #include #include #include char* dataLimite(char nomefile[], float limCredito) { FILE* fp = fopen(nomefile, "r"); if (fp == NULL) return NULL; char* dataDaRestituire = NULL; // o anche // char dataDaRestituire[11]; // char iban[27+1], dataMovimento[10+1], segno; float importo, saldo; fscanf(fp, "%s ", iban); fscanf(fp, "%.2f ", &saldo); while (feof(fp) == 0 && saldo >= limCredito) { fscanf(fp, "%s %.2f %c ", dataMovimento, &importo, &segno); if (segno == ꞌ+ꞌ) saldo += importo; else saldo -= importo; } // end while fclose(fp); if (saldo < limCredito) { dataDaRestituire = (char*) malloc(sizeof(char)*11); strcpy(dataDaRestituire, dataMovimento); } return dataDaRestituire; } // end dataLimite Se si continua sul retro di qualche foglio, indicare quale Informatica A – a.a. 2019/2020 – 2do Appello, Parte B – 04/02/2020 foglio 4 di 8 Esercizio 2 (8 punti) Dato il tipo di dato seguente typedef struct mov { char data[10+1]; float importo; char segno; } t_movimento; scrivere in C la funzione t_movimento* leggiEstratto(char nomefile[], int* lung, float* saldoIniziale) che prende come parametri il nome di un file contenente le informazioni di un conto corrente nel formato descritto nel precedente esercizio e restituisce un array dinamico contenente tutti i movimenti presenti all’interno del file. L’ array dinamico avrà quindi tante celle di tipo t_movimento quante sono le righe del file che descrivono un movimento. Il secondo e il terzo parametro sono da intendersi come parametri passati per indirizzo per restituire al chiamante la lunghezza del vettore dinamico e il saldo iniziale del conto corrente. Se si continua sul retro di qualche foglio, indicare quale Informatica A – a.a. 2019/2020 – 2do Appello, Parte B – 04/02/2020 foglio 5 di 8 Soluzione #include #include #include t_movimento* leggiEstratto(char nomefile[], int* lung, float* saldoIniziale) { FILE* fp = fopen(nomefile, "r"); if (fp == NULL) { *lung = 0; *saldoIniziale = 0; return NULL; } char iban[27+1]; t_movimento m; int cont = 0; fscanf(fp, "%s ", iban); fscanf(fp, "%.2f ", saldoIniziale); // ritorno il valore del saldo iniziale al chiamante tramite il terzo // parametro che e’ passato per indirizzo, quindi il nome della detta // variabile già indica una posizione (indirizzo) di memoria – // non c’e’ necessita’ di usare la & while (feof(fp) == 0) { fscanf(fp, "%s %.2f %c ", m.data, &m.importo, &m.segno); cont += 1; } // end while (*lung) = cont; // ritorno questo valore al chiamante tramite il // secondo parametro che e’ passato per indirizzo if (cont == 0) return NULL; t_movimento* res = (t_movimento*)malloc(sizeof(t_movimento)*count); rewind(fp); fscanf(fp, "%s ", iban); fscanf(fp, "%.2f ", saldoIniziale); for (int i = 0; i < cont; i++) { fscanf(fp, "%s %.2f %c ", m.data, &m.importo, &m.segno); res[i] = m; } // end for fclose(fp); return res; } // end leggiEstratto Se si continua sul retro di qualche foglio, indicare quale Informatica A – a.a. 2019/2020 – 2do Appello, Parte B – 04/02/2020 foglio 6 di 8 Esercizio 3 (8 punti) Si considerino le ulteriori definizioni di tipo di dato typedef struct t_entrateUscite{ float totEntrate; float totUscite; } t_bilancio; Scrivere in C il sottoprogramma void calcolaBilanciMensili(t_movimento *elenco, int lung, int anno, t_bilancio ris[12]); che prende come parametri un array contenente l’elenco dei movimenti di un conto corrente, la lunghezza dell’ array e un valore intero indicante un anno (per esempio: 2019). Il sottoprogramma riempie l’ array passato come quarto parametro memorizzando nella 1ma cella i totali delle entrate e delle uscite relative al mese di Gennaio, nella seconda cella i totali delle entrate e delle uscite relative al mese di Febbraio ecc. Nota: potrebbe essere utile definire e usare due sottoprogrammi int numAnno(char data[]); int numMese(char data[]); per ottenere dalla stringa con formato aaaa-mm-gg, passata come parametro, un numero con il valore dell’anno e un numero con il valore del mese, rispettivamente. Si assuma 1=Gennaio, 2=Febbraio, ecc. Soluzione #include int numAnno(char data[]); int numMese(char data[]); void calcolaBilanciMensili(t_movimento *elenco, int lung, int anno, t_bilancio ris[12]) { for (int i = 0; i < 12; i++) ris[i] = {0.0, 0.0}; t_movimento m; for (int i = 0; i < lung; i++) { m = elenco[i]; if (numAnno(m.data) == data) if (segno == ꞌ+ꞌ) ris[numMese(m.data)-1].totEntrate += m.importo; else ris[numMese(m.data)-1].totUscite += m.importo; } // end for } // end calcolaBilanciMensili Se si continua sul retro di qualche foglio, indicare quale Informatica A – a.a. 2019/2020 – 2do Appello, Parte B – 04/02/2020 foglio 7 di 8 int numAnno(char data[]) { char year[5] = { data[0], data[1], data[2], data[3], ꞌ\0ꞌ }; return atoi(year); } // end numAnno int numMese(char data[]) { char month[3] = { ꞌ\0ꞌ }; if (data[5] == ꞌ0ꞌ) { month[0] = data[6]; } else { month[0] = data[5]; month[1] = data[6]; } return atoi(month); } // end numMese Se si continua sul retro di qualche foglio, indicare quale Informatica A – a.a. 2019/2020 – 2do Appello, Parte B – 04/02/2020 foglio 8 di 8 Esercizio 4 (5 punti) Si consideri un array di interi che contiene in ogni cella un intero positivo da associare ai grammi di peso di una pallina per decorare un albero di natale. La prima e l’ultima cella dell’ array contengono i pesi delle palline sul primo livello dell’albero (quello più basso). La seconda e la penultima cella del vettore contengono i pesi delle palline sul secondo livello dell’albero, (cioé il livello immediatamente sopra quello più basso), ecc. Diciamo che un array di interi rappresenta un albero di natale, se  la somma dei pesi della coppia di palline su ogni livello è sempre maggiore o uguale alla somma dei pesi di tutte le palline nei livelli superiori e  la differenza di peso tra le due palline sullo stesso livello non supera i 5 grammi. Scrivere un sottoprogramma ricorsivo int natale (int vet[], int begin, int end); che preso come primo argomento un array di interi verifichi se può rappresentare un albero di natale o meno, restituendo la somma del peso palline in caso affermativo e -1 in caso contrario. Il secondo e il terzo argomento, sono intesi essere, rispettivamente, la posizione iniziale di una sequenza di interi consecutivi in vet[...] e la posizione finale di una sequenza di interi consecutivi in vet[...]. Esempio: int vetA[5]={8, 4, 2, 4, 6} // ok, ris = natale(vetA, 0, 4); calcola ris == 24 int vetB[5]={4, 8, 2, 6, 4} // NO, ris = natale(vetB, 0, 4); calcola ris == -1 int vetC[5]={12, 2, 2, 8, 12} // NO, ris = natale(vetC, 0, 4); calcola ris == -1 int vetD[4]={4, 4, 6, 8} // ok, ris = natale(vetD, 0, 3); calcola ris == 22 Soluzione int natale (int vet[], int begin, int end) { if (begin > end) return 0; if (begin == end) return vet[begin]; int t = natale(vet, begin+1, end-1); if ( t!=-1 && t < vet[begin]+vet[end] && (vet[begin]–vet[end] = -5) ) return t+vet[begin]+vet[end]; else return -1; }