Vezérlési szerkezetek Szelekció Ciklusok
Szelekciós vezérlés A program egy feltétel teljesülése alapján választja ki, hogy mely műveleteket hajtsa végre. Alakja: if ( feltétel ) { műveletek, ha feltétel teljesül (igaz) A else { műveletek, ha feltétel nem teljesül (hamis) B Az else ág opcionális.
Feltétel A feltétel Igaz Hamis A feltétel egy logikai kifejezés. Ezt a program a szelekciós vezérlőszerkezet végrehajtásakor kiértékeli, és ha a kiértékelés eredménye igaz, az if, ha hamis, az else ágat hajtja végre (ha van). Logikai kifejezés: logikai változók/értékek és logikai operátorok Nincs logikai típus, egész típusokban tárolhatunk logikai értékeket: a 0 jelenti a hamisat, a nem nulla pedig az igazat. A B
C operátorok (nem teljes) a és b értékek: változók, konstansok, valamilyen művelet vagy függvény eredményei, vagy literálok (literál: helyben definiált adat, pl. 5, vagy 'A') a == b a < b a > b a <= b a >= b a!= b!a a && b a b - a egyenlő-e b-vel - a kisebb-e b-nél - a nagyobb-e b-nél - a kisebb-egyenlő-e b-nél - a nagyobb-egyenlő-e b-nél - a nem egyenlő-e b-vel - a kifejezés értéke NEM a, (igaz, ha a hamis) - a kifejezés értéke a ÉS b (igaz, ha a és b is igaz) - a kifejezés értéke a VAGY b (igaz, ha a és b közül legalább az egyik igaz)
Feladat: Készíts egy programot, ami bekér egy egész számot és kiírja, hogy az adott szám páros vagy páratlan-e. #include <stdio.h> int main() { int x; printf("kérek egy egész számot:"); scanf("%d", &x); if (x%2 == 0) // látható, hogy elhagyható a { printf("a megadott szám páros.\n"); else printf("a megadott szám páratlan.\n"); return 0;
Feladat: Módosítsuk most a programot úgy, hogy két egész számot kérjen be a program majd írja ki, hogy az első szám osztható-e a másodikkal (osztoja.c)! #include <stdio.h> int main() { int x,y; printf("kérek egy egész számot:"); scanf("%d", &x); printf("kérek egy másik egész számot:"); scanf("%d", &y); Mi történik, ha a 2. szám nulla? if (x % y!= 0) { printf("%d nem osztója %d-nek.", y, x); else { printf("%d osztója %d-nek.", y, x); return 0;
Javítsuk! Írjuk meg többszörös szelekcióval is! #include <stdio.h> int main() { int x,y; printf("kérek egy egész számot:"); scanf("%d", &x); printf("kérek egy másik egész számot:"); scanf("%d", &y); Mi történik, ha elrontjuk a feltételt? (y=0) Mit mond a Wall kapcsolóval a fordító? if (y==0) { printf("nullával nem osztunk!\n"); else { if (x % y!= 0) { printf("%d nem osztója %d-nek.", y, x); else { printf("%d osztója %d-nek.", y, x); return 0; Egymásba ágyazhatóak!
Lusta kiértékelés Logikai kifejezések esetében, ha az eddig megvizsgált tagok alapján egyértelmű a kifejezés eredménye (pl. && esetén, van egy hamis tag, akkor az eredmény biztosan hamis), akkor nem vizsgálja azt tovább, így a benne ezután meghívott függvényeket sem hajtja végre.
Használjuk ki a lusta kiértékelést, és írjuk meg a programot if-else nélkül! #include <stdio.h> int main() { 1. Ha 0!= y igaz, akkor az egész int x,y; kifejezés igaz, printf nem fut le printf("kérek egy egész számot:"); scanf("%d", &x); printf("kérek egy másik egész számot:"); scanf("%d", &y); (0!= y) printf("nullaval nem osztunk!\n"); (0!= y) && (x % y == 0) && printf("%d osztója %d-nek.", y, x); (0!= y) && (x % y!= 0) && printf("%d nem osztója %d-nek.", y, x); return 0; 2. - 3. Ha 0!= y hamis, akkor az egész kifejezés hamis, nem hajtódik végre az osztás (nullával osztás nem lesz hiba!), illetve a printf se fut le
Feltételes kifejezések Az if-else helyett feltételes kifejezések is használhatók. Tömörebb formában fogalmazható meg ugyanaz. Egy adott helyre behelyettesítendő érték kiválasztására is használható. Alakja: feltétel? művelet ha igaz : művelet ha hamis;
Feladat: Írjuk ki egyetlen printf segítségével, hogy egy szám páros vagy páratlan-e! #include <stdio.h> int main() { int x; printf("kérek egy egész számot: "); scanf("%d", &x); printf("a szám %s.\n", (x%2 == 0)? "páros" : "páratlan"); return 0;
F: Írjuk ki egyetlen printf használatával, hogy egy szám osztója-e egy másiknak. #include <stdio.h> int main() { int x, y; printf("kérek egy egész számot: "); scanf("%d", &x); printf("kérek egy másik egész számot: "); scanf("%d", &y); printf("osztoja-e %d-nek %d?. %s\n", x, y, (y==0)? "A kerdes ertelmetlen!" : ((x%y==0)? "Igen, osztója." : "Nem, nem osztója.")); return 0;
Esetkiválasztásos szelekciós vezérlés Az if-else if (többszörös szelekciós vezérlés) helyett használható, annál átláthatóbb és gyorsabb szerkezet. Akkor alkalmazható, ha a feltétel egy egész változó értékén alapul. Több lehetséges értéket definiálhatunk, és mindegyik esetében megadhatunk végrehajtandó műveleteket. Alakja: switch ( egész_érték ) { case címke : műveletek; break; case címke : műveletek; break;... case címke : műveletek; break; default : műveletek; break; K? H1 H2 Hn A1 A2 An B
Esetkiválasztásos szelekciós vezérlés Az "egész_érték": változó vagy függvényhívás Címkék: egész értékként felfogható konstansok vagy literálok (változók nem). Karakterek: ASCII kódjukkal tárolódnak egészek A default címke akkor hajtódik végre, ha egyik case után megadott címke se teljesül. A default elhagyható és a switchen belül bárhova áthelyezhető. A break; utasítás kiugrasztja a switchből a vezérlést, ha kihagyjuk, az a következő címkére kerül.
F: írjunk egy függvényt, ami egy "x" egész számot kap paraméterként és kiírja, hogy a hét x. napja milyen nap. void hetnapja_switch (short int x) { switch (x) { case 1: printf("hétfő\n"); break; case 2: printf("kedd\n"); break; case 3: printf("szerda\n"); break; case 4: printf("csütörtök\n"); break; case 5: printf("péntek\n"); break; case 6: printf("szombat\n"); break; case 7: printf("vasárnap\n"); break; default: printf("hiba! x értéke legalább 1 és legfeljebb 7 lehet!\n");
Feladatok: Kérdés: Hogyan kéne módosítani a függvényt akkor, ha számok helyett a napok kezdőbetűit szeretnénk használni? Kérdés: Működne-e ugyanez akkor, ha egész v. karakter típusú változó helyett pl. float vagy double típusú változó lenne a switch feltételében? F: próbáld ki! módosítsd a paraméter típusát 'unsigned int'- ről 'float'-ra, készíts egy main fgvt, ami meghívja a hetnapja_switch(4.0)-t. F: nézzük meg mi történik, akkor ha elhagyjuk a csütörtök és a péntek napok után a break utasítást. a korábban elkészített main függvényünkben hívjuk most meg a hetnapja_switch függvényt a 4,5 és 6 paraméterekkel. F: Írjuk meg a függvényt úgy, hogy a napok kezdőbetűjét fogadja! Működjön kis- és nagybetűkkel is!
Feladatok szelekcióra Írj egy programot, ami egy évszámról eldönti, hogy szökőév-e! (if) Írj egy programot, ami bekéri egy dolgozat lehetséges maximális és aktuális pontszámát, majd kiírja, hogy a dolgozat sikeres vagy sikertelen volt! A dolgozat akkor sikeres, ha az aktuális pontszám legalább a maximális pontszám fele. (felt. kif) Írj egy programot, ami a hónap sorszáma alapján kiírja a hónap nevét! (switch)
Kezdőfeltételes ismétléses vezérlés Más néven előltesztelős ciklus, vagy while-ciklus Ha egy műveletet addig kell ismételgetni, amíg valamilyen feltétel fennáll A műveletek végrehajtása előtt ellenőrzi, hogy el kell-e őket végezni, így előfordulhat az is, hogy egyszer sem fut le a ciklus törzse. Alakja: while ( feltétel ) { műveletek; Ahol a feltétel logikai kifejezés.
While ciklus Működése: 1. Feltétel kiértékelése 2. ha hamis: a ciklushoz tartozó blokk utáni első utasításra ugrik ha igaz: végrehajtja a műveleteket a blokkban, majd ugrás az 1. pontra FONTOS, hogy a feltétel egyszer hamissá váljon, különben végtelen ciklust kapunk, ami soha nem áll meg. Ilyenkor a program 100%-os processzorterhelés mellett nem csinál semmit. F M
F: írjunk egy programot, ami kiírja 1-től 10-ig számokat. #include <stdio.h> int main() { int i; i=1; while (i<=10) { printf("%d\n", i); i += 1; return 0;
F: Írjunk olyan prgramot, ami addig kér be számokat a billentyűzetről, amíg a beírt szám nem 0! (0 az adott végjel) #include <stdio.h> int main() { int x; printf("kérek egy számot (kilépéshez: 0):"); scanf("%d", &x); while (x!=0) { printf("kérek egy számot (kilépéshez: 0):"); scanf("%d", &x); return 0;
F: Módosítsuk a programot úgy, hogy végeredményként írja ki a beírt számok összegét! #include <stdio.h> int main() { int x, osszeg = 0; printf("kérek egy számot (kilépéshez: 0):"); scanf("%d", &x); while (x!=0) { osszeg+=x; printf("kérek egy számot (kilépéshez: 0):"); scanf("%d", &x); printf("a számok összege: %d\n", osszeg); return 0;
F: Módosítsuk a programot úgy, hogy végeredményként írja ki a beírt számok összegét! #include <stdio.h> int main() { int x, osszeg = 0; while (1) { printf("kérek egy számot (kilépéshez: 0):"); scanf("%d", &x); if (x==0) { break; else { osszeg+=x; printf("a számok összege: %d\n", osszeg); A switch-nél látott break; utasítás ciklusokból való "kitörésre" is alkalmazható. Végtelen ciklus!! Egy feltétel alapján kilépünk vagy folytatjuk! return 0; hurok ismétléses vezérlés
Végfeltételes ismétléses vezérlés hátultesztelős ciklus, vagy do-while-ciklus Ha addig kell ismételgetni a műveletet, amíg egy feltétel nem teljesül. "hátultesztelős": mindig a műveletek végrehajtása után ellenőrzi, hogy el kell-e őket végezni újból, így a ciklus törzse legalább egyszer mindig lefut. A C nyelvben egy módosított verzió található: a "sima" while-ciklushoz hasonlóan addig ismétel, amíg az ismétlési feltétel igaz marad. Alakja: do { műveletek; while ( feltétel ); Feltétel: logikai kifejezés. Pontosvesszőt kell írni a végére!!
Do-while ciklus Működése: 1. Műveletek végrehajtása 2. Feltétel kiértékelése 3. ha hamis: kiugrás a ciklusból ha igaz: ugrás az 1. pontra F M Tehát egész addig ismételgeti a műveleteket, amíg a feltétel igaz marad.
F: Írjunk egy olyan programot 'do-while' ciklus segítségével, ami 0 végjelig kér be számokat, majd kiírja azok összegét. A ciklusban ne szerepeljen a 'break' utasítás. #include <stdio.h> int main() { int x; int osszeg = 0; do { printf("kérek egy számot (kilépéshez: 0):"); scanf("%d", &x); osszeg += x; while (x!= 0); printf("a számok összege: %d\n", osszeg); return 0; Miért dolgozhatjuk fel a végjelet?
Számlálásos ismétléses vezérlés for-ciklus. Ha egy műveletet egy bizonyos darab ismétléssel kell végrehajtani. Alakja: for ( értékadó_kifejezés_1; feltétel; értékadó_kifejezés_2 ) { műveletek; Az értékadó kifejezések: több is lehet. A ciklusváltozót manipuláljuk: az elsővel a kezdőértéket állítjuk be, míg a másodikkal a számláló növelését, ill. csökkentését végezzük. A feltétellel (logikai kifejezés) általában azt ellenőrizzük, hogy elértee már a számláló a végértéket. A ciklus fejlécében lévő utasítások közül egyiket sem kötelező megadni, de a pontosvesszőket ki kell írni.
For-ciklus i:= a->b Működése: 1. Az első értékadó kifejezés végrehajtása (inicializálás) 2. Feltétel kiértékelése 3. ha hamis: kiugrás a ciklusból ha igaz: műveletek végrehajtása 4. a második értékadó kifejezés végrehajtása (számlás) 5. ugrás a 2. pontra M
Inkrementálás, dekrementálás A++; A = A + 1; (avagy A += 1;) A--; A = A - 1; (avagy A -= 1;) Postfix és prefix alakban is használhatóak, jelentésük kicsit különböző: B = A++; 1. B = A; 2. A = A + 1; Tehát B A korábbi értékét kapja. B = ++A; 1. A = A + 1; 2. B = A; Tehát B A megnövelt értékét kapja meg. Ugyanez érvényes a -- operátorra is. A for-ciklushoz (a 2. értékadó művelet helyén) MINDEGY melyik verziót használjuk.
F: Írjunk egy programot, ami összeszorozza 1-10-ig a számokat. #include <stdio.h> int main() { int i; int szorzat; for (i=1, szorzat=1; i<=10; ++i) { szorzat*=i; printf("a számok szorzata: %d\n", szorzat); return 0; Hogyan nézne ki ugyanez a program while ciklussal?
F: Módosítsuk a for ciklust úgy, hogy csak minden 3-mal osztható számot szorozzon össze! #include <stdio.h> int main() { int i; int szorzat; for (i=3, szorzat=1; i<=10; i+=3) { szorzat*=i; printf("a számok szorzata: %d\n", szorzat); return 0;
Feladatok F: Próbáljuk ki mit csinál az alábbi for ciklus: int i,j,out; for (i=1, j=100, out=0; i<=10; i++, j--) out+=i*j; (Módosítsuk a ciklusmagot úgy, hogy egy printf segítségével kiírjuk az i,j és out aktuális értékét.) K: Mi a, művelet eredménye? a=(1,2,3,4)? K: Mit csinál az a = 4, b = a + 3, c = b * 2 + 1; utasítás? Melyik kifejezéseket értékeli ki, milyen sorrendben és mi lesz a kifejezés értéke?
Feladatok Olvass be a 0 végjelig pozitív egész számokat! Írd ki a beolvasott számok összegét és átlagát! (while, dowhile) Írj programot, amelyben a felhasználónak egy, a program által meghatározott számot kell kitalálnia! A felhasználó tippjét a program vagy elfogadja, vagy megmondja, hogy a gondolt szám annál kisebb vagy nagyobb, és kéri a következő tippet! (while, hurok) (véletlen-generálás: http://cplusplus.com/reference/clibrary/cstdlib/ra nd/) Írj egy programot ami bekér egy n számot, majd kiírja az n! értékét! (for)
Kérj be folyamatosan karaktereket addig, amíg egy '#' jelet nem kapsz. Ha megkaptad a végjelet, akkor írd ki, hogy addig hány kisbetűt, nagybetűt, és hány számot olvastál! Írj programot, mely bekéri a hónap sorszámát és a napot, és megállapítja, hogy helyes-e! (switch) Számítsuk ki a fogyasztás és a hónap alapján az adott hónapban fizetendő gázárat, ha tudjuk, hogy a gázár sávosan változik: (1) az első 1000 egység ára 100/egység; (2) a második 1000 egység ára már 200/egység; (3) egyébként a gázár 300/egység; és (4) a téli hónapokban (nov, dec, jan, feb) a gázárat 1.2 -vel szorozzák. A húsvét vasárnap dátumát a níceai zsinat a következőképpen határozta meg: a tavaszi napéjegyenlőséget követő első holdtölte utáni első vasárnap. A dátum március 22-e és április 25-e között változhat. A dátum meghatározására alkalmas a következő algoritmus: Jelölje T az évszámot (1800<=T<=2099). Kiszámítjuk a következő osztási maradékokat: A = T / 19 maradéka B = T / 4 maradéka C = T / 7 maradéka D = ( 19 * A + 24 ) / 30 maradéka E = ( 2 * B + 4 * C + 6 * D + 5 ) / 7 maradéka Ezekből a húsvét vasárnap dátuma: H = 22 + D + E ami márciusi dátum, ha H <= 31, különben áprilisban H-31-e. Két kivétel van: ha E = 6 és D = 29, akkor H = 50, ha E = 6 és D = 28 és A > 10, akkor H = 49. Készítsünk függvényt, amely bekér egy évszámot, és meghatározza, majd kiírja a húsvét vasárnap dátumát!
Házi feladat 1. csoport - feltételes műveletek A számolásokat úgy oldd meg, hogy 1-1 külön függvényben megoldod iffel, feltételes kifejezéssel, illetve switch-csel, majd ezt a 3 függvényt a mainben meghívod. A beolvasás és a kiírás a mainben legyen, ha megoldható! Olvass be egy karaktert! Döntsd el és írd ki, hogy kis-, nagybetűt, számot vagy egyéb karaktert olvastál-e be! Írj egy programot ami egy jegyhez (osztályzathoz) megadja a szöveges értékelést, vagy kiírja, ha rossz értéket kapott! (1 - elégtelen, 2 - elégséges, 3 - közepes, 4 - jó, 5 - kiváló) Írj egy programot ami leosztályoz egy maximálisan 100 pontos dolgozatot az 50,65,80,90 ponthatárok szerint! A határérték a jobb jegyhez tartozik. Ha a pontszám negatív vagy száznál nagyobb, akkor írja ki, hogy hibás az adat! 2. csoport - ciklusok A számolásokat úgy oldd meg, hogy 1-1 külön függvényben megoldod while-lal, do-while-lal, illetve forral, majd ezt a 3 függvényt a mainben meghívod. A beolvasás és a kiírás a mainben legyen, ha megoldható! Írj egy programot ami bekér egy n nemnegatív számot, majd 1-től n-ig kiírja a páros számok négyzetét! - Írj egy programot ami kiírja 1-től 12-ig az n! értékét! Írj programot, ami kiírja az első 1000 szám közül a prímeket!
Puzzle Írj egy programot, ami kiszámítja és kiírja a következő N összeget (összegenként külön sorba): 1, 1+2, 1+2+3,..., 1+2+3+...+N. Az N értékét kérd be a felhasználótól! A main-ben csak egyetlen ciklust használhatsz! A kiíratás formátuma legyen minden sorban: N aktuális értéke összeg