Programozás (GKxB_INTM021) Széchenyi István Egyetem, Gy r 2018. március 3.
Függvények Mi az a függvény (function)? Programkód egy konkrét, azonosítható, paraméterezhet, újrahasznosítható blokkja Miért használunk függvényeket? Hosszú forrásszöveg áttekinthet, kisebb részekre tördelése (modularitás) Többszöri felhasználás lehet sége egy programon belül, kódismétlés nélkül több programban, gyakran használt részeket nem kell újra megírni (ld. sqrt, pow)
Függvények Függvény deníció Teljes formai információ a függvényr l: visszatérési érték típusa, azonosító, formális paraméterek, függvénytest (ld. main) Pontosan egy létezhet bel le Forrásfájlokban vagy el fordított könyvtárakban tárolják 4 double a b s z o l u t ( double szam ) { 5 r e t u r n szam <0.? szam : szam ; 6 }
Függvények Függvényhívás A függvénynek a híváskor ismertnek kell lennie Vezérlés + aktuális paraméterek átadása Érték szerinti paraméterátadás Vezérlés visszaadása + visszatérési érték szolgáltatása: return 8 i n t main ( ) { 9 d o u b l e v ; 10 c o u t << "Szam : " ; c i n >> v ; 11 c o u t << " A b s z o l u t e r t e k e : " << a b s z o l u t ( v ) 12 << " \ n a b s z o l u t ( 3) == " << a b s z o l u t ( 3) 13 << " \ n a b s z o l u t ( v 3 ) == " << a b s z o l u t ( v 3 ) 14 << " \ n a b s z o l u t ( a b s z o l u t ( 3)) == " 15 << a b s z o l u t ( a b s z o l u t ( 3)) << e n d l ; 16 r e t u r n 0 ; 17 }
Függvények Visszatérési érték Vt. típusa nem lehet tömb return utáni kifejezés: hozzárendelési konverzió szükséges lehet void típus: valaminek a hiányát jelzi (eljárás) Formális paraméterlista Nincsenek paraméterek: int main() {...} Egy paraméter: double abszolut(double szam) {...} Két paraméter: double hatvany(double alap, double kitevo) {...} Aktuális paraméterek hozzárendelési konverzió formális paraméterek Tömb átadása speciális eset
Függvények Függvény teste tartalmazhat mindent, ami a main-ben is megengedett volt, azaz Változók deklarációit A blokkon kívül deklarált tételekre történ hivatkozásokat Tevékenységet meghatározó utasításokat Visszatérés a függvényb l a függvény végén return utasítással (a fv. tartalmazhat több return-t is) Karakter els el fordulásának keresése string-ben 4 i n t k e r e s ( s t r i n g miben, c h a r m i t ) { 5 f o r ( u n s i g n e d i =0; i <miben. l e n g t h ( ) ; i ++) { 6 i f ( miben [ i ] == m i t ) r e t u r n i ; 7 } 8 r e t u r n 1; 9 }
Függvények Függvények deníciói nem ágyazhatóak egymásba! i n t main ( ) { double a b s z o l u t ( double szam ) { r e t u r n szam <0.? szam : szam ; } c o u t << a b s z o l u t ( 1) << e n d l ; r e t u r n 0 ; } Fordítási hiba beagyazas.cpp: In function `int main()': beagyazas.cpp:2:32: error: a function-denition is not allowed here before `{' token double abszolut(double szam) {
Hozzárendelési konverzió El fordulások: változónak történ értékadáskor, pl. fv. visszatérési értékének átalakításakor unsigned int signed int 4 i n t k e r e s ( s t r i n g miben, c h a r mit ) { 5 f o r ( u n s i g n e d i =0; i <miben. l e n g t h ( ) ; i ++) { 6 i f ( miben [ i ] == mit ) r e t u r n i ; 7 } 8 r e t u r n 1; 9 }
Hozzárendelési konverzió El fordulások: változónak történ értékadáskor, pl.?: operátor használatakor int char 4 i n t main ( ) { 5 c h a r k ; 6 c o u t << " K a r a k t e r : " ; c i n >> k ; 7 k = k>=' a ' and k<=' z '? k ' a '+ 'A ' : k ; 8 c o u t << " Nagybetus a l a k : " << k ; 9 r e t u r n 0 ; 10 }
Hozzárendelési konverzió El fordulások: változónak történ értékadáskor, pl. fv. aktuális paraméterének konverziójakor int double 4 d o u b l e a b s z o l u t ( d o u b l e szam ) { 5 r e t u r n szam <0.? szam : szam ; 6 } 12 << "\ n a b s z o l u t ( 3) == " << a b s z o l u t ( 3)
Hozzárendelési konverzió Részletek: cppreference.com Néhány példa: Mir l? Mire? Kimenetel signed+ unsigned signed unsigned el jel funkcióvesztése long int int értékvesztés veszélye int double pontosságvesztés veszélye oat double double oat pontosságvesztés veszélye double int törtrész levágás
Mintapélda függvények használatára Megvalósítandó szolgáltatások (függvények): Kombináció Adott n különböz elem. Ha n elem közül k(0 < k n) elemet úgy választunk ki, hogy mindegyik csak egyszer kerül sorra, és a kiválasztás sorrendje nem számít, akkor az n elem egy k-ad osztályú ismétlés nélküli kombinációját kapjuk. Jele: C k n C k = n! n (n k)!k! = ( ) n k Példa: hányféleképpen tudunk három gyümölcs (mondjuk alma, körte, barack) közül kett t kiválasztani? 1 alma, körte 2 alma, barack 3 körte, barack
Mintapélda függvények használatára Megvalósítandó szolgáltatások (függvények): Faktoriális Egy n nemnegatív egész szám faktoriálisa az n-nél kisebb vagy egyenl pozitív egész számok szorzata. Jele: n! n! = n k=1 k minden n 0 számra. Megállapodás szerint 0! = 1 n elemet n! sorrendbe lehet állítani (permutációk) Példa: hányféleképpen tudunk három gyümölcsöt (mondjuk alma, körte, barack) sorba állítani? 1 alma, körte, barack 2 alma, barack, körte 3 körte, alma, barack 4 körte, barack, alma 5 barack, alma, körte 6 barack, körte, alma
Mintapélda függvények használatára Megvalósítandó szolgáltatások (függvények): Beolvasás Beolvasandó n és k értéke F program Adatok beolvasása, ( n k) megjelenítése main beker kombinacio faktorialis
Mintapélda függvények használatára main beker kombinacio faktorialis be: n vissza: n be: k vissza: k mennyi n alatt k? vissza: n alatt k mennyi n!? vissza: n! mennyi k!? vissza: k! mennyi (n-k)!? vissza: (n-k)!
Mintapélda függvények használatára 1 #i n c l u d e <i o s t r e a m > 2 #i n c l u d e < c l i m i t s > 3 using namespace s t d ; 4 5 i n t b e k e r ( i n t max ) { 6 i n t szam ; 7 bool h i b a s ; 8 do { 9 c o u t << "Szam : " ; 10 c i n >> szam ; 11 h i b a s = szam<1 or szam>max ; 12 i f ( h i b a s ) c o u t << " H i b a s a d a t! \ n" ; 13 } w h i l e ( h i b a s ) ; 14 r e t u r n szam ; 15 }
Mintapélda függvények használatára 17 u n s i g n e d l o n g f a k t o r i a l i s ( i n t n ) { 18 i f ( n < 2) r e t u r n 1 ; 19 u n s i g n e d l o n g f = 1 u l ; 20 f o r ( i n t i =1; i <=n ; i ++) { 21 f = i ; 22 } 23 r e t u r n f ; 24 } 25 26 u n s i g n e d l o n g k o m b i n a c i o ( u n s i g n e d l o n g n, u n s i g n e d l o n g k ) { 27 r e t u r n f a k t o r i a l i s ( n ) / ( f a k t o r i a l i s ( k ) f a k t o r i a l i s ( n k ) ) ; 28 } 29 30 i n t main ( ) { 31 i n t n = b e k e r (INT_MAX ) ; 32 i n t k = b e k e r ( n ) ; 33 c o u t << k o m b i n a c i o ( n, k ) ; 34 r e t u r n 0 ; 35 }
Mintapélda függvények használatára Függvények felültöltése (overloading): a függvényt a neve és paramétereinek száma, típusa együttesen azonosítja. A fordító híváskor az aktuális paraméterek alapján választ az azonos nev ek közül. beker() beker(int) 4 i n t b e k e r ( ) { 5 i n t szam ; 6 b o o l h i b a s ; 7 do { 8 c o u t << "Szam : " ; 9 c i n >> szam ; 10 h i b a s = szam <1; 11 i f ( h i b a s ) 12 c o u t << " H i b a s a d a t! \ n" ; 13 } w h i l e ( h i b a s ) ; 14 r e t u r n szam ; 15 } i n t b e k e r ( i n t max ) { i n t szam ; b o o l h i b a s ; do { c o u t << "Szam : " ; c i n >> szam ; h i b a s = szam<1 o r szam>max ; i f ( h i b a s ) c o u t << " H i b a s a d a t! \ n" ; } w h i l e ( h i b a s ) ; r e t u r n szam ; } 17 18 19 20 21 22 23 24 25 26 27 28
Mintapélda függvények használatára Alapértelmezett függvényparaméterek: Ha egy paraméternek alapértelmezett értéket adunk, minden t le jobbra es nek is adni kell! Ha híváskor elhagyunk egy alapértelmezett paramétert, minden t le jobbra lev t is el kell hagyni! 5 i n t b e k e r ( i n t max=int_max) { 6 i n t szam ; 7 b o o l h i b a s ; 8 do { 9 c o u t << "Szam : " ; 10 c i n >> szam ; 11 h i b a s = szam<1 o r szam>max ; 12 i f ( h i b a s ) c o u t << " H i b a s a d a t! \ n" ; 13 } w h i l e ( h i b a s ) ; 14 r e t u r n szam ; 15 }
Fogalmak élettartam Élettartam (lifetime, duration): az a periódus a futásid alatt, amíg a változó/függvény létezik, memóriát foglal. Típusai: Statikus Futás kezdetét l végéig foglal memóriát Összes függvény, és globális (függvényeken kívül deklarált) változó ilyen Globális változók implicit inicializálása: minden bit zérus érték Lehet leg kerülni kell a globális változók használatát + Paraméter-átadás költsége megtakarítható Nehézkes újrahasznosíthatóság, rugalmatlan, környezetfügg kód, névütközések veszélye,...
Fogalmak élettartam Lokális blokkba belépést l annak elhagyásáig rendelnek memóriát hozzájuk függvényparaméterek, vezérlési szerkezetek deníciói is ilyenek csak explicit inicializáció történhet u n s i g n e d l o n g f a k t o r i a l i s ( i n t n ) { i f ( n < 2) r t u r n 1 ; e u n s i g n e d l o n g f = 1 u l ; f o r ( i n t i =1; i <=n ; i ++) { f = i ; } r e t u r n f ; } 17 18 19 20 21 22 23 24 Élettartamok: faktorialis program teljes futásideje alatt létezik n f i 3 fv. hívás miatt 3x létrejön a fv. hívásakor/megsz nik visszatéréskor (18 v. 23. sor) létrejön ha n elég nagy, és megsz nik amikor a végrehajtás a 23. sorhoz ér a 20. sor elérése pillanatában jön létre, és a ciklusból kilépéskor felszabadul
Fogalmak hatáskör Hatáskör (érvényességi tartomány, hatókör, scope): meghatározza, hogy az objektumot a program mely részén lehet elérni; deklarációtól és annak helyét l függ en: Blokk (lokális, bels ) Deklarációtól a tartalmazó blokk végéig, beleértve a beágyazott blokkokat is Pl. függvény formális paraméterei, lokális változói Fájl (globális, küls ) minden függvény testén kívül deklarált azonosítók; deklarációs ponttól a fájl végéig Pl. függvények, globális változók
Fogalmak láthatóság Láthatóság (visibility): A forráskód területe, melyben az azonosító elérhet, hivatkozható Hatáskör és láthatóság általában fedik egymást, de a beágyazott blokkban deklarált azonosító ideiglenesen elrejtheti a befoglaló blokkban lév azonosítót rossz programozói gyakorlat, kerülend!
Rekurzió Rekurzív függvényhívás Minden fv. hívhatja magát közvetlenül vagy közvetve Minden hívásnál új területet foglalnak a formális paramétereknek, lokális változóknak A globális változók mindig ugyanazon a területen maradnak! El kell kerülni a végtelen mélység rekurziót! 17 u n s i g n e d l o n g f a k t o r i a l i s ( i n t n ) { 18 i f ( n < 2) r e t u r n 1 ; 19 r e t u r n n f a k t o r i a l i s ( n 1); 20 }
Rekurzió Hatványozás szorzásokra visszavezetve 4 l o n g h a t v a n y ( i n t a l a p, u n s i g n e d k i t e v o ) { 5 l o n g eredmeny = 1 ; 6 u n s i g n e d i ; 7 f o r ( i =0; i <k i t e v o ; i ++) { 8 eredmeny = a l a p ; } 9 r e t u r n eredmeny ; } Rekurzív hatványozás, pl. 3 5 = 3 2 2 3 1 = 243 4 l o n g h a t v a n y ( i n t a l a p, u n s i g n e d k i t e v o ) { 5 l o n g eredmeny ; 6 i f ( k i t e v o == 0) r e t u r n 1 ; 7 i f ( k i t e v o == 1) r e t u r n a l a p ; 8 eredmeny = h a t v a n y ( a l a p, k i t e v o / 2 ) ; 9 eredmeny = eredmeny ; // nem h i v j u k 2 x! 10 i f ( k i t e v o %2 == 1) eredmeny = a l a p ; 11 r e t u r n eredmeny ; }
Rekurzió Fibonacci-sorozat: másodrendben rekurzív sorozat. Képzeletbeli nyúlcsalád növekedése: hány pár nyúl lesz n hónap múlva, ha az els hónapban csak egyetlen újszülött nyúl-pár van, az újszülött nyúl-párok két hónap alatt válnak termékennyé, minden termékeny nyúl-pár minden hónapban egy újabb párt szül, és a nyulak örökké élnek. F n = 0, ha n = 0 1, ha n = 1 F n 1 + F n 2 ha n > 1
Rekurzió Iteratív változat 4 u n s i g n e d l o n g f i b o n a c c i ( u n s i g n e d ho ) { 5 u n s i g n e d l o n g i =0, j =1, k ; 6 i f ( ho < 2) r e t u r n ho ; 7 f o r ( u n s i g n e d n=1; n<ho ; n++) { 8 k = i+j ; 9 i = j ; 10 j = k ; 11 } 12 r e t u r n k ; 13 } Rekurzív változat 4 u n s i g n e d l o n g f i b o n a c c i ( u n s i g n e d ho ) { 5 i f ( ho < 2) r e t u r n ho ; 6 r e t u r n f i b o n a c c i ( ho 1)+ f i b o n a c c i ( ho 2); 7 }