Programozás alapjai 3.Gy: C elágazások, ciklusok. P R O A L A G 1/39 B ITv: MAN 2018.10.08
Kövessük a kódot 1. 2. 3. 4. 5. 6. 7. 8. 9. void main() { int a, b, seged; printf("\nkerek ket egesz szamot: "); scanf("%d, %d", &a, &b); seged=a; a=b; b=seged; printf("\ncsere utan: a=%d, b=%d\n", a, b); Csere algoritmus. Akkor alkalmazzuk, ha két változó értékét fel kell cserélni. 2/39
Kövessük a kódot? int a; printf("\nkérek egy egész számot: "); scanf("%d", &a); printf( (a % 2 == 0)? " páros" : " páratlan" ); a%2 az a osztva 2-vel osztási maradéka Logikai vizsgálatban az egyenlőséget 2 db = jellel adjuk meg: a%2 == 0 printf( (a%2 == 0)? a : b ); Értelmezése: ha a kisebb b állítás igaz, akkor kiírja a-t, egyébként kiírja b-t. Logikai vizsgálat 3/39 2 lehetséges kimenetet jelző operátor Igaz kimenethez tartozó érték Hamis kimenethez tartozó érték 2 kimenetet elválasztó operátor
Kövessük a kódot? int a; printf("\nkérek egy egész számot: "); scanf("%d", &a); if (a%2) printf(" páratlan\n"); else printf(" páros\n" ); a%2 az a osztva 2-vel osztási maradéka, értéke lehet 0 vagy 1 A C nyelvben egy logikai állítás ha igaz, akkor annak a program által kiértékelt értéke 1, ha hamis, akkor annak értéke 0. Az if (a%2) kódot kb. így lehet értelmezni: ha a-t 2-vel elosztva 1-et kapok (vagyis igaz értéket), akkor írd ki hogy páratlan, egyébként írd ki, hogy páros 4/39
Kövessük a kódot? int a; printf("adj meg egy számot: "); scanf("%d", &a); switch(a%2) { case 0: printf("páros.\n"); break; case 1: printf("páratlan.\n"); break; switch(kifejezés) Sok lehetséges kimenetelű elágazás case érték: utasítás; break; Egy lehetséges kimenet leírása. A break hatására lép ki a vezérlés a switch utasításból! Az érték típusának meg kell egyeznie a kifejezés típusával (itt egész szám) 5/39
Kövessük a kódot 1. 2. 3. char k; printf("add meg a kódot! (A,B,C): "); k = getchar(); switch(k) { case 'A': printf("alma"); break; case 'B': printf("banán"); break; case 'C': printf("citrom"); break; default : printf ("Érvénytelen kód!"); default Ha egy érték sem egyezik meg a kifejezés értékével, akkor ez lesz az eredmény. Nem kötelező használni. 6/39
Kövessük a kódot 1. 2. 3. char k; printf("add meg a kódot! (A,B,C): "); k = getchar(); switch(k) { case 'A': printf("alma"); case 'B': printf("banán"); case 'C': printf("citrom"); default : printf ("Érvénytelen kód!"); Ha lemaradnak a break utasítások, akkor a belépési pont utáni összes utasítást végrehajtja a program! 7/39
Ciklusszervezés Egy vagy több művelet ismétlését nevezzük ciklusnak. Az ismétlődés addig tart, amíg ezt valamilyen feltétel teljesülése meg nem állítja. Három ciklusképző utasítás van a C-ben: while elöltesztelő for taxatív (számláló) do while hátultesztelő 8/39
While ciklus while (kifejezés) { ciklusmag Amíg (a kifejezés igaz) { hajtsd végre a ciklusmag utasításait 9/39
While ciklus Összegezzük a számokat 1 és N között. N értékét olvassuk be! Használjuk a while ciklust! int N, i, sum=0; printf("\nszámok összegzése 1-N-ig"); printf("\nkérem N értékét: "); scanf("%d", &N); i=1; while (i<=n) { sum = sum+i; i = i+1; printf("\nösszeg: %d\n", sum); 10/39
While ciklus Profi módon Összegezzük a számokat 1 és N között. N értékét olvassuk be! Használjuk a while ciklust! int N, i, sum=0; printf("\nszámok összegzése 1-N-ig"); printf("\nkérem N értékét: "); scanf("%d", &N); i=1; while (i<=n) { sum += i; i++; sum = sum+i; i = i+1; printf("\nösszeg: %d\n", sum); 11/39
do while ciklus Mivel hátul tesztelő ciklus, egyszer mindenképpen lefut! do { ciklusmag while (kifejezés); Hajtsd végre a ciklusmag utasításait amíg a kifejezés igaz 12/39
do while ciklus Összegezzük a számokat 1 és N között. N értékét olvassuk be! Használjuk a do while ciklust! int N, i, sum=0; printf("\nszámok összegzése 1-N-ig"); printf("\nkérem N értékét: "); scanf("%d", &N); i=1; do { sum+=i; i++; while (i<=n); printf("\nösszeg: %d\n", sum); 13/39
for ciklus: for (1.kifejezés; 2.kifejezés; 3.kifejezés) { ciklusmag ciklus (kezdőérték, bennmaradási feltétel, növekmény) { ciklusmag utasításai 14/39
for ciklus Összegezzük a számokat 1 és N között. N értékét olvassuk be! Használjuk a for ciklust! int N, i, sum=0; printf("\nszámok összegzése 1-N-ig"); printf("\nkérem N értékét: "); scanf("%d", &N); for (i=1; i<=n; i++) { sum+=i; printf("\nösszeg: %d\n", sum); 15/39
A for ciklus csodái int N, i, sum; printf("\nszámok összegzése 1-N-ig"); printf("\nkérem N értékét: "); scanf("%d", &N); for (i=1,sum=0; i<=n; sum+=i,i++) { printf("\nösszeg: %d\n", sum); int N, sum; printf("\nszámok összegzése 1-N-ig"); printf("\nkérem N értékét: "); scanf("%d", &N); for (int i=1,sum=0; i<=n; sum+=i,i++); printf("\nösszeg: %d\n", sum); 16/39 A ciklusmag üres, a végrehajtandó utasítás a növekmény előtt van megadva! Ha üres a ciklusmag, nem kellenek a kapcsos zárójelek sem!!
Számkitaláló int tipp, szam, kesz; szam=57; kesz=1; printf ("\ntalálj ki egy számot 1-100 között!\n"); do { printf("kérem a tippet: "); scanf ("%d", &tipp); if (tipp < szam) printf ("A tipp kisebb a számtól!\n"); if (tipp == szam) {kesz=0; printf ("Eltaláltad!"); if (tipp > szam) printf ("A tipp nagyobb a számtól!\n"); while (kesz); A C nyelvben az 1 logikai igazat, a 0 logikai hamisat jelent. A ciklusok addig futnak, míg a feltételük igaz, így egy 1 vagy 0 értéket felvevő változóval vezérelhetők. A while (kesz) értelmezése: amíg kesz értéke 1 (igaz), addig fut a ciklus, 17/39 ha az érték 0 lesz (hamis), akkor kilép a program a ciklusból
Számkitaláló Profiknak! #include <stdlib.h> #include <time.h> int tipp, szam, kesz=1; srand(time(null)); szam = rand()%100+1; Szükséges könyvtári modulok Ha ez az utasítás kimarad, mindig ugyanazt a véletlenszámot kapjuk! printf ("\ntalálj ki egy számot 1-100 között!\n"); do { printf("kérem a tippet: "); scanf ("%d", &tipp); if (tipp < szam) printf ("A tipp kisebb a számtól!\n"); if (tipp == szam) {kesz=0; printf ("Eltaláltad!"); if (tipp > szam) printf ("A tipp nagyobb a számtól!\n"); while (kesz); srand véletlenszám generátor inicializálása 18/39 rand() véletlenszám generálás
Egy szám egész osztóinak kiíratása Írassuk ki egy szám egész osztóit. A szám értékét olvassuk be! Programlogika: 1. Kell szervezni egy ciklust, ami 1-től indul, végértéke a beolvasott szám (legyen a neve x) (ciklus 1-től x-ig) 2. A ciklusmagban vizsgálni kell, hogy az az érték, ahol a ciklus jár (i), egész osztója-e a számnak (x-nek): x%i == 0 3. Ha egész osztó az i, akkor kiírjuk a képernyőre az i értékét, ha nem egész osztó, nem csinálunk semmit sem 4. A választott ciklusnak megfelelően az i ciklusváltozó növekedéséről gondoskodni kell 5. A ciklusból kilépve vége a kódnak 19/39
Egy szám egész osztóinak kiíratása Írassuk ki egy szám egész osztóit. A szám értékét olvassuk be! int x, i=1; printf("\nszám osztóinak kiírása"); printf("\nkérem a szám értékét: "); scanf("%d", &x); while (i<=x) { if (x%i == 0) printf("\na szám osztója: %d", i); i++; 20/39
Egy szám egész osztóinak darabszáma Számoljuk meg, hogy egy beolvasott számnak hány darab egész osztója van! Programlogika: 1. Deklaráljunk egy változót, legyen a neve db, melyben majd nyilvántartjuk az egész osztók darabszámát. A kód elején ennek az értéke 0 legyen. 2. Kell szervezni egy ciklust, ami 1-től indul, végértéke a beolvasott szám (legyen a neve x) (ciklus 1-től x-ig) 3. A ciklusmagban vizsgálni kell, hogy az az érték, ahol a ciklus jár (i), egész osztója-e a számnak (x-nek): x%i == 0 4. Ha egész osztó az i, akkor a db változó értékét növelni kell 1-el 5. A választott ciklusnak megfelelően az i ciklusváltozó növekedéséről gondoskodni kell 6. A ciklusból kilépve ki kell írni a db változó értékét, ez a program végeredménye 21/39
Egy szám egész osztóinak darabszáma Számoljuk meg, hogy egy beolvasott számnak hány darab egész osztója van! int x, i=1, db=0; printf("\nszám osztóinak kiírása"); printf("\nkérem a szám értékét: "); scanf("%d", &x); while (i<=x) { if (x%i == 0) { printf("\na szám osztója: %d", i); db++; i++; printf("\na szám osztóinak száma: %d", db); 22/39 Ellenőrzésként kiíratjuk az osztók értékét. Ha minden rendben, kitöröljük ezt a sort!
A C kód adatbeolvasási logikája! int x; printf("\nadatbeolvasás"); printf("\nkérek egy egész számot: "); scanf("%d", &x); printf("\na szám: %d", x); Beolvasunk egy egész számot, és kiírjuk a képernyőre Mi történik, ha hibás számot (betűket) adunk meg? Nagy gond, hiszen látszólag minden rendben! Magyarázat: ha deklarálunk egy változót, a memóriában lefoglalja a helyét a program. Ezen a helyen mindig vannak 0-ák, és 1-esek. Ezt a véletlen értéket kapjuk ilyen esetben! 23/39
A C kód adatbeolvasási logikája! A probléma kiküszöbölése: 1. teendő: kezdőérték adás Mindig adjunk kezdőértéket int x=-333; a beolvasandó változónak! printf("\nadatbeolvasás"); printf("\nkérek egy egész számot: "); scanf("%d", &x); printf("\na szám: %d", x); Mi történik most, ha hibás számot (betűket) adunk meg? Nem oldottuk meg a hibás adatbevitel problémáját, de legalább észrevesszük! 24/39
A C kód adatbeolvasási logikája! A probléma kiküszöbölése: 2. teendő: ellenőrzött beolvasás Ellenőrzött beolvasás int x=-333; printf("\nadatbeolvasás"); printf("\nkérek egy egész számot: "); if (scanf("%d", &x)!= 1) printf("hibás adat!\n"); else printf("\na szám: %d", x); A scanf függvény visszaadja, hogy hány adatot tudott a megadott formátumnak megfelelően beolvasni Majdnem kész a megoldás, már csak arra kell rávenni a programot, hogy hibás beolvasáskor ismételje meg a beolvasást. Kell egy ciklus! 25/39
A C kód adatbeolvasási logikája! A probléma kiküszöbölése: 3. teendő: ciklus szervezés int x=-333; int adb=0; char sz[100]; printf("\nadatbeolvasás"); do { printf("\nkérek egy egész számot: "); adb=scanf("%d", &x); if (adb==0) { printf("hibás adat!\n"); scanf("%s", sz); while (adb!=1); printf("\na szám: %d", x); 26/39 Értelmezzük a kódot lépésről lépésre! A scanf függvény a beírt adatot egy pufferbe írja, és innen csak annyit olvas be, amennyit az adott formátumnak megfelelően értelmezni képes, a többi adat a pufferben marad. Ezt a megismételt olvasás előtt ki kell onnan törölni, pl. szövegként kiolvasni.
A C kód adatbeolvasási logikája! Értelmezzük a kódot lépésről lépésre! int x=-333; int adb=0; char sz[100]; printf("\nadatbeolvasás"); do { printf("\nkérek egy egész számot: "); adb=scanf("%d", &x); if (adb==0) { printf("hibás adat!\n"); scanf("%s", sz); while (adb!=1); printf("\na szám: %d", x); 27/39 1. Kiíródik a Kérek egy egész számot szöveg 2. Beírjuk, hogy: ww 3. Az adb értéke 0 lesz, hiszen hibás a szám 4. Mivel adb=0, kiíródik a Hibás adat, és beolvassuk szövegként a beírt ww-t. Így kiürül a puffer! 5. Mivel adb=0, visszatér a ciklus az elejére, és újból megjelenik a Kérek egy egész számot szöveg
A C kód adatbeolvasási logikája! Értelmezzük a kódot lépésről lépésre! int x=-333; int adb=0; char sz[100]; printf("\nadatbeolvasás"); do { printf("\nkérek egy egész számot: "); adb=scanf("%d", &x); if (adb==0) { printf("hibás adat!\n"); scanf("%s", sz); while (adb!=1); printf("\na szám: %d", x); 28/39 6. Beírjuk, hogy: 23 7. Az adb értéke 1 lesz, hiszen helyes a szám 8. Mivel adb=1, az if feltétel nem hajtódik végre 9. Mivel adb=1, már nem teljesedik a bennmaradási feltétel, így kilép a program a ciklusból 10.Kiíródik: A szám értéke: 23 szöveg
Házi feladatok 1. Írjon C programot, amely két megadott számról eldönti, hogy melyik a nagyobb (szelekciós utasítás). Vizsgálja az egyenlőségüket is! Megoldható-e a feladat switch szerkezettel? Válaszát indokolja! 2. Három beolvasott számról döntsük el, hogy lehetnek-e egy háromszög oldalai. Háromszög egyenlőtlenség: bármely két oldal összege nagyobb mint a harmadik oldal. A háromszög területét kiszámító programot (3. gyak.) egészítsük ki az oldalak ellenőrzött beolvasásával. 3. Készítsen C programot, amely kiszámítja két pozitív szám számtani és mértani közepét. Egész és lebegőpontos számokkal is teszteljék a kódot. 29/39
Házi feladatok 4. Írjon C programot egy beolvasott N érték faktoriálisának kiszámítására (4. és 6. feladat alapján). Figyelem! 8! = 40320, ami már nem fér el egy int típusú változóban. Korlátozza N értékét 0 és 10 közé, és válasszon megfelelő adattípust a faktoriális tárolásához! 5. Írjon C programot a másodfokú egyenlet valós megoldásainak kiszámítására. 6. Implementálja a 2. gyakorlat algoritmusait. Mértani átlag számításhoz segítség: egy szám n-edik gyöke egyenlő az 1/n-edik hatványával. A math.h hatványozó függvénye : double pow(double alap, double kitevo); 30/39
31/39 Sivatagi elágazás
Feladat Algoritmizálás ZH C csoport Feladat: Adjuk meg az első N db prímszám összegét kiszámoló algoritmus pszeudokódját és folyamatábráját! A megoldás folyamata: Kell egy változó, amivel a darabszámot kezeljük, legyen db=0 Kell egy változó, amiben a prímek összege lesz, legyen s=0 Beolvassuk N-t Elindulunk egy ciklussal 2-től egyesével (legyen a ciklusváltozó: i), akkor lesz vége a ciklusnak, ha találunk N darab prím számot A ciklus biztosítja a számokat egyesével növekedve, ezeket a számokat fogjuk megvizsgálni, hogy prímek-e Megvizsgáljuk, hogy a szám (i) prímszám-e (csak 2 osztója van) Ha prímszám, a db-t növeljük 1-el, és az s-hez hozzáadjuk i-t Ha a db eléri N-t, akkor megállunk, és kiírjuk s-t! 32/39
Feladat Feladat: Hogyan dönthető el egy számról (x), hogy prímszám-e? Megoldás: A prímszámnak csak 2 osztója van, az 1, és önmaga Kell egy változó, amiben az osztók darabszáma lesz, legyen odb=0 Kell egy ciklus, 1-től a szám-ig (x-ig), amiben vizsgáljuk, hogy a ciklusváltozó (j) értéke osztója-e x-nek: (x mod j == 0) Ha igen, az odb-t növeljük 1-el A ciklusból kilépve vizsgáljuk odb értékét: (odb == 2) Ha igaz a feltétel, az x prímszám! Ha beépítjük ezt a részt az előző részbe, a vizsgálandó szám (x), az ottani ciklusváltozó (i) értéke lesz! Azért használunk itt j ciklusváltozót, hogy a külső ciklus i változójával ne keveredhessen össze az értéke! Rajzoljuk meg ennek a résznek a folyamatábráját! 33/39
Feladat Kapjuk x-et, a vizsgálandó számot Hogyan dönthető el egy számról (x), hogy prímszám-e? Osztók darabszáma Ciklusváltozó, megy 1-től x-ig j egész osztója x-nek? Találtunk egy egész osztót Nem Nem 1 odb := 0 j := 1 j <= x Igen x mod j=0 Igen odb++ Prímszám? (2 osztója van?) Prímek számát növelem 1-el Egyszerűsítés (bonyolítás): a ciklus mehet 2-től az x feléig. Ekkor nem találjuk meg osztóként az 1-et, és önmagát sem. Ez esetben akkor prím a 34/39 szám, ha nincs egyetlen osztója sem (odb==0) Nem j++ odb==2 db++ 2 Igen
Feladat Az első N db prímszám összege Prímek összege Prímek darabszáma Külső ciklus feltétele. Ha megvan a kellő számú prím, leáll a ciklus. Minden prím vizsgálat előtt be kell állítani a prímek darabszámát 0-ra, a belső ciklus induló értékét 1-re! Nem START Be: N s := 0 db := 0 i := 2 db <= N odb := 0 j := 1 1 Ki: s Igen 2 Nem Nem Nem 1 j <= i Igen i mod j=0 Igen odb++ j++ odb==2 Igen db:=db+1 s:=s+i 2 35/39 STOP i++
Feladat Feladat: Az első N db prímszám összegét kiszámoló algoritmus pszeudokódja: BE: N s:=0 (a prímszámok összege) db:=0 (prímszámok darabszáma) odb:=0 (osztók darabszáma) i:=2 (külső ciklusváltozó, ez biztosítja az egyesével növekvő számokat) j:=1 (belső ciklusváltozó, osztók megállapításához) 36/39
Feladat: Az első N db prímszám összegét kiszámoló algoritmus pszeudokódja: AMÍG db<=n ADDIG odb=0 j:=1 AMÍG j<=i ADDIG HA (i mod j = 0) AKKOR odb:=odb+1 FELTÉTEL VÉGE j:=j+1 CIKLUS VÉGE HA odb = 2 AKKOR db:=db+1 s:=s+i FELTÉTEL VÉGE i:=i+1 CIKLUS VÉGE 37/39 KI:s
Feladat: Az első N db prímszám összegét kiszámoló algoritmus pszeudokódja: STOP 38/39 BE: N db:=0 sum:=0 i:=2 AMÍG db<=n ADDIG oszto:=2; talalt:=0; AMÍG oszto<=i/2 and!talalt ADDIG HA (i mod oszto = 0) AKKOR talalt:=igaz FELTÉTEL VÉGE oszto:=oszto+1 CIKLUS VÉGE HA!talalt AKKOR db:=db+1 sum:=sum+i FELTÉTEL VÉGE i:=i+1 CIKLUS VÉGE KI:s
VÉGE VÉGE 39/39