Esame di Calcolatori Elettronici Appello del 30/1/'02 (Telecomunicazioni) Esercizio 1) Realizzare in Assembler GNU la seguente funzione (scrivere sul file es1.s ed eseguire): struct r1 { int v[4]; int n; }; struct r2 { int m; char cc[4]; int p; }; extern "C" r1 f (r1& ra, r2 rb) { r1 rr; for (int i = 0; i < 4; i++) rr.v[i] = (int)rb.cc[i] + rb.m*rb.p; for (int i = 0; i < 4; i++) ra.v[i] = (int)rb.cc[i] - rb.p; rr.n = ra.v[3]; ra.n = ra.v[0]+rb.p; return rr; } Esercizio 2) Realizzare quanto richiesto in C++ (scrivere sul file es2.cc ed eseguire). Siano date le seguenti dichiarazioni, contenute nel file cc.h: enum booleano {F,T}; class albin { struct elem {char* cognome; char* nome; int num; elem* l; elem* r;}; elem* root; elem* ins(elem*, char[], char[], int); void contaal(elem*,char,int&); void stampaal(elem*); void salva(elem* , ofstream* ); public: albin(){root=0;} void insert(char[], char [], int); void stampa(); int conta(char c);albin riord(); } La classe albin realizza un albero binario ordinato in modo tale che facendo una visita dell'albero in ordine simmetrico i campi cognome risultino ordinati per valori alfabeticamente crescenti e, in caso di campi cognome uguali, i campi nome risultino ordinati per valori alfabeticamente crescenti. Realizzare: 1) la funzione membro insert(), che inserisce un nuovo elemento nell'albero mantenendo l'ordinamento; nella realizzazione della funzione si consiglia di definire ed utilizzare la funzione privata ins(); 2) la funzione membro conta() che restituisce la somma dei campi num di tutti gli elementi il cui campo cognome inizia per il carattere passato come parametro alla funzione; nella realizzazione della funzione si consiglia di definire ed usare la funzione privata contaal(); 3) la funzione membro riord() che: a) apre il file di nome "temp" in scrittura, b) salva gli elementi dell'albero sul file, c) chiude il file, d) crea un nuovo albero, e) apre il file di nome "temp" in lettura, f) legge dal file (fino ad arrivare alla fine del file) un cognome (di massimo 20 caratteri), un nome (di massimo 20 caratteri) ed un numero intero e li inserisce nel nuovo albero scambiando il cognome con il nome in modo tale che visitando il nuovo albero in ordine simmetrico gli elementi risultino ordinati per valori alfabeticamente crescenti dei nomi (che nel nuovo albero sono memorizzati nel campo cognome); nella realizzazione della funzione, per salvare l'albero su file si consiglia di definire la funzione privata salva(). La funzione membro stampa() stampa su uscita standard gli elementi dell'albero visitando l'albero in ordine simmetrico. La funzione stampa() Š implementata nel file ccob.o. Esercizio 3) Realizzare quanto richiesto in C++ (scrivere sul file es3.cc ed eseguire). Scrivere un programma che: 1. dichiara due strutture ra e rr di tipo r1; 2. dichiara una struttura rb di tipo r2 inizializzando il campo m ad 1, il campo cc con i caratteri da 'a' a 'd' e il campo p con l'intero 2; 3. chiama la funzione f() passandole ra e rb come primo e secondo parametro, rispettivamente, e assegnando la struttura restituita a rr; 4. stampa su uscita standard le strutture ra e rr; 5. crea due alberi alb e alb1; 6. apre il file "ingr" in lettura e fino ad arrivare alla fine del file legge due stringhe (al massimo di 20 caratteri) ed un numero intero e li inserisce nell'albero alb; 7. chiama la funzione insert() su alb passandole "Russo", "Gianni" e ra.n; 8. stampa l'albero alb su uscita standard; 9. stampa su uscita standard la somma dei campi num degli elementi il cui campo cognome inizia con il carattere 'C'; 10. stampa su uscita standard la somma dei campi num degli elementi il cui campo cognome inizia con il carattere 'R'; 11. chiama la funzione riord() su alb e assegna il risultato ad alb1; 12. stampa su uscita standard l'albero alb1. Esame di Calcolatori Elettronici Appello del 30/1/2002 - Soluzioni # file es1.s .text .global _f _f: pushl %ebp movl %esp,%ebp subl $24,%esp #spazio per le var. locali pushl %edi pushl %esi pushl %ebx pushl %edx movl $0,-24(%ebp) for1: cmpl $4,-24(%ebp) jl corpo1 jmp finefor1 corpo1: movl -24(%ebp),%ecx movl 24(%ebp),%eax imull 16(%ebp) #rb.m*rb.p in %edx-%eax movsbl 20(%ebp,%ecx),%ebx #(int)rb.cc[i] addl %ebx,%eax movl %eax,-20(%ebp,%ecx,4) #rr.v[i]=(int)rb.cc[i]+rb.m*rb.p incl -24(%ebp) jmp for1 finefor1: movl $0,-24(%ebp) movl 12(%ebp),%edx for2: cmpl $4,-24(%ebp) jl corpo2 jmp finefor2 corpo2: movl -24(%ebp),%ecx movsbl 20(%ebp,%ecx),%ebx #(int) rb.cc[i] subl 24(%ebp),%ebx movl %ebx,(%edx,%ecx,4) #ra.v[i]=(int)rb.cc[i]-rb.p incl -24(%ebp) jmp for2 finefor2: movl 12(%edx),%ecx #rr.n=ra.v[3] movl %ecx,-4(%ebp) movl (%edx),%ebx #ra.n=ra.v[0]+rb.p addl 24(%ebp),%ebx movl %ebx,16(%edx) leal -20(%ebp),%esi #return rr movl 8(%ebp),%edi movl %edi, %eax cld movl $5,%ecx rep movsl popl %edx popl %ebx popl %esi popl %edi leave ret Esercizio 2 //file cc.h esistente #include enum booleano {F,T}; class albin { struct elem {char* cognome; char* nome; int num; elem* l; elem* r;}; elem* root; elem* ins(elem*, char[], char[], int); void contaal(elem*,char,int&); void stampaal(elem*); void salva(elem* , ofstream* ); public: albin(){root=0;} void insert(char[], char [], int); void stampa(); int conta(char c); albin riord(); }; //file ccob.cc esistente #include "cc.h" void albin::stampa() { stampaal(root); cout << endl << endl; } void albin::stampaal(elem* p) { if (p!=0) { stampaal(p->l); cout << p->cognome << ' ' << p->nome << ' ' << p->num << endl; stampaal(p->r); } } //file es2.cc #include #include "cc.h" void albin :: insert(char cognome[], char nome[], int d) { root=ins(root,cognome, nome,d); } albin::elem* albin::ins(elem* p, char cognome[], char nome[], int d) { if (p==0) { p=new elem; p->num=d; p->l=0; p->r=0; p->cognome=new char[strlen(cognome)+1]; strcpy(p->cognome,cognome); p->nome=new char[strlen(nome)+1]; strcpy(p->nome,nome); } else { if (strcmp(p->cognome,cognome)>0 || (strcmp(p->cognome,cognome)==0 && strcmp(p->nome,nome)>=0)) p->l=ins(p->l,cognome,nome,d); else p->r=ins(p->r,cognome,nome,d); } return p; } int albin::conta(char c) { int num=0; contaal(root,c,num); return num; } void albin::contaal(elem* p,char c,int& num) { if (p!=0) { contaal(p->l,c,num); if (p->cognome[0]==c) num+=p->num; contaal(p->r,c,num); } } void albin::salva(elem* p, ofstream* out) { if (p!=0) { salva(p->l,out); *out << p->cognome << ' ' << p->nome << ' ' << p->num << endl; salva(p->r,out); } } albin albin::riord() { ofstream out("temp"); if (!out) { cerr << "Errore nell'apertura del file temp" << endl; exit(1); } salva(root,&out); out.close(); albin al; ifstream in("temp"); char cognome[20], nome[20]; int d; while (in >> cognome >> nome >> d) al.insert(nome, cognome, d); return al; } Esercizio 3 //file es3.cc #include "cc.h" struct r1 { int v[4]; int n; }; struct r2 { int m; char cc[4]; int p; }; extern "C" r1 f (r1& ra, r2 rb); void stampa(r1 r) { cout << "v[] = "; for (int i=0; i<4; i++) cout << r.v[i] << ' '; cout << endl; cout << "n = " << r.n << endl << endl; } void main() { r1 ra,rr; r2 rb={1,{'a','b','c','d'},2}; rr=f(ra,rb); cout << "Stampa della struttura ra " << endl; stampa(ra); cout << "Stampa della struttura rr " << endl; stampa(rr); albin alb, alb1; char cognome[20], nome[20]; int d; ifstream in("ingr"); if (!in) { cerr << "Errore nell'apertura del file ingr" << endl; exit(1); } while (in >> cognome >> nome >> d) alb.insert(cognome, nome, d); alb.insert("Russo", "Gianni", ra.n); cout << "Stampa dell'albero alb" << endl; alb.stampa(); cout << "Somma campi num con campo cognome che inizia per C " << alb.conta('C') << endl; cout << "Somma campi num con campo cognome che inizia per R " << alb.conta('R') << endl; cout << endl << endl; alb1=alb.riord(); cout << "Stampa dell'albero alb1" << endl; alb1.stampa(); }