440 likes | 601 Views
Elemi alkalmazások fejlesztése II. Mutatók. Készítette: Szabóné Nacsa Rozália. Memória. int i = 2;. 00000000. 00000010. Adataink a memóriában egy adott helyen – címen – vannak.
E N D
Elemi alkalmazások fejlesztése II. Mutatók Készítette: Szabóné Nacsa Rozália
Memória int i = 2; 00000000 00000010 Adataink a memóriában egy adott helyen – címen – vannak. Megadhatunk olyan változókat, amelyek ilyen címek tárolására alkalmasak. Ezeket a változókat mutatóknak, vagy pointereknek nevezzük.
Mutató deklarálása - példa int *p2; char *p1; Vector3D *p3; A mutatók deklarálásakor meg kell mondani, hogy milyen típusú adatra mutatunk vele. int p2:
Mutató értéke, mutató által mutatott érték int *p ; int i = 2; p=&i; *p=3; cout << *p << endl; Mutatók esetében különbséget kell tenni a mutató értéke, és a mutató által mutatott érték között. &i: int *p i: p:
Mutatókkal végezhető műveletek: növelés „ char v[6]="Körte"; char *p=v+4; cout << *p << endl; // (*p)=„e” p++; cout << *p << endl; // (*p)=0 . . . ö K r t e 0 p++; p: A mutató típusa meghatározza, hány byte-tal növekszik a cím.
Mutatókkal végezhető műveletek: csökkentés char v[6]="Körte"; char*p=v+4; cout << *p << endl; // (*p)=„e” p--; cout << *p << endl; // (*p)=„t” . . . ö K r t e 0 p--; p: A mutató típusa meghatározza, hány byte-tal csökken a cím.
Mutatókkal végezhető műveletek: növelés tömb végén char v[6]="Körte"; char*p=v+5; cout << *p << endl; // (*p)=0 p++; cout << *p << endl; // hiba . . . ö K r t e 0 p++; p: Megengedett, de nem hivatkozhatunk az általa mutatott objektumra.
Mutatókkal végezhető műveletek: csökkentés tömb elején char v[6]="Körte"; char*p=v; cout << *p << endl; // (*p)=0 p--; cout << *p << endl; // hiba . . . ö K r t e 0 p--; ! p: Nem megengedett, mert értéke nem definiált.
Mutatókkal végezhető műveletek: kivonás char v[6]=”Körte”; char*p2=v + 5; char*p1=v + 1; int i = p2-p1; //i=4 ö K r t e 0 p2 p1 4 i=p1-p2; A mutatóknak ugyanarra a tömbre kell mutatni.
Mutató – Statikus tömb T v[4]; T* p; p=v; A tömb elemei a veremben lesznek. v v[0] v[1] v[2] v[3] +2 p *(v+2) *(p+2) p[2]
Mutató – Dinamikus tömb(„egydimenziós”) //Dinamikus helyfoglalás int *v = newint[3]; //Kezdeti értékadás for (int i=0; i<3; i++) v[i] = i; //Tárterület felszabadítása delete[] v; A tömb elemei a szabad tárhelyen („heap”) lesznek. 1 2 3 *(v+i) = i; v: 0 1 2 Az előző félévben a dinamikus tömbök kezelésekor már dolgoztunk mutatókkal.
//Dinamikus helyfoglalás int **w; w= newint*[3]; for (int i=0; i<3; i++) w[i]= new int[4]; //Kezdeti értékadás for (int i=0; i<3; i++) { for (int j=0; j<4; j++) *(w[i]+j) = i*10 + j; } //Tárterület felszabadítása for (int i=0; i<3; i++) delete[ ] w[i]; delete[] w; Mutató – Dinamikus tömb („kétdimenziós”) 1 2 //Kiíratás for (int i=0; i<3; i++) { for (int j=0; j<4; j++) cout << *(w[i]+j) << endl; } 3 w: 0 1 2 3 10 11 12 13 20 21 22 23
Referencia típus: T& int i=0; int& r = i; r++; cout << i << endl; // i=1 cout << r << endl; // r=1 r az i „álneve”, melynek deklaráláskor értéket is kell kapnia. int& r = 2; //HIBA!! Initialization of non-const reference ‘int&’ from rvalue r: i:
Érték szerinti paraméterátadás void main (){ int x=1; int y=2; csere(x,y); cout << x << “,” << y << endl; } y: x: 1 2 b: a: 1 2 void csere (int a, intb){ int s; s=a; a=b; b=s; } b: a: 2 1
Érték szerinti paraméterátadás void main (){ int x=1; int y=2; csere(x,y); cout << x << “,” << y << endl; return 0; } y: x: 1 2 b: a: 1 2 void csere (int a, intb){ int s; s=a; a=b; b=s; } b: a: 2 1
Cím (referencia) szerinti paraméterátadás void main (){ int x=1; int y=2; csere(x,y); cout << x << “,” << y; } y: x: void csere (int& a, int& b){ int s; s=a; a=b; b=s; }
* és & lehetséges előfordulási helyei - összefoglalás Deklarátorok * (mutató) & (referencia) char s[] = "Eper"; char* p=s; int i; int& r = i; Operátorok * (dereferencia) char* p1; char* p2; char c='A'; char d='D'; p2=&d; p1=&c; *p2 = *p1; & (címe operátor) char c=‘A’; char* p= &c ; Cím szerinti paraméterátadás void csere (int&a, int&b)…
Feladat Egy szöveges állományban megadunk térvektorokat. Olvassuk be a térvektorokat egy tömbbe, majd keressük meg a leghosszabb térvektort. Maximumkeresés
A Vector3D osztály: deklaráció class Vector3D { public: Vector3D(double x, double y, double z); Vector3D(); double abs(void) const; double x() { return _x; } double y() { return _y; } double z() { return _z; } void setX(double x) { _x=x;} void setY(double y) { _y=y;} void setZ(double z) { _z=z;} private: double _x; double _y; double _z; }; vector3d.h
A Vector3D osztály: implementáció vector3d.cpp #include "vector3d.h" Vector3D::Vector3D(double x, double y, double z):_x(x),_y(y),_z(z){} Vector3D::Vector3D() { Vector3D(0,0,0); } double Vector3D::abs(void) const { return sqrt(_x*_x+_y*_y+_z*_z); } Ha Vector3D típusú elemeket tömbben szeretnénk elhelyezni, akkor kell lennie default konstruktornak.
Modulszerkezet main.cpp vector3d.h vector3d.cpp
Implementációs döntés Tömb elemei térvektorok A tömb elemei térvektorokra mutató pointerek 2 1 tomb: tomb: A tömb minden egyes elemében egy-egy térvektorra mutató pointer van. A tömb minden egyes elemében egy-egy térvektor van. max: max_pt:
Az első változat gyengéi tomb: „Drága” művelet 1 A tömb minden egyes elemében egy-egy térvektor van. Át kell gondolni, jól működik-e az értékadás operátor. 2 max:
Megoldás – második változat A tömb elemei térvektorokra mutató pointerek. tomb: A tömb minden egyes elemében egy-egy térvektorra mutató pointer van. max_pt:
Tárterület lefoglalása //Foglalás Vector3D** tomb; tomb= new Vector3D*[n]; for (int i=0; i!=n; i++) { tomb[i]= new Vector3D(); } . . . tomb: 1 2 .. . .. . Lefoglalunk egy n elemű, mutatókat tartalmazó tömböt (a mutatók térvektorokra mutatnak), majd helyet foglalunk a Vector3D típusú elemek számára. Vector3D*típusú elem (mutató) Vector3D típusú elem. (adat)
Tárterület felszabadítása 1 2 tomb: //Felszabadítás for (int i=0; i!=n; i++) delete tomb[i]; delete[] tomb; . . . 1 2 Felszabadítjuk a térvektoroknak lefoglalt helyet, majd felszabadítjuk a térvektorokra mutató pointereket tartalmazó tömböt.
Hivatkozás az (i+1)- dik „mutatóra” tomb: . . .*(tomb+i+1) . . . *(tomb+i+1): tomb[i+1]
Hivatkozás az (i+1)-dik térvektorra tomb: . . .*(*(tomb+i+1)) . . . *(*(tomb+i+1)): *tomb[i+1]
Osztálymetódus használata 1. tomb: . . . (*(tomb+i+1))->abs() . . . *(tomb+i+1):
Osztálymetódus használata 2. tomb: . . . *(*(tomb+i+1)).abs() . . . *(*(tomb+i+1)): *(tomb+i+1):
Maximumkeresés - 1 tomb: //Maximumkeresés Vector3D* max_pt; int i=0; max_pt=*(tomb+i); while(i!=(n-1)) { if ((*(tomb+i+1))->abs() >= max_pt->abs()) max_pt=*(tomb+i+1); i=i+1; } *(tomb+i): max_pt:
Maximumkeresés -2 tomb: //Maximumkeresés Vector3D* max_pt; int i=0; max_pt=*(tomb+i); while(i!=(n-1)) { if ((*(tomb+i+1))->abs() >= max_pt->abs()) max_pt=*(tomb+i+1); i=i+1; } 1 2 *(tomb+i+1): max_pt: 3
Deklarációk #include <iostream> #include <fstream> #include <string> #include "vector3d.h" usingnamespace std; void read(istream& s, Vector3D** const v, constint i); void display(Vector3D** const v, constint i); . . . main.cpp
Fájlkezelés . . . int main() { //Adatok előkészítése és megjelenítése ifstream inp; string InpFileName; cout << "Kerem adja meg a fajl nevet: "; cin >> InpFileName; inp.open(InpFileName.c_str()); if(inp.fail()){ cerr << "A megadott fajlt nem talalom! ” << endl; return 1; } . . . main.cpp
Előfeltétel ellenőrzése . . . int n; inp >> n; cout << endl <<"Elemek szama: " << n << endl; //Előfeltétel ellenőrzése if(n<1){ cout << "Nincs elem" << endl; return 2; } . . . main.cpp
Dinamikus tárterület lefoglalása és a tömb feltöltése . . . //Dinamikus tárterület lefoglalása és a tömb feltöltése Vector3D** tomb; tomb= new Vector3D*[n]; for (int i=0; i!=n; i++) { tomb[i]= new Vector3D(); } for (int j=0; j!=n; j++){ read(inp,tomb,j); display(tomb,j); } inp.close(); . . . main.cpp
Maximumkeresés . . . //Maximumkeresés Vector3D* max_pt; int i=0; max_pt=*(tomb+i); while(i!=(n-1)) { if ((*(tomb+i+1))->abs() >= max_pt->abs()) max_pt=*(tomb+i+1); i=i+1; } . . . main.cpp
Eredmény megjelenítése . . . //Eredmény megjelenítése cout << endl << "A leghosszabb tervektor: " << "[" << max_pt->x() << "," << max_pt->y() << "," << max_pt->z() << "]" << "." << endl; . . . main.cpp
Tárterület felszabadítása . . . //Dinamikusan lefoglalt tárterület felszabadítása for (int i=0; i!=n; i++) { delete tomb[i]; } delete[] tomb; return 0; } . . . main.cpp
Vector3D::read művelet . . . void read(istream& s, Vector3D** constv, constint i) { double d; char separator; s >> separator; s >> d; (*(v+i))->setX(d); s >> separator; s >> d; (*(v+i))->setY(d); s >> separator; s >> d; (*(v+i))->setZ(d); s >> separator; } . . . main.cpp v: 3 [1,2,3] [4,5,6] . . . Az adatfájl felépítése
Vector3D::display művelet . . . void display(Vector3D** constv, constint i) { cout << endl << "[" << (*(v+i))->x() << "," << (*(v+i))->y() << "," << (*(v+i))->z() << "]" << endl; } . . . main.cpp