Az előadás letöltése folymat van. Kérjük, várjon

Az előadás letöltése folymat van. Kérjük, várjon

Programozás alapjai A C nyelv.

Hasonló előadás


Az előadások a következő témára: "Programozás alapjai A C nyelv."— Előadás másolata:

1 Programozás alapjai A C nyelv

2 Programozás Alapjai (2008)
A C nyelv A C egy nagyon kicsi nyelv. Szintaxisa a K&R-ben csupán néhány oldal. A nyelv érzékeny a kis- és nagybetűkre! Nincs beépítve I/O kezelés Sztring kezelés Matematikai függvények Viszont gazdagon kínál standard függvénykönyvtárakat. Programozás Alapjai (2008)

3 A C nyelv tulajdonságai
Kis méret Függvényhívások széleskörű használata A típus hanyagolása Struktúrált nyelv Alacsony szintű programozás olvasható elérése Pointer széleskörű használata: memória, tömb, struktúra, függvény Programozás Alapjai (2008)

4 A C nyelv tulajdonságai
Miért vált a C széleskörűen használt profi programozási nyelvvé? Magas szintű konstrukciói vannak. Alacsony szintű tevékenységeket is kezelni tud. Hatékony programot készítenek a fordítók. A számítógépek sok változatán találunk C fordítót. Programozás Alapjai (2008)

5 A C nyelv rövid története
UNIX fejlesztése 1969 körül az AT&T Bell Laboratóriumában Ken Thomson és Dennis Ritchie Első változat Assembly nyelven DEC PDP-7 gépen. BCPL – felhasználóbarát operációs rendszer fejlesztő nyelv Legfőbb jellemzője, hogy típustalan. Unalmasan hosszú kód sok hibával. Egy új nyelv, a "B", a második kísérlet 1970 körül Programozás Alapjai (2008)

6 A C nyelv rövid története
1971: teljesen új nyelv, a "C", a "B" leszármazottja 1973-ban a UNIX operációs rendszert átírták "C"-re. Az AT&T "hivatalos" változata a System V (System Five), amely a 4. Release-nél tart, rövidítve SVR4) : ANSI C American National Standards Institute 1999: ISO C 99 International Organization for Standardization Programozás Alapjai (2008)

7 A C nyelv rövid története
A C nyelv és a UNIX összefonódása miatt C shell (csh) parancsértelmező C-szerű szintaxissal man cc, man gcc, man a.out, man ldd, stb. sok man oldal van a 3-as szekcióban, pl. man 3 printf, man 3 scanf, stb. A hírcsoportok (newsgroup) közül érdemes megemlíteni: comp.lang.c comp.lang.c.moderated Programozás Alapjai (2008)

8 Programozás Alapjai (2008)
Anyag a C nyelvhez A GNU project dokumentációi a gyakran használt leírások, kézikönyvek között találhatók: vagy közvetlenül a oldalon. Megtalálhatjuk a dokumentációk .dvi és .ps változatait is a /pub/egyeb/doku/dvi/ illetve /pub/egyeb/doku/ps/ alkönyvtárakban. Programozás Alapjai (2008)

9 C fejlesztői környezetek
MSVC Microsoft Visual C Integrált fejlesztői rendszer Windows alá fordít Programozás Alapjai (2008)

10 C fejlesztői környezetek
GNU C gcc fordító programok linux alatt is gcc, ld, as i486-linux targetre fordít anjuta fejlesztői rendszer sokféle programnyelvhez Programozás Alapjai (2008)

11 Fordítás Linux rendszerben
C fordítás Jobb megoldás, ha a programnak nevet adunk $ gcc program.c $ ./a.out $ gcc -o program program.c $ ./program Programozás Alapjai (2008)

12 Programozás Alapjai (2008)
C fájlok A szabályos végződések: file.c C source (forrás) file file.h C header (fejléc) file file.i preprocessed C (preprocesszált) file file.s assembly language file file.o object file a.out link edited output Programozás Alapjai (2008)

13 A C forrás fordításának folyamata
A fordítási folyamat sok lépésből is állhat, de 4 olyan lépés van, ahol a folyamatot elkezdeni illetve befejezni lehet. preprocessing – előfeldolgozás compilation – fordítás (assembly nyelvre) assembly – fordítás (gépi kódra) linking – szerkesztés Programozás Alapjai (2008)

14 A C forrás fordításának folyamata
A fájl végződése utal a programozási nyelvre és arra, hogy mit kell vele csinálni: preprocesszor C fordító assembler linker .c .i .s .o a.out .h p.c gcc -E p.c >p.i p.i gcc -S p.i p.s gcc -c p.s p.o gcc p.o a.out as p.s ld p.o ... gcc -S p.c gcc p.s gcc -c p.c gcc p.i gcc -c p.i gcc p.c Programozás Alapjai (2008)

15 Programozás Alapjai (2008)
Minimális C program /* * Minimális C program, ami nem csinál semmit * Készítette: Dévényi Károly, * Február 26. */ main() { } Programozás Alapjai (2008)

16 Programozás Alapjai (2008)
Hello World C nyelven /* * Helló Világ! * Készítette: Gergely Tamás, * November 3. */ #include <stdio.h> int main() { printf ("Helló Világ!\n"); } Programozás Alapjai (2008)

