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