Informatica 1 Prova di recupero 17 Febbraio 2003 Si risolvano i seguenti esercizi. Ai fini della determinazione del voto finale il loro punteggio andrà sommato al punteggio del laboratorio. Il tempo complessivo a disposizione è di 2 ore e ½. Chi dovesse recuperare solo la prima prova dovrà risolvere solo la parte 1 in un tempo di 1 ora e ½. Chi dovesse recuperare solo la seconda prova dovrà risolvere solo la parte 2 in un tempo di 1 ora e ½. Si ricorda che, una volta consegnata una qualsiasi delle due parti, il punteggio acquisito nella corrispondente prova viene annullato.
Recupero parte 1 Esercizio 1 (4 punti) (12 punti) Definire un tipo di dato TipoStrumentista che descrive i dati relativi ad un musicista jazz. Ogni musicista è definito da un nome (massimo 40 caratteri), da una data di nascita, e dallo strumento che suona. Ogni musicista suona un solo strumento, ed il tipo di strumento suonato può essere solo uno dei seguenti (non sono ammessi altri strumenti): pianoforte, basso, batteria, sax, tromba, trombone, flauto, clarinetto, voce. Definire un tipo TipoQuartetto che contiene i dati relativi ad un quartetto di musicisti. Ogni quartetto è caratterizzato da un nome (al massimo 30 caratteri) e da esattamente 4 musicisti (non uno di più, non uno di meno). Definire infine una variabile ElencoQuartetti che può contenere al massimo 100 quartetti. (se si ritiene utile, si possono definire altri tipi di dati, di supporto a quelli richiesti) Esercizio 2 (8 punti) Scrivere un frammento di programma C che, per ogni quartetto senza pianoforte (cioè in cui nessuno strumentista suona il pianoforte) presente nell'elenco ElencoQuartetti, stampa a video il nome del quartetto. In seguito stampa a video il nome di tutti i quartetti con pianoforte. Nel realizzare il frammento di programma si supponga che la variabile ElencoQuartetti di cui al punto precedente sia già stata inizializzata (sia cioè già stata caricata di dati, che non devono essere riletti da tastiera), e si supponga inoltre che un'altra variabile numquartetti, di tipo int (anch'essa già inizializzata) contenga il numero di quartetti effettivamente inseriti in ElencoQuartetti.
Recupero parte 2 (10-12-14 punti) Esercizio 1 (5 punti) Si definiscano i tipi TipoStrumentista e TipoQuartetto come nell'esercizio 1 del recupero della parte 1. Si definisca inoltre un tipo TipoConcerto costituito dal nome della località in cui il concerto si è tenuto (massimo 40 caratteri), dalla data in cui si è tenuto il concerto, e dal quartetto che ha tenuto il concerto. Esercizio 2 Si supponga di avere un file binario contenente un elenco di concerti. Si supponga inoltre che il file sia già stato aperto in modalità (binaria) lettura/scrittura. Si risolva uno (ed uno solo) dei seguenti punti. Variante 2a (punti 5) Dopo avere dichiarato eventuali variabili globali, definire una funzione CancellaConcertiDiQuartetto che riceve in ingresso il nome di un quartetto, e crea un nuovo file (sempre binario), di nome NuovaListaConcerti.dat, contenente l'elenco di tutti i concerti esclusi quelli del quartetto il cui nome è stato passato alla funzione. La funzione ritorna 1 se l'operazione è andata a buon fine, 0 altrimenti. Il file originario con l'elenco dei concerti rimane immutato. Variante 2b (punti 7) Dopo avere dichiarato eventuali variabili globali, definire una funzione CancellaConcertiDiQuartetto che riceve in ingresso il nome di un quartetto, e cancella dal file con l'elenco dei concerti tutti i concerti tenuti dal quartetto il cui come è stato passato alla funzione. La funzione ritorna 1 se l'operazione è andata a buon fine, 0 altrimenti; essa modifica il file originario con l'elenco dei concerti. In questa variante è ammesso (anzi, è consigliato) aprire file temporanei, in aggiunta al file originario. Variante 2c (punti 9) Dopo avere dichiarato eventuali variabili globali, definire una funzione CancellaConcertiDiQuartetto che riceve in ingresso il nome di un quartetto, e cancella dal file con l'elenco dei concerti tutti i concerti tenuti dal quartetto il cui come è stato passato alla funzione. La funzione ritorna 1 se l'operazione è andata a buon fine, 0 altrimenti; essa modifica il file originario con l'elenco dei concerti. In questa variante non è ammesso aprire file temporanei aggiuntivi, si può lavorare solo sul file originario. Aiuto per le varianti 2b e 2c: per troncare un file f alla lunghezza data dalla posizione corrente nel file, l istruzione da usare è la seguente: ftruncate(fileno(f), ftell(f));
Soluzioni Parte 1 (recupero primo compitino) Esercizio 1 #define L_NOME_MUS 40 #define L_NOME_QUAR 30 #define MAX_QUARTETTI 100 short giorno; short mese; int anno; TipoData; typedef enum {pianoforte, basso, batteria, sax, trombone, flauto, clarinetto, voce TipoStrumento; char nome[l_nome_mus+1]; TipoData data_nascita; TipoStrumento strumento; TipoStrumentista; char nome[l_nome_quar+1]; TipoStrumentista musicisti[4]; TipoQuartetto; TipoQuartetto ElencoQuartetti[MAX_QUARTETTI];
Esercizio 2 main() { TipoQuartetto ElencoQuartetti[MAX_QUARTETTI]; int numquartetti[max_quartetti]; /* inizializzazione delle variabili sopra dichiarate, da considerare già fatta */ TipoQuartetto QuartettiSenzaPiano[MAX_QUARTETTI]; TipoQuartetto QuartettiConPiano[MAX_QUARTETTI]; int numquarsenzapiano = 0, numquarconpiano = 0, i, j, trovato; for (i=0; i<numquartetti; i++){ j = 0; trovato = 0; while (trovato == 0 && j<4){ if (ElencoQuartetti[i].musicisti[j].strumento == pianoforte){ trovato = 1; j++; if (trovato == 0) { QuartettiSenzaPiano[numQuarSenzaPiano] = ElencoQuartetti[i]; numquarsenzapiano++; else { QuartettiConPiano[numQuarConPiano] = ElencoQuartetti[i]; numquarconpiano++; printf( Quartetti senza piano:\n ); for (i=0; i<numquarsenzapiano; i++){ printf( %s\n, QuartettiSenzaPiano[i].nome); printf( Quartetti con piano:\n ); for (i=0; i<numquarconpiano; i++){ printf( %s\n, QuartettiConPiano[i].nome);
Parte 2 (recupero secondo compitino) Esercizio 1 #define L_NOME_MUS 40 #define L_NOME_QUAR 30 #define MAX_QUARTETTI 100 short giorno; short mese; int anno; TipoData; typedef enum {pianoforte, basso, batteria, sax, trombone, flauto, clarinetto, voce TipoStrumento; char nome[l_nome_mus+1]; TipoData data_nascita; TipoStrumento strumento; TipoStrumentista; char nome[l_nome_quar+1]; TipoStrumentista musicisti[4]; TipoQuartetto; #define L_NOME_CONC 40 char nome_loc[l_nome_conc+1]; TipoData data; TipoQuartetto quartetto; TipoConcerto;
Esercizio 2a #include <string.h> #include <stdio.h> FILE *f_concerti; int CancellaConcertiDiQuartetto(char nome_quar[]){ TipoConcerto curr_conc; FILE *nf = fopen( NuovaListaConcerti.dat, wb ); if (nf == NULL) return 0; rewind(f_concerti); while (!feof(f_concerti)){ if (fread(&curr_conc, sizeof(tipoconcerto), 1, f_concerti) == 1) { if (strcmp(curr_conc.quartetto.nome, nome_quar)!= 0) { if (fwrite(&curr_conc, sizeof(tipoconcerto), 1, nf)!= 1) { fclose(nf); return 0; else { fclose(nf); return 0; if (fclose(nf) == 0) return 1; else return 0;
Esercizio 2b #include <string.h> #include <stdio.h> FILE *f_concerti; int CancellaConcertiDiQuartetto(char nome_quar[]){ TipoConcerto curr_conc; FILE *tmp_f = fopen( _temp.dat, wb+ ); if (tmp_f == NULL) return 0; rewind(f_concerti); while (!feof(f_concerti)){ if (fread(&curr_conc, sizeof(tipoconcerto), 1, f_concerti) == 1) { if (strcmp(curr_conc.quartetto.nome, nome_quar)!= 0) { if (fwrite(&curr_conc, sizeof(tipoconcerto), 1, tmp_f)!= 1) { fclose(tmp_f); return 0; else { fclose(tmp_f); return 0; rewind(f_concerti); rewind(tmp_f); while (!feof(tmp_f)){ if (fread(&curr_conc, sizeof(tipoconcerto), 1, tmp_f) == 1) { if (fwrite(&curr_conc, sizeof(tipoconcerto), 1, f_concerti)!= 1) { fclose(tmp_f); return 0; else { fclose(tmp_f); return 0; /* tronco il file all ultima posizione in cui ho scritto (il file riscritto è in generale più corto del file originario */ ftruncate(fileno(f_concerti), ftell(f_concerti)); if (fclose(tmp_f) == 0) return 1; else return 0;
Esercizio 2c #include <string.h> #include <stdio.h> FILE *f_concerti; int CancellaConcertiDiQuartetto(char nome_quar[]){ TipoConcerto curr_conc; /* tengo due indici nel file: la prossima posizione in cui devo scrivere (pos_next_write) e la prossima posizione da cui devo leggere (pos_next_read) */ long pos_next_write, pos_next_read; rewind(f_concerti); pos_next_write = ftell(f_concerti); while (!feof(f_concerti)){ if (fread(&curr_conc, sizeof(tipoconcerto), 1, f_concerti) == 1) { if (strcmp(curr_conc.quartetto.nome, nome_quar)!= 0) { /* se il concerto è da mantenere, lo riscrivo nel file f_concerti alla prossima posizione in cui devo scrivere. Prima di scrivere, però, devo memorizzare la poszione corrente nel file, perchè a questa posizione dovrò poi tornare per ricominciare a leggere. */ pos_next_read = ftell(f_concerti); /* mi sposto nel file alla posizione in cui devo scrivere, e poi effettivamente scrivo. */ if (fseek(f_concerti, pos_next_write, SEEK_SET)) return 0; if (fwrite(&curr_conc, sizeof(tipoconcerto), 1, f_concerti)!= 1) return 0; /* memorizzo la posizione corrente, che è la prossima posizione in cui dovrò scrivere, e mi riporto nella posizione che è la prossima da cui devo leggere */ pos_next_write = ftell(f_concerti); if (fseek(f_concerti, pos_next_read, SEEK_SET)) return 0; else { return 0; /* mi riporto sulla posizione che è la prossima in cui scrivere (cioè appena dopo l ultimo concerto che va conservato, e tronco il file (il file riscritto è in generale più corto
del file originario */ if (fseek(f_concerti, pos_next_write, SEEK_SET)) return 0; ftruncate(fileno(f_concerti), ftell(f_concerti)); return 1;