17 Egy kicsit bonyolultabb C program
main(l ,a,n,d)char**a;{ for(d=atoi(a[1])/10*80- CLCCGZAAQBEAADAFaISADJABBA^\ SNLGAQABDAXIMBAACTBATAHDBAN\ ZcEMMCCCCAAhEIJFAEAAABAfHJE\ TBdFLDAANEfDNBPHdBcBBBEA_AL\ H E L L O, W O R L D! " [l++-3];)for(;n-->64;) putchar(!d+++33^ l&1);} Programozás Alapjai (2008)

18 … és a futásának eredménye
$ ./where 46 20 !!!!!!!!!!! !!! !!! !!!!!!! ! !!!!!!!!!!!!!!!!! !!!!! ! ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!! !!!! ! !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!! !!!!"!! !!!!!!!!!!!!!!!!! !! ! !!!!!!!!! !! ! !!!!!!!!!!!!!!!!!!!! ! ! !!!! ! !!!!!!!!!!!!!!!!!!!!!!!!!! !!!!! !!!!!!!!!!!!! !!! !!! ! !!!!! !!!!!!!!!! ! ! ! ! !!!!!!!! !!!!! !! !!!!!! !!!! ! !!!!! !!!! !! !!!!!!!! !! !! !! ! ! $ Programozás Alapjai (2008)

19 Programozás alapjai A C nyelv alapjai

20 Programozás Alapjai (2008)
A C nyelv alapjai Egy C programozási nyelven írt forrásfájl programegységek deklarációjából és definíciójából áll. Deklarálhatunk Konstanst Típust Változót Függvényt #define N 42 egyben N definíciója is typedef unsigned long ui32; int magassag; double mertani_kozep(double, double); Programozás Alapjai (2008)

21 Programozás Alapjai (2008)
Deklaráció Egy programkomponens deklarációja egy azonosító hozzárendelése az adott komponenshez. Ezzel az azonosítóval hivatkozhatunk a program további részében az adott komponensre. A program egy adott pontján csak azok a komponensek használhatók (hivatkozhatók), amelyeket e pontot megelőzően már deklaráltunk, ellenkező esetben fordítási hiba lép fel. Programozás Alapjai (2008)

22 Programozás Alapjai (2008)
Definíció Egy programkomponens definíciója egy (a komponens deklarációjában meghatározott típusú) érték hozzárendelése a komponens azonosítójához. A program egy adott pontján csak azoknak a komponenseknek az értékét szabad felhasználni, amelyeket e pontot megelőzően már definiáltunk, ellenkező esetben a program nem fordítható, nem szerkeszthető, vagy működése véletlenszerű, akár hibás is lehet. Programozás Alapjai (2008)

23 Programozás Alapjai (2008)
Adattípus Az adattípus olyan egysége a programnak, amely két összetevője által meghatározott: Értékhalmaz Az értékhalmaz elemein végezhető műveletek Minden adattípus vagy elemi, vagy más adattípusokból képzett összetett adattípus. Programozás Alapjai (2008)

24 Programozás Alapjai (2008)
Változó A változó olyan programegység, amely a hozzá rendelt adattípus értékhalmazából műveletek hatására tetszőleges értéket felvehet, és értékét a program végrehajtása során akárhányszor megváltoztathatjuk. A változó értéke kezdetben definiálatlan, és az marad, amíg valamilyen művelettel értéket nem adunk neki. Programozás Alapjai (2008)

25 Programozás Alapjai (2008)
Változó (folyt.) A változók alapvetően úgynevezett értékadó művelet végrehajtásával kaphatnak értéket. Ennek jelölése: V = E ahol V egy meghatározott adattípusú változó E ezen adattípus egy értéke Feltételezhetjük, hogy az értékadó művelet minden elemi adattípus műveletei között szerepel. magassag = 100; magassag = (magassag + 83); Programozás Alapjai (2008)

26 Programozás Alapjai (2008)
Konstans A konstans olyan komponense a programnak, amely a definíciójában megadott értéket azonosítja, és ez az érték a program végrehajtása során nem változtatható meg. Típusa a definíciója által meghatározott adattípus. Programozás Alapjai (2008)

27 Programozás Alapjai (2008)
Függvény A függvény a matematikai értelemben vett függvény általánosítása, gyakorlatilag egy (rész-)algoritmus megvalósítása. A függvény deklarációja azt mondja meg, hogy milyen típusú értékekből milyen típusú értéket állít elő. A függvény definíciója megmondja, hogy a függvény végrehajtása során milyen algoritmust kell végrehajtani. A függvény meghívásakor azt adjuk meg, hogy milyen konkrét értékeken hajtsuk végre a függvény által leírt algoritmust. Programozás Alapjai (2008)

28 Programozás Alapjai (2008)
Függvény (folyt.) A C nyelvben a függvény fogalma bővebb, mint a matematikában Vannak olyan függvények, amiknek valamilyen jól definiált „mellékhatása” is van a visszatérési érték kiszámítása mellett, ilyenek például a szöveget megjelenítő (pl. printf), vagy adatbevitelt kezelő (pl. scanf) függvények. Adott esetben az is előfordulhat, hogy egy függvénynek csak a „mellékhatása” fontos, ilyenkor lehet, hogy a függvény (matematikai értelemben) nem is számít ki semmilyen visszatérési értéket. Az ilyen függvényeket nevezhetjük eljárásnak. Programozás Alapjai (2008)

29 Deklarációk, definíciók C-ben
Változók deklarációja: típusmegadás azonosító; Konstansok definíciója: #define azonosító érték int i; double f; #define N 42 #define EPS 1e-10 Programozás Alapjai (2008)

30 Programozás Alapjai (2008)
Szintaxis A kommunikáció ember és gép között véges jelhalmazból (ábécé) vett, meghatározott formai szabályokat kielégítő, véges hosszúságú jelsorozatokkal történik. Ezek a jelsorozatok alkotják a kommunikáció nyelvét. Szintaxis Formai szabályok olyan rendszerét, amely meghatározza, hogy egy adott kommunikációs nyelvben melyek a szabályos jelsorozatok, a nyelv szintaxisának nevezzük. Programozás Alapjai (2008)

31 Programozás Alapjai (2008)
Szintaxisdiagram Szintaxis megadására számos módszer ismeretes, mi szintaxis diagramokat használunk. Ebben minden szintaktikus egység egyedi elnevezést kap, és a szintaktikus egységhez tartozó szabályos jelsorozatokat egy diagram (ábra) definiálja Az ábrában a szintaktikus egységneveket tartalmazó dobozokat (téglalapokat) és konkrét jelsorozatokat irányított vonalak kötik össze Minden diagramnak egy bemenete és egy kimenete van Programozás Alapjai (2008)

32 Szintaxisdiagram (folyt.)
Szintaxis diagramok egy (véges) rendszerében egy diagram azokat és csak azokat a jelsorozatokat határozza meg, amelyek úgy kaphatók, hogy a diagram bemenetéről indulva az irányított vonalak mentén haladva a kijáratig, valahányszor érintünk egy egységet, egymás után írjuk az úton érintett egység által meghatározott jelsorozatok egy elemét. A diagramban a konkrét jelsorozatok önmagukat definiálják. Programozás Alapjai (2008)

33 Programozás Alapjai (2008)
Szintaxis Azonosító Számjegy Betű _ Programozás Alapjai (2008)

34 Programozás Alapjai (2008)
Szintaxis Betű Számjegy A Z a z 1 2 3 4 5 6 7 8 9 Programozás Alapjai (2008)

35 A C nyelv elemi adattípusai
int Egész float Valós A C-ben nincs logikai típus, de logikai igaz és hamis értékek keletkeznek, és logikai műveletek is vannak Programozás Alapjai (2008)

36 Programozás Alapjai (2008)
Logikai műveletek Egy operandusú műveletek (logikai -> logikai) ! Tagadás művelet Két operandusú műveletek (logikai x logikai -> logikai) && 'és' művelet || 'vagy' művelet !a a && b a || b Programozás Alapjai (2008)

37 Programozás Alapjai (2008)
Logikai műveletek Relációs műveletek (logikai x logikai -> logikai) == Egyenlőség != Nemegyenlő < Kisebb > Nagyobb <= Kisebb vagy egyenlő >= Nagyobb vagy egyenlő a == b a != b a < b a > b a <= b a >= b Programozás Alapjai (2008)

38 Programozás Alapjai (2008)
Az int adattípus A C nyelv eleve definiált elemi adattípusa. Egész értékek tárolására alkalmas. Értékkészlete [INT_MIN, INT_MAX] zárt intervallumba eső egész számok halmaza Az INT_MIN és INT_MAX eleve definiált konstans azonosítók, használatukhoz a program elejére be kell szúrni az alábbi sort: #include <limits.h> Programozás Alapjai (2008)

39 Az int adattípus műveletei
Egy operandusú műveletek (int -> int ) - Előjel váltás Két operandusú műveletek (int x int -> int) + Összeadás - Kivonás * Szorzás / Egészosztás hányadosa % Egészosztás maradéka -a a + 8 7 - a 6 * 7 a / 3 42 % a Programozás Alapjai (2008)

40 Az int adattípus műveletei
Relációs műveletek (int x int -> logikai) == Egyenlőség != Nemegyenlő < Kisebb > Nagyobb <= Kisebb vagy egyenlő >= Nagyobb vagy egyenlő 3 == a a != 7 a < 42 a > 77 0 <= a 8 >= a Programozás Alapjai (2008)

41 Az int adattípus műveletei
Az int adattípus műveleteire teljesülnek az aritmetika ismert azonosságai, feltéve, hogy a művelet eredménye az adattípus értékhalmazába esik. Ha a művelet eredménye nem esne az adattípus értékhalmazába, túlcsordulásról beszélünk. 2 * (3 * * 4) == 4 * 2 * * 2 * 7 == Programozás Alapjai (2008)

42 Programozás Alapjai (2008)
A float adattípus A C nyelv eleve definiált elemi adattípusa. A matematikai valós számok és műveleteik számítógépes modellezésére használható. A matematikai valós számok megközelíthetők az adattípus értékeivel, a matematikai műveletek pedig az adattípus műveleteivel. A közelítés mértéke a konkrét gépi megvalósítástól függ. A float adattípust valós típusnak is hívjuk. Programozás Alapjai (2008)

43 Programozás Alapjai (2008)
A float adattípus Értékkészlete Az adattípus értékei egy adott intervallumba esnek úgy, hogy minden valós szám ebből az intervallumból adott relatív pontossággal megközelíthető float adattípusbeli értékkel. Ez azt jelenti, hogy bármely a valós számhoz van olyan x float típusú érték, hogy |(x-a)/a| < relatív pontosság Programozás Alapjai (2008)

44 A float adattípus műveletei
Egy operandusú műveletek (float -> float) - Előjel váltás Két operandusú műveletek (float x float -> float) + Összeadás - Kivonás * Szorzás / Osztás a – 0.5 * a a / 2.0 Programozás Alapjai (2008)

45 A float adattípus műveletei
Relációs műveletek (float x float -> logikai) == Egyenlőség != Nemegyenlő < Kisebb > Nagyobb <= Kisebb vagy egyenlő >= Nagyobb vagy egyenlő 3.0 == a a != 7.2 a < 1e-10 a > 0.2E3 0.33 <= a 42.0 >= a Programozás Alapjai (2008)

46 A float adattípus műveletei
A matematikai függvények és konstansok, mint például a sin cos M_PI log exp nem részei a nyelvnek, de egy könyvtárban össze vannak gyűjtve. Használatukhoz szükséges a matematikai függvénykönyvtár include-olása double sin(double x); double cos(double x); #define M_PI double log(double x); double exp(double x); #include <math.h> Programozás Alapjai (2008)

47 Numerikus adattípusok
Az int és a float adattípusokat összefoglalóan numerikus adattípusoknak nevezzük. Numerikus adattípus értékeinek leírására számleírást, röviden számokat használunk. Az int adattípus értékeit nyolcas, tízes vagy tizenhatos számrendszerbeli leírással adhatunk meg. (Tizenhatos számrendszerben a számjegyek értéke decimálisan: A=10, B=11, C=12, D=13, E=14, F=15.) Valós számok leírására tizedes törtet használhatunk, kiegészítve tízes exponenssel. Programozás Alapjai (2008)

48 Szintaxis Szám Előjeltelen szám Előjeltelen egész szám
+ - Előjeltelen egész szám Előjeltelen valós szám Számjegy Hexadecimális számjegy Oktális számjegy 0x Nem 0 számjegy Programozás Alapjai (2008)

49 Programozás Alapjai (2008)
Szintaxis Előjeltelen valós szám Hexadecimális számjegy . Számjegy + - E e 42 052 0x2a 3e5 3E+6 271.72e-2 A Számjegy a B b C c D d E e F f Programozás Alapjai (2008)

50 Programozás Alapjai (2008)
Kifejezés Kifejezésen olyan programkomponenst értünk, amely egy adattípus értékének olyan jelölése, amely műveleteket is tartalmazhat. A kifejezés által jelölt értéket a kifejezés kiértékelése határozza meg. A kifejezés szintaxisa (egyelőre) Numerikus kifejezés Logikai kifejezés Programozás Alapjai (2008)

51 Programozás Alapjai (2008)
Kifejezés szintaxisa Numerikus kifejezés Numerikus tag Numerikus tag + - Numerikus tényező * / % Programozás Alapjai (2008)

52 Kifejezés szintaxisa Numerikus tényező Numerikus változó
Konstans azonosító Előjeltelen szám Numerikus kifejezés Numerikus tényező Numerikus függvényhívás ( ) + - Programozás Alapjai (2008)

53 Programozás Alapjai (2008)
Kifejezés szintaxisa Logikai kifejezés Logikai tag Logikai tag || Logikai tényező && Programozás Alapjai (2008)

54 Kifejezés szintaxisa Logikai tényező Logikai változó
Logikai konstans azonosító Relációs kifejezés Logikai kifejezés Logikai tényező Logikai függvényhívás ( ) ! Programozás Alapjai (2008)

55 Programozás Alapjai (2008)
Kifejezés szintaxisa Relációs kifejezés Kifejezés == != < > <= >= (sin(M_PI + alfa) < 0.2 * alfa + 1e-1) && (beta != M_PI) Programozás Alapjai (2008)

56 Kifejezések kiértékelése
A kifejezés kiértékelését két előírás együttesen határozza meg A kifejezés szerkezetén alapuló prioritási előírás A haladás irányára vonatkozó előírás Programozás Alapjai (2008)

57 Programozás Alapjai (2008)
Prioritási előírás A műveletek között definiálva van egy erősségi sorrend, az úgynevezett prioritás. Ez azt jelenti, hogy egy A m1 B m2 C alakú kifejezésben, ahol m2 magasabb prioritású művelet, mint m1, az A m1(B m2 C) zárójelezésnek megfelelően értékelődik ki. a < b && a * b < 7 || c != b ((a < b) && ((a + ((- 5) * b)) < 7)) || (c != b) Programozás Alapjai (2008)

58 Programozás Alapjai (2008)
Műveletek prioritása Prioritás csökkenő sorrendben: a prefix művelet (prefix -, prefix +, ! ) a multiplikatív műveletek ( *, /, % ) az additív műveletek ( +, - ) a kisebb-nagyobb relációs műveletek ( <=, >=, <, > ) az egyenlő-nem egyenlő műveletek ( ==, != ) a logikai 'és' művelet ( && ) a logikai 'vagy' művelet ( || ) Programozás Alapjai (2008)

59 Műveletek asszociativitása
Azonos prioritású műveletek esetén a kiértékelést az asszociativitás iránya szerint kell elvégezni. Ez azt jelenti, hogy egy A m1 B m2 C alakú kifejezés, ahol m1 és m2 azonos prioritású műveletek, a balról-jobbra asszociativitás esetén (A m1 B) m2 C jobbról-balra asszociativitás esetén A m1 (B m2 C) zárójelezésnek megfelelően értékelődik ki. Az eddig ismertetett műveletek balról-jobbra asszociatívak. a + 5 – b – 7 + c (((a + 5) – b) – 7) + c Programozás Alapjai (2008)

60 Programozás Alapjai (2008)
Logikai kifejezések A logikai kifejezések kiértékelése mindig a rövidített kiértékelés szerint történik, vagyis Az A || B kifejezés rövidített kiértékelése során először kiértékelődik az A logikai tag, ha ennek értéke igaz, akkor a B tag kiértékelése elmarad és természetesen a kifejezés értéke igaz lesz. Az A && B kifejezés rövidített kiértékelése során először kiértékelődik az A logikai tényező, ha ennek értéke hamis, akkor a B tényező kiértékelése elmarad és természetesen a kifejezés értéke hamis lesz. Programozás Alapjai (2008)

61 Numerikus kifejezések típusa
Minden numerikus kifejezés int vagy float típusú. A kifejezés típusának meghatározása a kifejezés felépítése szerinti indukcióval a következő Tényező típusa: ha a tényező változó, akkor a deklarációjában megadott típus konstans, akkor a számleírás szerinti típus (K), akkor a K kifejezés típusa +T , akkor a T tényező típusa -T , akkor a T tényező típusa függvényhívás, akkor a függvényművelet eredménytípusa Programozás Alapjai (2008)

62 Numerikus kifejezések típusa (folyt.)
Tag típusa: legyen A m B alakú a tag, ahol A és B tényezők, m pedig multiplikatív műveleti jel. Ha m %, akkor A és B típusa csak int lehet, és a tag típusa is int /, és A és B típusa is int, akkor az eredmény is int, és a művelet az egészosztás hányadosa /, és A vagy B float, akkor a tag típusa is float, és a művelet a valós osztás *, akkor az eredmény tag típusa csak akkor lesz int, ha mindkét operandus típusa int, egyébként pedig float Kifejezés típusa: ha a tagok mindegyike int típusú, akkor a kifejezés típusa is int, egyébként float. Programozás Alapjai (2008)

63 Programozás Alapjai (2008)
A / művelet A / lehet maradékos osztás de valós osztás is 15 / 6 == 2 15.0 / 6 == 2.5 15 / 6.0 == 2.5 15.0 / 6.0 == 2.5 Programozás Alapjai (2008)

64 Programozás Alapjai (2008)
Konverziók Az int adattípus nem része a float adattípusnak. float típusú változó vagy konstans akkor sem szerepelhet olyan műveletben, amely csak az int típus művelete (%), ha az értéke egész számértek. Megengedett azonban, hogy a float típus egy műveletének egyik argumentuma float, a másik argumentuma pedig int típusú legyen. A művelet eredményének típusa ekkor float lesz. Programozás Alapjai (2008)

65 Programozás Alapjai (2008)
Konverziók (folyt.) Az ilyen művelet végrehajtása előtt az int típusú argumentum automatikusan átkonvertálódik float típusúvá. Ez a konverzió azonban tényleges műveletet jelent és így időt igényel. Ajánlatos a 2*x művelet helyett 2.0*x műveletet használni, ha x float típusú (még akkor is, ha a fordítóprogramok az ilyen típusú konverziót már fordítási időben el tudják végezni). Programozás Alapjai (2008)

66 Programozás Alapjai (2008)
Értékadó művelet Az értékadás jele az = De ez művelet, és nem utasítás, vagyis a változóazonosító = kifejezés művelet eredménye a kifejezés aktuális értéke, amit a megfelelő programkomponensben is eltárolunk. Természetesen nincs akadálya a művelet többszöri alkalmazásának Az = művelet jobb-asszociatív, prioritása az eddig ismertetett műveletek után következik. i = j = k = 1; Programozás Alapjai (2008)

67 Programozás Alapjai (2008)
Utasítások A ; zárja le műveletek sorozatát, tehát „utasítást csinál a kifejezésből”. A C-ben szokásos példa: kifejezés utasítás i = 1 i = 1; Programozás Alapjai (2008)

68 Összetett utasítások képzése
Tudunk tehát kifejezésekből egyszerű utasításokat gyártani. Most mélyebb magyarázat nélkül átnézzük, hogy a C nyelv milyen lehetőségeket ad összetett utasítások képzésére. Programozás Alapjai (2008)

69 Programozás Alapjai (2008)
Utasítások sorozata Ha az utasításokat adott sorrendben kell végrehajtani, akkor egyszerűen { és } jelek között az adott sorrendben egymás után leírjuk őket. Számoljuk ki, melyik órában (o), percben (p) melyik másodperc (m) lesz a nap másodperce. { e = 54321; o = e / 3600; e = e % 3600; p = e / 60; m = e % 60; } Programozás Alapjai (2008)

70 Programozás Alapjai (2008)
Függvények Egy C nyelven írt program tulajdonképpen nem más, mint függvények (megfelelően struktúrált és rendezett) összessége. Egy-egy függvény valamilyen bemenő adatok alapján kiszámol egy értéket, mint ahogyan azt a matematikában már megszokhattuk. Függvényeket lehet deklarálni, definiálni és meghívni. Programozás Alapjai (2008)

71 Programozás Alapjai (2008)
Függvények (folyt.) Deklarációnál csak azt mondjuk meg, hogy mennyi és milyen típusú paraméterekből milyen típusú értéket fog kiszámolni a függvényünk. Definíciónál azt is meg kell adnunk, hogy hogyan számoljon. A függvényhívásnál pedig konkrét értékekre alkalmazzuk a függvényt, és a kiszámított értéket felhasználhatjuk további számolásainkhoz. Programozás Alapjai (2008)

72 Függvények szintaxisa C-ben
Függvény deklaráció Függvény definíció (egyben deklaráció is) Függvény fejléc int f(int a, int b); Függvény fejléc ; int f(int a, int b) { return a+b; } Függvény fejléc { Utasítások } Azonosító Típus ( ) , Programozás Alapjai (2008)

73 Programozás Alapjai (2008)
A return utasítás A return utasítás Minden függvényben szerepelnie kell legalább egy return utasításnak. Ha a függvényben egy ilyen utasítást hajtunk végre, akkor a függvény értékének kiszámítása befejeződik. A hívás helyén a függvény a return által kiszámított értéket veszi fel. int f(int a, int b) { return a+b; } Kifejezés return ; Programozás Alapjai (2008)

74 Függvényhívás szintaxisa C-ben
Természetesen egy függvénynek a híváskor pontosan annyi és olyan típusú paramétert kell átadni, amennyi és amilyen paraméterekkel deklarálva lett. Azonosító ( ) Kifejezés , int c; c = f(3,5); Programozás Alapjai (2008)

75 Programozás Alapjai (2008)
Függvények A C nyelvben van a main függvénynek kitüntetett szerepe van. Amikor elindítjuk a programot, a vezérlés a main függvény elején indul, tehát ez a függvény viselkedik főprogramként. Az operációs rendszertől ez a függvény is kaphat paramétereket, de ezekkel egyelőre nem foglalkozunk. A main által kiszámított értéket szintén az operációs rendszer értelmezi (miután befejeződött a program), de erről is később lesz szó. Programozás Alapjai (2008)

76 Programozás Alapjai (2008)
Függvények Írjunk egy programot, ami óra, perc, másodperc alapján egy függvény segítségével kiszámolja az éjfél óta eltelt másodperceket. int masodpercek(int ora, int perc, int masodperc) { return 3600 * ora + 60 * perc + masodperc; } int main() int mp1, mp2; mp1 = masodpercek(12, 5, 7); mp2 = masodpercek(6, 45, 0); Programozás Alapjai (2008)

77 Programozás Alapjai (2008)
Az if utasítás Ha valamilyen feltétel alapján egyik vagy másik utasítást akarjuk végrehajtani Szintaxis Logikai kifejezés if else Utasítás ) ( Programozás Alapjai (2008)

78 Programozás Alapjai (2008)
Az if utasítás Végre kell-e hajtani valamit? Számoljuk ki f abszolútértékét! Két utasítás közül az egyiket hajtsuk végre! a és b közül melyik a kisebb érték? if(f < 0) f = -f; if(f < 0) { f = -f; } if(a <= b) k = a; else k = b; if(a <= b) { k = a; } else { k = b; } Programozás Alapjai (2008)

79 Programozás Alapjai (2008)
A switch utasítás Ha egy kifejezés értéke alapján többféle utasítás közül kell választanunk Szintaxis switch ( ) Kifejezés { } case default : Konstans Utasítás break ; Programozás Alapjai (2008)

80 Programozás Alapjai (2008)
A switch utasítás Megadhatjuk, hogy hol kezdődjön és meddig tartson az utasítás-sorozat végrehajtása Gyakorlati jegyből csináljunk háromfokozatú minősítést! switch (gy) { case 5: case 4: printf("jól "); case 3: case 2: printf("megfelelt"); break; case 1: printf("nem felelt meg"); default: printf("nincs ilyen jegy"); } Programozás Alapjai (2008)

81 Programozás Alapjai (2008)
A while utasítás Ha valamilyen műveletet mindaddig végre kell hajtani, amíg egy feltétel igaz. Ha a feltétel kezdetben hamis volt, a műveletet egyszer sem hajtjuk végre. (A feltétel ellenőrzése a művelet előtt történik.) Szintaxis Logikai kifejezés while Utasítás ( ) Programozás Alapjai (2008)

82 Programozás Alapjai (2008)
A while utasítás A művelet végrehajtása nem szükséges a feltétel kiértékeléséhez Adjuk meg, hogy 0 fokról indulva adott mértékű pozitív irányú forgás után milyen irányban áll egy mutató. while (360 <= szog) { szog = szog – 360; } Programozás Alapjai (2008)

83 Programozás Alapjai (2008)
A do while utasítás Ha valamilyen műveletet mindaddig végre kell hajtani, amíg egy feltétel igaz. A műveletet legalább egyszer végrehajtjuk akkor is, ha a feltétel kezdetben hamis volt. (A feltétel ellenőrzése a művelet után történik.) Szintaxis Logikai kifejezés while Utasítás ( ) do Programozás Alapjai (2008)

84 Programozás Alapjai (2008)
A do while utasítás A művelet végrehajtása szükséges a feltétel kiértékeléséhez Kérjünk egy 0 és 999 közötti véletlenszámot, de zárjuk ki a 100 és 200 közötti számokat do { x = random() % 1000; } while ((100 <= x) && (x <= 200)) Programozás Alapjai (2008)

85 Programozás Alapjai (2008)
A for utasítás Ha valamilyen műveletet sorban több értékére is végre kell hajtani, akkor ezt érdemes használni. Szintaxis Kifejezés for Utasítás ( ) ; Programozás Alapjai (2008)

86 Programozás Alapjai (2008)
A for utasítás A C-ben a for utasítás általános alakja így néz ki: ami egyenértékű a alakkal. for (kif1; kif2; kif3) utasítás kif1; while (kif2) { utasítás kif3; } Programozás Alapjai (2008)

87 Programozás Alapjai (2008)
A for utasítás Többnyire kif1 és kif3 értékadás vagy függvényhívás, kif2 pedig relációs kifejezés. A három kifejezés bármelyike elhagyható, de a pontosvesszőknek meg kell maradniuk. Ha kif1 vagy kif3 marad el, akkor a ; egyszerűen elmarad a kifejtésből. Ha a kif2 vizsgálat nem szerepel, akkor állandóan igaznak tekintjük, így végtelen ciklus, amelyből más módon kell kiugrani (pl. return vagy break révén). for (;;) { /* ... */ } Programozás Alapjai (2008)

88 Programozás Alapjai (2008)
A for utasítás Hajtsunk végre egy műveletet adott számú alkalommal „És most büntetésből százszor leírod a nevedet!” Egy változót lépésenként ugyanúgy változtatunk Írassuk ki egy mértani sorozat elemeit a kezdőelem duplájáig for(i=0; i<100; i++) { printf("neved\n"); } for(x = a0; x < 2.0 * a0; x = q * x) { printf("%lf\n", x); } Programozás Alapjai (2008)

89 A break és continue utasítások
A C nyelvben a ciklusmag folyamatos végrehajtásának megszakítására két utasítás használható: break Megszakítja a ciklust, a vezérlés a ciklusmag utáni első utasítással foglalkozik continue Megszakítja a ciklus aktuális lefutását, a vezérlés a ciklus feltételének kiértékelésével folytatódik Programozás Alapjai (2008)

90 Egyszerű ki- és bevitel
Ahhoz, hogy egyszerű példát mutassunk be, szükségünk van beviteli és kiviteli utasításokra is. A nyelv nem tartalmaz ilyen utasításokat, de minden implementációban vannak standard függvénykönyvtárak ezek megvalósításaival. Programozás Alapjai (2008)

91 Egyszerű ki- és bevitel
A ki- és bevitel használatához szükségünk van az sorra a program elején Ezek után használhatjuk az alábbi két függvényt: scanf(const char *, ...) a bemenetről tudunk olvasni printf(const char *, ...) a kimenetre tudunk írni #include <stdio.h> Programozás Alapjai (2008)

92 Egyszerű ki- és bevitel
Anélkül, hogy a két függvényt részletesen elmagyaráznánk, egyelőre megmutatjuk, hogyan lehet int illetve float értékek beolvasására, valamint ugyanilyen típusú értékek és tetszőleges szöveg kiíratására használni őket. Programozás Alapjai (2008)

93 Egyszerű ki- és bevitel
Mindkét függvény első paramétere egy úgynevezett formátumsztring, ami tulajdonképpen egy speciális szövegkonstans. Szöveg (szövegkonstans): Karakter, kivéve ” és \ \” \\ Programozás Alapjai (2008)

94 Egyszerű ki- és bevitel
A printf használata: A szövegben az egyes kifejezések helyét a %d (int) és %f (float) karakterkombinációk jelzik: A \n hatására a kiírás végén új sor kezdődik ( printf Szöveg Kifejezés ) , printf("Hello world\n"); printf("Pi értéke kb. %f\n", ); printf("%d + %d = %d\n", 2, 3, 2+3); Programozás Alapjai (2008)

95 Egyszerű ki- és bevitel
A scanf használata: Az egyes beolvasandó számok típusát szintén %d (int) és %f (float) karakterkombinációk jelzik: ( scanf Szöveg Változó ) , & scanf("%d", &egesz); scanf("%f %f", &valos1, &valos2); Programozás Alapjai (2008)

96 Egyszerű ki- és bevitel
Nagyon fontos, hogy a beolvasandó értékek illetve a kiírandó kifejezések számát és típusát sorban és pontosan adjuk meg. Egy float típusú kifejezés vagy változó esetén tehát akkor sem a %d kombinációt használjuk, ha tudjuk, hogy maga az érték egész, és int típusú kifejezés illetve változó esetén sem használhatjuk a %f –et. Az alábbi példák tehát hibásak: printf("%d", 10.0); printf("%f", 10); Programozás Alapjai (2008)

97 Egy C program felépítése
Egy egyszerű C program így néz ki: /* A program adatai */ #include <stdio.h> main() { Változódeklarációk Utasítások } Programozás Alapjai (2008)

98 Egy C program felépítése
Egy kevésbé egyszerű pedig így: /* A program adatai */ #include <stdio.h> Függvénydefiníciók main() { Változódeklarációk Utasítások } Programozás Alapjai (2008)

99 Programozás Alapjai (2008)
Eltelt idő Problémafelvetés Kiszámítandó a nap két időpontja között eltelt idő. Specifikáció A bemenő adat két időpont óra és perc formában, jelöljük ezeket O1, P1 illetve O2, P2-vel. A bemeneti feltétel: (0 <= O1 < 24) és (0 <= P1 < 60) (0 <= O2 < 24) és (0 <= P2 < 60) (O1 < O2) vagy (O1 == O2) és (P1 <= P2) A kimenő adatok O és P. A kimeneti feltétel: Az első időponttól a másodikig O óra és P perc telt el Programozás Alapjai (2008)

100 Programozás Alapjai (2008)
Eltelt idő (folyt.) Algoritmustervezés Az eltelt idő percben kifejezve (O2 * 60 + P2) - (O1 * 60 + P1) Tehát O, P akkor és csak akkor megoldás, ha O * 60 + P == (O2 * 60 + P2) - (O1 * 60 + P1) 0 <= P < 60 Ez tulajdonképpen a kimeneti feltételek formális megadása, de az első feltétel már mindenképpen az algoritmustervezés fázisához kapcsolódik Programozás Alapjai (2008)

101 Programozás Alapjai (2008)
Szerkezeti ábra Az algoritmus tervezése során le kell írnunk valamilyen nyelvezetet használva azt, hogy a problémát milyen részproblémákra dekomponáltuk, és a megoldásukat milyen módon raktuk össze. Mi erre úgynevezett szerkezeti ábrát (structure diagram, struktúradiagram) használunk. Minden vezérlési módhoz bevezetünk egy szerkezeti ábra jelölést. Programozás Alapjai (2008)

102 Szerkezeti ábra tulajdonságai
A szerkezeti ábra egyszerre fejezi ki az algoritmustervezés folyamatát és a kifejlesztett algoritmust is. Egy részprobléma megoldását leíró szerkezeti ábrarész különálló ábrával is kifejezhető, amelynek gyökerében a részprobléma megnevezése áll. Programozás Alapjai (2008)

103 Szekvenciális vezérlés
A P problémát P1, ... , Pn részproblémákra bontjuk, és ezek megoldásait ebben a sorrendben egymás után végrehajtva kapjuk P megoldását P P1 P2 Pn P1, ... , Pn elemi műveletek, vagy részproblémák megnevezése. Utóbbi esetben a részproblémát tovább kell bontani. Programozás Alapjai (2008)

104 Programozás Alapjai (2008)
Eltelt idő (folyt.) Szerkezeti ábra Eltelt idő Számolás Beolvasás Kiíratás K = eltelt percek O és P kiszámolása K = (O2 * 60 + P2) - (O1 * 60 + P1) P = K/60 maradéka O = K/60 egészrésze Programozás Alapjai (2008)

105 Programozás Alapjai (2008)
Eltelt idő (folyt.) Az Eltelt idő algoritmusban használt változók O1, P1, O2, P2, O, P, K: valamennyi egész típusú, értékük tetszőleges egész szám lehet Az egész értékeken a következő műveleteket alkalmaztuk Összeadás (+) Kivonás (-) Szorzás (*) Osztás egészrésze (/) Osztás maradéka (%) Programozás Alapjai (2008)

106 Szekvenciális vezérlés C nyelven
Kódolása C nyelven: { P1; P2; . Pn; } P P2 P1 Pn Programozás Alapjai (2008)

107 Programozás Alapjai (2008)
Eltelt idő /* * Egy nap két időpontja között mennyi idő telt el. * Készítette: Dévényi Károly, * Szeptember 26. Péntek */ #include <stdio.h> main() { int o1,p1; /* az első időpont */ int o2,p2; /* a második időpont */ int o,p; /* az eltelt idő */ int k; /* az eltelt idő percben */ >>> Programozás Alapjai (2008)

108 Programozás Alapjai (2008)
Eltelt idő /* beolvasás */ printf("Kérem az első időpontot óra perc formában\n"); scanf("%d %d", &o1, &p1); printf("Kérem a második időpontot óra perc formában\n"); scanf("%d %d", &o2, &p2); /* számítás */ /* különbség számítás */ k = 60 * o2 + p2 - (60 * o1 + p1); o = k / 60; p = k % 60; /* kiíratás */ printf("Az eltelt idő: %d óra %d perc.\n", o, p); } Programozás Alapjai (2008)

109 Programozás Alapjai (2008)
Eljárásvezérlés Adott művelet alkalmazása adott argumentumokra, ami az argumentumok értékének pontosan meghatározott változását eredményezi Az eljárásvezérlés fajtái Eljárásművelet Függvényművelet Programozás Alapjai (2008)

110 Eljárásvezérlés megvalósítása
Vannak olyan programozási nyelvek, ahol a függvény és eljárásműveletek meg vannak különböztetve. Mivel azonban e kurzus keretében csak a C nyelvről lesz szó, egyelőre csak a függvényművelettel foglalkozunk, és a szerkezeti ábrán is igazodni fogunk a C nyelvhez. Programozás Alapjai (2008)

111 Programozás Alapjai (2008)
Függvényművelet A matematikai függvény fogalmának általánosítása. Ha egy részprobléma célja egy érték kiszámítása adott értékek függvényében, akkor a megoldást megfogalmazhatjuk függvényművelettel. Programozás Alapjai (2008)

112 Függvény specifikációja
A függvényművelet specifikációja tartalmazza: A művelet elnevezését A formális argumentumok felsorolását Mindegyik argumentum adattípusát A függvényművelet eredménytípusát A művelet hatásának leírását Programozás Alapjai (2008)

113 Programozás Alapjai (2008)
Függvényművelet A függvényművelet jelölésére a T F(T1 X1, ... ,Tn Xn) formát használjuk, ahol T a függvényművelet eredménytípusa F a függvényművelet neve Ti az i-edik formális argumentum adattípusa Xi az i-edik formális argumentum azonosítója A zárójeleket üres paraméterlista esetén is ki kell tenni. Programozás Alapjai (2008)

114 Programozás Alapjai (2008)
Függvényművelet A C jelölésmódhoz igazodva, a függvény algoritmusa egy olyan szerkezeti ábrával adható meg, melynek a feje így néz ki: Továbbá a szerkezeti ábrában lennie kell (legalább) egy olyan return utasításnak, amely visszaadja a függvény által kiszámított értéket. T F(T1 X1, ... ,Tn Xn) Programozás Alapjai (2008)

115 Programozás Alapjai (2008)
Függvényművelet A fent jelölt függvényműveletnek adott A1, ..., An aktuális argumentumokra történő végrehajtását függvényhívásnak nevezzük és az F(A1, ... ,An) jelölést használjuk. A függvényhívás kifejezés. A zárójeleket paraméter nélküli függvény hívása esetén is ki kell tenni. Programozás Alapjai (2008)

116 Függvények szintaxisa C-ben
Függvény deklaráció Függvény definíció (egyben deklaráció is) Függvény fejléc Függvény fejléc ; Függvény fejléc { Utasítások } Azonosító Típus ( ) , Programozás Alapjai (2008)

117 Függvények szintaxisa C-ben
A return utasítás Minden függvényben szerepelnie kell legalább egy return utasításnak, amely kiszámítja a megadott kifejezés értékét, majd visszatér a függvényből. A hívás helyén a függvény a return által kiszámított értéket veszi fel. Kifejezés return ; Programozás Alapjai (2008)

118 Függvényhívás szintaxisa C-ben
Természetesen egy függvénynek a híváskor pontosan annyi és olyan típusú paramétert kell átadni, amennyi és amilyen paraméterekkel deklarálva lett. Azonosító ( ) Kifejezés , Programozás Alapjai (2008)

119 Függvény megvalósítása
Ha a függvény szerkezeti ábrája ez: Akkor a függvénydefiníció C-ben: T F(T1 X1, ... ,Tn Xn) M T F(T1 X1, ..., Tn Xn) { M; } Programozás Alapjai (2008)

120 Programozás Alapjai (2008)
Függvényművelet Például Régen C-ben a így kellett függvényt deklarálni: float atlag(float a, float b) { return (a + b)/2; } float atlag(a,b) float a, float b; { return (a + b)/2; } Programozás Alapjai (2008)

121 Eltelt idő Szerkezeti ábra
int eltelt_percek(int ora1, int perc1, int ora2, int perc2) eltelt percek kiszámítása return (ora2 * 60 + perc2) - (ora1 * 60 + perc1) Programozás Alapjai (2008)

122 Eltelt idő (folyt.) Szerkezeti ábra Eltelt idő Számolás Beolvasás
Kiíratás O és P kiszámolása P = eltelt_percek(O1, P1, O2, P2) /60 maradéka O = eltelt_percek(O1, P1, O2, P2) /60 egészrésze Programozás Alapjai (2008)

123 Programozás Alapjai (2008)
Eltelt idő /* * Egy nap két időpontja között mennyi idő telt el. * Készítette: Gergely Tamás, * Augusztus 30. */ #include <stdio.h> int eltelt_percek(int ora1, int perc1, int ora2, int perc2) { return 60 * ora2 + perc2 - (60 * ora1 + perc1); } >>> Programozás Alapjai (2008)

124 Programozás Alapjai (2008)
Eltelt idő main() { int o1,p1; /* az első időpont */ int o2,p2; /* a második időpont */ int o,p; /* az eltelt idő */ /* beolvasás */ printf("Kérem az első időpontot óra perc formában\n"); scanf("%d %d", &o1, &p1); printf("Kérem a második időpontot óra perc formában\n"); scanf("%d %d", &o2, &p2); /* számítás */ /* különbség számítás */ o = eltelt_percek(o1, p1, o2, p2) / 60; p = eltelt_percek(o1, p1, o2, p2) % 60; /* kiíratás */ printf("Az eltelt idő: %d óra %d perc.\n", o, p); } Programozás Alapjai (2008)

125 Szelekciós vezérlések
Szelekciós vezérléssel azt írjuk elő, hogy véges sok rögzített művelet közül, véges sok adott feltétel alapján, melyik művelet kerüljön végrehajtásra. Típusai: Egyszerű Többszörös Esetkiválasztásos A fenti három „egyébként” ággal Programozás Alapjai (2008)

126 Egyszerű szelekciós vezérlés
Egyszerű szelekció esetén egy feltétel és egy művelet van. Legyen F logikai kifejezés, A pedig tetszőleges művelet. Az F feltételből és az A műveletből képzett egyszerű szelekciós vezérlés a következő vezérlési előírást jelenti: 1.) Értékeljük ki az F feltételt és folytassuk a 2.) lépéssel. 2.) Ha F értéke igaz, akkor hajtsuk végre az A műveletet és fejezzük be az összetett művelet végrehajtását. 3.) Egyébként, vagyis ha F értéke hamis, akkor fejezzük be az összetett művelet végrehajtását. Programozás Alapjai (2008)

