Programozás alapjai C nyelv 5. gyakorlat Szeberényi Imre BME IIT <szebi@iit.bme.hu> Programozás alapjai I. (C nyelv, gyakorlat) BME-IIT Sz.I. 2005.10.17. -1- Tömbök Azonos típusú adatok tárolására. Index mindig nullától indul, és csak egész típusú (char is egész) lehet. Pl: m[2][3] int alma[8]; float m[3][4]; m[0][0] alma[0] m[0][3] alma[7] m[2][0] Programozás alapjai I. (C nyelv, gyakorlat) BME-IIT Sz.I. 2005.10.17. -2- Tömbök (2) Értékkészlet - elemek értékkészletéből Konstansok - elemek konstansaiból Művelethalmaz indexelés (hivatkozás egy elemére) hivatkozhatunk a címére, így átadhatjuk fv. paraméterként (azaz leírjuk a nevét) tömb neve == tömb címe más művelete nincs!!! Írjunk ki fordítva! Feladat: Olvassunk be 10 valós számot a standard inputról és írjuk ki azokat a beolvasással ellentétes sorrendben! Programozás alapjai I. (C nyelv, gyakorlat) BME-IIT Sz.I. 2005.10.17. -3- Programozás alapjai I. (C nyelv, gyakorlat) BME-IIT Sz.I. 2005.10.17. -4- Írjunk ki fordítva! (2) Vázlat: Tárolni kell tömb for i, 0 to 9 olvas(i) for i, 9 to 0 kiir(i) Programozás alapjai I. (C nyelv, gyakorlat) BME-IIT Sz.I. 2005.10.17. -5- Írjunk ki fordítva! (3) #include <stdio.h> int main() float tomb[10]; int i; for (i = 0; i < 10; i++) scanf( %f, &tomb[i]); for (i = 9; i >= 0; i--) printf( %f, tomb[i]); return 0; Nem trükközünk a for ciklusban, mert így mindenkinek sokkal olvashatóbb!! Programozás alapjai I. (C nyelv, gyakorlat) BME-IIT Sz.I. 2005.10.17. -6-
Tömbök (3) Többdimenziós tömbök, for, register int tomb3d[100][100][100]; int i,j; register int k; for (i = 0; i < 100; i++) for (j = 0; j < 100; j++) for (k = 0; k < 100; k++) tomb3d[i][j][k]++; k-ra 1000000-szor hivatkozunk. Hogy gyors legyen a kód, CPU regiszterbe kérjük Programozás alapjai I. (C nyelv, gyakorlat) BME-IIT Sz.I. 2005.10.17. -7- Jellemző fordulat: Tömbök (4) int tomb[100]; int i, n = sizeof(tomb)/sizeof(int); for (i = 0; i < n; tomb[i++] = 0) ; a tömb méretét a fordító határozza meg; ha változtatunk, elég 1 helyen inicializáljuk a tömböt a for léptető részében, így üres a ciklusmag Programozás alapjai I. (C nyelv, gyakorlat) BME-IIT Sz.I. 2005.10.17. -8- Tömbök (5) Kezdeti értékadás tömböknek - elemkonstansok felsorolása: char sztring[] = hello ; int primek[] = 2,3,5,7,11,13; a tömb méretét a fordító határozza meg felsorolt elemkonstansok alapján ilyenkor nagyon fontos a sizeof(primek)/sizeof(int); fordulat az elemszám (logikai méret) megahtározásához Mekkora a sztring tömb? 6 karakteres a \0 miatt. Programozás alapjai I. (C nyelv, gyakorlat) BME-IIT Sz.I. 2005.10.17. -9- Összefoglalás A tömbök ugyanolyan típusú alapelembőlsokategy egységként tekintünk Pl. karakter tömbök, sztring-konstansok indexelés: 0-tól tömbméret-1-ig, csak egésszel többdimenziós tömbök fizikai tömbméret: sizeof(tombváltozó) logikai tömbméret (elemek száma): sizeof(tombváltozó)/sizeof(elemtípus) Programozás alapjai I. (C nyelv, gyakorlat) BME-IIT Sz.I. 2005.10.17. -10- Felsorolás v. enumeráció Elsősorban absztrakciós eszköz. Olyan egyedi típus, melynek értékkészlete a névvel megadott értékek halmaza. felsorolás_spec: enum felsorolás_tip_azon opc felsorolás_lista enum szinek piros, zold, tok = 13, makk; sz1, k23, kartya_szin; 0, 1, 13, 14 enum szinek s1 = makk; sz1 = zold; s1 = 0; k23 = 2;??? Programozás alapjai I. (C nyelv, gyakorlat) BME-IIT Sz.I. 2005.10.17. -11- Felsorolás v. enumeráció (2) Értékkészlet a névvel megadott értékek halmaza Konstansok a névvel megadott értékek halmaza + egészek halmaza Művelethalmaz egészekre vonatkozó műveletek Programozás alapjai I. (C nyelv, gyakorlat) BME-IIT Sz.I. 2005.10.17. -12-
ly számláló Készítsünk algoritmust és C programot, ami megszámolja a standard bemeneten fájl végéig érkező szövegben az ly sorozatotokat! Az lly sorozat kettőnek számít! Egyéb változat pl: llly esetén nem írjuk elő, hogy mit kell csinálni. Első változatban csak kisbetűket figyelünk. ly számláló (vázlat) sz = 0 while olvas(ch) begin ha ch = y, akkor az előzmények alapján növeljük a számlálót (sz) end (olvas(ch) beolvassa a következő karaktert és hamis fv.értékkel jelzi, ha fájl vége van) Programozás alapjai I. (C nyelv, gyakorlat) BME-IIT Sz.I. 2005.10.17. -13- Programozás alapjai I. (C nyelv, gyakorlat) BME-IIT Sz.I. 2005.10.17. -14- Az előzmények Mik azok az előzmények? Volt-e l betű? Ha volt, akkor hány l betű volt? Hogyan emlékezhetünk az előzményekre? Kóddal, azaz hol jár a program?. Adattal, vagyis egy változóban tároljuk. ly számláló algoritmusa sz = 0 while olvas(ch) begin if ch == l if olvas(ch) begin if ch == y sz = sz + 1 else if ch == l and olvas(ch) if ch == y sz = sz + 2 end end kiír(sz) Még nem jött l betű. Jött l betű. Két l betű jött Programozás alapjai I. (C nyelv, gyakorlat) BME-IIT Sz.I. 2005.10.17. -15- Programozás alapjai I. (C nyelv, gyakorlat) BME-IIT Sz.I. 2005.10.17. -16- ly számláló programja #include <stdio.h> #define olvas(c) (c = getchar())!= EOF main() int sz = 0, ch; while (olvas(ch)) if (ch == l ) if (olvas(ch)) if (ch == y ) sz += 1; Logikailag karakter, akkor miért int? else if ((ch == l ) && olvas(ch)) if (ch == y ) sz += 2; printf( ly-ok szama: %d\n, sz); Programozás alapjai I. (C nyelv, gyakorlat) BME-IIT Sz.I. 2005.10.17. -17- Állapot fogalma 3 állapot van nem jött l (alap) jött l (l_jott) ll jött (ll_jott) Az állapottól és a következő karaktertől függ a tevékenység és az új állapot. Az állapotinformáció is tárolható adatként. Állapotgép Programozás alapjai I. (C nyelv, gyakorlat) BME-IIT Sz.I. 2005.10.17. -18-
ly számláló állapottere ly számláló állapottáblával egyéb alap l y / +1 egyéb y / +2 l_jott l állapot l y egyéb alap l_jott alap alap l_jott ll_jott alap/+1 alap ll_jott ll_jott alap/+2 alap egyéb ll_jott l A gráf szemléletesebb, a táblázatból viszont nehezebb kihagyni átmenetet. Programozás alapjai I. (C nyelv, gyakorlat) BME-IIT Sz.I. 2005.10.17. -19- Programozás alapjai I. (C nyelv, gyakorlat) BME-IIT Sz.I. 2005.10.17. -20- Vázlat: ly számláló állapotgéppel sz = 0 all = alap while olvas(ch) sz_növelés_és_állapot_váltás(ch, all) kiír(sz) ly számláló állapotgéppel #include <stdio.h> #define olvas(c) (c = getchar())!= EOF void main() int sz = 0, ch; enum alap, l_jott, ll_jott all = alap; while (olvas(ch)) Programozás alapjai I. (C nyelv, gyakorlat) BME-IIT Sz.I. 2005.10.17. -21- Programozás alapjai I. (C nyelv, gyakorlat) BME-IIT Sz.I. 2005.10.17. -22- ly számláló állapotgéppel switch (all) case alap: if (ch == l ) all = l_jott; break; case l_jott: if (ch == l ) all = ll_jott; else all = alap; if (ch == y ) sz += 1; break; case ll_jott: if (ch!= l ) all = alap; if (ch == y ) sz += 2; /* end while */ printf( ly-ok szama: %d\n, sz); Programozás alapjai I. (C nyelv, gyakorlat) BME-IIT Sz.I. 2005.10.17. -23- Állapotgép előnyei Könnyebb átlátni, megérteni. Könnyebb módosítani. Mechanikus optimalizálási módszerekkel a felesleges állapotok könnyen kiszűrhetők. Mechanikus a kódolása. Az egész program táblázatok kitöltéséből áll. Programozás alapjai I. (C nyelv, gyakorlat) BME-IIT Sz.I. 2005.10.17. -24-
Megoldás általánosítása Állapot- és tevékenységtábla A beolvasott karaktertől és az állapottól függően két feladatunk van: tev.tábla tevékenység új állapot meghatározása tevékenység elvégzése Három fajta beolvasott karakterünk és 3 állapotunk van, azaz 3x3 adat határozza meg a következő állapotot, és a tevékenységet. input állapot áll.tábla új állapot Programozás alapjai I. (C nyelv, gyakorlat) BME-IIT Sz.I. 2005.10.17. -25- Programozás alapjai I. (C nyelv, gyakorlat) BME-IIT Sz.I. 2005.10.17. -26- Állapot- és tevékenységtábla(2) Táblázatvezérelt program álapot / típus alap l_jott ll_jott l y egyéb l_jott / ll_jott / ll_jott / betű típus +1 +2 Ötlet: Tegyük bele a tevékenységeket és az új állapotot is egy-egy táblázatba. Ebből egyszerű indexeléssel elérhető a köv. állapot ill. a tevékenység. Programozás alapjai I. (C nyelv, gyakorlat) BME-IIT Sz.I. 2005.10.17. -27- Programozás alapjai I. (C nyelv, gyakorlat) BME-IIT Sz.I. 2005.10.17. -28- Táblázatvezérelt program sz = 0; all = alap; while beolv(ch) begin tip = ch_típusa; sz = sz + tev_tab[all][tip]; all = all_tab[all][tip]; end; Megvalósítási kérdések Hogyan töltjük fel a táblázatokat? elemenként kezdeti értékadással Hogyan állapítjuk meg a ch típusát? elemi utasításokkal újabb tömbbel Programozás alapjai I. (C nyelv, gyakorlat) BME-IIT Sz.I. 2005.10.17. -29- Programozás alapjai I. (C nyelv, gyakorlat) BME-IIT Sz.I. 2005.10.17. -30-
ly számláló táblázatai typedef enum alap, l_jott, ll_jott all_t; typedef enuml_betu,y_betu,egyeb_betu betu_t; int all_tab[3][3] = l_jott, alap, alap, ll_jott, alap, alap, ll_jott, alap, alap ; int tev_tab[3][3] = 0, 0, 0, 0, 1, 0, 0, 2, 0 ; Programozás alapjai I. (C nyelv, gyakorlat) BME-IIT Sz.I. 2005.10.17. -31- ly számláló táblázattal void main() int sz = 0, ch; betu_t tip; all_t all = alap; while (olvas(ch)) switch (ch) case 'l': tip = l_betu; break; case 'y': tip = y_betu; break; default : tip = egyeb_betu; sz += tev_tab[all][tip]; all = all_tab[all][tip]; printf("ly-ok szama: %d\n", sz); Programozás alapjai I. (C nyelv, gyakorlat) BME-IIT Sz.I. 2005.10.17. -32- A típus is táblázattal A betűtípus meghatározása is lehetséges tömbbel. Gyakori, hogy a karakter osztályozó függvényeket is /isxxx()/ így valósítják meg. Ha az enum definícioját megváltoztatjuk, akkor kihasználhatjuk egyeb_betu==0. Így egyszerűbb a betu_tip globális a tömb feltöltése: typedef enumegyeb_betu, l_betu, y_betu betu_t; betu_t tip_tab[256]; /* ebben minden 0 */ Ez a változtatás sajnos a táblázatok feltöltését is érinti, hiszen megváltozott az index sorrend. Programozás alapjai I. (C nyelv, gyakorlat) BME-IIT Sz.I. 2005.10.17. -33- ly számláló tip. táblával void main() int sz = 0, ch; betu_t tip; all_t all = alap; tip_tab['l'] = l_betu; tip_tab['y'] = y_betu; while (olvas(ch)) tip = tip_tab[ch]; sz += tev_tab[all][tip]; all = all_tab[all][tip]; printf("ly-ok szama: %d\n", sz); Programozás alapjai I. (C nyelv, gyakorlat) BME-IIT Sz.I. 2005.10.17. -34- Mutatók és címek Indirekció Minden változó és függvény memóriában levő helye (címe) képezhető. (pl: &valtozo) Ez a cím ún. pointerben vagy mutatóban tárolható. A pointer egy olyan típus, amelynek az értékkészlete cím, és mindig egy meghatározott típusú objektumra mutat. int i; int *ip; *ip = 13; 13 i cime float f; float *fp; int i, *ip; float f, *fp; int-re mutató pointer float-ra mutató pointer ip = &i; fp = &f; ip = &i Memória Programozás alapjai I. (C nyelv, gyakorlat) BME-IIT Sz.I. 2005.10.17. -35- Programozás alapjai I. (C nyelv, gyakorlat) BME-IIT Sz.I. 2005.10.17. -36-
Mire jó? Bonyolultabban írjuk le az i =13-at? Lehet egy cél, de nem ez az igazi ok. Hardver közeli megoldások. Olvasható assembly. Memóriába ágyazott I/O. Dinamikus memóriakezelés. Nagyon fontos. Változó paraméter hiányának kiváltása. Legalább ennyire fontos. Pointer típus jellemzői Értékkészlet - adott objektum címe Konstansok - NULL (0) Művelethalmaz: értékadás indirekció címaritmetika relációk Programozás alapjai I. (C nyelv, gyakorlat) BME-IIT Sz.I. 2005.10.17. -37- Programozás alapjai I. (C nyelv, gyakorlat) BME-IIT Sz.I. 2005.10.17. -38- Címaritmetika C nyelv egyik jellegzetessége, és a gépközeli jelleget erősíti. Jelöljük i-vel az egész értéket, p-vel a pointert: p+i p p = p + i * sizeof(obj) p-i p p = p - i * sizeof(obj) p-p i p = (p - p) / sizeof(obj) Eggyel való növelés a következő objektum címzését eredményezi. (p = p + 1, p += 1, p++) Programozás alapjai I. (C nyelv, gyakorlat) BME-IIT Sz.I. 2005.10.17. -39- Címaritmetika példák int *ip, t[10]; for (ip = &t[0]; ip < &t[10]; *ip++ = 0); Már nem létezik float *fp, ft[10]; for (fp = &ft[0]; fp < &ft[10]; *fp++ = 0); Az ip++ ill. az fp++ elemről-elemre lép. Pont akkorát lép, amekkora az adott elem (int ill. float) mérete. Programozás alapjai I. (C nyelv, gyakorlat) BME-IIT Sz.I. 2005.10.17. -40- Címaritmetika példák (2) int *ip, t[10]; *(t+2) = 12; t[2] = 12; A tömb azonosítója a 0. elem címét jelenti. ip = &t[10] ip t== 10 t[i] *(t+i) &t[i] t+i A prioritásra, kötési szabályra és a sorrendre ügyelni!!! int *ip, i, t[10]; ip = t; *ip++ = 23; /* mi a fő- és mellékhatás? */ *++ip = 23; /* hova ír? */ (*ip)++; /* ez mit növel? */ /* Vigyázat a kiértékelés sorrendjét nem * határozza meg a prioritás */ *ip++ = *ip++; /* nem definiált működés!! */ t[i++] = i++; /* nem definiált működés!! */ *i = *ip+++*ip;/* ravasz, de nem jó */ Programozás alapjai I. (C nyelv, gyakorlat) BME-IIT Sz.I. 2005.10.17. -41- Programozás alapjai I. (C nyelv, gyakorlat) BME-IIT Sz.I. 2005.10.17. -42-