You are on page 1of 28

Programiranje I

Dinamika alokacija memorije

Stek (stog)
Stek predstavlja tzv. LIFO (last-in-first-out) strukturu u
kojoj
se
posljednje
pohranjena
vrijednost
(komponenta) brie prva
Stek se smatra glavnim dijelom memorije za alokaciju
i pohranjivanje statikih objekata
Postupak alokacije i dealokacije na steku je u
potpunoj ingerenciji raunara, te se obavlja
automatski
Glavne operacije na steku su : push, pop i top

Hrpa (heap)
Heap predstavlja tzv. FIFO (first-in-first-out) strukturu
u kojoj se prvo brie vrijednost (komponenta) koja je
prva i pohranjena
Smatra se da heap predstavlja glavni dio memorije za
alokaciju i pohranjivanje dinamikih podataka
Postupak
dinamike
memorijske
alokacije
(rezervisanja) i dealokacije (oslobaanja) je u
ingerenciji programera i obavlja se koristei operatore
new (alokacija) i delete (dealokacija)

Alociranje memorije
Deklaracija varijable int broj kompajleru daje instrukciju
da:
Alocira blok memorije dovoljno veliki da pohrani vrijednost tipa
int
Pridrui (asocira) ime broj adresi memorijskog bloka

Vrijednost izraza &broj daje adresu alociranog memorijskog


bloka
Memorijski blok asociran sa imenom varijable alocira se u
toku kompajliranja i ne moe biti promijenjen bez
modifikacije programa i njegovog rekompajliranja. Upravo
zbog toga, ova vrsta alokacije se naziva compiletime
allocation i vezana je za probleme loeg koritenja
memorijskih resursa raunara opisan u nastavku...

Alociranje memorije
Deklaracija niza
const int duzina = 50;
double niz[duzina];
alocira memorijski prostor u koji se moe smjestiti 50
double vrijednosti. Definisani broj elemenata esto nee
biti iskoriten (moda se bude koristilo npr. 5 - 10 vrijednosti
tipa double) pa e vei dio memorijskog bloka najee biti
neiskoriten.

Alociranje memorije
Naa elja i potreba je da u vrijeme izvravanja programa
alociramo onoliki memorijski blok koliki je potreban za odreeni
objekat (varijablu, niz ...) i da taj memorijski blok oslobodimo
kada nam vie nije potreban
Programski jezik C++ omoguava koritenje free memory store-a
(hrpa, gomila) upotrebom operatora new (alokacija) i delete
(dealokacija)
Operator new od operativnog sistema zahtijeva dodatni
memorijski prostor u vremenu izvravanja programa. Ako je
zahtjev mogue ispuniti, operator new vraa adresu alociranog
memorijskog bloka, a u spurotnom vraa NULL vrijednost.

Alociranje memorije
Poto operator new vraa adresu, a adresa moe biti
pohranjena u pokaziva, oekivano je je da se operator new,
gotovo uvijek, koristi u kombinaciji sa pokazivaem.
int * pok = new int;

Potrebno je izvriti provjeru da li je alocirana zahtjevana


memorija:
if (pok == NULL){
cerr<<"Nema raspoloive memorije"<<endl;
exit(-1);
}

Alociranje memorije
Drugi nain za provjeru da li je alocirana zahtijevana memorija je
koritenje mehanizma assert:
assert(pok!=NULL);

Assert mehanizam radi na nain da ako je alociranje uspjelo


program nastavlja normalno izvravanje, u suprotnom programa se
prekida i daje se odgovarajua poruka o greci.
Za koritenje assert funkcije potrebno je ukljuiti assert biblioteku:
#include<assert.h>

Alociranje memorije
int * pok = new int;
pok
0x20

0x20

*pok = 35;

pok
0x20

Memorija alocirana,
adresa dodijeljena
pokazivau

*pok
0x20

35

Dereferencirani
pokaziva ima pristup
objektu

Primijetite da objekat ne posjeduje naziv!