127 Egyszerű szelekciós vezérlés
A vezérlés bővíthető úgy, hogy a 3. pontban üres művelet helyett egy B műveletet hajtunk végre. Legyen F logikai kifejezés, A és B pedig tetszőleges művelet. Az F feltételből és az A és B műveletből képzett egyszerű szelekciós vezérlés a következő vezérlési előírást jelenti: 1.) Értékeljük ki az F feltételt és folytassuk a 2.) lépéssel. 2.) Ha F értéke igaz, akkor hajtsuk végre az A műveletet és fejezzük be az összetett művelet végrehajtását. 3.) Egyébként, vagyis ha F értéke hamis, hajtsuk végre B-t és fejezzük be az összetett műveletet végrehajtását. Programozás Alapjai (2008)

128 Egyszerű szelekciós vezérlés
Az egyszerű szelekciós vezérlés szerkezeti ábrája F i n A Programozás Alapjai (2008)

129 Egyszerű szelekciós vezérlés
Az egyébként ággal kiegészített egyszerű szelekciós vezérlés szerkezeti ábrája F i n A B Programozás Alapjai (2008)

130 Egyszerű szelekciós vezérlés
A vezérlés lényege: Ha az F feltétel igaz, hajtsuk végre az A műveletet. Ha az F feltétel hamis, hajtsuk végre a B műveletet. Programozás Alapjai (2008)

131 Többszörös szelekciós vezérlés
Ha a szelekciós vezérlésben a feltételek száma nagyobb, mint egy, akkor többszörös szelekcióról beszélünk. Ekkor minden kiválasztó feltételhez tartozik egy alternatív művelet. Legyenek Fi logikai kifejezések, Ai pedig tetszőleges műveletek (1<=i<=n). Programozás Alapjai (2008)

132 Többszörös szelekciós vezérlés
Az Fi kiválasztó feltételekből valamint az Ai műveletekből képzett többszörös szelekciós vezérlés a következő vezérlési előírást jelenti: 1.) Az Fi feltételek kiértékelésével adjunk választ a következő kérdésre: Van-e olyan i (1<=i<=n), amelyre teljesül, hogy az Fi feltétel igaz és az összes Fj (1<=j<i) feltétel hamis? Folytassuk a 2.) lépéssel. 2.) Ha van ilyen i, akkor hajtsuk végre az Ai műveletet és fejezzük be az összetett művelet végrehajtását. 3.) Egyébként, vagyis ha minden Fi feltétel hamis, akkor fejezzük be az összetett művelet végrehajtását. Programozás Alapjai (2008)

133 Többszörös szelekciós vezérlés
Bővíthetjük a többszörös szelekciós vezérlést azzal, hogy a 3.) pontban ne az üres művelet, hanem egy előre megadott B tetszőleges művelet végrehajtását írjuk elő. Legyenek Fi logikai kifejezések, Ai és B pedig tetszőleges műveletek (1<=i<=n). Programozás Alapjai (2008)

134 Többszörös szelekciós vezérlés
Az Fi kiválasztó feltételekből, valamint az Ai és B műveletekből képzett többszörös szelekciós vezérlés a következő vezérlési előírást jelenti: 1.) Az Fi feltételek kiértékelésével adjunk választ a következő kérdésre: Van-e olyan i (1<=i<=n), amelyre teljesül, hogy az Fi feltétel igaz és az összes Fj (1<=j<i) feltétel hamis? Folytassuk a 2.) lépéssel. 2.) Ha van ilyen i, akkor hajtsuk végre az Ai műveletet és fejezzük be az összetett művelet végrehajtását. 3.) Egyébként, vagyis ha minden Fi hamis, hajtsuk végre B-t és fejezzük be az összetett művelet végrehajtását. Programozás Alapjai (2008)

135 Többszörös szelekciós vezérlés
A többszörös szelekciós vezérlés szerkezeti ábrája ? F1 F2 Fn A1 A2 An Programozás Alapjai (2008)

136 Többszörös szelekciós vezérlés
Az egyébként ággal kiegészített többszörös szelekciós vezérlés szerkezeti ábrája ? F1 F2 Fn A1 A2 An B Programozás Alapjai (2008)

137 Többszörös szelekciós vezérlés
A vezérlés lényege Hajtsuk végre a legelső olyan Ai műveletet, aminek az Fi feltétele igaz. Ha nincs olyan Fi ami igaz, akkor hajtsuk végre a B műveletet. Programozás Alapjai (2008)

138 Háromszögek osztályozása
Problémafelvetés Milyen háromszöget határoz meg három valós szám, mint a háromszög három oldalhosszúsága? Specifikáció A probléma inputja A,B,C valós számok Outputja a következő szövegek egyike ‘nem háromszög’, ‘szabályos háromszög’, ‘egyenlőszárú háromszög’, ‘egyenlőszárú derékszögű háromszög’, ‘derékszögű háromszög’, ‘egyéb háromszög’ Programozás Alapjai (2008)

139 Háromszögek osztályozása
Algoritmustervezés: fogalmazzuk meg a feltételeket magyarul és a matematika nyelvén ‘nem háromszög’ ‘szabályos háromszög’ ‘egyenlőszárú háromszög’ ‘egyenlőszárú derékszögű háromszög’ ‘derékszögű háromszög’ ‘egyéb háromszög’ Programozás Alapjai (2008)

140 Háromszögek osztályozása
Algoritmustervezés A feltételek megfogalmazása érdekében célszerűnek látszik a bemenő adatokat úgy átrendezni, hogy az A változó tartalmazza a legnagyobb értéket. Ekkor a feltételek rendre NP feltétel: (A<=0) vagy (B<=0) vagy (C<=0) N feltétel: A >= B + C Sz feltétel: (A == B) és (B == C) E feltétel: (A == B) vagy (B == C) vagy (A == C) D feltétel: A2 = B2 + C2 Az osztályozás eredményét közvetlenül kiírjuk. Programozás Alapjai (2008)

141 Háromszögek osztályozása
Struktúradiagram Háromszögek osztályozása Átrendezés Beolvasás Osztályozás Programozás Alapjai (2008)

142 Háromszögek osztályozása
Struktúradiagram Osztályozás ? NP Nem N SZ Szabályos E Egyenlőszárú D Derékszögű Egyéb i n Egyenlőszárú derékszögű Programozás Alapjai (2008)

143 Háromszögek osztályozása
Struktúradiagram Átrendezés A és B átrendezése A<B i n A=B A és C átrendezése A és B cseréje M=A B=M A<C A=C A és C cseréje C=M Programozás Alapjai (2008)

