Вы находитесь на странице: 1из 8

Politecnico di Milano - Dipartimento di Elettronica e informazione

Prof. Mauro Negri

Informatica I – II appello 13 luglio 2004

Matricola __________ Cognome _____________________ Nome _______________________

Istruzioni
1. La prova dura 2 ore.
2. ALLA FINE DELLA PROVA VA CONSEGNATO SOLO QUESTO PLICO (SCRIVETE
CON CARATTERI DI DIMENSIONE ADEGUATA). Scrivere solo sui fogli distribuiti. Non
separare questi fogli. Si può utilizzare la matita.
3. È vietato portare all’esame libri, eserciziari, appunti o calcolatrici. Chiunque venga trovato in
possesso di documentazione relativa al corso – anche se non strettamente attinente alle domande
proposte – vedrà annullata la propria prova.
4. Non è possibile uscire dall’aula durante la prova o lasciare l’aula conservando il tema della
prova in corso.
NEGLI ESERCIZI DI PROGRAMMAZIONE SI SUPPONGA CHE:
- I VALORI LETTI DA TERMINALE E/O DA FILE SIANO SEMPRE COMPATIBILI COL
TIPO DELLE VARIABILI CORRISPONDENTI E CHE TALI VALORI NON GENERINO
OVERFLOW,
- LE FUNZIONI DI LETTURA/SCRITTURA A TERMINALE E/O FILE E DI CHIUSURA
DEI FILE NON GENERINO ERRORE.
TUTTE LE ALTRE CONDIZIONI DI ERRORE CHE SI POSSONO VERIFICARE VANNO
CONTROLLATE.

Esercizio A (8 punti) _______________________________

Esercizio B (11 punti) _______________________________

Esercizio C (5 punti) _______________________________

Voto finale (24 punti – insuff. se <14 punti): ________________


Esercizio A Esercizio in linguaggio C
Si supponga di avere un file di nome “dati.dat” che in un generico istante di tempo può contenere sino ad un
massimo di 100 record per la memorizzazione dei dati di autoveicoli; ogni record ha le seguente struttura:
struct rec {char nome[50]; int serialNum; int quantita;}. Il contenuto del file è scaricato periodicamente in un
vettore di nome VET per le successive elaborazioni.
Si devono realizzare le seguenti parti di un programma C:
a) tutte le strutture dati (costanti, tipi e VARIABILI) globali necessarie per il funzionamento delle
seguenti funzioni (la funzione main può definire variabili al proprio interno solo se servono per la
gestione delle strutture di controllo, ad esempio la variabile di controllo di un for).
b) Una funzione di nome InitVettore che riceve come parametro il vettore VET ed eventuali variabili di
supporto e provvede ad eliminare il contenuto esistente nel vettore in modo che sia di nuovo disponibile
per un ulteriore caricamento dati da file; infine la funzione ritorna, come parametri, il vettore e i dati di
supporto al programma chiamante.
c) Una funzione Leggi che riceve come parametro il nome del file, il vettore VET e provvede ad accedere
al file per scaricarne il contenuto nel vettore (1 record di tipo rec del file è memorizzato in un elemento
del vettore); il vettore caricato è restituito come parametro al programma e il contenuto del file viene
cancellato. Infine la funzione ritorna 1 se ha funzionato correttamente o 0 se si è verificato un errore.
d) La funzione main che invoca prima InitVettore, poi invoca Leggi e infine provvede, se andata a buon
fine, a visualizzare a video, uno per riga, i record caricati nel vettore che hanno nel campo nome
“Rover472”, altrimenti visualizza un messaggio di errore.

pp. 2 / 4
Esercizio B. Esercizio in linguaggio C
Data una lista dinamica nella quale ogni elemento punta al successivo e al precedente e definita dalle
seguenti dichiarazioni (si noti che "primo" punta al primo elemento della lista e permette tramite la scansione
del campo "prossimo" di ogni elemento di raggiungere l'ultimo elemento puntato da "ultimo"):

typedef struct el { int valore; struct el * prossimo; struct el * precedente; } ElemLista;


typedef struct {ElemLista *primo; ElemLista *ultimo;} t_pointer;
t_pointer pointer = {NULL,NULL};

Si devono realizzare le seguenti parti di un programma C:


a) tutte le strutture dati (costanti, tipi e VARIABILI) globali necessarie per il funzionamento delle
seguenti funzioni (incluse le 3 dichiarazioni precedenti).
b) Una funzione Insert, che riceve come parametri la lista e due numeri interi NUM e POS (i numeri NUM
e POS possono assumere un qualsiasi valore intero). La funzione crea un elemento dinamico inserendo
NUM nel campo valore e procede a cercare la posizione POS di inserimento dell’elemento nella lista,
partendo da “primo” (se POS vale P significa che l’elemento può essere inserito se e solo se è possibile
inserirlo come P-esimo elemento della lista, altrimenti l’inserimento non deve avvenire). La funzione
ritorna come parametri la lista aggiornata e 1 se l’aggiornamento è avvenuto o 0 se non è stato possibile
inserire l’elemento.
c) Completare la seguente funzione main (i ”........” indicano la presenza di possibili altre istruzioni):
void main()
{..............
/*richiede a terminale due numeri interi (il valore da inserire in un nuovo elemento della lista e la
posizione) senza effettuare controlli sui valori letti
e poi invoca INSERT passando i numeri letti da terminale
e visualizza aterminale l’esito dell’insert */
...............
}

