540 likes | 839 Views
Funkcije. *. Zadatak: y=x 3. Želimo izračunati y=x 3 pri čemu x=2, x=3. Rezultat se ispisuje na zaslonu. Klasično rješenje #include <iostream> using namespace std; int main() { int x=2; int y=x*x*x; cout<< " 2 na trecu je " <<y <<endl; x=3; y=x*x*x;
E N D
Funkcije *
Zadatak: y=x3 Želimo izračunati y=x3 pri čemu x=2, x=3. Rezultat se ispisuje na zaslonu. Klasično rješenje #include<iostream>using namespace std; int main() { int x=2; int y=x*x*x; cout<<"2 na trecu je "<<y <<endl; x=3; y=x*x*x; cout<<"3 na trecu je "<<y <<endl; system("pause"); return 0; } Rješenje s funkcijom #include<iostream> using namespace std; int Funkcija(int x); int main() { cout<<"2 na trecu je " <<Funkcija(2)<<endl; cout<<"3 na trecu je " <<Funkcija(3)<<endl; cout<<endl<<"Za kraj <1>: "; system("pause"); return 0; } int Funkcija(int x) { return x*x*x; } deklaracija funkcijepoziv funkcijedefinicija funkcije *
Deklaracija funkcije: format <povratni tip> ime_funkcije (<tip> argument_1, <tip> argument_2, ..., <tip> argument_n); povratni tip tip argumenta int Funkcija (int x); ime funkcije argument(parametar) *
Funkcije: deklaracija - poziv - definicija Deklaracija prototip funkcije int Funkcija (int x); stvarni argument formalni argument Poziv cout<< ... <<Funkcija(2)<<endl; cout<< ... <<Funkcija(3)<<endl; Definicija int Funkcija (int x) { return x*x*x; } formalni argument tijelo funkcije *
Tip funkcije Tip funkcije određuje kakvog će tipa biti podatak koji funkcija vraća kôdu koji ju je pozvao: int funkcijaPrva(int x); //tipa int float funkcijaDruga(float x); //tipa float char* funkPok(); //vraća pokazivač na znak return Naredbom ‘return’ rezultat funkcije se proglašava povratnom vrijednošću, izvođenje funkcije se prekida, a vrijednost se vraća pozivajućem kôdu: float apsolutno(float X){ return(x>=0) ? x:-x; } *
Funkcije tipa void Kad funkcija ne treba vratiti vrijednost, deklarira se tipom ‘void’: void ispisiKvadrat(float x){ cout<<(x*x)<<endl;} *
Poziv funkcije #include<iostream> using namespace std; intFunkcija(int Formalni_x); //deklaracija int main(){ int Stvarni_x=2; int xNaCetvrtu=Funkcija(Stvarni_x)*Stvarni_x;//poziv int xNaDevetu=Funkcija(Funkcija(Stvarni_x)); //poziv int a=3; int b=4; int Suma=Funkcija(a)+Funkcija(b); //poziv cout << Suma << endl; system("pause"); return 0; } int Funkcija(int Formalni_x){ //definicija return(Formalni_x*Formalni_x*Formalni_x); } *
Program:blagajna (izdavanje računa) #include<iostream> #include<iomanip> using namespace std; double Total(int P1, float P2); //deklaracija funkcije int main(){ cout<<"Unesi cijenu <dec.podatak> i broj komada <cijeli broj>: "; int Broj; float Cijena; cin>>Cijena>>Broj; //ulancano citanje cout<<endl<<Broj<<" proizvoda po KN"<<setw(6)<<Cijena <<endl; cout<<"iznosi ukupno KN"<<setw(6)<<Total(Broj,Cijena) <<endl; //ispis s pozivom funkcije cout<<"ukljucujuci 22% PDV-a"<<endl; system("pause");return 0;} double Total(int P1,float P2){ //definicija funkcije //vraca umnozak cijene P1 i kolicine P2 //uvecan za 22% PDV-a return (P1*P2+(P1*P2*.22));}; *
Funkcije: definicija - poziv int Funkcija (int x) { return x*x*x; } Definicija formalni argument stvarni argument tijelo funkcije Poziv cout<< ... <<Funkcija(2)<<endl; cout<< ... <<Funkcija(3)<<endl; Ako je definicija funkcije navedena prije njenog prvog poziva u programu, nije potrebno posebno navoditi deklaraciju, već se definicija smatra ujedno i deklaracijom. *
Poziv funkcije #include<iostream> using namespace std; int Funkcija(int Formalni_x){ //definicija return(Formalni_x*Formalni_x*Formalni_x); } int main(){ int Stvarni_x=2; int xNaCetvrtu=Funkcija(Stvarni_x)*Stvarni_x;//poziv int xNaDevetu=Funkcija(Funkcija(Stvarni_x)); //poziv int a=3; int b=4; int Suma=Funkcija(a)+Funkcija(b); //poziv cout << Suma << endl; system("pause"); return 0; } *
Rekurzija • Funkcija poziva sama sebe s drugim argumentima. • #include<iostream> • using namespace std; • int Faktorijela(int n){ • if (n==0) return 1; • else return Faktorijela(n-1)*n; • } • int main(){ • intn; • cout << "Upisite n: "; • cin >> n; • cout << n << "!=" << Faktorijela(n) << endl; • system("pause"); return 0;}
Rekurzija – Cjeloviti primjer • Tornjevi Hanoja su vrlo poznata igra koja je zadana na sljedeći način: • Imamo 3 Stupića 1, 2 i 3. Na stupiću 1 nalazi se n kolutova poredanih tako da se svaki kolut nalazi iznad većeg koluta. Cilj je prebaciti sve kolutove na stupić 3 uz pomoć stupića 2 ali tako da se prbacuje jedan po jedan i da ni u kojem trenutku ne smije biti veći kolut na bilo kojem stupiću iznad manjeg.
Rekurzija – Cjeloviti primjer • Problem se lagano rješava rekurzijom. • Globalno gledano, rješenje je sljedeće: • Treba n-1 kolutova prebaciti sa stupića 1 na stupić 2 • Treba 1 kolut prebaciti sa stupića 1 prebaciti na na stupić 3 • Treba n-1 kolutova prebaciti sa stupića 2 na stupić 3. • Kako n-1 kolutova prebaciti s 1 na 2 i kasnije s 2 na 3? • Rekurzijom!
Rekurzija – Cjeloviti primjer Matematička indukcija • Proširimo neznatno problem tako da rješava problem prebacivanja n kolutova sa stupića sa na stupić na. Problem treba promatrati induktivno: • Ako je n=1, onda jednostavno premjestimo kolut sa stupića sa na stupić na. • Pretpostavimo da znamo kako se premještaju kolutovi ako ih ima manje ili jednako n-1. • Tada se n kolutova premješta na sljedeći način: • Premjesti se n-1 kolutova sa stupića sa na pomoćni stupić • Premjesti se 1 kolut sa stupića sa na stupić na. • Premjesti se kolutova sa pomoćnog stupića na stupić na.
Rekurzija – Cjeloviti primjer Kako odrediti broj pomoćnog stupića? Stupići imaju brojeve 1, 2 i 3. Ukupna suma tih brojeva je 6. Ako imamo dva zadana stupića, onda se broj trećeg izračunava po formuli 6-sa-na • Proširimo neznatno problem tako da rješava problem prebacivanja n kolutova sa stupića sa na stupić na. Problem treba promatrati induktivno: • Ako je n=1, onda jednostavno premjestimo kolut sa stupića sa na stupić na. • Pretpostavimo da znamo kako se premještaju kolutovi ako ih ima manje ili jednako n-1. • Tada se n kolutova premješta na sljedeći način: • Premjesti se n-1 kolutova sa stupića sa na pomoćni stupić • Premjesti se 1 kolut sa stupića sa na stupić na. • Premjesti se kolutova sa pomoćnog stupića na stupić na.
Rekurzija – cjeloviti primjer • #include<iostream> • using namespace std; • voidHanoi(int n, int sa, int na){ • if (n==1) • cout << sa << "->" << na << endl; • else { • Hanoi(n-1,sa, 6-sa-na); • cout << sa << "->" << na << endl; • Hanoi(n-1,6-sa-na,na); • } • } • int main(){ • intn; • cout << "Upisite n: "; • cin >> n; • Hanoi(n,1,3); • system("pause"); return 0; • }
Kako radi program s funkcijama i argumentima? • Kod poziva funkcija koristi se programski stog. • Kod svakog poziva na stog se zapisuje aktivacijski zapis funkcije: Lokalne varijable Parametri Dinamička veza Povratna adresa *
Kako radi program s funkcijama i argumentima? • Kod poziva funkcija koristi se programski stog. • Kod svakog poziva na stog se zapisuje aktivacijski zapis funkcije: Lokalne varijable Parametri Dinamička veza Adresa kamo se program vraća nakon izvođenja funckije Povratna adresa *
Kako radi program s funkcijama i argumentima? • Kod poziva funkcija koristi se programski stog. • Kod svakog poziva na stog se zapisuje aktivacijski zapis funkcije: Lokalne varijable Parametri Pokazivač na vrh aktivacijskog zapisa funkcije koja je pozvala ovu funkciju Dinamička veza Povratna adresa *
Kako radi program s funkcijama i argumentima? • Kod poziva funkcija koristi se programski stog. • Kod svakog poziva na stog se zapisuje aktivacijski zapis funkcije: Lokalne varijable Adrese parametara (argumenti) funkcije Parametri Dinamička veza Povratna adresa *
Kako radi program s funkcijama i argumentima? • Kod poziva funkcija koristi se programski stog. • Kod svakog poziva na stog se zapisuje aktivacijski zapis funkcije: Adrese lokalnih varijabli funkcije Lokalne varijable Parametri Dinamička veza Povratna adresa *
Kako radi program s funkcijama i argumentima? • Kod povratka iz funkcije, deaktiviraju se (oslobodi prostor) lokalne varijabli funkcije, obriše se njen aktivacijski blok sa stoga, se nazad aktiviraju varijable pozivne funkcije, koje su zapisane u stogu i vraća se vrijednost (ako funkcija nije void) funkcije. *
Kako radi program s funkcijama i argumentima? • Treba napomenuti da se kod poziva funkcije njeni parametri prepisuju na novu memorijsku lokaciju, a ne radi se s onom koja je zapisana u aktivacijskom stogu. • Stoga promjene argumenata, iako su moguće unutar funkcije, neće biti vidljive izvan same funkcije. *
Stog (stack) je tzv. LIFO (last-in-first-out) struktura u kojoj se posljednjapohranjena komponenta briše prva. Dio glavne memorije za alokaciju i pohranjivanje statičkih objekata. Postupak alokacije i dealokacije u ingerenciji je računala i obavlja se automatski. *
Primjer • #include<iostream> • using namespace std; • voidFunkcija(int n){ • cout << "Funkcija: " << endl; • while (n>0) { • cout << n << endl; • n/=2; • } • } • int main(){ • intn; • cout << "Upisite n: "; • cin >> n; • Funkcija(n); • cout << "Glavni program: " << endl << n << endl; • system("pause"); • return 0; • } Argument funkcije MOŽE se mijenjati unutar funkcije Promjene argumenta funkcije NEĆE se reflektirati izvan funkcije
Kako radi program s funkcijama i argumentima? • Što ako želimo funkciji dati argument koji želimo da ona promijeni i da ostane promijenjen nakon povratka iz funkcije? • Odgovor idući puta *
Kako radi program s funkcijama i argumentima void f2(int r) { int s,t; ... f1(s); ... } void main() { float p; ... f2(p); ... } void f3(int q) { ... } void f1(int x) { int y; ... f3(y); ... }
Kako radi program s funkcijama i argumentima void f2(int r) { int s,t; ... f1(s); ... } void main() { float p; ... f2(p); ... } void f3(int q) { ... } void f1(int x) { int y; ... f3(y); ... } local p
Kako radi program s funkcijama i argumentima void f2(int r) { int s,t; ... f1(s); ... } void main() { float p; ... f2(p); ... } void f3(int q) { ... } void f1(int x) { int y; ... f3(y); ... } local t local s Poziv funkcije f2 parameter r Return (main) local p
Kako radi program s funkcijama i argumentima void f2(int r) { int s,t; ... f1(s); ... } void main() { float p; ... f2(p); ... } void f3(int q) { ... } void f1(int x) { int y; ... f3(y); ... } local y Poziv funkcije f1 parameter x Return (f2) local t local s Poziv funkcije f2 parameter r Return (main) local p
Kako radi program s funkcijama i argumentima void f2(int r) { int s,t; ... f1(s); ... } void main() { float p; ... f2(p); ... } Poziv funkcije f3 parameter q void f3(int q) { ... } void f1(int x) { int y; ... f3(y); ... } Return (f1) local y Poziv funkcije f1 parameter x Return (f2) local t local s Poziv funkcije f2 parameter r Return (main) local p
Funkcije: pravila Funkcija je potprogram (logička cjelina) koja se poziva i izvodi po potrebi jednom ili veći broj puta na mjestima gdje je to potrebno. Ustrojstvo funkcije ne mora biti poznato korisniku. On mora znati što funkcija radi, ali mu nije bitno kako ona to radi. Funkcije imaju parametre ili argumente (engl. parameters, arguments) koji se zadaju prilikom poziva. Rezultat funkcije je povratna vrijednost (engl. return value). Funkcija može pozvati drugu funkciju, ali i samu sebe (rekurzija). Deklaracija daje prototip funkcije. Ona ne sadržava opis što i kako funkcija radi. Funkcija može imati n argumenata, a može biti i bez argumenata. Broj argumenata, njihov redoslijed i tip zajednički se nazivaju potpis funkcije. Naredbe koje se izvode po pozivu funkcije čine tijelo funkcije (engl. function body). *
Problem Na osnovi poznavanja cijene i broja komada kupljenog proizvoda potrebno je izdati blagajnički račun u kunama (KN). Pritom se 22% poreza na dodanu vrijednost (PDV) neki puta računa, a neki puta ne. Potrebno je omogućiti ponavljanje za veći broj računa. Analiza Općenito, iznos u kunama izračunava se po formuli: Iznos = Cijena u kunama * Broj komada . Ukoliko se iznosu treba pribrojiti PDV, formula glasi Iznos = Cijena u kunama * Broj komadaPostotak = Iznos * 22 / 100Konačni iznos = Iznos + Postotak ili Iznos = Cijena * Broj +Cijena * Broj * 0.22 *
Podaci Ulaz float Cijena; //cijena proizvoda u KN int Broj; //broj kupljenih komada char C; //indikator PDV-a char Kraj; //indikator kraja Izlaz ispis iznosa sa ili bez PDV-a (varijabla nepotrebna, radi se s funkcijama) Funkcije Total(int P1, float P2); izračunava iznos uvećan za PDV; formalni parametri P1 (broj kupljenih komada) P2 (cijena) PDV(char Znak, int N1, float N2); izračunava iznos bez PDV-a ustanovljava treba li obračunati PDV ili ne poziva proceduru Total *
Oblikovanje algoritma U glavnoj funkciji (main) upotrijebit će se iteracija s uvjetnim izlazom na vrhu (while). Glavna funkcija poziva funkciju PDV, a ova funkciju Total. Algoritam POČETAK 1. Kraj=1 2. Ponavljanje sve dok (Kraj==1) 2.1 Učitavanje: Cijena, Broj, C 2.2 Ispitivanje 2.2.1 Ako (C==‘d’) Iznos=Cijena*Broj+(Cijena*Broj*0.22) u protivnom Iznos=Cijena*Broj 2.3 Ispis računa 2.4 Učitavanje: Kraj ZAVRŠETAK *
#include<iostream> #include<iomanip> using namespace std; double PDV(char Znak,int N1, float N2); double Total(int P1, float P2); int main(){ cout<<endl<<"BLAGAJNA: IZDAVANJE RACUNA SA ILI BEZ PDV-a"<<endl<<endl; char Kraj='d'; while((Kraj=='d')||(Kraj=='D')){ cout<<"Unesi cijenu <dec.podatak> i broj komada <cijeli broj>: "; int Broj; float Cijena; cin>>Cijena>>Broj; char C; cout<<"PDV<d/n>: "; cin>>C; cout<<endl<<Broj<<" proizvoda po KN "<<setw(6) <<Cijena<<endl; cout<<"iznosi ukupno KN"<<setw(6) <<PDV(C,Broj,Cijena)<<endl; Program *
if ((C=='n')||(C=='N')) cout<<"oslobodjeno PDV-a"<<endl; else cout<<"ukljucujuci 22% PDV-a"<<endl; cout<<endl<<"Jos<d/n>:"; cin>>Kraj; cout<<endl<<endl; } return 0; } double PDV(char Znak,int N1, float N2){ if ((Znak=='n')||(Znak=='N')) return (N1*N2); else return (Total(N1,N2));} double Total(int P1,float P2){ //vraca umnozak cijene P1 i kolicine P2 //uvecan za 22% PDV-a return (P1*P2+(P1*P2*.22)); }; *
Polja kao argumenti Zadatak: napišite program koji ‘briše’ sadržaj polja, odnosno pridružuje članovima nule (0). #include<iostream>using namespace std; void Brisi(int polje[],int dulj){ while(--dulj>=0) polje[dulj]=0;} void Ispis(int polje[],int dulj){ while(--dulj>=0) cout<<"b["<<dulj<<"]="<<polje[dulj]<<endl;} int main() { int b[]={5,10,15}; cout<<endl<<"PROGRAM PRIDRUZUJE NULE CJELOBROJNOM POLJU"<<endl; cout<<endl<<"Sadrzaj polja prije pridruzivanja nula:"<<endl; Ispis(b,3); Brisi(b,3); cout<<endl<<"Sadrzaj polja nakon pridruzivanja nula:"<<endl; Ispis(b,3); system("pause"); return 0;} U funkciju se ne prenosi cijelo polje, već samo njegova memorijskaadresa Zbog toga će se promjene na elementima polja napravljene u funkciji reflektirati i izvan nje *
Primjer apstraktnog programa s dvije funkcije //deklaracije funkcija <tip> funkcijaPrva(); <tip> funkcijaDruga(); //glavni program (glavna funkcija) <tip>main(){ //... funkcijaPrva();//poziv //... funkcijaDruga();//poziv } //definicije funkcija <tip>funkcijaPrva(){ //... } <tip>funkcijaDruga(){ //... funkcijaPrva();//poziv //... } datotekezaglavlja modul 1 modul 2 modul 3 *
Isti primjer programa razbijenog u module extern <tip> funkcijaPrva();//deklaracija DATOTEKA ZAGLAVLJA: funk1.h extern <tip> funkcijaDruga(); //deklaracija DATOTEKA ZAGLAVLJA: funk2.h #include “funk1.h” //uključuje deklaraciju funkcije ‘funkcijaPrva’ #include “funk2.h” //uključuje deklaraciju funkcije ‘funkcijaDruga’ int main(){ //... funkcijaPrva(); //poziv //... funkcijaDruga(); //poziv } MODUL 1: glavni.cpp <tip> funkcijaPrva(){ //definicija funkcije //... } MODUL 2: funk1.cpp #include “funk1.h” //uključuje deklaraciju funkcije ‘funkcijaPrva’ <tip> funkcijaDruga(){//definicija //... funkcijaPrva(); //poziv } MODUL 3: funk2.cpp *
Pozor!!! #include<iostream> #include<iomanip> #include “funk1.h” ovo je uputa procesoru da datoteku prvo potraži u tekućem imeniku (direktoriju), pa tek onda u imenicima definiranim u prevoditelju prilikom instaliranja *
Microsoft VisualStudio97&Visual C++ 5.0: postupak izrade, prevođenja i povezivanja programa s eksternim modulima • 1. Glavni program: kodiranje (File + Files + New C++ Source File) i spremanje (Save As) • 2. Funkcije:kodiranje i spremanje (isti postupak kao pod 1.) 3. Kodiranje dat. zaglavlja (File + Files + New C/C++ Header File) 4. Prvo prevođenje (compile) glavnog programa i povezivanje (build): sve mora biti uključeno u isti projekt/Workspace 5. Ako je bilo pogrešaka: popravljanje, ponavljanje prevođenja i povezivanja (Rebuild All) dok se ne dobije izvedbena (*.exe) verzija glavnog programa 6. Testiranje (izvođenje) glavnog programa 7. Ako je bilo logičkih pogrešaka 7.1 Ponavljanje od 5. 8. Završetak (Save All, Save/Close Workspace) Demonstracija *
Modularno rješenje: blagajna - izdavanje računa extern double funkcijaPrva(char Znak,int N1, float N2);//deklaracija DATOTEKA ZAGLAVLJA: funk1.h extern double funkcijaDruga(int P1,float P2);//deklaracija DATOTEKA ZAGLAVLJA: funk2.h #include "funk2.h”//uključuje funkciju ‘funkcijaDruga’ double funkcijaPrva(char Znak,int N1, float N2){//definicija if (Znak==‘n’) return (N1*N2); else return (funkcijaDruga(N1,N2));}//poziv MODUL 2: funk1.cpp double funkcijaDruga(int P1,float P2){//definicija //vraca umnozak cijene P1 i kolicine P2 //uvecan za 22% PDV-a return (P1*P2+(P1*P2*.22)); }; MODUL 3: funk2.cpp *
#include<iostream.h> #include<iomanip.h> #include “funk1.h”//uključuje funkciju ‘funkcijaPrva’ int main(){ cout<<endl<<"BLAGAJNA: IZDAVANJE RACUNA SA ILI BEZ PDV-a”<<endl <<endl; char Kraj='d'; while((Kraj=='d')||(Kraj=='D')){ cout<<"Unesi cijenu<dec.podatak> i broj komada<cijeli broj>: "; int Broj; float Cijena; cin>>Cijena>>Broj; char C; cout<<"PDV<d/n>: "; cin>>C; cout<<endl<<Broj<<" proizvoda po KN "<<setw(6)<<Cijena<<endl; cout<<"iznosi ukupno KN"<<setw(6)<<funkcijaPrva(C,Broj,Cijena) <<endl;//poziv uključen u čitanje if (C==‘n’) cout<<"oslobodjeno PDV-a"<<endl; else cout<<"ukljucujuci 22% PDV-a"<<endl; cout<<endl<<"Jos<d/n>:"; cin>>Kraj; cout<<endl<<endl;} return 0;} MODUL 1: glavni.cpp *