Umjesto naziva - dereferencirani pokaziva

Alokaciju je mogue izvriti i koristei funkciju malloc funkciju


koja vraa void * pa je potrebno uraditi cast.

Oslobaanje memorije
Kada odreeni dio memorije vie nije potreban, operator delete
vraa (oslobaa) memoriju u free store
Forma (sintaksa) :
delete pok;
ili
delete [] pok;
Proces:
prvi iskaz oslobaa memoriju alociranu u run-time vremenu za
objekt ija je adresa pohranjena u pokazivau
drugi iskaz oslobaa memoriju alociranu u run-time vremenu za
niz objekata ija je adresa pohranjena u pokazivau
Vraanje memorije u free store je mogue uraditi i koristei funkciju
free

Dinamiki nizovi
#include <iostream>
#include <assert.h>
using namespace std;
void main(){
int brojElemenata=0;
int * niz = NULL;
cout<<"Koliko brojeva unosite: ";
cin>>brojElemenata;
niz = new int [brojElemenata];
assert(niz!=NULL);
for(int i=0;i<brojElemenata;i++){
cout<<"niz["<<i<<"]: ";
cin>>niz[i];
}
cout<<"niz["<<brojElemenata<<"] = { ";
for(int i=0;i<brojElemenata;i++)
cout<<niz[i]<<" ";
cout<<"}"<<endl;
delete [] niz;
niz = NULL;
system("pause");
}

Koliko brojeva unosite: 5


niz[0]: 1
niz[1]: 2
niz[2]: 3
niz[3]: 4
niz[4]: 5
niz[5] = { 1 2 3 4 5 }
Press any key to continue . . .

Dinamiki nizovi

#include<iostream>
#include<assert.h>
using namespace std;
void main(){
//...
//funkcija prima broj bajta koje je potrebno alocirati
//i vraca void *
niz = (int*)malloc(brojElemenata * sizeof(int));
assert(niz != NULL);
//...
free(niz);
niz = NULL;
system("pause");
}
Koliko brojeva unosite:

niz[0]: 1
niz[1]: 2
niz[2]: 3
niz[3]: 4
niz[4]: 5
niz[5] = { 1 2 3 4 5 }
Press any key to continue . . .

Alociranje memorije: viedimenzionalni nizovi


Viedimenzionalni
nizovi memoriu se
linearno

int(*a)[5]=new int[2][5];
float(*b)[5]=new float[n][5];

Okrugla zagrada ima


vei prioritet od znaka
za pokaziva

Osim prve, sve


dimenzije moraju biti
poznate.

delete[]a;//brisanje: oslobaanje memorijskog


delete[]b;//prostora dinamikih objekata

Alociranje memorije: viedimenzionalni nizovi


float(*a)[5]=new float[2][5];

a
------------100

a[0][0]:

a[0][1]:

a[0][2]:

a[0][3]:

a[0][4]:

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

Pokaziva na pokaziva
PROBLEM: Potrebno je kreirati niz dimenzija n*m, tj. niz kome
dimenzije nisu unaprijed poznate
Dvodimenzionalni dinamiki niz moe imati varijabilan broj
redova, ali broj kolona mora biti poznat
RJEENJE: Deklarisanjem pokazivaa na jednodimenzionalni
niz pokazivaa. Svaki lan podniza pokazivaa e pokazivati na
poetak jednog reda
Deklarisanjem reda dimenzije [kolona+1] pri emu prva kolona
sadri informaciju o stvarnom broju lanova s podacima.
Ukoliko e broj kolona biti identian u svim redovima, onda je
potrebna dimenzija [kolona]

Alociranje memorije
Deklaracija pokazivaa na pokaziva

int ** pok = NULL; //ili


int ** pok = nullptr;

Alokacija prostora za niz pokazivaa


pok = new int *[redova];

Alokacija nizova za svaki pokaziva u nizu pokazivaa


