570 likes | 913 Views
Pokazivači. *. Pokazivači: pointers. primjer int *pok; //pokazivač int N=5; //varijabla pok =&N; //usmjeravanje. format tip_podatka * identifikator;. usmjeravanje pokazivača na N. pokazivač. varijabla N. adresa N. int N ---------------------- 5. pok=&N;. pok. int*pok;.
E N D
Pokazivači: pointers primjer int *pok; //pokazivač int N=5; //varijabla pok=&N; //usmjeravanje format tip_podatka *identifikator; usmjeravanje pokazivača na N pokazivač varijabla N adresa N int N ---------------------- 5 pok=&N; pok int*pok; int N=5; deklaracija pokazivača na int deklaracija i definicija varijable *
Pokazivači: pointers Pokazivač je objekt koji pokazuje na drugi objekt. Pokazivač sadrži memorijsku adresu objekta na koji pokazuje: int *pok; //pokazivač na int int N=5; //varijabla pok=&N; //usmjeravanje na N Operator * operator dereferenciranja ili indirekcije (dereferencing, indirection operator) - izravno pridruživanje vrijednosti objekta pokazivaču. Operator & operator adrese (address-of operator) *
int*pok; int a=8; pok=&a; cout<<“a= “<<a<<endl; cout<<“*pok= “<<*pok<<endl; cout<<“pok= “<<pok<<endl; *pok+=1; a=*pok-1; int b=4; pok=&b; //pokazivač na int //usmjeravanje pokazivača na a //ispisuje 8 //... i opet 8 //ispisuje memorijsku adresu//varijable a //isto što i a+=1; a=9 //isto kao a=a-1; a=8 //preusmjeravanje pokazivača Pokazivači: primjeri *
Pokazivači tipa void int n = 5; //cjelobrojna varijabla nint*pokn = &n; //njezin pokazivač float x = 10.27; //realna varijabla xfloat*pokx = &x; //njezin pokazivač pokx = pokn; //pogreškapokx = &n; //pogreška (varijable nisu istog tipa) void*nesvrstan; //pokazuje na neodređeni tip, tj.//na općenitu memorijsku lokaciju nesvrstan = &n; //usmjeravanje na varijablu n nesvrstan = pokx; //preusmjeravanje na varijablu x *nesvrstan = x; //pogreška: void se ne može//dereferencirati (ne može mu se //izravno pridružiti vrijednost *
Nul-pokazivači: NULL-pointers int*x = 0; ili int*x = NULL; Nul-pokazivač ne pokazuje nikuda; vrijednost pokazivača nije postavljena! Čemu služi pokazivač koji ne pokazuje nikuda? *
Pokazivači i polja float x[5]; float a = x[2]; isto je što i float a = *(x+2); !!! Identifikator polja bez indeksa ima značenje pokazivača na prvi element !!! int b[ ] = {10,20,30}; cout<<b<<endl; //ispisuje adresu b[0] cout <<(b+1)<<endl; //adresa člana b[1] cout<<&(b[1])<<endl; //isto, adresa b[1] Razlika Identifikator polja je sinonim za pokazivač na prvi element, no sam pokazivač nije nigdje alociran (nije mu dodijeljena memorija). *
Izračunavanje dana: rješenje s pokazivačima • #include<iostream>usingnamespace std; • int main() { • //inicijalizacija i deklaracija • int Dat[3]; • int Mjes[]={31,28,31,30,31,30,31,31,30,31,30}; • int j=1; • //ponavljanje • cout<<"Izracunavanje dana: rjesenje s pokazivacima" • <<endl<<endl; • while (j==1) { • //unosenje datuma • cout<<"Unos datuma(dan,mjesec,godina): "; • for(int i=0;(i<=2);i++) • cin>>*(Dat+i); • cout<<endl; • //prestupna godina? • if ((*(Dat+2))%4==0) • *(Mjes+1)=29; • else • *(Mjes+1)=28; *
//inicijalizacija sume dana • intSuma=*Dat; • //izracunavanje • for(inti=0;i<=(*(Dat+1)-2);i++) • Suma+=(*(Mjes+i)); • //ispis • cout <<"Od 01.01. do " • <<*Dat<<"."<<*(Dat+1) • <<"."<<*(Dat+2)<<"."<<" proslo je " • <<Suma<<" dana."<<endl; • //indikacija kraja • cout<<"Za nastavak <1>, za prekid <0>: "; • cin>>j; • cout<<endl; • } • system("pause"); • return0; • } *
Operatori new i delete dinamički objekt, pohranjuje se u programsku hrpu (heap) float*pok; pok=new float(); *pok=10.234; ili Float*pok=new float(10.234=*); delete pok; float Broj; float *pokBroj=&Broj; *pokBroj=10.234; automatski objekt, pohranjuje se u programski stog (stack) Pitanje:treba li nam uopćevarijabla? Dinamičke objekte valja vlastoručno uništiti!!!! *
Vezana lista • Vezana lista je dinamička struktura podataka koja predstavlja niz elemenata. • Razlike između liste i polja: • U polju se elementima pristupa izravno, preko indeksa, dok se elementima vezane liste pristupa slijedno • Polju mora broj elemenata biti zadan prije korištenja polja dok se broj elemenata vezane liste dinamički mijenja
Vezana lista vrijednost an a1 a2 a3 zaglavlje posljednji element liste sadrži NULL-pokazivač pokazivač na sljedeći element
Vezana lista vrijednost • Na početak liste se stavlja "prazan" element, koji se naziva zaglavlje vezane liste (header) • Zaglavlje služi za lakše manipuliranje praznom listom te za lakše umetanje novih elemenata i brisanje postojećih. an a1 a2 a3 zaglavlje posljednji element liste sadrži NULL-pokazivač pokazivač na sljedeći element
Vezana lista • Napravimo stog pomoću vezane liste. • Sjetimo se! U stogu element koji je posljednji ušao u stog, prvi iz stoga izlazi.
Vezana lista • Napravimo program koji će učitavati riječ i izokretati je naopako.
Vezana lista učitaj niz čitaj slovo po slovo i stavljaj svako novo slovo na početak liste briši element po element iz liste i ispisuj ga na zaslon
Vezana lista Upisi rijec: alen
Vezana lista Upisi rijec: alen a
Vezana lista Upisi rijec: alen l a
Vezana lista Upisi rijec: alen e l a
Vezana lista Upisi rijec: alen n e l a
Vezana lista Upisi rijec: alen e l a n
Vezana lista Upisi rijec: alen l a ne
Vezana lista Upisi rijec: alen a nel
Vezana lista Upisi rijec: alen nela
Vezana lista Definicija liste #include<iostream> usingnamespace std; struct list { char vrijednost; list *sljedeci; }; typedef list *lista; typedef list element;
Vezana lista Punjenje liste void Punjenje(char c[],lista l){ int i=0; element *e; while (c[i] != '\0') { e=new element(); e->vrijednost=c[i]; e->sljedeci=l->sljedeci; l->sljedeci=e; i++; } }
Vezana lista Pražnjenje liste i ispis slova void Praznjenje(char c[],lista l){ element *e; while (l->sljedeci !=NULL) { e=l->sljedeci; l->sljedeci=l->sljedeci->sljedeci; cout << e->vrijednost; delete e; } cout << endl; }
Vezana lista Glavni program int main() { lista l; element *e; char c[100]; e=new element(); e->sljedeci=NULL; l=e; cout << "Upisite rijec: "; cin.getline(c,sizeof(c)); Punjenje(c,l); Praznjenje(c,l); system("pause"); return 0; }
Dinamička alokacija: polja Primjer s konačnim brojem elemenata int*sati=newint[5]; ... delete[]sati; sati[0]: podaci sati[1]: podaci sati[2]: podaci sati[3]: podaci sati[4]: podaci sati-------------adresa 10 adresa 10
Dinamička alokacija: polja Primjer s konačnim brojem elemenata int*sati=newint[5]; ... delete[]sati; podaci podaci podaci podaci podaci adresa 10 *
Dinamička alokacija: polja Prvo izvođenje: Koliko elemenata? 5 Primjer s varijabilnim brojem elemenata cout<<“Koliko elemenata?“<<endl; int n; cin>>n; int*polje=newint[n]; ... delete[]polje; polje[0]: podaci polje[1]: podaci polje[2]: podaci polje[3]: podaci polje[4]: podaci polje-------------20 adresa 20
Dinamička alokacija: polja Prvo izvođenje: Koliko elemenata? 5 Primjer s varijabilnim brojem elemenata cout<<“Koliko elemenata?“<<endl; int n; cin>>n; int* polje=newint[n]; ... delete[]polje; Drugo izvođenje: Koliko elemenata? 3 podaci podaci podaci podaci podaci adresa 20 polje-------------55 polje[0]: podaci polje[1]: podaci polje[2]: podaci adresa 55
Dinamička alokacija: polja Prvo izvođenje: Koliko elemenata? 5 Primjer s varijabilnim brojem elemenata cout<<“Koliko elemenata?“<<endl; int n; cin>>n; int* polje=newint[n]; ... delete[]polje; Drugo izvođenje: Koliko elemenata? 3 podaci podaci podaci podaci podaci adresa 20 podaci podaci podaci adresa 55 *
Dinamička alokacija: višedimenzionalna polja Višedimenzionalna polja memoriraju se linearno int(*a)[5]=new int[2][5]; float(*b)[5]=new float[n][5]; Osim prve, sve dimenzije moraju biti poznate. Okrugla zagrada ima viši prioritet od znaka za pokazivač delete[]a; //brisanje: oslobađanje memorijskog delete[]b; //prostora dinamičkih objekata *
Dinamička alokacija: višedimenzionalna polja primjer float(*a)[5]=new float[2][5]; a[0][0]: a[0][1]: a[0][2]: a[0][3]: a[0][4]: a-------------100 adresa 100 adresa 102 adresa 104 adresa 106 adresa 108 a[1][0]: a[1][1]: a[1][2]: a[1][3]: a[1][4]: adresa 110 adresa 112 adresa 114 adresa 116 adresa 118 Adresa a[1][2] == adresa a[1][1] + 2 byte-a == adresa a[0][0] + 14 byte-ova *
Varijabilni argumenti funkcije • Rekli smo da se na povratku iz funkcije vraćaju vrijednosti koje su imali prije pokretanja funkcije. • Kako napraviti funkciju kojoj se mijenjaju argumenti? • Pomoću pokazivača
Varijabilni argumenti funkcije #include<iostream> using namespace std; void funkcija(int a,int b,int *c) { *c=a+b; } int main() { int a,b,c=0; cin >> a >> b; funkcija(a,b,&c); cout << c << endl; system("pause"); return 0; } *
Zadatak: dinamičko polje proizvoljnog broja redaka i stupaca (1) Provedite postupak dinamičke alokacije memorijskog pro- stora za dvodimenzionalno polje tipa int proizvoljnog broja redaka i proizvoljnog broja stupaca u svakom pojedinom ret- ku. Pridružite članovima polja vrijednosti.(2) Prvi podatak u retku neka bude podatak o broju članova za taj redak.(3) Ispišite vrijednosti članova polja.(4) Nakon upotrebe, dealocirajte memorijski prostor. (5) Ponovite postupak proizvoljan broj puta. Napomena: primjer je opisan u “Borland C++ 4.5 Programmer’s Guide”, 1994. *
Problem (1) Dvodimenzionalno dinamičko polje može imati varijabilan broj redaka, ali broj stupaca mora biti poznat. (2) Zadatak traži polje dimenzija n*m, tj. polje u kojem unapri- jed ništa nije poznato. Kako to riješiti? (1) Deklariranjem pokazivača na jednodimenzionalno polje po- kazivača. Svaki član polja pokazivača će pokazivati na poče- tak jednog retka. (3) Deklariranjem retka dimenzije [stupaca+1] pri čemu prvi stu- pac sadržava informaciju o stvarnom broju članova s podaci- ma. *
Ključni momenti dinamičke alokacije Deklaracija pokazivača na pokazivačint**A; Alokacija prostora za polje pokazivača A=newint*[redaka]; Alokacija prostora za članove jednog retka A[i]=newint[stupaca+1]; *
početak alokacija(ponavljanje) učitavanje: n //broj redaka ponavljanje(i=0;j<n;j++) //formiranje reda učitavanje: m //broj stupaca u A[i][0]=m 1.element reda ponavljanje(j=1;j<=m;j++) //postavljanje A[i][j]=i*10+j+10 vrijednosti od kraj_ponavljanja 2. elementa kraj_ponavljanja ispis ponavljanje(i=0;i<n;i++) //ispis reda ponavljanje(j=1;j<=A[i][0];j++)//stupaca u redu ispis: A[i][j] kraj_ponavljanja kraj_ponavljanja dealokacija ponavljanje(i=0;i<n;i++) //redak brisanje: A[i] kraj_ponavljanja brisanje: []A //cijelo polje kraj Pseudokôd *
Polje proizvoljnog broja redaka i stupaca: program #include<iostream> usingnamespace std; int main() { int Kraj=1; while(Kraj==1) { //alokacija prostora int**A; int i,j,n,m; //unos n redaka//alokacija polja pokazivaca od (n) clanova cout<<"Broj redaka: "; cin>>n; A=new int*[n]; //unos broja stupaca//alokacija polja od (n*m+1) clanova for(i=0;i<n;i++) { cout<<"Broj clanova u "<<(i+1)<<". retku: "; cin>>m; A[i]=new int[m+1]; A[i][0]=m; //pridruzivanje vrijednosti for(j=1;j<=m;j++) A[i][j]=i*10+j+10; } *
//ispis cout<<"Ispis clanova polja: "<<endl; for(i=0;i<n;i++) { cout<<endl; for(j=0;j<=A[i][0];j++) cout<<"["<<i<<"]["<<j<<"]="<<A[i][j]<<endl; } //dealokacija for(i=0;i<n;i++) delete[]A[i]; delete[]A; cout<<"Za nastavak <1>, za kraj <0>: "; cin>>Kraj; }//while return 0; } *