La presentazione è in caricamento. Aspetta per favore

La presentazione è in caricamento. Aspetta per favore

1 laboratorio di calcolo II AA 2003/04 seconda settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza 159 - tel. (06 5517) 7281 www.fis.uniroma3.it/~orestano.

Presentazioni simili


Presentazione sul tema: "1 laboratorio di calcolo II AA 2003/04 seconda settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza 159 - tel. (06 5517) 7281 www.fis.uniroma3.it/~orestano."— Transcript della presentazione:

1 1 laboratorio di calcolo II AA 2003/04 seconda settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza tel. ( ) UNIVERSITA DEGLI STUDI ROMA TRE DIPARTIMENTO DI FISICA E. AMALDI

2 2 Indice Puntatori Puntatori e vettori Vettori di caratteri e stringhe Allocazione dinamica della memoria Strutture dati Reference Passaggio dei dati ad una funzione per referenza e per valore nella prossima lezione

3 3 Puntatori Un puntatore è un oggetto che fa riferimento ad un altro oggetto Lo si dichiara in uno dei due modi seguenti int* p; Dove p è il puntatore Non gli si può assegnare un valore direttamente, ma solo un oggetto cui puntare int i=3;// loggetto salvato in memoria int *p=&i; // dove &i è lindirizzo di memoria di i (questa istruzione equivale a int *p; p=&i;) Loggetto puntato si ottiene dereferenziando il puntatore: *p Se p vale 0 (puntatore nullo) *p non è definito (il programma si ferma!) int * p: i: int 3

4 4 Esempio int numero = 82485; // un oggetto intero a 32 bit // che in binario si scrive // // int * puntatore; // puntatore ad un oggetto intero puntatore = № // puntatore a numero // (posto uguale all'indirizzo di numero) puntatorenumero 0x x

5 5 Puntatori e Vettori (Arrays) float x[5]; // dichiarazione di un vettore di numeri reali con 5 elementi x e &x[0] sono la stessa cosa: il puntatore al primo elemento dellarray *x e x[0] sono la stessa cosa: il primo elemento dellarray float * x: x[4]x[0]x[1]x[2] float x[3]

6 6 Aritmetica dei puntatori float x[5]; float *y=&x[0]; // y è un puntatore a x[0] float *z=x; // z è un puntatore a x[0] (y+1) punta a x[1] *(y+1), y[1] e x[1] accedono lo stesso oggetto sono consentite operazioni di somma e sottrazione ed è possibile confrontare tra loro due puntatori (si confrontano gli indirizzi di memoria, che sono numeri interi)

7 7 Esempi di uso dei puntatori somma degli elementi di un vettore float x[5]; // qui gli elementi vengono inizializzati… double sum=0; for(int i=0;i<5;i++) { sum+=x[i]; } oppure float x[5]; // qui gli elementi vengono inizializzati… float *y=x; double sum=0; for(int i=0;i<5;i++) { sum+=*y++; }

8 8 Esempi inversione dellordine degli elementi di un vettore float x[10]; // qui gli elementi vengono inizializzati… float *left = &x[0]; float *right = &x[9]; while(left < right) { float temp = *left; *left++ = *right; *right-- = temp; } azzeramento degli elementi di un vettore float x[10]; // qui gli elementi vengono inizializzati… float *p = &x[10]; //attenzione a non usare *p !!! while ( p != x ) *--p=0;

9 9 vettori di caratteri e stringhe Programma che usa char e stringhe C #include int main() { // Voglio scrivere il mio nome // Introduco un vettore di caratteri nomechar, // lungo 7 caratteri, ed introduco il mio // nome, 1 lettera alla volta. // L'output utilizza un loop, con o senza il // puntatore (piu' o meno raffinato) // input dei dati char nomechar[7]; nomechar[0] = D'; nomechar[3] = nomechar[5] = i'; nomechar[1] = o'; nomechar[2] = m'; nomechar[4] = z'; nomechar[6] = a';

