Informatica 1
Transcript
Informatica 1
Informatica 1 Prova di recupero – 13 Luglio 2005 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 3 ore. Esercizio 1 (3 punti) Si rappresentino in complemento a due i numeri 72 e -15, usando parole di 8 bit. Quindi si rappresenti il numero -72.15, assumendo che vengano usati 8 bit per la parte intera e altri 8 bit per la parte decimale, e che la parte decimale sia espressa (in maniera approssimata!) mediante le potenze negative di 2. Esercizio 2 (6 punti) Si considerino le seguenti dichiarazioni nel linguaggio C typedef struct EL { int i; struct EL *n; } myType; myType *myVar; Scrivere una sequenza di istruzioni nel linguaggio di von Neumann che sia equivalente alle seguenti istruzioni C: while(myVar != NULL){ printf("%f", myVar->i); myVar = myVar->n; } Si possono fare le seguenti assunzioni: 1. Una variabile di tipo int occupa una cella di memoria; una variabile di tipo puntatore occupa anch'essa una cella di memoria, indipendentemente dal tipo dell'oggetto puntato. La cella della macchina di von Neumann corrispondente alla variabile myVar è la cella 101. I campi delle variabili di tipo struttura sono memorizzati in celle consecutive. Il valore NULL corrisponde al valore 0 (cioè all'indirizzo 0). 2. Le istruzioni del linguaggio di von Neumann utilizzabili sono le seguenti LOAD xxx STORE xxx ADD xxx SUB xxx BR zzz BEQ zzz BG zzz (Salta all’istruzione numero zzz) (Salta all’istruzione numero zzz se il contenuto dell’accumulatore è 0) (Salta all’istruzione numero zzz se il contenuto dell’accumulatore è > 0) BGE zzz BLE zzz (Salta all’istruzione numero zzz se il contenuto dell’accumulatore è >= 0) (Salta all’istruzione numero zzz se il contenuto dell’accumulatore è <= 0) L’aggiunta del simbolo ‘=’ subito dopo il codice operativo di un’istruzione indica la modalità di indirizzamento immediata. L’aggiunta del simbolo ‘@’ subito dopo il codice operativo di un’istruzione indica la modalità di indirizzamento indiretta. 3. Le istruzioni del linguaggio di von Neumann che realizzano il codice C suddetto siano numerate a partire dal numero k Esercizio 3 (18 punti) Parte a. (4 punti) Definire dei tipi di dato per contenere informazioni relative ad un albero genealogico. Ogni persona è caratterizzata dai suoi dati anagrafici e dai suoi parenti più stretti. I dati anagrafici di una persona sono il suo codice fiscale (che è una stringa alfanumerica di esattamente 16 cifre), nome e cognome, il luogo e la data di nascita, il suo sesso e lo stato matrimoniale (single o sposato). Inoltre, ad ogni persona sono associati le seguenti informazioni: il codice fiscale dello sposo/sposa (naturalmente se la persona è sposata); i codici fiscali dei genitori; il codici fiscali dei figli (si assuma pure che una coppia non possa avere più di 10 figli). Se qualcuna di queste informazioni non è disponibile, il cofice fiscale corrispondente contiene solo '0' (per esempio se la persona non è sposata, il codice fiscale associato allo sposo/a è 0000000000000000). Parte b. (3 punti) Codificare un sottoprogramma che prende in ingresso un codice fiscale e le informazioni di una persona (dati anagrafici e parenti più stretti), e ritorna true se la persona passata ha il codice fiscale corrispondente al primo parametro. Parte c. (11 punti) Codificare un sottoprogramma che prende in ingresso il descrittore di un file binario (supposto già aperto in sola lettura) contenente le informazioni di un insieme di persone, il quale stampa a video i nomi delle coppie di persone sposate, indicando prima il marito, e poi la moglie (deve cioè stampare, su ogni riga, i nomi di una coppia marito-moglie, indicando prima il marito). NB: Ogni coppia va stampata una volta sola. L'ordine con cui vengono stampate le coppie può essere qualunque. Il file in ingresso può anch'esso avere le persone in ordine qualunque. Il sottoprogramma deve essere side-effect-free, cioè quando termina esso deve lasciare il file in ingresso ESATTAMENTE nello stesso stato in cui questo era all'inizio del sottoprogramma. Eventuali sottoprogrammi di appoggio (che non facciano parte della standard library del C) devono essere codificati nella loro interezza. Soluzioni Esercizio 1 7210 = 010010002 1510 = 000011112 -1510 = 111100012 72.1510 = 01001000.001001102 -72.1510 = 10110111.110110102 Esercizio 2 /* if myVar == NULL GOTO end */ k. LOAD k+1. BEQ 101 k+10 /* printf (myVar->i) */ k+2. LOAD@ 101 k+3. WRITE /* myVar = (myVar->n) */ k+4. LOAD 101 k+5. ADD= 1 k+6. STORE 102 k+7. LOAD@ 102 k+8. STORE 101 k+9. BR k Esercizio 3 Parte a. typedef TipoCF char[16]; typedef TipoSesso enum{M, F}; typedef struct { TipoCF cf; char nome[30]; char cognome[30]; char luogoNascita[30]; TipoData dataNascita; TipoSesso s; bool sposato; } TipoDatiAnagrafici typedef struct { TipoDatiPersona anagrafica; TipoCF sposo; TipoCF padre; TipoCF madre; TipoCF figli[10]; int nfigli; } TipoDatiPersona Con i seguenti classici tipi: typedef enum{false, true} bool; typedef struct{ short giorno; short mese; int anno; } TipoData; Parte b. bool confrontaCF(TipoCF cf, TipoDatiPersona pers){ int i; for(i=0; i<16; i++){ if(cf[i] != pers.anagrafica.cf[i]) return false; } return true; } Parte c. include #stdio.h; void stampaSposi(FILE *f;){ bool trovaPersonaInFile(TipoCF cf, FILE *f, TipoDatiPersona *dpOut); long oldPos = ftell(f); TipoCF cfSposo; TipoDatiPersona dp, sposo; TipoDatiPersona *marito, *moglie; rewind(f); while(!feof(f)){ fread(&dp, sizeof(TipoDati(Persona), 1, f); if(dp.anagrafica.sposato){ if(trovaPersonaInFile(marito.anagrafica.cf, f, &sposo,)){ if(dp.anagrafica.sesso == M){ marito = &dp; moglie = &sposo; } else { marito = &sposo; moglie = &dp; } printf("%s %s, %s %s\n", marito->anagrafica.nome, marito->anagrafica.cognome, moglie->anagrafica.nome, moglie->anagrafica.cognome); } } } fseek(f, posCorr, SEEK_SET); } /* Funzione che prende in ingresso il codice fiscale di una * persona ed un file in cui cercarla, e ritorna true se la * persona esiste nella porzione di file seguente al punto * in cui si trova il puntatore nel file al momento della chiamata, * altrimenti ritorna false (nel caso cioè in cui o la persona non * esiste, oppure, se esiste, si trova nel file in un punto precedente). * Se la persona esiste, i suoi dati sono caricati nella variabile * dp passata per indirizzo. * La funzione lascia il puntatore nel file nel punto in cui lo * aveva trovato all'inizio dell'esecuzione. */ bool trovaPersonaInFile(TipoCF cf, FILE *f, TipoDatiPersona *dpOut){ long posCorr = ftell(f); TipoDatiPersona dp; while(!feof(f)){ fread(&dp, sizeof(TipoDati(Persona), 1, f); if(confrontaCF(cf, dp) == true){ *dpOut = dp; fseek(f, posCorr, SEEK_SET); return true; } } fseek(f, posCorr, SEEK_SET); return false; }