144 Programozás Alapjai (2008)
Az if utasítás Ha valamilyen feltétel alapján egyik vagy másik utasítást akarjuk végrehajtani Szintaxis Logikai kifejezés if else Utasítás ) ( Programozás Alapjai (2008)

145 Egyszerű szelekciós vezérlés
Az egyszerű szelekciós vezérlés szerkezeti ábrája és C megvalósítása F i n if ( F ) { A; } A Programozás Alapjai (2008)

146 Egyszerű szelekciós vezérlés
Az egyébként ággal kiegészített egyszerű szelekciós vezérlés szerkezeti ábrája és C megvalósítása F i n if ( F ) { A; } else { B; } A B Programozás Alapjai (2008)

147 Többszörös szelekció megvalósítása
C nyelvben nincs külön utasítás a többszörös szelekció megvalósítására, ezért az egyszerű szelekció ismételt alkalmazásával kell azt megvalósítani. Ez azon az összefüggésen alapszik, hogy a többszörös szelekció levezethető egyszerű szelekciók megfelelő összetételével. Programozás Alapjai (2008)

148 Többszörös szelekció megvalósítása
Az alábbi két ábra ugyanazt a vezérlési előírást fejezi ki. ? B A1 An A2 F1 Fn F2 F1 i n A1 F2 A2 Fn An B Programozás Alapjai (2008)

149 Többszörös szelekció megvalósítása
A többszörös szelekciós vezérlés szerkezeti ábrája és C megvalósítása if ( F1 ) { A1; } else if ( F2 ) { A2; ... } else if ( Fn ) { An; } ? A1 An A2 F1 Fn F2 Programozás Alapjai (2008)

150 Többszörös szelekció megvalósítása
Az egyébként ággal kiegészített többszörös szelekciós vezérlés szerkezeti ábrája és C megvalósítása if ( F1 ) { A1; } else if ( F2 ) { A2; ... } else if ( Fn ) { An; } else { B; } ? B A1 An A2 F1 Fn F2 Programozás Alapjai (2008)

151 Háromszögek osztályozása
/* Milyen háromszöget határoz meg három pozitiv valós szám, * mint a háromszög három oldalhosszúsága? * Október 13. Dévényi Károly */ #include <stdio.h> main() { float A, B, C; /* a háromszög oldalhosszúságai */ float M; /* munkaváltozó a cseréhez */ printf("Kérem a három pozitív valós számot!\n"); scanf("%f%f%f", &A, &B, &C); >>> Programozás Alapjai (2008)

152 Háromszögek osztályozása
/* A,B,C átrendezése úgy, hogy A>=B,C legyen */ if (A < B) { /* A és B átrendezése */ M = A; A = B; B = M; } if (A < C) { /* A és C átrendezése */ A = C; C = M; /* osztályozás */ if (A <= 0 || B <= 0 || C <= 0) { printf(" Nem háromszög!\n"); /* 1. alternatíva */ >>> Programozás Alapjai (2008)

153 Háromszögek osztályozása
} else if (A >= B + C) { printf(" Nem háromszög!\n"); /* 2. alternatíva */ } else if (A == B && B == C) { printf(" Szabályos háromszög.\n"); /* 3. alternatíva */ } else if (A == B || B == C || A == C) { if (A * A == B * B + C * C) { /* 4. alternatíva */ printf(" Egyenlőszárú derékszögű háromszög.\n"); } else { printf(" Egyenlőszárú háromszög.\n"); } } else if (A * A == B * B + C * C) { printf(" Derékszögű háromszög.\n"); /* 5. alternatíva */ printf(" Egyéb háromszög.\n"); /* egyébként */ } /* vége a többszörös szelekciónak */ Programozás Alapjai (2008)

154 if utasítások ismételt alkalmazása
Az if utasítások ismételt alkalmazása esetén figyelembe kell venni, hogy a következő utasítás a mellette látható vezérlési szerkezet megvalósítása F1 if ( F1 ) if ( F2 ) A1; else A2; i n F2 i n A1 A2 Programozás Alapjai (2008)

155 if utasítások ismételt alkalmazása
Az if utasítások ismételt alkalmazása esetén figyelembe kell venni, hogy a következő utasítás a mellette látható vezérlési szerkezet megvalósítása F1 if ( F1 ) { if ( F2 ) A1; else A2; } i n F2 i n A1 A2 Programozás Alapjai (2008)

156 if utasítások ismételt alkalmazása
Az if utasítások ismételt alkalmazása esetén figyelembe kell venni, hogy a következő utasítás a mellette látható vezérlési szerkezet megvalósítása F1 if ( F1 ) { if ( F2 ) A1; } else { A2; } i n F2 A2 i n A1 Programozás Alapjai (2008)

157 Esetkiválasztásos szelekciós vezérlés
A többszörös szelekció egy speciális esete az, amikor minden Fi (1<=i<=n) feltétel így szól: Egy adott K kifejezés aktuális értéke eleme-e az értékek egy előre megadott Hi halmazának? Vagyis legyen a K egy szelektor kifejezés, Hi kiválasztó halmazok, Ai pedig tetszőleges műveletek (1<=i<=n). Ezekből képzett esetkiválasztásos szelekciós vezérlés a következő vezérlési előírást jelenti: Programozás Alapjai (2008)

158 Esetkiválasztásos szelekciós vezérlés
1.) Értékeljük ki a K kifejezést és folytassuk a 2.) lépéssel. 2.) Adjunk választ a következő kérdésre: Van-e olyan i (1<=i<=n), amelyre teljesül, hogy a kiszámolt érték eleme a Hi halmaznak és nem eleme az összes Hj (1<=j<i) halmaznak? Folytassuk a 3.) lépéssel. 3.) Ha van ilyen i, akkor hajtsuk végre az Ai műveletet és fejezzük be az összetett művelet végrehajtását. 4.) Egyébként, vagyis ha a kiszámolt érték nem eleme a Hi (1<=i<=n) halmazok egyesítésének, akkor fejezzük be az összetett művelet végrehajtását. Programozás Alapjai (2008)

159 Esetkiválasztásos szelekciós vezérlés
Bővíthetjük az esetkiválasztásos szelekciós vezérlést azzal, hogy a 4.) pontban ne az üres művelet, hanem egy előre megadott B tetszőleges művelet végrehajtását írjuk elő. Legyen a K egy szelektor kifejezés, Hi kiválasztó halmazok, Ai és B pedig tetszőleges műveletek (1<=i<=n). Ezekből képzett esetkiválasztásos szelekciós vezérlés a következő vezérlési előírást jelenti: Programozás Alapjai (2008)

160 Esetkiválasztásos szelekciós vezérlés
1.) Értékeljük ki a K kifejezést és folytassuk a 2.) lépéssel. 2.) Adjunk választ a következő kérdésre: Van-e olyan i (1<=i<=n), amelyre teljesül, hogy a kiszámolt érték eleme a Hi halmaznak és nem eleme az összes Hj (1<=j<i) halmaznak? Folytassuk a 3.) lépéssel. 3.) Ha van ilyen i, akkor hajtsuk végre az Ai műveletet és fejezzük be az összetett művelet végrehajtását. 4.) Egyébként, vagyis ha a kiszámolt érték nem eleme a Hi (1<=i<=n) halmazok egyesítésének, akkor hajtsuk végre a B műveletet és fejezzük be az összetett művelet végrehajtását. Programozás Alapjai (2008)

161 Esetkiválasztásos szelekciós vezérlés
Az esetkiválasztásos szelekciós vezérlés szerkezeti ábrája K ? A1 An A2 H1 Hn H2 Programozás Alapjai (2008)

162 Esetkiválasztásos szelekciós vezérlés
Az egyébként ággal kiegészített esetkiválasztásos szelekciós vezérlés szerkezeti ábrája K ? B A1 An A2 H1 Hn H2 Programozás Alapjai (2008)

163 Esetkiválasztásos szelekciós vezérlés
A vezérlés lényege Értékeljük ki a K kifejezést. Hajtsuk végre a legelső olyan Ai műveletet, aminek a Hi halmazában benne van a K értéke. Ha K értéke nem eleme egyetlen Hi halmaznak sem, akkor hajtsuk végre a B műveletet. Programozás Alapjai (2008)

164 Esetkiválasztásos szelekciós vezérlés
A kiválasztó halmazok megadása az esetkiválasztásos szelekció kritikus pontja. Algoritmusok tervezése során minden effektív halmazmegadást használhatunk, azonban a tényleges megvalósításkor csak a választott programozási nyelv eszközeit alkalmazhatjuk. Programozás Alapjai (2008)

165 Programozás Alapjai (2008)
Dátum helyessége Problémafelvetés Eldöntendő, hogy egy dátumként megadott számpár helyes dátum-e? Specifikáció Input Egy (hónap, nap) alakban megadott dátum Output A dátum akkor és csak akkor helyes, ha 1 <= hónap <= 12 és a nap érték is a megfelelő intervallumba esik. Programozás Alapjai (2008)

166 Programozás Alapjai (2008)
Dátum helyessége Algoritmustervezés Dátum Hónap ? 2 Jó= (1<=Nap) És (Nap<=28) 1,3,5,7,8,10,12 4,6,9,11 Be(Hónap,Nap) Kiíratás Jó= (1<=Nap) És (Nap<=30) Jó= (1<=Nap) És (Nap<=31) Jó=Hamis Programozás Alapjai (2008)

167 Programozás Alapjai (2008)
A switch utasítás Ha egy kifejezés értéke alapján többféle utasítás közül kell választanunk Szintaxis switch ( ) Kifejezés { } case default : Konstans Utasítás break ; Programozás Alapjai (2008)

168 Programozás Alapjai (2008)
A switch utasítás A szelektor kifejezés és a konstansok típusának meg kell egyeznie. Egy konstans legfeljebb egyszer szerepelhet case mögött egy switch utasításban. A default kulcsszó csak egyszer szerepelhet egy switch utasításban. Programozás Alapjai (2008)

169 Esetkiv. szelekció megvalósítása
Az esetkiválasztásos szelekciós vezérlés C megvalósítása switch (K) { case H1 : A1; break; ... case Hn : An; } K ? A1 An A2 H1 Hn H2 Programozás Alapjai (2008)

170 Esetkiv. szelekció megvalósítása
Az egyébként ággal kiegészített esetkiválasztásos szelekciós vezérlés C megvalósítása switch (K) { case H1 : A1; break; ... case Hn : An; default : B; } K ? B A1 An A2 H1 Hn H2 Programozás Alapjai (2008)

171 A switch utasítás tulajdonságai
C-ben a H1, ..., Hn halmazok csak egyeleműek lehetnek, amelyeket így egyszerűen az elem megadásával jelölhetünk. A hatékonyabb kódolás érdekében azonban kihasználhatjuk a switch utasítás tulajdonságát: A K kifejezés értékétől csak az függ, hogy melyik helyen kezdjük el végrehajtani a switch magját. Ha a végrehajtás elkezdődik, akkor onnantól kezdve az első break utasításig, vagy a switch végéig sorban hajtódnak végre az utasítások. Programozás Alapjai (2008)

172 A switch utasítás tulajdonságai
Tegyük fel, hogy a H1 halmaz elemei x1,x2, ... ,xm Ezt C-ben a kódrészlettel tudjuk lekódolni. case x1: case x2: ... case xm: A1; break; Programozás Alapjai (2008)

173 A switch utasítás tulajdonságai
A default ág olyan, mintha a K kifejezés összes lehetséges de a switch-ben fel nem sorolt értékét megadnánk egy-egy case ággal. Így a default ág a switch magján belül tetszőleges helyen lehet, de csak akkor kezdődik itt a vezérlés, ha a kifejezés aktuális értéke egyetlen case-ben sem szerepel, beleértve a default után megadott case-eket is. Éppen ezért a default ágban is mindig használjunk break utasítást. Programozás Alapjai (2008)

174 Logikai adattípus C nyelven
Az algoritmustervezés során használtunk egy „Jó” nevű változót, amely logikai értéket tárolt. A C nyelvben nincs logikai típus, de azért logikai értékek persze keletkeznek. Ezeket az értékeket eltárolhatjuk egy int változóban. Ha egy logikai értéket egy int típusú változóba tettünk, akkor a logikai hamis érték tárolása után az int típusú változó értéke 0, az igaz érték tárolása után pedig nem 0. (Sok megvalósításban 1, de ezt nem használhatjuk ki, ha gépfüggetlen programot szeretnénk.) Programozás Alapjai (2008)

175 Programozás Alapjai (2008)
Dátum helyessége /* Eldöntendő, hogy egy dátumként megadott számpár helyes dátum-e? * Október 4. Dévényi Károly, */ #include <stdio.h> main() { int Honap, Nap; int Jo; /* a Boolean érték tárolására */ printf("Kérem a dátumot (hónap, nap) !\n"); scanf("%d%d", &Honap, &Nap); switch (Honap) { case 2: Jo = (1 <= Nap && Nap <= 28); break; >>> Programozás Alapjai (2008)

176 Programozás Alapjai (2008)
Dátum helyessége case 4: case 6: case 9: case 11: Jo = (1 <= Nap && Nap <= 30); break; case 1: case 3: case 5: case 7: case 8: case 10: case 12: Jo = (1 <= Nap && Nap <= 31); >>> Programozás Alapjai (2008)

177 Programozás Alapjai (2008)
Dátum helyessége default: Jo = 0; break; } /* switch */ /* Kiíratás */ printf("A dátum "); if (!Jo) { /* Ezt másképpen szokták */ printf("nem "); } printf("helyes.\n"); Programozás Alapjai (2008)

178 Programozás Alapjai (2008)
Feltételes kifejezés A feltételes operátor a C nyelv egyetlen háromoperandusú művelete. A K&R könyv feltételes kifejezésnek említi. Először a kif1 kerül kiértékelésre, ha ez Igaz (nem 0), a kifejezés értéke kif2 lesz Hamis (0), a kifejezés értéke kif3 lesz kif1 ? kif2 : kif3 Programozás Alapjai (2008)

179 Programozás Alapjai (2008)
Feltételes kifejezés Az előző programban a kiíratás ez volt: printf("A dátum "); if (!Jo) { printf("nem "); } printf("helyes.\n"); Programozás Alapjai (2008)

180 Programozás Alapjai (2008)
Feltételes kifejezés Ez lerövidíthető: vagy printf("A dátum "); printf(Jo ? " " : " nem "); printf("helyes.\n"); printf(Jo ? "A dátum helyes.\n" : "A dátum nem helyes.\n"); Programozás Alapjai (2008)

181 Programozás Alapjai (2008)
Feltételes kifejezés Illesszük be prioritási sorba az = és a ?: műveleteket! prefix művelet (prefix -, ! ) multiplikatív műveletek ( *, /, % ) additív műveletek ( +, - ) kisebb-nagyobb relációs műveletek ( <=, >=, <, > ) egyenlő-nem egyenlő relációs műveletek ( ==, != ) logikai 'és' művelet ( && ) logikai 'vagy' művelet ( || ) feltételes művelet ( ? : ) értékadó művelet ( = ) Programozás Alapjai (2008)

182 Programozás Alapjai (2008)
Feltételes kifejezés Így a következő programrészlet átírható így: vagy akár: if (a > b) { z = a; } else { z = b; } z = (a > b) ? a : b; z = a > b ? a : b; Programozás Alapjai (2008)

183 Ismétléses vezérlések
Ismétléses vezérlésen olyan vezérlési előírást értünk, amely adott műveletnek adott feltétel szerinti ismételt végrehajtását írja elő. Az ismétlési feltétel szerint öt formáját különböztetjük meg az ismétléses vezérléseknek 1. Kezdőfeltételes 2. Végfeltételes 3. Számlálásos 4. Hurok 5. Diszkrét Programozás Alapjai (2008)

184 Ismétléses vezérlések
Az algoritmustervezés során a leginkább megfelelő ismétléses vezérlési formát használjuk, függetlenül attól, hogy a megvalósításra használt programozási nyelvben közvetlenül megvalósítható-e ez a vezérlési mód. Ismétléses vezérlés képzését ciklusszervezésnek is nevezik, így az ismétlésben szereplő műveletet ciklusmagnak hívjuk. Programozás Alapjai (2008)

185 Kezdőfeltételes ismétléses vezérlés
Legyen F logikai kifejezés, M pedig tetszőleges művelet. Az F ismétlési feltételből és az M műveletből (a ciklusmagból) képzett kezdőfeltételes ismétléses vezérlés a következő vezérlési előírást jelenti 1.) Értékeljük ki az F feltételt és folytassuk a 2.) lépéssel. 2.) Ha F értéke hamis, akkor az ismétlés és ezzel együtt az összetett művelet végrehajtása befejeződött. 3.) Egyébként, vagyis ha az F értéke igaz, akkor hajtsuk végre az M műveletet, majd folytassuk az 1.) lépéssel. Programozás Alapjai (2008)

186 Kezdőfeltételes ismétléses vezérlés
A kezdőfeltételes ismétléses vezérlés szerkezeti ábrája F M Programozás Alapjai (2008)

187 Kezdőfeltételes ismétléses vezérlés
Az algoritmus tervezésekor a ciklusmag olyan részprobléma megoldása is lehet, aminek a megoldását a tervezés adott stádiumában még nem ismerjük. Ekkor a ciklusmag helyére a részprobléma megnevezését írjuk, majd ehhez kapcsoljuk a tervezés során a ciklusmagot megfogalmazó szerkezeti ábrarészt. Programozás Alapjai (2008)

188 Kezdőfeltételes ismétléses vezérlés
Ha az F értéke hamis, az összetett művelet végrehajtása befejeződik anélkül, hogy az M művelet egyszer is végrehajtásra kerülne Ha az F értéke igaz, és az M művelet nincs hatással az F feltételre, akkor F igaz is marad, tehát az összetett művelet végrehajtása nem tud befejeződni. Ilyenkor végtelen ciklus végrehajtását írtuk elő. Fontos tehát, hogy az M művelet hatással legyen az F feltételre. Programozás Alapjai (2008)

189 Programozás Alapjai (2008)
Minimax program Problémafelvetés Határozzuk meg egy valós számsorozat legkisebb és legnagyobb elemét, valamint a sorozat átlagát! Specifikáció A probléma inputja a valós számsorozat. Az input számsorozat végét egy végjel fogja jelezni, amit a felhasználó ad meg inputként, nyilván a számsorozat előtt. Az output a sorozat legkisebb és legnagyobb eleme, valamint az átlaga. Programozás Alapjai (2008)