for (int i = 0; i < redova; i++)
pok[i] = new int [kolona];

Alociranje memorije

pok
002F8B08

3
0

kolona-1

kolona-1

002F8B08

004A8B40

004A8118

002F8B0C

004A8B40

004A8158

002F8B10

77
004A8118
0
redova-1
004A8158

pok[1][2] = 77;

kolona-1

Viedimenzionalni nizovi
#include<iostream>
#include<iomanip>
using namespace std;
void main() {
int Kraj=1;
do {
int** niz = nullptr;
int redova =0, kolona = 0;
cout<<"Unesite broj redova: ";
cin>>redova;
niz = new int*[redova]; // da li je potreban assert
for(int i=0;i<redova;i++) {
cout<<"Unesite broj kolona u "<<(i+1)<<". redu: ";
cin>>kolona;
niz[i]=new int[kolona+1];
niz[i][0]=kolona;
for(int j=1;j<=kolona;j++)
niz[i][j]=i*10+j+10;
}

Viedimenzionalni nizovi
//u ovom primjeru svaki red moze imati razlicit broj kolona,
//pa je zbog toga u svakom redu potrebno pamtiti odabrani broj
for(int j=1;j<=kolona;j++)
niz[i][j]=i*10+j+10;
}
//ispis
cout<<"Ispis clanova polja: "<<endl;
Unesite broj redova: 3
for(int i=0;i<redova;i++) {
Unesite broj kolona u 1. redu: 5
cout<<endl;
Unesite broj kolona u 2. redu: 8
Unesite broj kolona u 3. redu: 2
for(int j=1;j<=niz[i][0];j++)
Ispis clanova polja:
cout<<setw(4)<<niz[i][j];
}
11 12 13 14 15
21 22 23 24 25 26 27 28
//dealokacija
31 32
for(int i=0;i<redova;i++)
Za nastavak <1>, za kraj <0>:
delete[]niz[i];
delete[]niz;
niz = NULL;
cout<<endl<<"Za nastavak <1>, za kraj <0>: ";
cin>>Kraj;
}while(Kraj==1);
}

Viedimenzionalni nizovi
#include<iostream>
#include<iomanip>
#include<assert.h>
using namespace std;
void Unos(int ** niz, int redova, int kolona){
for(int i=0;i<redova;i++)
for(int j=0;j<kolona;j++){
//ako zelite unositi vrijednosti clanova niza
//uklonite komentar sa naredne dvije linije code-a
//a stavite komentar na trecu liniju koja automatski
//inicijalizuje vrijednosti
//cout<<"niz["<<i<<"]["<<j<<"]: ";
//cin>>niz[i][j];
niz[i][j]=i*10+j+10;
}
}
void Alokacija(int **& niz, int & redova, int & kolona){
cout<<"Unesite dimenzije matrice: ";
cin>>redova>>kolona; //obavite provjere validnosti
niz = new int*[redova];
assert(niz!=NULL);
for(int i=0;i<redova;i++)
niz[i]=new int[kolona];
}

Viedimenzionalni nizovi

void Ispis(int ** niz, int redova, int kolona){


for(int i=0;i<redova;i++) {
for(int j=0;j<kolona;j++)
cout<<"+----";
cout<<"+"<<endl;
for(int j=0;j<kolona;j++)
cout<<"|"<<setw(4)<<niz[i][j];
cout<<"|"<<endl;
}
for(int j=0;j<kolona;j++)
cout<<"+----";
cout<<"+"<<endl;
}
void Dealokacija(int **& niz, int redova){
for(int i=0;i<redova;i++)
delete [] niz[i];
delete [] niz;
niz = NULL;
}