pp. 3 / 4
Esercizio C.
1. Si indichi, utilizzando 10 bit, il valore in base 2, in base 16 del numero 333 e in complemento a
due dei numeri -333, -100
333 base 2: base 16:
-333
-100
2. Convertire il valore esadecimale EFF8 (16 bit) in binario e trovare il numero decimale
corrispondente supponendo che sia un numero naturale
EFF8 base 2: base 10:
3. Quali vantaggi offre al programmatore la traduzione dei programmi divisa in due fasi separate
(compilazione + collegamento) quando sta realizzando un programma suddiviso in più file?
Rispondere brevemente.

4. Si supponga di avere un’operazione O che può essere realizzata come circuito hardware da
inserire nell’Unità aritmetico logica (ALU) del calcolatore oppure come funzione C (realizzata
implementando O in termini di operazioni più elementari disponibili nella ALU) resa disponibile
tramite una libreria memorizzata sul calcolatore. Confrontando le due soluzioni indicare,
motivando brevemente la risposta, quale possa essere
a. la soluzione più efficiente (tempo di esecuzione)

b. e indicare quali operazioni fisico/logiche si debbano eseguire in entrambi i casi quando si


decida di modificare la realizzazione proposta (ad esempio, modificando il circuito hardware o
l’algoritmo software) e indicare se il calcolatore richieda di essere spento per effettuare la
sostituzione.

5. Date le seguenti variabili globali: int c=3, d=5, e=2; e la seguente funzione
int f(int a, int *b) {*b=a; b=&a; b=3; return (a+c);}
indicare quali valori assumerebbero le variabili globali c, d, e dopo l’esecuzione delle seguenti
istruzioni (ogni istruzione deve essere eseguita considerando i valori iniziali delle variabili
globali):
e = f(6,&c); c= d= e=

pp. 4 / 4
c = f(4,&d); c= d= e=

pp. 5 / 4
SOLUZIONE ESERCIZIO A

a)
#include <stdio.h>
#include <string.h>

struct rec {char nome[50]; int serialNum; int quantita;};


struct rec VET[100]; int ultimo;
char * nomefile="dati.dat";

b)
void InitVettore(struct rec V[], int *u)
{*u=-1;}

c)
int Leggi (char *nome, struct rec V[], int *u)
{ FILE *f; struct rec temp;
if ((f = fopen(nome, "rb"))==NULL) { printf("errore apertura file"); return 0;}
else
{*u=-1;
while (fread(&temp, sizeof(struct rec),1,f)==1)
{ *u=*u+1; V[*u]=temp;
}
fclose (f);
}
if ((f = fopen(nome, "wb"))==NULL) { printf("errore riapertura file per cancellazione"); return 0;}
else {fclose(f); return 1;}
}

d)
void main()
{int i;
InitVettore(VET,&ultimo);
if (Leggi(nomefile,VET,&ultimo)==1)
{ for (i=0; i<=ultimo;i++)
if (strcmp(VET[i].nome,"Rover472")==0)
printf("\nnome=%s,S/N=%d,quantità=%d",VET[i].nome,VET[i].serialNum,VET[i].quantita);
}
else printf(“Leggi non corretta”);
}

SOLUZIONE ESERCIZIO B

Si devono considerare i vari stati nei quali si può trovare la lista e le varie posizioni di inserimento.

Sequenza di ragionamento basata sulla posizione (soluzione implementata)


Pos<1 : errore poiché pos minima è 1
Pos=1: si inserisce sempre, tuttavia nel caso di lista vuota ricordarsi che il nuovo elemento è anche l’ultimo
Pos>1: verifica che pos corrisponda al più alla lunghezza della lista +1, altrimenti non è possibile inserire. Se
inseribile allora esistono due casi:
a) inserimento in posizione intermedia della lista
b) inserimento in ultima posizione (non esiste successivo)

Sequenza di ragionamento basata sullo stato della lista:


lista vuota: pos diverso da 1 implica errore, altrimenti inserimento come unico elemento presente
lista con elementi:
a) pos<1 errore
b) pos=1 inserimento in testa (non c’è precedente),
c) pos intermedia (ci sono precedente e prossimo)
d) pos=ultimo inserimento in coda (non c’è prossimo)
e) pos > numero elementi in coda +1 errore