190 Programozás Alapjai (2008)
Minimax program Algoritmustervezés Elsőre talán az tűnne a legegyszerűbb megoldásnak, ha beolvasnánk az összes számot, majd ezek között keresgélnénk. Ez a megoldás egy összetett adatszerkezetet (tömböt) igényelne. Ha viszont végiggondoljuk, a „következő” elem beolvasásakor elegendő az eddigi sorozatból csak a lényeges információkat tárolni: a legkisebb elem értékét, a legnagyobb elem értékét, az elemek összegét, és az elemek darabszámát. Programozás Alapjai (2008)

191 Programozás Alapjai (2008)
Minimax program Algoritmustervezés Minimax Szám!=Végjel Összeg=Összeg+Szám Db=Db+1 Inicializálás Szám feldolgozása Be(Szám) Szám<Min i n Min=Szám Kiíratás Szám>Max Max=Szám Programozás Alapjai (2008)

192 Programozás Alapjai (2008)
Minimax program Algoritmustervezés Inicializálás Összeg=0 Be(Szám) Min=Szám Be(Végjel) Max=Szám Db=0 Db==0 i n Kiíratás Ki(„Üres sorozat”) Ki(Min,Max,Átlag) Programozás Alapjai (2008)

193 Programozás Alapjai (2008)
A while utasítás Ha valamilyen műveletet mindaddig végre kell hajtani, amíg egy feltétel igaz. Ha a feltétel kezdetben hamis volt, a műveletet egyszer sem hajtjuk végre. (A feltétel ellenőrzése a művelet előtt történik.) Szintaxis Logikai kifejezés while Utasítás ( ) Programozás Alapjai (2008)

194 A kezdőfeltételes vezérlés megvalósítása
A kezdőfeltételes ismétléses vezérlés szerkezeti ábrája és C megvalósítása Az M utasítás tetszőleges, összetett utasítás lehet. F M while ( F ) { M; } Programozás Alapjai (2008)

195 Programozás Alapjai (2008)
A C értékadó műveletei Mielőtt elhamarkodottan lekódolnánk a szerkezeti ábrán található programot, megismerkedünk a C nyelv azon műveleteivel, amelyek használata tömörré teszi a programok kódját. Programozás Alapjai (2008)

196 Inkrementáló és dekrementáló műv.
A C nyelv tartalmaz két operátort, amelyekkel változók inkrementálhatók és dekrementálhatók. A ++ inkrementáló operátor az operandusához 1-et ad hozzá A -- dekrementáló operátor az operandusából 1-et von le A ++ és a -- egyaránt használható prefix operátorként (++i, --i ) postfix operátorként (i++, i--) Programozás Alapjai (2008)

197 Inkrementáló és dekrementáló műv.
Az i változó a prefix és postfix használat esetén is pontosan eggyel nő (csökken) A különbség a kétféle használat között az, hogy prefix művelet esetén a ++i (--i) kifejezés értéke az i változó új, azaz eggyel megnövelt (csökkentett) értéke postfix esetben az i++ (i--) kifejezés értéke az i eredeti értéke Tehát ha nem csak a művelet inkrementáló (dekrementáló) tulajdonságát, hanem a kifejezés értékét is felhasználjuk, akkor a pre- és postfix használat között különbség van. Programozás Alapjai (2008)

198 Inkrementáló és dekrementáló műv.
Például, ha i értéke 5, akkor az x-et 5-re állítja, de x-et 6-ra állítja. i értéke mindkét esetben 6 lesz. Ezek az operátorok csak változókra (l-value) alkalmazhatók; az olyan kifejezés, mint nem megengedett! x = i++; x = ++i; (i + j)++ Programozás Alapjai (2008)

199 Értékadó műveletek és kifejezések
Az olyan kifejezések, mint például a += értékadó operátor segítségével az tömörített alakban is írhatók. A C-ben a legtöbb operátornak megvan az op= alakú megfelelője, ahol az op egy műveleti szimbólum. Az eddig megismertek közül op lehet: + - * / % i = i + 2 i += 2 Programozás Alapjai (2008)

200 Értékadó műveletek és kifejezések
Ha e1 és e2 kifejezés, akkor e1 op= e2 jelentése e1 = (e1) op (e2) Ügyeljünk az e2 körüli zárójelekre: nem pedig x *= y + 1 x = x * (y + 1) x = (x * y) + 1 Programozás Alapjai (2008)

201 Értékadó műveletek és kifejezések
Illesszük be a prioritási sorba a ++ és -- valamint az értékadó műveleteket! a egyoperandusú műveletek (prefix -, ++, --, ! ) a multiplikatív műveletek ( *, /, % ) az additív műveletek ( +, - ) a kisebb-nagyobb relációs műveletek ( <=, >=, <, > ) az egyenlő-nem egyenlő relációs műveletek ( ==, != ) a logikai 'és' művelet ( && ) a logikai 'vagy' művelet ( || ) a feltételes művelet ( ? : ) értékadó művelet ( =, +=, -=, *=, /=, %= ) Programozás Alapjai (2008)

202 Értékadó műveletek és kifejezések
Az értékadó műveletek természetesen mind jobb-asszociatívak. Óvatosan és csak a céljának megfelelően szabad használni ezeket a műveleteket. Nézzünk néhány példát! Programozás Alapjai (2008)

203 Értékadó műveletek és kifejezések
Mi lesz a kiírt érték? Nálunk ez 49, de lehetne 42 vagy 56 is. Az ANSI szabvány szerint az aritmetikai részkifejezések kiértékelésének sorrendje tetszőleges. Tehát i értékét csak akkor inkrementáljuk, ha i sehol máshol nem szerepel az egész kifejezésben. int i = 7; printf("%d\n", i-- * i++); Programozás Alapjai (2008)

204 Programozás Alapjai (2008)
Minimax program /* Határozzuk meg egy valós számsorozat legkisebb * és legnagyobb elemét, valamint a sorozat átlagát! * Október 25. Dévényi Károly, */ #include <stdio.h> main() { double Vegjel, Szam, Osszeg, Min, Max, Atlag; int Db; /* az összegzett elemek száma */ printf("Ez a program valós számsorozat minimális,\n"); printf("maximális elemét és átlagát számolja.\n"); printf("Az input sorozatot végjel zárja.\n"); printf("Kérem a végjelet!\n"); /* inicializálás */ scanf("%lf", &Vegjel); >>> Programozás Alapjai (2008)

205 Programozás Alapjai (2008)
Minimax program printf("Kérem az input számsorozatot!\n"); printf("? "); scanf("%lf", &Szam); Min = Max = Szam; Osszeg = 0.0; Db = 0; while (Szam != Vegjel) { /* a ciklus kezdete */ Osszeg += Szam; /* összegzés */ Db++; /* számláló növelés */ if (Szam < Min) { /* min-max számítás */ Min = Szam; } else if (Szam > Max) { Max = Szam; } /* a következő szám beolvasása */ } /* a ciklus vége */ >>> Programozás Alapjai (2008)

206 Programozás Alapjai (2008)
Minimax program if (Db == 0) { printf("Üres számsorozat érkezett.\n"); } else { Atlag = Osszeg / Db; printf("Minimum = %10.3f Maximum= %10.3f\n", Min, Max); printf("Az átlag = %10.3f\n", Atlag); } Programozás Alapjai (2008)

207 Végfeltételes ismétléses vezérlés
Az F ismétlési feltételből és M műveletből (ciklusmagból) képzett végfeltételes ismétléses vezérlés a következő vezérlési előírást jelenti 1.) Hajtsuk végre az M műveletet majd folytassuk a 2.) lépéssel. 2.) Értékeljük ki az F feltételt és folytassuk a 3.) lépéssel. 3.) Ha F értéke igaz, akkor az ismétléses vezérlés és ezzel együtt az összetett művelet végrehajtása befejeződött. 4.) Egyébként, vagyis ha az F értéke hamis, akkor folytassuk az 1.) lépéssel. Programozás Alapjai (2008)

208 Végfeltételes ismétléses vezérlés
A végfeltételes ismétléses vezérlés szerkezeti ábrája F M Programozás Alapjai (2008)

209 Végfeltételes ismétléses vezérlés
Látható, hogy a végfeltételes ismétléses vezérlés alapvetően abban különbözik a kezdőfeltételes ismétléses vezérléstől, hogy a ciklusmag legalább egyszer végrehajtódik. Programozás Alapjai (2008)

210 Végfeltételes ismétléses vezérlés
Ha az M művelet nincs hatással az F feltételre, akkor Ha az F értéke igaz, igaz is marad, így az M művelet egyszer került végrehajtásra és az összetett művelet végrehajtása befejeződik Ha az F értéke hamis, hamis is marad, tehát az összetett művelet végrehajtása nem tud befejeződni. Ilyenkor végtelen ciklus végrehajtását írtuk elő Fontos tehát, hogy az M művelet hatással legyen az F feltételre. Programozás Alapjai (2008)

211 Ismétléses vezérlések kapcsolata
A kezdő és végfeltételes ismétléses vezérlések kifejezhetőek egymás segítségével. F M !F F M !F i n Programozás Alapjai (2008)

212 Ismétléses vezérlések kapcsolata
Az algoritmus tervezésekor előfordulhat, hogy mind a kezdőfeltételes ismétléses vezérlés, mind a végfeltételes ismétléses vezérlés alkalmasnak látszik a probléma megoldására. Ilyenkor érdemes megvizsgálni, hogy az F feltétel szükséges feltétele-e az M művelet végrehajtásának? Ha igen, akkor a kezdőfeltételes ismétléses vezérlést kell választani. Programozás Alapjai (2008)

213 Programozás Alapjai (2008)
Szinusz Problémafelvetés Szinusz(x) közelítő értékének kiszámítása Specifikáció Input X valós szám Outputja sin(X) Nem hívhatjuk meg a C standard sin(x) függvényét Programozás Alapjai (2008)

214 Programozás Alapjai (2008)
Szinusz Algoritmustervezés Ismeretes, hogy sin(x) értéke az x - x3/3! + x5/5! (-1)(i-1)*x(2i-1)/(2i-1)! +... végtelen sor összege. Ezen végtelen sor kezdőszeletének összegével közelítjük sin(x) értékét, úgy, hogy az összegzés befejeződik, ha az utolsó tag abszolút értéke kisebb, mint a konstansként megadott epsz pontosság. Programozás Alapjai (2008)

215 Programozás Alapjai (2008)
Szinusz Algoritmustervezés Nyilvánvaló, hogy nem célszerű a számolást úgy szervezni, hogy i minden értékére külön kiszámoljuk a tagot, hiszen az i. tag kiszámolható az (i-1)-ik tagból. A tag számlálójának és nevezőjének külön számolása egyébként is pontatlanná tenné a számítást, mert mindkettő, különösen a nevező rohamosan növekedik i függvényében. Programozás Alapjai (2008)

216 Szinusz Struktúradiagram Szinusz Abs(Tag)<Epsz Összeg=Összeg+Tag
Inicializálás Következő tag kiszámítása j+=2 Tag= -Tag*XX/j/(j+1) Ki(Összeg) Programozás Alapjai (2008)

217 Programozás Alapjai (2008)
Szinusz A float típus tulajdonságai miatt nem érdemes abszolút értékben nagy X értékekkel számolni. Kihasználjuk, hogy a sin(x) függvény periodikus. Inicializálás Tag=X X transzf. Osszeg=0.0 Be(X) j=2 XX=X*X Xorig=X X<-Pi X+=2.0*Pi Pi<X X-=2.0*Pi Programozás Alapjai (2008)

218 Programozás Alapjai (2008)
A do while utasítás Ha valamilyen műveletet mindaddig végre kell hajtani, amíg egy feltétel igaz. A műveletet legalább egyszer végrehajtjuk akkor is, ha a feltétel kezdetben hamis volt. (A feltétel ellenőrzése a művelet után történik.) Szintaxis Logikai kifejezés while Utasítás ( ) do Programozás Alapjai (2008)

219 A végfeltételes vezérlés megvalósítása
A végfeltételes ismétléses vezérlés szerkezeti ábrája és C megvalósítása Az M utasítás tetszőleges, összetett utasítás lehet. F M do { M; } while ( !F ) Programozás Alapjai (2008)

220 Programozás Alapjai (2008)
Szinusz /* sin(x) közelítő értékének kiszámítása a beépített sin(x) * függvény alkalmazása nélkül. * X értékét transzformáljuk a (-Pi,Pi) intervallumba. * Október 25. Dévényi Károly, */ #include <stdio.h> #include <math.h> #define EPSZ 1e /* a közelítés pontossága */ main() { double Osszeg; /* a végtelen sor kezdőösszege */ double Tag; /* a végtelen sor aktuális tagja */ double X; /* argumentum */ double Xorig; /* az argumentum értékének megőrzése*/ double XX; /* sqr(x) */ int j; /* a nevező kiszámításához */ >>> Programozás Alapjai (2008)

221 Programozás Alapjai (2008)
Szinusz printf("Kérem sin(x)-hez az argumentumot\n"); scanf("%lg%*[^\n]", &X); getchar(); /* ez most már ReadLn */ Xorig = X; while (X < -M_PI) { /* transzformálás */ X += 2 * M_PI; } while (M_PI < X) { X -= 2 * M_PI; Osszeg = 0.0; j = 2; /* inicializálás */ Tag = X; XX = X * X; >>> Programozás Alapjai (2008)

222 Programozás Alapjai (2008)
Szinusz do { /* ciklus kezdete */ Osszeg += Tag; Tag = -(Tag * XX / j / (j + 1)); /* következő tag */ j += 2; } while (fabs(Tag) >= EPSZ); /* végfeltétel, ciklus vége */ printf("sin(%8.5f)= %13.10f\n", Xorig, Osszeg); } Programozás Alapjai (2008)

223 Programozás Alapjai (2008)
Eljárásvezérlés Adott művelet alkalmazása adott argumentumokra, ami az argumentumok értékének pontosan meghatározott változását eredményezi Az eljárásvezérlés fajtái Eljárásművelet Függvényművelet Programozás Alapjai (2008)

224 Programozás Alapjai (2008)
Eljárásművelet Eljárásműveleten olyan tevékenységet értünk, amelynek alkalmazása adott argumentumokra az argumentumok értékének pontosan meghatározott megváltozását eredményezi. Minden eljárásműveletnek rögzített számú argumentuma van, és minden argumentum rögzített adattípusú. Az argumentumok lehetnek Bemenő argumentumok Kimenő argumentumok Be- és kimenő argumentumok Programozás Alapjai (2008)

225 Argumentumok kezelési módjai
Bemenő argumentum Ha a művelet bármely végrehajtása nem változtatja meg az adott argumentum értékét. Kimenő argumentum Ha a művelet hatása nem függ az adott argumentumnak a végrehajtás előtti értékétől, azonban az adott argumentum értéke a művelet hatására megváltozhat. Be- és kimenő argumentum Ha a művelet hatása függ az adott argumentumnak a végrehajtás előtti értékétől, és az adott argumentum értéke a művelet hatására megváltozhat. Programozás Alapjai (2008)

226 Programozás Alapjai (2008)
Függvényművelet A matematikai függvény fogalmának általánosítása. Ha egy részprobléma célja egy érték kiszámítása adott értékek függvényében, akkor a megoldást megadhatjuk függvényművelettel. A függvényművelet argumentumai ugyanúgy lehetnek kimenő és be- és kimenő módúak is, mint az eljárásműveletek esetén, tehát a függvényművelet végrehajtása az aktuális argumentumok megváltozását is eredményezheti. Programozás Alapjai (2008)

227 Eljárás és függvény specifikációja
Eljárásművelet specifikációja tartalmazza: A művelet elnevezését A formális argumentumok felsorolását Mindegyik argumentum adattípusát és kezelési módját A művelet hatásának leírását A függvényművelet specifikációja a fentieken túl tartalmazza még: A függvényművelet eredménytípusát Programozás Alapjai (2008)

228 Eljárásművelet általános jelölése
Eljárásműveletek (általános) jelölése: P(m1 X1:T1; ... ;mn Xn:Tn) ahol P az eljárásművelet neve Xi az i-edik formális argumentum azonosítója mi az i-edik formális argumentum kezelési módja -> bemenő mód <- kimenő mód <-> be- és kimenő mód. Ti az i-edik formális argumentum adattípusa Programozás Alapjai (2008)

229 Eljárásművelet általános jelölése
Az eljárásműveletnek adott A1, ... ,An aktuális argumentumokra történő végrehajtását eljárásutasításnak (eljáráshívásnak) nevezzük Jelölése P(A1, ... ,An) Ha az i-edik argumentum módja kimenő vagy be- és kimenő, akkor az Ai aktuális argumentum csak változó lehet. Programozás Alapjai (2008)

230 Programozás Alapjai (2008)
Eljárásművelet Algoritmustervezés során nem csak elemi (eleve definiált) eljárásműveleteket használhatunk. Részproblémák megoldását is kifejezhetjük olyan eljárásműveletekkel, melyek megvalósítását részprogrammal adjuk meg. A részprogramot különálló szerkezeti ábrával írjuk le, amelynek feje P(m1 X1:T1; ... ;mn Xn:Tn) Programozás Alapjai (2008)

231 Függvényművelet általános jelölése
Függvényműveletek (általános) jelölése F(m1 X1:T1; ... ;mn Xn:Tn):T ahol F az függvényművelet neve Xi az i-edik formális argumentum azonosítója mi az i-edik formális argumentum kezelési módja Ti az i-edik formális argumentum adattípusa T a függvényművelet eredménytípusa Programozás Alapjai (2008)

232 Programozás Alapjai (2008)
Függvényművelet A fent jelölt függvényműveletnek adott A1, ... ,An aktuális argumentumokra történő végrehajtását függvényhívásnak nevezzük Jelölése F(A1, ... ,An) Részproblémák megoldását függvényművelettel is kifejezhetjük, ekkor a szerkezeti ábra feje F(m1 X1:T1; ... ;mn Xn:Tn):T Programozás Alapjai (2008)