Viedimenzionalni nizovi
void main() {
int Kraj=1;
do {
int** niz = NULL;
int redova=0, kolona=0;
Alokacija(niz,redova,kolona);
Unos(niz,redova,kolona);
Ispis(niz,redova,kolona);
Dealokacija(niz,redova);
cout<<endl<<"Za nastavak <1>, za kraj <0>: ";
cin>>Kraj;
}while(Kraj==1);
Unesite dimenzije matrice: 5 8
}
+----+----+----+----+----+----+----+----+
| 10| 11| 12| 13| 14| 15| 16| 17|
+----+----+----+----+----+----+----+----+
| 20| 21| 22| 23| 24| 25| 26| 27|
+----+----+----+----+----+----+----+----+
| 30| 31| 32| 33| 34| 35| 36| 37|
+----+----+----+----+----+----+----+----+
| 40| 41| 42| 43| 44| 45| 46| 47|
+----+----+----+----+----+----+----+----+
| 50| 51| 52| 53| 54| 55| 56| 57|
+----+----+----+----+----+----+----+----+
Za nastavak <1>, za kraj <0>:

Zadatak
Za vjebu rada s dinamikim viedimenzionalnim poljima u
nastavku je opisan jednostavan problem stepenovanja
(gradacije) studenata na takmienju iz programiranja

Svaki uesnik je rjeavao tri programska zadatka


Rjeenja su ocijenjena bodovima od 1 do 10
Broj uesnika nije ogranien
eli se dobiti rang lista uesnika prema uspjehu

Definicija problema: Za svakog pojedinog uesnika uitavaju


se po tri (3) bodovna rezultata. Program e ispisati rang listu
koja obuhvata:
redni broj uesnika
prosjek osvojenih bodova
pojedinane bodove za svako od navedena 3 programska rjeenja

Na kraju, program treba ispisati, za svaki programski zadatak


posebno, ukupan prosjek bodova.

Analiza
Problem podataka: Potrebno je pronai metodu koja e omoguiti da
se, nakon uitavanja, sauvaju svi bodovni rezultati i izraunati
prosjeci svih uesnika
Rjeenje: Program e raditi s tri (3) polja: jedno cjelobrojno
dvodimenzionalno polje dimenzija [N] redova (broj uesnika)* [3]
kolona (uitani rezultati), i dva (2) realna jednodimenzionalna polja jedno od [N] kolona (izraunati prosjeci) i jedno od [3] kolone (skupni
prosjeci pojedinih programskih zadataka):
int (*Bodovi)[N] = new int[N][3];
float * Prosjek = new float[N];
float Prog[3];

Analiza
S obzirom na to da se indeksi u C++ jeziku raunaju od nule (0),
imati emo sljedee algoritme:
int i = rbs - 1;
int j = rbpz - 1;

pri emu rbs predstavlja redni broj studenta, rbpz redni


broj programskog zadatka.
Bodovi[i][j] oznaava broj bodova koje je student [i]
dobio za rjeenje programskog zadatka [j], Prosjek[i]
oznaava prosjek bodova studenta [i], dok npr. Prog[1]
oznaava prosjeni broj bodova svih studenata dobivenih za
programski primjer broj 2.

Organizacija podataka
Naredni crte prikazuje mogue vrijednosti polja Bodovi, Prosjek i Prog za 4
uesnika i 3 programska zadatka.

Prosjek

Bodovi

Prog

10

10

10

10.0

Prosjek[0]

1.0

Prosjek[1]

7.7

Prosjek[2]

10

7.7

Prosjek[3]

7.0

5.3

7.5

Prog[0]

Prog[1]

Prog[2]

Algoritam

Uitaj broj uesnika i alociraj memoriju za dinamika polja


Uitaj bodove
Izraunaj prosjek za svaki programski zadatak
prosjek_zadatak=suma_bodova_zadatka/N

Izraunaj prosjek za svakog uesnika


prosjek_ucesnika=suma_bodova_ucesnika/3

Sortiraj rezultate silazno po prosjecima ucesnika


Ispii rang listu ucesnika i skupne prosjeke
Dealociraj memorijski prostor

Kreirajte programsko rjeenje za prethodno opisani problem (zadatak)

KRAJ PREZENTACIJE

You might also like