pp. 6 / 4
A)
#include <stdio.h>
#include <stdlib.h>

typedef struct el { int valore; struct el *prossimo; struct el *precedente; } ElemLista;


typedef struct {ElemLista *primo; ElemLista *ultimo; } t_pointer;
t_pointer pointer={NULL,NULL};

B)
int INSERT(t_pointer *p, int val, int pos)
{ ElemLista *temp, *prec; int precpos;

if (pos<1) return 0;

if (pos==1)
{ temp=(ElemLista*) malloc(sizeof(ElemLista));
if (temp==NULL)return 0;
else
{temp ->valore=val; temp ->prossimo=p->primo; p->primo=temp; temp ->precedente=NULL;
// verifica esistenza di altro elemento nella lista
if (temp ->prossimo==NULL) p->ultimo=temp; else temp ->prossimo ->precedente=temp;
return 1;
}
}
else
//pos>1 verifica esistenza posizione
{ prec = p->primo; precpos=1;
while((prec!=NULL) && (precpos <(pos-1))) {precpos++; prec=prec->prossimo;}
if (prec==NULL)
//lista contiene meno elementi di quelli richiesti da pos
return 0;
else
{temp= malloc(sizeof(ElemLista));
if (temp==NULL)return 0;
else //inserimento
{temp ->valore=val; temp ->prossimo = prec->prossimo;
prec->prossimo=temp;
temp ->precedente=prec;
if (temp ->prossimo==NULL) p->ultimo=temp; else temp ->prossimo ->precedente=temp;
}
}
return 1;
}
}

C)
void main()
{ int v,p;
printf("inserire valore e posizione"); scanf("%d",&v);scanf("%d",&p);
printf("\n%d",INSERT(&pointer, v,p));
}

SOLUZIONE ESERCIZIO C
Si indichi, utilizzando 10 bit, il valore in base 2, in base 16 del numero 333 e in complemento a due
dei numeri -333, -100
333 base 2: 01 0100 1101 base 16: 14D
-333 10 1011 0011
-100 11 1001 1100
Convertire il valore esadecimale EFF8(16 bit) in binario e decimale
EFF8 base 2: 1110 1111 1111 1000 base 10: 215 +214 +213 +211 ...+23

pp. 7 / 4
Quali vantaggi offre al programmatore la traduzione dei programmi divisa in due fasi separate
(compilazione + collegamento) quando sta realizzando un programma suddiviso in più file?
Rispondere brevemente.
- Permette di verificare la correttezza del codice scritto in ogni file attivando il compilatore
solo sul file realizzato indipendentemente dagli altri file;
- Permette di assegnare ogni file da realizzare a programmatori diversi che possono compilare
la propria parte indipendentemente dagli altri.
- Permette di riutilizzare file scritti da altri (librerie) senza averne il codice sorgente.
Si noti che ovviamente la correttezza complessiva richiede di realizzare l’eseguibile complessivo e
di verificarne la correttezza in esecuzione.

Si supponga di avere un’operazione O che può essere realizzata come circuito hardware da inserire
nell’Unità aritmetico logica (ALU) del calcolatore oppure come funzione C (realizzata
implementando O in termini di operazioni più elementari disponibili nella ALU) resa disponibile
tramite una libreria memorizzata sul calcolatore. Confrontando le due soluzioni indicare, motivando
brevemente la risposta, quale possa essere
la soluzione più efficiente (tempo di esecuzione)
la soluzione hardware permette di ottimizzare l’operazione O, mentre la soluzione software realizza
l’operazione O attraverso un algoritmo che coinvolge operazioni più semplici e pertanto in generale
non è sempre possibile ottenere lo stesso livello di ottimizzazione.

e indicare quali operazioni fisico/logiche si debbano eseguire in entrambi i casi quando si decida di
modificare la realizzazione proposta (ad esempio, modificando il circuito hardware o l’algoritmo
software) e indicare se il calcolatore richieda di essere spento per effettuare la sostituzione..
- Caso hardware: si deve realizzare una nuova scheda che va sostituita nel calcolatore e ciò
comporta il fermo macchina per il tempo necessario.
- Caso software: va realizzato il nuovo programma e poi sostituito al precedente e ciò non
comporta in generale il fermo macchina a meno che sia un programma che faccia parte del sistema
operativo.

Date le seguenti variabili globali: int c=3, d=5, e=2; e la seguente funzione
int f(int a, int *b) {*b=a; b=&a; b=3; return (a+c);}
indicare quali valori assumerebbero le variabili globali c, d, e dopo l’esecuzione delle seguenti
istruzioni (ogni istruzione deve essere eseguita considerando i valori iniziali delle variabili globali):
e = f(6,&c); c= 6 d= 5 e= 12
c = f(4,&d); c= 7 d= 4 e= 2

pp. 8 / 4

Вам также может понравиться