233 Eljárásvezérlés megvalósítása
Vannak olyan programozási nyelvek, ahol a függvény és eljárásműveletek meg vannak különböztetve, valamint a paraméterek módjaira sincs megkötés. Mivel azonban e kurzus keretében csak a C nyelvről lesz szó, a szerkezeti ábrán a továbbiakban (is) igazodni fogunk a C nyelvhez. Programozás Alapjai (2008)

234 Eljárásvezérlés megvalósítása
A C nyelvben lényegében csak függvényművelet van. C nyelvben a függvényművelet argumentumai bemenő módúak, tehát alapvetően a függvényművelet végrehajtása az aktuális argumentumok megváltozását nem eredményezheti. Programozás Alapjai (2008)

235 Programozás Alapjai (2008)
Függvényművelet A függvényművelet jelölésére a továbbiakban a T F(T1 X1, ... ,Tn Xn) formát használjuk, ahol T a függvényművelet eredménytípusa F a függvényművelet neve Ti az i-edik formális argumentum adattípusa Xi az i-edik formális argumentum azonosítója A zárójeleket üres paraméterlista esetén is ki kell tenni. Programozás Alapjai (2008)

236 Programozás Alapjai (2008)
Függvényművelet A C jelölésmódhoz igazodva, a függvényművelet szerkezeti ábrájának a feje így néz ki: Továbbá a szerkezeti ábrában lennie kell (legalább) egy olyan return utasításnak, amely visszaadja a függvény által kiszámított értéket. T F(T1 X1, ... ,Tn Xn) Programozás Alapjai (2008)

237 Programozás Alapjai (2008)
Függvényművelet A fent jelölt függvényműveletnek adott A1, ... ,An aktuális argumentumokra történő végrehajtását függvényhívásnak nevezzük és az F(A1, ... ,An) jelölést használjuk. A függvényhívás kifejezés. A zárójeleket paraméter nélküli függvény hívása esetén is ki kell tenni. Programozás Alapjai (2008)

238 Függvények szintaxisa C-ben
Függvény deklaráció Függvény definíció (egyben deklaráció is) Függvény fejléc Függvény fejléc ; Függvény fejléc { Utasítások } Azonosító Típus ( ) , Programozás Alapjai (2008)

239 Függvények szintaxisa C-ben
A return utasítás Minden függvényben szerepelnie kell legalább egy return utasításnak, amely kiszámítja a megadott kifejezés értékét, majd visszatér a függvényből. A hívás helyén a függvény a return által kiszámított értéket veszi fel. Kifejezés return ; Programozás Alapjai (2008)

240 Függvényhívás szintaxisa C-ben
Természetesen egy függvénynek a híváskor pontosan annyi és olyan típusú paramétert kell átadni, amennyi és amilyen paraméterekkel deklarálva lett. Azonosító ( ) Kifejezés , Programozás Alapjai (2008)

241 Függvény megvalósítása
Ha a függvény szerkezeti ábrája ez: Akkor a függvénydefiníció C-ben: T F(T1 X1, ... ,Tn Xn) M T F(T1 X1, ..., Tn Xn) { M; } Programozás Alapjai (2008)

242 Programozás Alapjai (2008)
Függvényművelet Például Régen C-ben a így kellett függvényt deklarálni: float atlag(float a, float b) { return (a + b)/2; } float atlag(a,b) float a, float b; { return (a + b)/2; } Programozás Alapjai (2008)

243 Programozás Alapjai (2008)
Eljárásművelet Ha eljárást szeretnénk készíteni, akkor a függvényművelet eredménytípusa void és ebben az esetben nem kötelező a return utasítás, illetve ha mégis van ilyen, akkor nem adható meg utána kifejezés. Programozás Alapjai (2008)

244 Vegyes és kimenő módú arg.
Mint említettük, C-ben csak bemenő módú argumentumok vannak. De mi magunk kezelhetjük a be- és kimenő illetve kimenő módú argumentumokat pointerek segítségével. Az alábbiakban egy, az alaptípusokra működő megoldást mutatunk. Programozás Alapjai (2008)

245 Vegyes és kimenő módú arg.
Ha az i. paramétert kimenő módúnak szeretnénk, akkor a függvény deklarációjában Ti Xi helyett Ti *Xi deklarációt, a függvénytörzsben pedig Xi helyett mindenhol (*Xi) változóhivatkozást használunk. Programozás Alapjai (2008)

246 Vegyes és kimenő módú arg.
Továbbá a függvény meghívásakor az Ai paraméter helyett az &Ai paramétert írjuk. Részletesebb magyarázatot és összetettebb típusokra működő megvalósítást a pointerek megismerése után adunk. Programozás Alapjai (2008)

247 Kamatos-kamat számítás
Problémafelvetés Számítsunk kamatos kamatot Specifikáció Input Osszeg valós, a betett összeg Kamatláb egész, az éves alapkamat Ev egész, az eltelt évek száma Output Ujosszeg a kamatos-kamattal növelt érték Programozás Alapjai (2008)

248 Kamatos-kamat számítás
Algoritmustervezés A kamatos-kamat számításhoz készítünk egy általános hatványozó függvényt és ezt hívjuk meg a kamatos-kamat számítás alapképletével. double hatvany(double X, int n) ? hatv= 1.0 n==0 hatv= 0.0 X==0 hatv= exp(n*ln(X)) X>0 hatv= -exp(n*ln(-X)) Odd(n) hatv= exp(n*ln(-X)) return hatv Programozás Alapjai (2008)

249 Bitenkénti logikai műveletek
A C nyelvben több bitmanipulációs operátor van, ezek a float és double típusú változókra nem alkalmazhatók. & bitenkénti ÉS, | bitenkénti megengedő (inkluzív) VAGY, ^ bitenkénti kizáró (exkluzív) VAGY, << bitléptetés (shift) balra, >> bitléptetés (shift) jobbra, ~ egyes komplemens (egyoperandusú). Programozás Alapjai (2008)

250 Bitenkénti logikai műveletek
A bitenkénti ÉS operátort gyakran használjuk valamely bithalmaz maszkolására. Például a páratlan(x) függvényt az ((x & 1) == 1) valósítja meg. A műveletekről később részletesen is lesz szó. Programozás Alapjai (2008)

251 Bitenkénti logikai műveletek
Illesszük be prioritási sorba a műveleteket! a egyoperandusú műveletek ( -, ++, --, !, ~ ) a multiplikatív műveletek ( *, /, % ) az additív műveletek ( +, - ) bitléptetés ( <<, >> ) a kisebb-nagyobb relációs műveletek ( <=, >=, <, > ) az egyenlő-nem egyenlő relációs műveletek ( ==, != ) bitenkénti 'és' művelet ( & ) bitenkénti 'kizáró vagy' művelet ( ^ ) bitenkénti 'vagy' művelet ( | ) a logikai 'és' művelet ( && ) a logikai 'vagy' művelet ( || ) a feltételes művelet ( ? : ) értékadó művelet ( =, +=, -=, *=, /=, %=, >>=, <<=, &=, ^=, |= ) Programozás Alapjai (2008)

252 Kamatos-kamat számítás
/* Kamatos-kamat számítás a hatványozás függvény segítségével. * Október 31. Dévényi Károly, */ #include <stdio.h> #include <math.h> >>> Programozás Alapjai (2008)

253 Kamatos-kamat számítás
double hatvany(double x, int n) { /* x n-edik hatványát kiszámító függvény */ double hatv; if (n == 0) { hatv = 1.0; } else if (x == 0.0) { hatv = 0.0; } else if (x > 0.0) { hatv = exp(n * log(x)); } else if (n & 1) { hatv = (-exp(n * log(-x))); } else { hatv = exp(n * log(-x)); } return(hatv); >>> Programozás Alapjai (2008)

254 Kamatos-kamat számítás
main() { double Osszeg, Ujosszeg; int Kamatlab, Ev; printf(" A kamatozó összeg ? "); scanf("%lg%*[^\n]", &Osszeg); getchar(); printf(" A kamatláb ? "); scanf("%d%*[^\n]", &Kamatlab); getchar(); printf(" A kamatozási évek száma ? "); scanf("%d%*[^\n]", &Ev); getchar(); Ujosszeg = Osszeg * hatvany(1.0 + Kamatlab / 100.0, Ev); printf("A kamatos kamattal növelt összeg:"); printf("%10.2f\n", Ujosszeg); } Programozás Alapjai (2008)

255 Blokkstruktúra a C nyelvben
A C nyelvben blokkon {} zárójelpárba zárt blokkot értünk. Egy C program blokkjai mellérendeltségi és alárendeltségi viszonyban vannak. Ezt a viszonyt az ide vonatkozó szabályokkal együtt blokkstruktúrának nevezzük. Programozás Alapjai (2008)

256 Blokkstruktúra a C nyelvben
1. Sorrendiségi szabály A program egy adott helyén csak olyan azonosítóra hivatkozhatunk, amely a hivatkozás helyét megelőzően deklarálva lett. Változó azonosító, függvény azonosító és típus azonosító megjelenése helyén deklaráltnak minősül. 2. Egyediségi szabály Egy adott blokkban deklarált minden azonosító csak egyszer deklarálható, nem számítva az alárendelt blokkokat. Programozás Alapjai (2008)

257 Blokkstruktúra a C nyelvben
main() { int b, b; a = 0; printf("? "); scanf("%d", &b); b = f(b); printf("%d (%d)\n", b, a); } int a; int f(int n) { a++; return (n>1) ? f(n-1) + f(n-2) : 1; Itt egyszerre két változót deklarálunk, és mindkettőnek a b nevet adjuk. Ha ezt megtehetnénk, hogy döntené el a fordító, hogy melyik esetben melyik változóval kellene dolgoznia? Itt pedig használjuk az f és az a azonosí- tókat, holott még azt sem tudjuk, hogy melyik micsoda. Itt már jogos az f és az a használata is, mert ezeken a pontokon már mindkettő deklarálva van, még ha f definíciója még nincs is teljesen befejezve. Programozás Alapjai (2008)

258 Blokkstruktúra a C nyelvben
3. Láthatósági szabály Egy B1 blokkban deklarált A azonosító akkor és csak akkor látható (hivatkozható) egy B2 blokkban, ha teljesül az alábbi két feltétel: a.) B1 megegyezik B2-vel, vagy B2 alárendeltje B1-nek és az A azonosító előbb van deklarálva, mint B2 b.) Az A azonosító nincs deklarálva egyetlen olyan C blokkban sem, amely alárendeltje B1-nek és amelynek B2 alárendeltje (beleértve azt, hogy B2 vagy megegyezik C-vel) Programozás Alapjai (2008)

259 Blokkstruktúra a C nyelvben
int a, b, c; { /* 2. BLOKK */ float c; a = 2; } c = 1; { /* 3. BLOKK */ float b; { /* 4. BLOKK */ b = 3.4; A fent deklarált a változó használható ezen a ponton, hiszen: a 2. blokk alárendeltje az 1. blokknak, a előbb van deklarálva mint a 2. blokk, nincs olyan blokk a kettő között, amelyben a deklarálva lenne. Ezen a ponton az 1. blokkban deklarált c változó használható. A 2. blokkban deklarált c ezen a ponton NEM használható, hiszen az 1. blokk nem alárendeltje a 2. blokknak. Így az itt leírt c az 1. blokkban deklarált c változót jelenti. Az 1. blokkban deklarált b ezen a ponton NEM használható, mert a 4. blokk ugyan alárendeltje az 1. blokknak, és később fordul elő, mint b 1. blokkbeli deklarációja, de van közben egy 3. blokk, amelynek a 4. blokk szintén alárendeltje, és amiben b szintén deklarálva van. A 3. blokkban deklarált b viszont használható, így azután a 4. blokkban leírt b a 3. blokk változóját jelenti. Programozás Alapjai (2008)

260 Blokkstruktúra a C nyelvben
Azon blokkok összességét, amelyből egy A azonosító látható, az A azonosító hatáskörének nevezzük. Egy azonosítót lokálisnak nevezünk egy blokkra nézve, ha az azonosító az adott blokkban van deklarálva. Azt mondjuk, hogy egy A azonosító globális egy B blokkra nézve, ha nem B-ben van deklarálva, de látható B-ben. Programozás Alapjai (2008)

261 Blokkstruktúra a C nyelvben
A blokkstruktúra alapján látható, hogy a C nyelvben vannak úgynevezett lokális változók, sőt általában ezeket használjuk. Látható azonban az is, hogy a programfájlban deklarált programegységek globálisak az összes függvénydeklarációra nézve, vagyis ezek minden blokkban láthatóak a deklarálásuktól kezdve az újradeklarálásukig. Ezeket csak nagyon indokolt esetben szoktuk használni. Programozás Alapjai (2008)

262 Blokkstruktúra a C nyelvben
Megjegyzések gcc-hez: A gcc néha elviseli, ha egy függvényt hamarabb használunk, mint ahogyan deklarálnánk (tehát megsértjük a sorrendiségi szabályt). A hívásból ugyanis ki tudja deríteni a paraméterek számát és típusát, a visszatérési értéket viszont ilyen esetekben int-ként kezeli. Az ansi C nem engedi meg a deklarációk és utasítások keveredését, tehát már a blokk elején deklarálni kell az összes változót. A gcc ennél rugalmasabb, már warningot is csak a –pedantic kapcsolóval ad ilyen esetekre. Programozás Alapjai (2008)

263 Programozás Alapjai (2008)
Tárolási osztályok auto Az auto az automatikus memóriafoglalásra utal. Ezt az alapszót nem szoktuk kiírni. static A lokális változó értéke megmarad a blokk végrehajtása után is és az újabb függvényművelet végrehajtásakor a megőrzött érték felhasználható. extern A programegységet csak deklaráljuk, de nem ebben a fájlban kerül definiálásra. A szerkesztőprogram feladata lesz a külső hivatkozás feloldása. Programozás Alapjai (2008)

264 Programozás Alapjai (2008)
Tárolási osztályok /* A static változót mutatjuk be. * November 7. Dévényi Károly, */ #include <stdio.h> void stat(); main() { int i; /* ciklusváltozó */ for (i = 0; i < 5; i++) { stat(); } >>> Programozás Alapjai (2008)

265 Programozás Alapjai (2008)
Tárolási osztályok void stat() { int ideiglenes = 1; static int allando = 1; printf("ideiglenes = %d allando = %d\n", ideiglenes, allando); ideiglenes++; allando++; } Programozás Alapjai (2008)

266 Programozás Alapjai (2008)
Tárolási osztályok A példaprogram ezt írja ki: ideiglenes = 1 allando = 1 ideiglenes = 1 allando = 2 ideiglenes = 1 allando = 3 ideiglenes = 1 allando = 4 ideiglenes = 1 allando = 5 Programozás Alapjai (2008)

267 Programozás Alapjai (2008)
Hanoi tornyai Problémafelvetés: Egy oszlopon egyre csökkenő átmérőjű korongok vannak. Pakoljuk át a korongokat egy másik oszlopra úgy, hogy Egyszerre csak egy korongot mozgatunk, amelyik valamelyik oszlop tetején van Nagyobb átmérőjű korong nem kerülhet kisebbre Rendelkezésre áll egy kezdetben szabad oszlop is Programozás Alapjai (2008)

268 Programozás Alapjai (2008)
Hanoi tornyai Specifikáció: Input Db pozitiv egész szám, a torony magassága Két különböző, pozitiv egész szám: Honnan és Hova (1<=Honnan, Hova<=3), melyek jelentése, hogy melyik toronyról melyik toronyra kell átpakolni. Output Egy tevékenységsorozat szövegesen, amit mechanikusan végrehajtva ténylegesen átpakolhatjuk a tornyot. Programozás Alapjai (2008)

269 Programozás Alapjai (2008)
Hanoi tornyai Algoritmustervezés: Készítsünk egy rekurzív eljárást, amelyik az N magasságú torony átpakolását visszavezeti az N-1 magasságú torony átpakolására. Az 1 magasságú torony átpakolása nem igényel előkészületet, azonnal elvégezhető. Programozás Alapjai (2008)

270 Programozás Alapjai (2008)
Hanoi tornyai Algoritmustervezés: Az N magasságú torony átpakolását visszavezetjük az N-1 magasságú torony átpakolására. Programozás Alapjai (2008)

271 Programozás Alapjai (2008)
Hanoi tornyai Megjegyzés: Mivel az X magasságú torony, amit az egyik rúdról a másikra pakolunk mindig az X legkisebb korongból áll, a harmadik rudat akkor is használhatjuk segédrúdként, ha azon van korong, mivel ez biztosan nagyobb, mint a legnagyobb, amit mi át szeretnénk pakolni. Programozás Alapjai (2008)

272 Hanoi tornyai Algoritmustervezés: void Hanoi( int N, int Rol, int Ra)
Mozgat(Rol, Ra) Hanoi(N-1,Rol,6-Rol-Ra) N-1 magas tornyot tegyük a segédre Hanoi(N-1,6-Rol-Ra,Ra) n N-1 magas tornyot tegyük a helyére Programozás Alapjai (2008)

273 Programozás Alapjai (2008)
Hanoi tornyai /* A Hanoi tornyai játék megvalósítása rekurzív eljárással. * Október 31. Dévényi Károly, */ #include <stdio.h> int Honnan; /* erről a toronyról kell átrakni */ int Hova; /* erre a toronyra */ int Db; /* a torony ennyi korongból áll */ void Mozgat(int Innen, int Ide) { /* Átrak egy korongot Innen Ide */ printf(" Tegyünk át egy korongot"); printf(" a %d. oszlopról a %d. oszlopra!\n", Innen, Ide); } >>> Programozás Alapjai (2008)

274 Programozás Alapjai (2008)
Hanoi tornyai void Hanoi(int N, /* ilyen magas a torony */ int Rol, /* erről a toronyról */ int Ra) /* erre a toronyra */ { if (N == 1) { Mozgat(Rol, Ra); } else { Hanoi(N - 1, Rol, 6 - Ra - Rol); Hanoi(N - 1, 6 - Ra - Rol, Ra); } >>> Programozás Alapjai (2008)

275 Programozás Alapjai (2008)
Hanoi tornyai main(int argc, char *argv[]) { printf("Kérem adja meg a torony magasságát: "); scanf("%d%*[^\n]", &Db); getchar(); printf("Kérem adja meg, hogy a torony hol áll? (1,2,3) "); scanf("%d%*[^\n]", &Honnan); printf("Kérem adja meg, hogy melyik oszlopra tegyük át? "); scanf("%d%*[^\n]", &Hova); if (Db > 0 && 1 <= Honnan && Honnan <= 3 && 1 <= Hova && Hova <= 3 && Honnan != Hova) { Hanoi(Db, Honnan, Hova); } else { printf("Hibás adat\n"); } Programozás Alapjai (2008)

276 Programozás Alapjai (2008)
Rekurzió Az előző példában rekurzív függvénydeklarációt láthattunk. A C nyelven bármelyik függvény lehet rekurzív illetve részt vehet rekurzív függvényrendszerben. Programozás Alapjai (2008)

277 Programozás Alapjai (2008)
Végrehajtás Az F(A1, ... ,An) függvényművelet végrehajtása sorrendben a következő tevékenységeket jelenti 1.) Memória helyfoglalás a függvényblokk paraméterei és lokális változói számára. int A(int X) { int i, k; ... i=3; k=A(X-1); X=5; } int E,F; int main() { ... E=A(E+F); } X k i E=2 E=2 F=8 F=8 Programozás Alapjai (2008)

278 Programozás Alapjai (2008)
Végrehajtás 2.) Paraméterátadás. Először tetszőleges sorrendben kiértékelődnek az aktuális paraméterek. Mivel mind értékparaméter, az i-edik kiértékelt aktuális paraméter értéke átadódik az i-edik formális paraméternek, vagyis az aktuális paraméter értéke bemásolódik a formális paraméter számára foglalt memóriahelyre. int A(int X) { int i, k; ... i=3; k=A(X-1); X=5; } int E,F; int main() { ... E=A(E+F); } X X=10 k k i i E=2 E=2 F=8 F=8 Programozás Alapjai (2008)

279 Programozás Alapjai (2008)
Végrehajtás 3.) A függvényblokk utasításrészének végrehajtása. int A(int X) { int i, k; ... i=3; k=A(X-1); X=5; } int E,F; int main() { ... E=A(E+F); } X=10 X=5 k k=34 i i=3 E=2 E=2 F=8 F=8 Programozás Alapjai (2008)

280 Programozás Alapjai (2008)
Végrehajtás 4.) A függvényblokk formális paraméterei és lokális változói számára foglalt memória felszabadítása. int A(int X) { int i, k; ... i=3; k=A(X-1); X=5; } int E,F; int main() { ... E=A(E+F); } X=5 k=34 i=3 E=2 E=65 F=8 F=8 Programozás Alapjai (2008)