10 10 // In realta' sarebbe anche possibile // istanziare e inizializzare nomechar con // una sola istruzione. La dimensione viene // assegnata automaticamente dal compilatore. // La linea di istruzione equivalente alle // precedenti e': // char nomechar[] // = {D,o,m,i,z,i,a }; // Oppure l'input potrebbe essere gestito // tramite lettura da tastiera // cout << "Assegnare il nome( 7 caratteri): " // << endl; // for (int i=0; i<7; i++) { // cin >> nomechar[i]; // };

11 11 // Passiamo all'output // Senza l'uso del puntatore cout << endl << " Output senza l'uso del puntatore: "; for(int m=0;m<=7;m++) { cout << nomechar[m]; }; //Ora passiamo all'uso delle stringhe di tipo C // Istanzio un puntatore alla stringa C che // contiene il nome char *nomeC; nomeC = Domizia"; // Notare l'uso e la funzione del doppio apice cout << endl << " Stringa di tipo C: " << nomeC << endl;

12 12 // Da notare che si puo' effettuare l'output // anche pensando alla stringa C come una serie // di caratteri cout << "Output carattere per carattere: "; for(int j=0;j<7;j++) { cout << ' ' << nomeC[j] ; }; cout << endl; // oppure... cout << " "; char *q=nomeC; // q e un puntatore ad un carattere for(int j=0;j<7;j++) { cout << ' ' << *q++; }; cout << endl << endl; return 0; }

13 13 Programma che usa le stringhe C++ #include int main() { string name; name = Domizia"; cout << name << endl; string cognome=Orestano"; string tutto=name+" "+cognome; cout << endl << tutto << endl; return 0; }

15 15 Dimensionamento dei vettori (1) // Un esempio da CorpoCeleste class CorpoCeleste { protected: char *Nome; …………….}; // Variante a dimensione fissa, // memoria allocata a compilation time class CorpoCeleste { protected: char Nome[20] ; ……………};

16 16 // Tentativo di variante a dimensione variabile, // ma non compila! class CorpoCeleste { protected: int n; char Nome[n]; …………….}; vettori di dimensione variabile, fissata in fase di esecuzione, non possono essere inseriti tra gli attributi di una classe !