281 Végrehajtás (rekurzió)
R:1-2.) Rekurzió esetén (mint bármely függvényhívásnál) ugyanezek a lépések fognak végrehajtódni, tehát minden függvényhíváshoz saját változók tartoznak. X X=9 k k int A(int X) { int i, k; ... i=3; k=A(X-1); X=5; } i int E,F; int main() { ... E=A(E+F); } i X=10 X=10 X=10 k k k i=3 i=3 i=3 E=2 E=2 E=2 F=8 F=8 F=8 Programozás Alapjai (2008)

282 Végrehajtás (rekurzió)
R:3-4.) A rekurzióból (mint bármely függvényhívásból) visszatérve az elhagyott függvény paraméterei és lokális változói szűnnek meg, majd a hívó függvény folytatódik. X=9 X=5 k k=21 i int A(int X) { int i, k; ... i=3; k=A(X-1); X=5; } i=3 int E,F; int main() { ... E=A(E+F); } X=10 X=10 X=5 k k k=34 i=3 i=3 i=3 E=2 E=2 E=2 F=8 F=8 F=8 Programozás Alapjai (2008)

283 Programozás Alapjai (2008)
Végrehajtás A C nyelven blokknak hívjuk a program {} zárójelek közötti részét is, és itt is lehet programelemeket deklarálni. Egy ilyen blokk végrehajtása a következő három tevékenységet jelenti: 1.) Memória helyfoglalás a blokk lokális változói számára. 2.) A blokk utasításrészének végrehajtása. 3.) A blokk lokális változói számára foglalt memória felszabadítása. A memória azon részét, ahol a fenti tevékenységek lezajlanak, veremnek nevezzük. Programozás Alapjai (2008)

284 Függvények mellékhatása
Függvény mellékhatásán azt értjük, hogy a függvényhívás hatására nem csak a függvényérték számítódik ki, hanem megváltozhat egy globális változó értéke is. Mellékhatás következménye, hogy az összeadás kommutativitása nem feltétlenül teljesül, ha a tagok függvényhívások. Programozás Alapjai (2008)

285 Függvények mellékhatása
Vegyük az alábbi példát int A,B,Z; int f(int x) { int r; r = x + A; A = x + 1; return r; } main () { A = 1; B = 2; Z = f(A) + f(B); /* f(A)+f(B) == 6 */ /* f(B)+f(A) == 9 */ Programozás Alapjai (2008)

286 Függvények mellékhatása
A mellékhatást kerülni kell! Egy változót tehát vagy globális változóként használjunk, vagy aktuális paraméterként, de egyszerre mindkét céllal ne! A C-ben nincs meghatározva, hogy két részkifejezés közül melyiket kell előbb kiértékelni, tehát az sem világos, hogy ha mindkettőben van függvényhívás, melyik hajtódik végre előbb. Programozás Alapjai (2008)

287 Programozás Alapjai (2008)
Függvények előnyei Függvények használata programozás során a következő előnyöket biztosítja Többszörös felhasználás. Hasonló részproblémák megoldására elég egy függvényt készíteni és a különböző adatokra végrehajtatni a részalgoritmust. Így a program méretét csökkenteni lehet. Memória igény csökkentése. Az függvények lokális változói számára csak az függvény végrehajtása idejére foglalódik memória. Függvények használatával a program áttekinthetőbb lesz. A tervezés során a részproblémák függvénnyel történő megoldása lehetővé teszi a figyelem lokalizálását. Függvények alkalmazása megkönnyíti a bizonyítást, a program tesztelését, a hibakeresést, a javítást és a program módosítását. Programozás Alapjai (2008)

288 Számlálásos ismétléses vezérlés
Számlálásos ismétléses vezérlésről beszélünk, ha olyan ismétlést írunk elő, amely szerint a ciklusmagot végre kell hajtani egy változó minden olyan értékére (növekvő vagy csökkenő sorrendben), amely egy adott intervallumba esik. Legyen a és b valamely egész érték i egész típusú változó M tetszőleges művelet Programozás Alapjai (2008)

289 Növekvő számlálásos vezérlés
Szerkezeti ábra A növekvő számlálásos ismétléses vezérlés a következő vezérlési előírást jelenti i = a -> b M i=a i <= b M i++ Programozás Alapjai (2008)

290 Növekvő számlálásos vezérlés
Szokásos elnevezések i változó, a ciklusváltozó a kifejezés, az ismétlés kezdőértéke b kifejezés, az ismétlés végértéke M utasítás (művelet), a ciklusmag i = a -> b az ismétlési előírás Fontos, hogy az M művelet nem lehet hatással az ismétlési előírás egyik elemére sem. Programozás Alapjai (2008)

291 Csökkenő számlálásos vezérlés
Szerkezeti ábra A csökkenő számlálásos ismétléses vezérlés a következő vezérlési előírást jelenti i = a <- b M i=b i >= a M i-- Programozás Alapjai (2008)

292 Csökkenő számlálásos vezérlés
Szokásos elnevezések i változó, a ciklusváltozó b kifejezés, az ismétlés kezdőértéke a kifejezés, az ismétlés végértéke M utasítás (művelet), a ciklusmag i = a <- b az ismétlési előírás Fontos, hogy az M művelet nem lehet hatással az ismétlési előírás egyik elemére sem. Programozás Alapjai (2008)

293 Programozás Alapjai (2008)
n alatt k Problémafelvetés n alatt k kiszámítása Specifikáció Input n és k nemnegatív egész számok Output n alatt k értéke Programozás Alapjai (2008)

294 Programozás Alapjai (2008)
n alatt k Algoritmustervezés Készítsünk az n alatt k kiszámolására egy függvénydeklarációt Ismeretes, hogy n alatt k = n!/(k!*(n-k)!). Nyilvánvaló, hogy nem célszerű a számolást úgy szervezni, hogy a faktoriálisokat egyenként kiszámoljuk, hiszen ezek nagy értékek lehetnek és így kiléphetünk az Integer értékkészletből. A nevező egyik tényezőjével egyszerűsítve egy törtet kapunk, amelynek a számlálója is és a nevezője is azonos számú tényezőből álló szorzat. Ez indokolja a számlálásos ismétléses vezérlés alkalmazását. Programozás Alapjai (2008)

295 Programozás Alapjai (2008)
n alatt k int nAlk(int n, int k) (n>=k) && (k>=0) i n i = 1 -> k nak = 0 nak = nak*(n-i+1) / i nak =1 return nak Programozás Alapjai (2008)

296 Programozás Alapjai (2008)
A for utasítás Ha valamilyen műveletet sorban több értékére is végre kell hajtani, akkor ezt érdemes használni. Szintaxis Kifejezés for Utasítás ( ) ; Programozás Alapjai (2008)

297 Programozás Alapjai (2008)
A for utasítás A C-ben a for utasítás általános alakja így néz ki: ami egyenértékű a alakkal. for (kif1; kif2; kif3) utasítás kif1; while (kif2) { utasítás kif3; } Programozás Alapjai (2008)

298 Programozás Alapjai (2008)
A for utasítás Többnyire kif1 és kif3 értékadás vagy függvényhívás, kif2 pedig relációs kifejezés. A három kifejezés bármelyike elhagyható, de a pontosvesszőknek meg kell maradniuk. Ha kif1 vagy kif3 marad el, akkor a ; egyszerűen elmarad a kifejtésből. Ha a kif2 vizsgálat nem szerepel, akkor állandóan igaznak tekintjük, így végtelen ciklus, amelyből más módon kell kiugrani (pl. return vagy break révén). for (;;) { /* ... */ } Programozás Alapjai (2008)

299 Programozás Alapjai (2008)
A , művelet Előfordulhat, hogy a ciklus előkészítése nem egy kifejezés kiértékeléséből áll, illetve minden egyes ciklusmenetben több adminisztrativ lépés is lehet. A for utasításban ekkor alkalmazhatjuk a , műveletet, (sequential expression) amely végülis szekvenciális vezérlést ír elő. Programozás Alapjai (2008)

300 Programozás Alapjai (2008)
A , művelet A egyenértékű a utasítással. for (kif11, kif12, kif13; kif2; kif31, kif32, kif33) { utasítás } kif11; kif12; kif13; while (kif2) { utasítás kif31; kif32; kif33; } Programozás Alapjai (2008)

301 Programozás Alapjai (2008)
A , művelet A , műveletet nyilvánvalóan a prioritási sor aljára kell helyeznünk a egyoperandusú műveletek ( -, ++, --, !, ~ ) a multiplikatív műveletek ( *, /, % ) az additív műveletek ( +, - ) bitléptetés ( <<, >> ) a kisebb-nagyobb relációs műveletek ( <=, >=, <, > ) az egyenlő-nem egyenlő relációs műveletek ( ==, != ) bitenkénti 'és' művelet ( & ) bitenkénti 'kizáró vagy' művelet ( ^ ) bitenkénti 'vagy' művelet ( | ) a logikai 'és' művelet ( && ) a logikai 'vagy' művelet ( || ) a feltételes művelet ( ? : ) értékadó művelet ( =, +=, -=, *=, /=, %=, >>=, <<=, &=, ^=, |= ) szekvencia művelet ( , ) Programozás Alapjai (2008)

302 Programozás Alapjai (2008)
Ábécé A feladat: írassuk ki felváltva az ábécé kis és nagybetűit Egy karakter tárolására C-ben a char típus használható. Programozás Alapjai (2008)

303 Programozás Alapjai (2008)
Ábécé /* Az ábécé kis- és nagybetűinek kiíratása összefésülve. * A for ciklusban a , műveletet alkalmazzuk. * November 7. Dévényi Károly, */ #include <stdio.h> main() { char cha; /* az ábécé kisbetűinek */ char chA; /* az ábécé nagybetűinek */ for ( cha = 'a', chA = 'A'; cha <= 'z'; cha++, chA++ ) { printf ( "%c%c", cha, chA ); } printf ( "\n" ); Programozás Alapjai (2008)

304 Programozás Alapjai (2008)
A for utasítás A növekvő számlálásos ismétléses vezérlés szerkezeti ábrája és megvalósítása C-ben i = a -> b M for (i = a; i <= b; ++i) { M; } Programozás Alapjai (2008)

305 Programozás Alapjai (2008)
A for utasítás A csökkenő számlálásos ismétléses vezérlés szerkezeti ábrája és megvalósítása C-ben i = a <- b M for (i = b; i >= a; --i) { M; } Programozás Alapjai (2008)

306 Programozás Alapjai (2008)
n alatt k int nAlk(int n, int k) { /* n alatt k értéke nem rekurzív függvénnyel */ int i, nak; if (n >= k && k >= 0) { /* input adatok jók-e? */ nak = 1; /* inicializálás */ for (i = 1; i <= k; i++) { /* ciklus */ nak = nak * (n - i + 1) / i; } } else { nak = 0; return nak; Programozás Alapjai (2008)

307 Programozás Alapjai (2008)
Pascal háromszög Problémafelvetés Pascal háromszög kiszámolása és megjelenítése 0 0 1 1 0 1 1 1 1 2 0 2 1 2 2 1 2 1 3 0 3 1 3 2 3 3 1 3 3 1 Programozás Alapjai (2008)

308 Programozás Alapjai (2008)
Pascal háromszög Specifikáció: Input n nemnegatív egész szám, a kiírandó sorok száma Output (n+1) db sor, rendre a Pascal háromszög sorai Algoritmustervezés: A főprogram feladata a beolvasás, input ellenőrzése, majd a nAlk függvényt alkalmas paraméterekkel aktivizálva a soronkénti kiíratás. Programozás Alapjai (2008)

309 Pascal háromszög P3szog Be(N) Kifér a képernyőre? i n Pozícionálás
Ki(nAlk(I,J)) Ki(‘Nem’) Sortörés I = 0 -> N J = 0 -> I Ki ((KepSz / 2) - (I + 1) * SZ / 2 - 1) db ‘ ‘ Programozás Alapjai (2008)

310 Programozás Alapjai (2008)
Pascal háromszög /* n alatt k értékének kiszámítása egy nemrekurzív függvénnyel és * az értékek elrendezése a Pascal háromszögben. * Október 31. Dévényi Károly, */ #include <stdio.h> #define SZAMSZ /* egy szám kiírási szélessége */ #define KEPSZ /* a képernyő szélessége */ >>> Programozás Alapjai (2008)

311 Programozás Alapjai (2008)
Pascal háromszög int nAlk(int n, int k) { /* n alatt k értékének kiszámítása nemrekurzív függvénnyel */ int i, nak; if (n >= k && k >= 0) { /* input adatok jók-e? */ nak = 1; /* inicializálás */ for (i = 1; i <= k; i++) /* ciklus */ nak = nak * (n - i + 1) / i; } else { nak = 0; } return (nak); main() { int n; /* a sorok száma */ int i, j; /* ciklusváltozók */ >>> Programozás Alapjai (2008)

312 Programozás Alapjai (2008)
Pascal háromszög printf("Kérem a Pascal háromszög sorainak számát\n"); scanf("%d%*[^\n]", &n); /* beolvasás */ getchar(); /* kifér-e a képernyőre? */ if (0 <= n && n <= KEPSZ / SZAMSZ - 2) { for (i = 0; i <= n; i++) { /* pozicionálás */ printf("%*c", KEPSZ / 2 - (i + 1) * SZAMSZ / 2 - 1, ' '); for (j = 0; j <= i; j++) { printf("%5d", nAlk(i, j)); /* kiíratás */ } putchar('\n'); } else { /* hibaüzenet */ printf("%d sor nem fér ki a képernyőre\n", n); Programozás Alapjai (2008)

313 Programozás Alapjai (2008)
Pascal háromszög Problémafelvetés Pascal háromszög kiszámolása és megjelenítése Specifikáció: Input n nemnegatív egész szám, a kiírandó sorok száma Output (n+1) db sor, rendre a Pascal háromszög sorai Programozás Alapjai (2008)

314 Programozás Alapjai (2008)
Pascal háromszög Algoritmustervezés: Készítsünk az n alatt k kiszámolására egy rekurzív függvényt. Ehhez felhasználjuk, hogy a Pascal háromszög szélén lévő érték 1, a belsejében lévő érték pedig a felete lévő két érték összege. A főprogram feladata a beolvasás, input ellenőrzése, majd a nAlk függvényt alkalmas paraméterekkel aktivizálva a soronkénti kiíratás. N-1 K-1 N-1 K N K Programozás Alapjai (2008)

315 n alatt k rekurzívan int nAlk(int n, int k) (n>=k) && (k>=0) i n
nak = 0 nak = 1 (n<=1) || (k==0) || (n==k) nak = nAlk(n-1,k-1) + nAlk(n-1,k) return nak Programozás Alapjai (2008)

316 Programozás Alapjai (2008)
Pascal háromszög /* n alatt k értékének kiszámítása egy rekurzív függvénnyel és * az értékek elrendezése a Pascal háromszögben. * Október 31. Dévényi Károly, */ #include <stdio.h> #define SZAMSZ /* egy szám kiírási szélessége */ #define KEPSZ /* a képernyő szélessége */ >>> Programozás Alapjai (2008)

317 Programozás Alapjai (2008)
Pascal háromszög int nAlk(int n, int k) { /* n alatt k értékének kiszámítása rekurzív függvénnyel */ int nak; if (n >= k && k >= 0) { /* input adatok jók-e? */ if (n <= 1 || n == k || k == 0) { /* alapesetek */ nak = 1; } else { /* rekurzív hívás */ nak = (nAlk(n - 1, k - 1) + nAlk(n - 1, k)); } } else { nak = 0; return (nak); main() { int n; /* a sorok száma */ int i, j; /* ciklusváltozók */ >>> Programozás Alapjai (2008)

318 Programozás Alapjai (2008)
Pascal háromszög printf("Kérem a Pascal háromszög sorainak számát\n"); scanf("%d%*[^\n]", &n); /* beolvasás */ getchar(); /* kifér-e a képernyőre? */ if (0 <= n && n <= KEPSZ / SZAMSZ - 2) { for (i = 0; i <= n; i++) { /* pozicionálás */ printf("%*c", KEPSZ / 2 - (i + 1) * SZAMSZ / 2 - 1, ' '); for (j = 0; j <= i; j++) { printf("%5d", nAlk(i, j)); /* kiíratás */ } putchar('\n'); } else { /* hibaüzenet */ printf("%d sor nem fér ki a képernyőre\n", n); Programozás Alapjai (2008)

319 Hurok ismétléses vezérlés
Az ismétléses vezérlésnek azt a módját, amikor a ciklusmag ismétlését a ciklusmagon belül vezéreljük, úgy, hogy ha adott feltétel, a kijárati feltétel teljesül, akkor a ciklusmag és ezzel együtt az összetett művelet végrehajtása befejeződik, hurok ismétléses vezérlésnek nevezzük. A ciklusmagban több kijárati feltételt is megadhatunk. Legyenek Fi (1<=i<=n) logikai kifejezések, Ki és Mi (0<=i<=n) pedig tetszőleges, (esetleg üres) műveletek. Programozás Alapjai (2008)

320 Hurok ismétléses vezérlés
Az Fi kijárati feltételekből, a Ki kijárati műveletekből és az Mi műveletekből képzett hurok ismétléses vezérlés a következő vezérlési előírást jelenti: 1.) A ciklusmag egységei szekvenciális vezérlést képeznek a felírásuk sorrendjében. 2.) Az ismétléses vezérlés a ciklusmag első egységének végrehajtásával kezdődik. Programozás Alapjai (2008)

321 Hurok ismétléses vezérlés
3.) A ciklusmag i-dik egységének végrehajtása azt jelenti, hogy Ha az művelet, akkor végrehajtódik a művelet, és a ciklusmag következő egysége kap vezérlést. Ha az kijárat és a kijárati feltétel igaz, akkor a Ki kijárati művelet végrehajtódik és a hurok ismétléses vezérlés végrehajtása véget ér Ha az kijárat és a kijárati feltétel hamis, akkor a kijárat hatástalan és a ciklusmag következő egysége kap vezérlést. 4.) Ha a ciklusmag utolsó egységének végrehajtása után, az az előírás, hogy a következő egység kap vezérlést, akkor a ciklusmag első egysége kap vezérlést. Programozás Alapjai (2008)

322 Hurok ismétléses vezérlés
Szerkezeti ábra M0 M1 Mn Mn-1 K1 K2 Kn F1 F2 Fn Programozás Alapjai (2008)

323 Hurok ismétléses vezérlés
Ha egyetlen Mi művelet sincs hatással egyetlen feltételre sem, akkor Vagy van olyan Fj, amelynek értéke igaz, és így az összetett művelet végrehajtása befejeződik mielőtt minden Mi művelet egyszer is végrehajtásra kerülne. Vagy az összes Fj értéke hamis, és mivel feltettük, hogy az Mi műveleteknek nincs hatása az Fj feltételekre, ezért az összes Fj értéke hamis is marad, tehát az összetett művelet végrehajtása nem tud befejeződni. Ilyenkor végtelen ciklus végrehajtását írtuk elő. Fontos tehát, hogy legyen olyan Mi, amelyik valamelyik kijárati feltételre hat. Programozás Alapjai (2008)

324 Hurok ismétléses vezérlés
A kezdő- és végfeltételes ismétléses vezérlések speciális esetei a hurok ismétléses vezérlésnek. F M Not F Programozás Alapjai (2008)

325 Legnagyobb közös osztó
Problémafelvetés: Pozitív egész számok legnagyobb közös osztójának meghatározása Specifikáció: Input Számsorozat melyet a 0 szám zár Output A számok legnagyobb közös osztója Programozás Alapjai (2008)

326 Legnagyobb közös osztó
Algoritmustervezés: Az algoritmus lényege egy olyan ismétléses vezérlés, amely ciklusmagjának egyszeri végrehajtása kiszámítja a már feldolgozott input számsor és a beolvasott következő szám legnagyobb közös osztóját. Látható, hogy a ciklusmag ismétlését célszerű a ciklusmagban vezérelni, mert az ismétlés befejeződhet úgy, hogy Végére értünk az inputnak A feldolgozott sorozat legnagyobb közös osztója 1 Programozás Alapjai (2008)

327 Legnagyobb közös osztó
Szerkezeti ábra a=LegNKO(a,b) b==0 a==1 Be(a) Ki(a) Be(b) LegNKOszt Programozás Alapjai (2008)

328 Legnagyobb közös osztó
Problémafelvetés Legnagyobb közös osztó kiszámítása Specifikáció Függvényműveletet készítünk Input x és y nemnegatív egész számok (bemenő argumentumok) Output Az LegNKO függvényművelet int típusú eredményt szolgáltat Tehát int LegNKO(int x, int y) Programozás Alapjai (2008)

329 Legnagyobb közös osztó
Algoritmustervezés Euklidesz algoritmusát valósítjuk meg. Mivel LegNKO(x,0)=x, így a következő algoritmus a probléma megoldását adja. A ciklusmag helyes megoldása biztosítja, hogy az ismétlés véges sok lépésben befejeződik. Programozás Alapjai (2008)

330 Legnagyobb közös osztó
Szerkezeti ábra m = x % y return x int LegNKO(int x, int y) y!=0 x = y y = m x módosítása és y csökkentése úgy, hogy LegNKO(x,y) értéke ne változzon és y maradjon nem negatív Programozás Alapjai (2008)

331 Legnagyobb közös osztó
A ciklusmag kivitelezéséhez vegyük figyelembe: LegNKO(x,y) = LegNKO(y,x % y), ha y>0 Ugyanis a % és / műveletek definíciója miatt x = y * (x / y) + x % y Tehát, Ha d osztója x-nek és y-nak, akkor osztója (x % y)-nak is Ha d osztója y-nak és (x % y)-nak, akkor x-nek is, Továbbá 0 <= (x % y) < y Ha a ciklusmagot így finomítjuk, akkor a megfogalmazott feltételek teljesülnek. Programozás Alapjai (2008)

332 Hurok vezérlés megvalósítása #1
A C nyelvben nincs olyan vezérlési forma, amellyel közvetlenül megvalósíthatnánk a hurok ismétléses vezérlést, de a kezdőfeltételes ismétléses vezérlés felhasználásával megtehetjük. A megvalósítás lényege, hogy választunk egy logikai változót (legyen az a tovabb), ez lesz az ismétlés feltétele és a ciklusmagban a feltételes kijáratokat úgy alakítjuk át, hogy Ha a feltétel igaz, akkor a tovabb hamis értéket kap Egyébként végrehajtódik a ciklusmag további része Programozás Alapjai (2008)

333 Hurok vezérlés megvalósítása #1
A LNKOszt algoritmusban szereplő hurok ciklus tehát a következőképpen valósítható meg tovabb Be(B) B==0 i n tovabb=false A=LegNKO(A,B) A==1 tovabb=true Programozás Alapjai (2008)

334 Legnagyobb közös osztó #1
/* Pozitív egész számok legnagyobb közös osztójának meghatározása. * A hurok ismétléses vezérlés megvalósítása break utasítással. * November 7. Dévényi Károly, * Augusztus 8. Gergely Tamás, */ #include <stdio.h> >>> Programozás Alapjai (2008)

335 Legnagyobb közös osztó #1
int LegNKO(int x, int y) { /* x és y legnagyobb közös osztójának meghatározása * Euklidesz algoritmusával. */ int m; while (y != 0) { m = x % y; x = y; y = m; } return x; >>> Programozás Alapjai (2008)

336 Legnagyobb közös osztó #1
main() { int a, b; int tovabb; /* logikai változó a ciklus megvalósításához */ printf("A program pozitív egész számok legnagyobb\n"); printf("közös osztóját számítja.\n"); printf("Kérem a számok sorozatát, amit 0 zár!\n"); printf("? "); scanf("%d%*[^\n]", &a); getchar(); >>> Programozás Alapjai (2008)

337 Legnagyobb közös osztó #1
tovabb = !0; while (tovabb) { /* a hurok ciklus kezdete */ printf("? "); scanf("%d%*[^\n]", &b); getchar(); if (b == 0) { /* első kijárat */ tovabb = 0; } else { a = LegNKO(a, b); if (a == 1) { /* második kijárat */ } } /* a hurok ciklus vége */ printf(" A számok legnagyobb közös osztója: %d\n",a); Programozás Alapjai (2008)

338 Hurok vezérlés megvalósítása #2
A hurok ismétléses vezérlés második megvalósítása a C nyelv break utasítását használja. A break utasítás „megtöri” az aktuális ismétléses (vagy mint láttuk, esetkiválasztásos szelekciós) vezérlést, és a vezérlési szerkezet utáni első utasításnál folytatja a programot. Programozás Alapjai (2008)

339 Hurok vezérlés megvalósítása #2
Mn Mn-1 K1 K2 Kn F1 F2 Fn while (1) { M0; if (F1) { K1; break; } M1; ... if (Fn) { Kn; break; } Mn; Programozás Alapjai (2008)

340 Hurok vezérlés megvalósítása #2
végtelen ciklus helyett alkalmazhatjuk a végtelen ciklus utasítást is. while (1) {} for (;;) {} Programozás Alapjai (2008)

341 Legnagyobb közös osztó #2
/* Pozitív egész számok legnagyobb közös osztójának meghatározása. * A hurok ismétléses vezérlés megvalósítása break utasítással. * November 7. Dévényi Károly, */ #include <stdio.h> >>> Programozás Alapjai (2008)

342 Legnagyobb közös osztó #2
int LegNKO(int x, int y) { /* x és y legnagyobb közös osztójának meghatározása * Euklidesz algoritmusával. */ int m; while (y != 0) { m = x % y; x = y; y = m; } return x; >>> Programozás Alapjai (2008)

343 Legnagyobb közös osztó #2
main() { int a, b; printf("A program pozitív egész számok legnagyobb\n"); printf("közös osztóját számítja.\n"); printf("Kérem a számok sorozatát, amit 0 zár!\n"); printf("? "); scanf("%d%*[^\n]", &a); getchar(); >>> Programozás Alapjai (2008)

344 Legnagyobb közös osztó #2
while (1) { /* a hurok ciklus kezdete */ printf("? "); scanf("%d%*[^\n]", &b); getchar(); if (b == 0) { /* első kijárat */ break; } a = LegNKO(a, b); if (a == 1) { /* második kijárat */ } /* a hurok ciklus vége */ printf(" A számok legnagyobb közös osztója: %d\n",a); Programozás Alapjai (2008)

345 Programozás Alapjai (2008)
break, continue A C nyelvben a ciklusmag folyamatos végrehajtásának megszakítására két utasítás használható: break Megszakítja a ciklust, a vezérlés a ciklusmag utáni első utasítással foglalkozik continue Megszakítja a ciklus aktuális lefutását, a vezérlés a ciklus feltételének kiértékelésével folytatódik Programozás Alapjai (2008)

346 Diszkrét ismétléses vezérlés
Diszkrét ismétléses vezérlésről beszélünk, ha azt a vezérlési előírást tesszük, hogy az x ciklusváltozó egy adott H véges halmaz minden elemét tetszőleges sorrendben felvéve hajtsuk végre az M ciklusmagot. Programozás Alapjai (2008)

347 Diszkrét ismétléses vezérlés
Fontos, hogy az M művelet nem lehet hatással az ismétlési előírás egyik elemére sem. A H halmaz számossága határozza meg tehát, hogy az M művelet hányszor hajtódik végre. Ha a H az üres halmaz, akkor a diszkrét ismétléses vezérlés az M művelet végrehajtása nélkül befejeződik. Programozás Alapjai (2008)

348 Diszkrét ismétléses vezérlés
x in H M A diszkrét ismétléses vezérlésnek nincs közvetlen megvalósítása a C nyelvben. Programozás Alapjai (2008)

349 Diszkrét vezérlés megvalósítása
A megvalósítás elsősorban attól függ, hogy az ismétlési feltételben megadott halmazt hogyan reprezentáljuk. Algoritmustervezés során szabadon használjuk a diszkrét ismétléses vezérlést, ha erre van szükség a probléma megoldásához. A halmaz reprezentálásáról pedig akkor döntsünk, amikor elegendő információ áll rendelkezésünkre, hogy a legmegfelelőbbet kiválaszthassuk. Programozás Alapjai (2008)

350 Programozás Alapjai (2008)
Folyamatábra Szerkezeti ábrával az algoritmusok tervezése során a lépésenkénti finomításokat és a kifejlesztett algoritmust egyaránt kifejezhetjük. Ha csak a kész algoritmus vezérlési szerkezetét akarjuk leírni, akkor használhatjuk a folyamatábrát, mint leíró nyelvezetet. Ez olyan ábra, amelyben az algoritmus egyes lépéseit és a lépések közötti vezérlési viszonyt szemléltethetjük irányított vonalakkal. Programozás Alapjai (2008)

351 Programozás Alapjai (2008)
Folyamatábra Legyen M={M1, ... ,Mk} műveletek és F={F1, ... ,Fl} feltételek. Az (M,F) feletti folyamatábrán olyan irányított gráfot értünk, amelyre teljesül a következő 5 feltétel: 1.) Egy olyan pontja van, amely a Start üres művelettel van címkézve és ebbe a pontba nem vezet él. 2.) Egy olyan pontja van, amely a Stop üres művelettel van címkézve és ebből a pontból nem indul él. Programozás Alapjai (2008)

352 Programozás Alapjai (2008)
Folyamatábra 3.) Minden pontja M-beli művelettel vagy F-beli feltétellel van címkézve, kivéve a Start és a Stop pontokat. 4.) Ha egy pont M-beli művelettel van címkézve, akkor belőle egy él indul ki F-beli feltétellel van címkézve, akkor belőle két él indul ki és ezek az i(igen) illetve n(nem) címkét viselik 5.) A gráf miden pontja elérhető a Start címkéjű pontból. Programozás Alapjai (2008)

353 Programozás Alapjai (2008)
Folyamatábra Egy folyamatábra a következő összetett vezérlési előírást jelenti i.) A végrehajtás a Start pontból indul. Az összetett művelet végrehajtása akkor ér véget, ha a Stop pont kap vezérlést. ii.) A gráf egy pontjának végrehajtása azt jelenti, hogy Ha a pontban M-beli művelet van, akkor a művelet végrehajtódik és a vezérlés a gráf azon pontjára kerül, amelybe a pontból kiinduló él vezet Ha a pont F-beli feltétellel van címkézve, akkor kiértékelődik a feltétel. Ha értéke igaz, akkor az a pont kap vezérlést, amelybe az i(igen) címkéjű él vezet, egyébként az a pont kap vezérlést, amelybe az n(nem) címkéjű él vezet. Programozás Alapjai (2008)

354 Programozás Alapjai (2008)
Folyamatábra Példa M={M1, M2} F={F1} M1 Stop Start M2 F1 i n Programozás Alapjai (2008)

355 Folyamatábra és struktúradiagram
Nevezzük szabályosnak az eddig bevezetett vezérlési módokat, ezen belül alapvetőnek a szekvenciális, egyszerű szelekciós és a kezdőfeltételes ismétléses vezérlést. Beláttuk, hogy a szabályos vezérlési módok megvalósíthatók az alapvető vezérlési módokkal. Programozás Alapjai (2008)

356 Folyamatábra és struktúradiagram
Az alapvető vezérlési módokat használó algoritmusok kifejezhetők folyamatábrával is. M1 Stop Start Mn i n F Stop Start A B i n F Stop Start M Programozás Alapjai (2008)

357 Folyamatábra és struktúradiagram
Megmutatjuk, hogy fordítva is igaz, tehát a folyamatábrával leírt algoritmusok megadhatók szabályos és így alapvető vezérlési módokat használva, feltéve, hogy bevezethetünk egész típusú segédváltozót. Programozás Alapjai (2008)

358 Folyamatábra és struktúradiagram
Legyen G egy folyamatábra (M,F) felett, amely pontjainak száma n. Sorszámozzuk meg a gráf pontjait úgy, hogy a Start pont sorszáma 1 és a Stop pont sorszáma n legyen. Vegyünk fel egy olyan új egész típusú változót. Legyen ennek az azonosítója pont. Programozás Alapjai (2008)

359 Folyamatábra és struktúradiagram
Tekintsük az alábbi C programot { pont = 1; while (pont != n) { switch (pont) { case 1 : U1; break; ... case n-1: Un-1; break; case n : /* Stop */ break; } /* switch */ } Programozás Alapjai (2008)

360 Folyamatábra és struktúradiagram
Ahol az Ui utasítás: Ha az i. pontban az Mi művelet volt és a belőle kiinduló él a j. pontba vezetett: Ha az i. pontban az Fi feltétel volt és az igennel címkézett él a j., a nemmel címkézett él pedig a k. pontba vezetett Az így megalkotott program a G folyamatábrával adott algoritmussal ekvivalens algoritmus kódolása lesz. { Mi; pont = j; } { if (Fi) { pont = j; } else { pont = k; } } Programozás Alapjai (2008)


Letölteni ppt "Programozás alapjai A C nyelv."

Hasonló előadás


Google Hirdetések