17 17 Puntatori a variabili locali (1) ===File prova_fp.h class prova_fp { private: // public : prova_fp() { } ; ~prova_fp() { } int * int_fp() { int a = 5 ; return &a ; }; ===Main: #include #include "prova_fp.h" int main() { int * p; prova_fp myprova; p = myprova.int_fp(); cout << endl << endl; cout << " Puntatore : " << p << endl ; cout << " Valore : " << *p << endl ; return 0; }; Warning in compilazione e stampa di un Valore privo di senso !

18 18 Allocazione dinamica della memoria Lallocazione statica degli oggetti in memoria consente maggiore velocità di esecuzione perchè lo spazio usato e il tempo di utilizzo (lifetime delloggetto) sono determinati già in fase di compilazione. due problemi: –vogliamo poter allocare di vettori di dimensione definita durante lesecuzione del programma –vogliamo avere accesso agli oggetti definiti localmente (allinterno di uno { scope}) una soluzione: allocazione dinamica della memoria. Gli oggetti vengono creati in unarea di memoria chiamata heap. Si utilizzano gli operatori –new –delete

19 19 Dimensionamento dei vettori (2) class CorpoCeleste { protected: char * Nome; …………….}; E poi nel costruttore inizializzato int n = strlen(nomeCorpo); Nome=new char[n]; Ma tutti gli oggetti creati con new devono essere distrutti esplicitamente con loperatore delete, questi oggetti infatti non vengono cancellati automaticamente alluscita dallo scope. In caso di vettori la sintassi è delete [ ] Nome; Dobbiamo modificare CorpoCeleste::~CorpoCeleste inserendovi questa istruzione!

20 20 #include "CorpoCeleste.h" #include CorpoCeleste::CorpoCeleste() { } CorpoCeleste::CorpoCeleste (const char *nomeCorpo, float mass, float xpos, float ypos, float vxi, float vyi) { Nome = new char[strlen(nomeCorpo)]; strcpy(Nome, nomeCorpo); m = mass; x = xpos; y = ypos; vx = vxi; vy = vyi; } void CorpoCeleste::calcolaPosizione( float fx, float fy, float t) { double ax = fx/m; double ay = fy/m; vx += ax*t; vy += ay*t; x += vx*t; y += vy*t; } CorpoCeleste.cc Prima parte

21 21 void CorpoCeleste::stampaPosizione() { cout.setf(ios::fixed); cout.setf(ios::showpos); cout << " " << setprecision(4) << setw(9) << x*1.e-11 << " " << setprecision(4) << setw(9) << y*1e-11 ; } void CorpoCeleste::stampaVelocita() { cout.setf(ios::fixed); cout.setf(ios::showpos); cout << " " << vx << " " << vy ; } CorpoCeleste::~CorpoCeleste() {delete [] Nome;} const char* CorpoCeleste::nome() {return Nome; } double CorpoCeleste::M() { return m; } double CorpoCeleste::X() { return x; } double CorpoCeleste::Y() {return y; } double CorpoCeleste::Vx() {return vx; } double CorpoCeleste::Vy() {return vy; } CorpoCeleste.cc Seconda parte

22 22 Puntatori a variabili locali (2) class prova_fp_n { private: // public : prova_fp_n() { } ; ~prova_fp_n() { } ; int * int_fp() { int * p = new int(5); return p ; }; ===Main: #include #include "prova_fp_n.h" int main() { int * p; prova_fp_n myprova; p = myprova.int_fp(); cout << endl << endl; cout << " Puntatore : " << p << endl ; cout << " Valore : " << *p << endl ; delete p; return 0; }; Nessun warning in compilazione e stampa del Valore corretto: 5!

23 23 Esercitazione Obiettivi: –Utilizzare la classe CorpoCeleste –Studiare il comportamento dei costruttori e del distruttore –Utilizzare puntatori, vettori, vettori di puntatori 1.Modificare il distruttore di CorpoCeleste includendo loperazione di delete [ ] Nome 2.Aggiungere stampe nei costruttori e nel distruttore 3.Provare i seguenti programmi che usano CorpoCeleste:

24 24 Programmi Es1_a.cc (costruttore, uso dei metodi Get, distruttore) Es1_b.cc (allocazione dinamica, puntatori) Es1_c.cc (vettore di oggetti, costruttore di default) Es1_cbis.cc (vettore di puntatori ad oggetti) Es1_d.cc (vettore con allocazione dinamica) Es1_dbis.cc (vettore di puntatori con allocazione dinamica)

25 25 #include "CorpoCeleste.h" #include CorpoCeleste::CorpoCeleste() { cout << invocato costruttore di default di CorpoCeleste<

26 26 void CorpoCeleste::stampaPosizione() { cout.setf(ios::fixed); cout.setf(ios::showpos); cout << " " << setprecision(4) << setw(9) << x*1.e-11 << " " << setprecision(4) << setw(9) << y*1e-11 ; } void CorpoCeleste::stampaVelocita() { cout.setf(ios::fixed); cout.setf(ios::showpos); cout << " " << vx << " " << vy ; } CorpoCeleste::~CorpoCeleste() { cout << invocato distruttore di CorpoCeleste <

27 27 #include #include "CorpoCeleste.h int main () { // istanzio una serie di oggetti di tipo CorpoCeleste CorpoCeleste sole("Sole", 2.e30,0.,0.,0.,0.); CorpoCeleste pietra("dolomite",1.,0.,0.,1.,1.); CorpoCeleste sasso("quarzo",2.,1.,0.,0.,1.); // Scrivo alcune caratteristiche degli oggetti che ho istanziato: // massa e posizione cout << endl << "Pianeta n. Massa Posizione iniziale " << endl << " x y " << endl << endl; cout << " " << "1" << " " << sole.M() << " " << sole.X() << " " << sole.Y() << endl; cout << " " << "2" << " " << pietra.M() << " " << pietra.X() << " " << pietra.Y() << endl; cout << " " << "3" << " " << sasso.M() << " " << sasso.X() << " " << sasso.Y() << endl; cout << endl; // Il programma e' finito. // Il compilatore provvede a distruggere gli oggetti di tipo CorpoCeleste return 0; } Es1_a.cc

28 28 #include #include "CorpoCeleste.h" int main () { // istanzio una serie di oggetti di tipo CorpoCeleste // Uso l'allocazione dinamica della memoria, tramite new CorpoCeleste * Psole = new CorpoCeleste("Sole", 2.e30,0.,0.,0.,0.); CorpoCeleste * Ppietra = new CorpoCeleste("dolomite",1.,0.,0.,1.,1.); CorpoCeleste * Psasso = new CorpoCeleste("quarzo",2.,1.,0.,0.,1.); // Scrivo alcune caratteristiche degli oggetti che ho istanziato; // Ad esempio la massa e la posizione cout << endl << "Pianeta n. Massa Posizione iniziale " << endl << " x y " << endl << endl; cout M() X() Y() << endl; cout M() X() Y() << endl; cout M() X() Y() << endl; cout << endl; Es1_b.cc Prima parte

29 29 // Ora devo cancellare gli oggetti allocati dinamicamente tramite new cout << endl << "Prima delle chiamate a delete " << endl; delete Psole; delete Ppietra; delete Psasso; cout << endl << "Dopo le chiamate a delete " << endl; // Il programma e' finito // Notate (tramite il distruttore intelligente) che il compilatore // ha provveduto a distruggere gli oggetti di tipo CorpoCeleste // ai quali puntavano Psole, Ppietra, Psasso. return 0; } Es1_b.cc Seconda parte

30 30 #include #include "CorpoCeleste.h" int main () { // uso un vettore di oggetti di tipo Corpoceleste const int np = 6; CorpoCeleste Pianeti[np]; // Con un loop scrivo gli elementi del vettore for (int i=0; i

31 31 #include #include "CorpoCeleste.h" int main () { // Ora uso un vettore di puntatori a oggetti di // tipo CorpoCeleste const int npp = 8; CorpoCeleste* MieiPianeti[npp]; // Con un loop scrivo gli elementi del vettore for ( int i=0; i

32 32 // devo ricordarmi di cancellare gli oggetti allocati dinamicamente for ( int i=0; i

33 33 #include #include "CorpoCeleste.h" int main () { // uso un vettore di oggetti di tipo Corpoceleste // Il vettore di oggetti e' allocato dinamicamente // tramite new, che fornisce il puntatore all'array const int np = 6; CorpoCeleste * Pianeti= new CorpoCeleste[np]; // Con un loop scrivo gli elementi del vettore for (int i=0; i

34 34 // Ora devo cancellare il vettore allocato dinamicamente cout << endl << endl << " Prima di chiamare delete [] Pianeti " << endl; delete [] Pianeti; cout << endl << " Dopo aver chiamato delete [] Pianeti " << endl; return 0; } Es1_d.cc Seconda parte

35 35 #include #include "CorpoCeleste.h" int main () { // Ora uso un vettore di puntatori a oggetti di tipo CorpoCeleste // Il vettore di puntatori e' a sua volta allocato dinamicamente, // tramite new, che fornisce il puntatore all'array di puntatori. // Per questo motivo la prima chiamata di new istanzia un oggetto di // tipo CorpoCeleste **, cioe' un puntatore ad un puntatore. const int npp = 8; CorpoCeleste** MieiPianeti = new CorpoCeleste*[npp]; // Con un loop scrivo gli elementi del vettore for (int i=0; i

36 36 for (int i=0; i


Scaricare ppt "1 laboratorio di calcolo II AA 2003/04 seconda settimana a cura di Domizia Orestano Dipartimento di Fisica Stanza 159 - tel. (06 5517) 7281 www.fis.uniroma3.it/~orestano."

Presentazioni simili


Annunci Google