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

SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)1 Halmaz típus  A programozásban számtalan.

Hasonló előadás


Az előadások a következő témára: "SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)1 Halmaz típus  A programozásban számtalan."— Előadás másolata:

1 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)1 Halmaz típus  A programozásban számtalan formában előfordulhatnak halmazok és halmazokkal végzett műveletek.  Legyen U egy egész típus, amit univerzumnak nevezünk. Tekintsük azt az értékhalmazt, amelynek elemei az U univerzum részhalmazai, ez lesz a Halmaz(U) új adattípus értékhalmaza.

2 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)2 Halmaz műveletei  (A Halmaz(U) adattípusra a továbbiakban a Halmaz azonosítót használjuk.)  Üresít( <- H : Halmaz); ■A művelet végrehajtása után a H változó értéke az üres halmaz.  Bővít( H : Halmaz; -> x : U); ■A művelet a H változó értékéhez hozzáveszi az x elemet.  Töröl( H : Halmaz; -> x : U); ■A művelet a H változó értékéből törli az x elemet.

3 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)3 Halmaz műveletei  Eleme( -> x : U; -> H : Halmaz) : bool; ■A függvényművelet akkor és csak akkor ad igaz értéket, ha x eleme a H halmaznak.  Egyesítés( -> H 1,H 2 : Halmaz; <- H : Halmaz); ■A művelet eredményeként a H változó értéke a H 1 és H 2 halmaz egyesítése lesz.  Metszet( -> H 1,H 2 : Halmaz; <- H : Halmaz); ■A művelet eredményeként a H változó értéke a H 1 és H 2 halmaz közös része lesz.

4 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)4 Halmaz műveletei  Különbség( -> H 1,H 2 : Halmaz; <- H : Halmaz); ■A művelet eredményeként a H változó azokat és csak azokat az x in U értékeket tartalmazza, amelyre x in H 1, de x nem eleme a H 2 halmaznak.  Egyenlő( -> H 1,H 2 : Halmaz) : bool; ■Az egyenlőség relációs művelet.  Rész( -> H 1,H 2 : Halmaz) : bool; ■Akkor és csak akkor ad igaz értéket, ha a H 1 halmaz minden eleme a H 2 halmaznak is eleme.

5 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)5 Halmaz műveletei  Ürese( -> H : Halmaz) : bool; ■Akkor és csak akkor ad igaz értéket, ha H értéke az üres halmaz.  Értékadás( H 2 : Halmaz); ■A művelet hatására a H 1 változó felveszi a H 2 értékét.

6 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)6 Halmaz megvalósítása  A C nyelvben a halmaznak nincs nyelvi megvalósítása.  A halmazok reprezentálásához induljunk ki abból, hogy tetszőleges U univerzum esetén az U részhalmazai megadhatók karakterisztikus függvényükkel.  Ha H az U részhalmaza, akkor karakterisztikus függvénye: k H : U ---> {0,1}, k H (x)=1 x in H

7 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)7 Halmaz megvalósítása  A karakterisztikus függvények és U részhalmazai között kölcsönösen egyértelmű megfeleltetést ad az előbbi összefüggés.  Ha U egész típus, a karakterisztikus függvényeket meg tudnánk valósítani a bool[U] típussal, de ez nem hatékony megoldás, mert U minden eleméhez a logikai bool típus megvalósításától függően legalább egy (de inkább 4) byte szükséges.  Az 1 bit/elem hatékonyságot el is tudjuk viszont érni, a bitműveletek segítségével.

8 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)8 Halmaz megvalósítása  A módszer lényege, hogy például egy int típusú változóban 32 bitet tárolhatunk, azaz egy 32 elemű kis halmaz reprezentálására ideális. vagy inkább:  Melyik jobb?

9 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)9 Halmaz megvalósítása  Az egyes biteket a bitműveletekkel érhetjük el.  A bit törlése, beállítása és lekérdezése az &, | és ~ műveletek segítségével történik << 0= << 1= << 31=

10 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)10 Halmaz megvalósítása  Nagyobb halmazt összerakhatunk kis halmazokból a következőképpen. 00K-1...1K2K-1... i=(N / K)iK(i+1)K-1 M-1(M-1)KMK K-1... N 0K-1...(N % K) 0K K-1... LogikailagFizikailag Kishalmaz sorszám

11 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)11 Halmaz megvalósítása  Képezzük az alábbi típusokat: #define K (8*sizeof(KisHalmaz)) #define M ??? #define H_MAX (M*K) typedef int KisHalmaz; typedef KisHalmaz Halmaz[M];

12 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)12 Halmaz megvalósítása  Minden x természetes szám egyértelműen meghatározott az (x / K, x % K) számpárral.  Tehát x akkor és csak akkor eleme a H változó által reprezentált halmaznak, ha teljesül, hogy a H[x / K] KisHalmaznak eleme az (x % K), azaz a megfelelő KisHalmaz megfelelő bitje 1.  Az univerzum halmaz ekkor a 0..H_MAX-1 intervallum lesz.

13 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)13 Halmaz műveletei  Üresít( <- H : Halmaz); void Uresit(Halmaz H) { long int i; for(i = 0; i < M; ++i) H[i] = 0; }

14 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)14 Halmaz műveletei  Bővít( H : Halmaz; -> x : U); void Bovit(Halmaz H, unsigned long int x) { if(x < H_MAX) H[x / K] |= (1 << (x % K)); }

15 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)15 Halmaz műveletei  Töröl( H : Halmaz; -> x : U); void Torol(Halmaz H, unsigned long int x) { if(x < H_MAX) H[x / K] &= ~(1 << (x % K)); }

16 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)16 Halmaz műveletei  Eleme( -> x : U; -> H : Halmaz) : bool; int Eleme(unsigned long int x, Halmaz H) { return (x < H_MAX) && (H[x / K] & (1 << (x % K))); }

17 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)17 Halmaz műveletei  Egyesítés( -> H1,H2 : Halmaz; <- H : Halmaz); void Egyesites(Halmaz H1, Halmaz H2, Halmaz H) { long int i; for(i = 0; i < M; ++i) H[i] = H1[i] | H2[i]; }

18 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)18 Halmaz műveletei  Metszet( -> H1,H2 : Halmaz; <- H : Halmaz); void Metszet(Halmaz H1, Halmaz H2, Halmaz H) { long int i; for(i = 0; i < M; ++i) H[i] = H1[i] & H2[i]; }

19 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)19 Halmaz műveletei  Különbség( -> H1,H2 : Halmaz; <- H : Halmaz); void Kulonbseg(Halmaz H1, Halmaz H2, Halmaz H) { long int i; for(i = 0; i < M; ++i) H[i] = H1[i] & ~(H2[i]); }

20 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)20 Halmaz műveletei  Egyenlő( -> H1,H2 : Halmaz) : bool; int Egyenlo(Halmaz H1, Halmaz H2) { long int i; for(i = 0; (i

21 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)21 Halmaz műveletei  Rész( -> H1,H2 : Halmaz) : bool; int Resz(Halmaz H1, Halmaz H2) { long int i; for(i = 0; (i

22 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)22 Halmaz műveletei  Ürese( -> H : Halmaz) : bool; int Urese(Halmaz H) { long int i; for(i = 0; (i

23 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)23 Halmaz műveletei  Értékadás( H2 : Halmaz); void Ertekadas(Halmaz H1, Halmaz H2) { long int i; for(i = 0; i < M; ++i) H1[i] = H2[i]; }

24 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)24 Halmaz típus  Azáltal, hogy az univerzum egész típus, lehetővé válik a diszkrét ismétléses vezérlés megfogalmazása ezekre a halmazokra.  Legyen U min, U max az univerzum minimális illetve maximális eleme. x in H M x= U min -> U max x in H in M

25 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)25 Halmaz típus  Ebben az esetben tehát a diszkrét ismétléses vezérlés megvalósítása C nyelven: for(x=Umin; x<=Umax; ++x) { if(Eleme(x,H)) { M; }

26 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)26 Klikkek  Problémafelvetés: ■Egy közösségben az emberek közötti barátsági kapcsolat alapján meg kell határoznunk a klikkeket.  Specifikáció: ■Sorszámozzuk 1-től N-ig az embereket és olvassuk be az R barátsági relációt. ■Input: –Számpárokat olvasunk be. Az input vége: 0 0. Az i,j pár azt jelenti, hogy az i. személy barátságban van a j. személlyel. ■Output: –Soroljuk fel a baráti csoportokat.

27 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)27 Klikkek  Algoritmustervezés: ■A matematika nyelvén: Tegyük fel, hogy a barátság reflexív, szimmetrikus és tranzitív reláció. Meg kell határozni az R relációt tartalmazó legszűkebb ekvivalencia reláció szerinti osztályozást. ■Induljunk ki abból, hogy minden személy csak saját magával van barátságban; tehát képezzük az {i} egyelemű halmazokat. Ha az input számpárokat valameddig feldolgozva meghatároztuk az osztályozást, a következő (i,j) számpárt beolvasva össze kell vonni azt a két részhalmazt, amelybe i illetve j tartozik, hisz mindenki, aki i-vel barátságban van, az barátságban van mindenkivel, akivel j barátságban van.

28 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)28 Klikkek  Az algoritmus C megvalósítása tehát az absztrakt Halmaz(U) adattípus műveleteivel. /* A beolvasott R relációt tartalmazó legszűkebb ekvivalencia reláció szerinti osztályozást határozzuk meg. Vázlat, nem fordítható C program Augusztus 14. Gergely Tamás, */ #include #define N 10 /* maximális elemszám */ typedef Halmaz(U) Halmaz; /* EZ ÍGY NEM C !!!*/ >>>

29 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)29 Klikkek int main() { Halmaz H[N]; unsigned short i,j, ti,tj; for(i = 1; i <= N; ++i) { /* inicializálás */ Uresit(H[i-1]); Bovit(H[i-1], i); } printf("Kérem a relációban lévő számpárokat!\n"); scanf("%hd%hd%*[^\n]", &i, &j); getchar(); >>>

30 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)30 Klikkek while(i != 0) { for(ti=0; !Eleme(i, H[ti]); ti++); /* amelyik H[ti] halmazban van i ? */ for(tj=0; !Eleme(j, H[tj]); tj++); /* amelyik H[tj] halmazban van j ? */ if(ti != tj) { /* H[ti] és H[tj] összevonása */ Egyesites(H[ti], H[tj], H[ti]); Uresit( H[tj] ); } scanf("%hd%hd%*[^\n]", &i, &j); getchar(); } >>>

31 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)31 Klikkek printf("Az osztályok: \n"); for (i = 1; i <= N; i++) { /* az osztályok kiíratása */ if (! Urese(H[i - 1])) { for (j = 1; j <= N; j++) { if (Eleme(j, H[i - 1])) printf("%4hd,", j); } putchar('\n'); }

32 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)32 Klikkek  Mivel N < 32, elég egy KisHalmaz. /* A beolvasott R relációt tartalmazó legszűkebb ekvivalencia reláció szerinti osztályozást határozzuk meg December 6. Dévényi Károly, Augusztus 14. Gergely Tamás, */ #include #define N 10 /* maximális elemszám */ typedef int Halmaz; /* N kicsi, ezért elegendő az int */ >>>

33 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)33 Klikkek main(int argc, char *argv[]) { Halmaz H[N]; unsigned short i, j, ti, tj; for (i = 1; i <= N; i++) /* inicializálás */ H[i - 1] = 1 << i; printf("Kérem a relációban lévő számpárokat!\n"); scanf("%hd%hd%*[^\n]", &i, &j); getchar(); >>>

34 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)34 Klikkek while (i != 0) { /* While */ for(ti = 0; ((1 << i) & H[ti]) == 0; ti++); /* azon ti index keresése, amelyik H[ti] halmazban van i */ for(tj = 0; ((1 << j) & H[tj]) == 0; tj++); /* azon tj index keresése, amelyik H[tj] halmazban van j */ if (ti != tj) { /* H[ti] és H[tj] összevonása */ H[ti] |= H[tj]; H[tj] = 0; } scanf("%hd%hd%*[^\n]", &i, &j); getchar(); } >>>

35 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)35 Klikkek printf("Az osztályok: \n"); for (i = 1; i <= N; i++) { /* az osztályok kiíratása */ if (H[i - 1] != 0) { for (j = 1; j <= N; j++) { if (j < 32 && ((1 << j) & H[i - 1]) != 0) printf("%4hd,", j); } putchar('\n'); }

36 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)36 Prímszámok  Problémafelvetés: ■Határozzuk meg az adott N természetes számnál nem nagyobb prímszámokat.  Specifikáció: ■Az N legyen konstans. ■Input: –Nincs ■Output: –Soroljuk fel a prímszámokat N-ig

37 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)37 Prímszámok  Algoritmustervezés: ■A jól ismert Erathosztenészi szita algoritmust valósítjuk meg. ■A halmazt kezdetben feltöltjük az egynél nagyobb páratlan számokkal. ■Megkeressük a halmaz még nem feldolgozott legkisebb elemét (ez prímszám lesz) és töröljük a többszöröseit. ■Az előző pontot addig ismételjük, míg el nem érjük az N gyökét. ■Az eredményhalmaz csak a prímszámokat fogja tartalmazni.

38 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)38 Prímszámok /* * Határozzuk meg az adott N természetes számnál nem nagyobb * prímszámokat. * Készítette: Dévényi Károly, * December 6. * Módosította: Gergely Tamás, * Augusztus 15. */ #include #define K (8*sizeof(KisHalmaz)) #define M 100 #define N (M*K) typedef int KisHalmaz; typedef KisHalmaz Halmaz[M]; >>>

39 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)39 Prímszámok int main() { Halmaz szita; KisHalmaz kicsi; /* a szita inicializálásához */ long int p,s,lepes,i,j; kicsi = 0; /* a szita inicializálása */ for(i = 0; i <= ((K-1) / 2); ++i) { kicsi |= (1 << (2*i+1)); } for(i = 0; i < M; ++i) { szita[i] = kicsi; } szita[0] &= ~2; /* 2 == (1 << 1) */ szita[0] |= 4; /* 4 == (1 << 2) */ >>>

40 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)40 Prímszámok p = 3; /* az első szitálandó prím */ while(p*p < N) { /* P többszöröseinek kiszitálása */ lepes = 2 * p; /* lépésköz = 2*p */ s = p*p; /* s az első többszörös */ while(s < N) { szita[s / K] &= ~(1 << (s % K)); s += lepes; } do { /* a következő prím keresése */ p += 2; } while( (p < N) && ! (szita[p / K] & (1 << (p % K))) ); } >>>

41 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)41 Prímszámok j = 0; /* a prímszámok kiíratása képernyőre */ printf("A prímszámok %d-ig:\n", N); for(p = 2; p < N; ++p) { if(szita[p / K] & (1 << (p % K))) { printf("%8d", p); if(++j == 9) { j = 0; putchar('\n'); } putchar('\n'); }

42 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)42 Dinamikus tömb típus  Ha a programban deklarálunk egy tömböt, azzal az lehet a baj, hogy a méretét fordítási időben meg kell adni.  Ez viszont nem mindig ismert, így előfordulhat, hogy a tömb számára kevés helyet foglaltunk, de az is, hogy feleslegesen sokat.  A megoldás: tömb helyett pointert deklarálunk, és ha tudjuk a kívánt méretet, memóriát már a megfelelő számú elemnek foglalunk.

43 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)43 Dinamikus tömb típus int tomb[MAX]; … for(i=0; i

44 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)44 Flexibilis tömb típus  A C nyelvben lehetőség van arra, hogy egy pointer számára már lefoglalt memóriaterület méretét megváltoztassuk. A void *realloc(void *ptr, size_t size) függvény a ptr által mutatott területet méretezi (és ha kell mozgatja) át.  Ez sem használható viszont, ha a memória túlságosan „széttöredezett”, azaz nincsennek benne nagy egybefüggő részek.

45 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)45 Flexibilis tömb típus  Egy megoldás a problémára a flexibilis tömb adattípus, ami a dinamikus tömb általánosítása.  Ennek van olyan művelete amivel az indextípus felső határát módosíthatjuk, ezáltal változó elemszámú sorozatokat kezelhetünk, továbbá a megvalósítása kis méretű tömbökkel dolgozik.  Adott E elemtípus esetén a flexibilis tömb (FTömb) adattípus értékhalmaza az összes A : 0..N ---> E függvény.

46 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)46 Flexibilis tömb műveletei  Kiolvas( -> A:FTömb; -> i:int; <- X:E) ■Az A függvény értékének kiolvasása  Módosít( A:FTömb; -> i:int; -> X:E) ■Az A függvény értékének módosítása  X=Y értékadás, ha X és Y FTömb típusú változók.  Létesít( A:FTömb; -> N:int) ■N elemű flexibilis tömböt létesít.  Megszüntet( A:FTömb) ■Törli az A flexibilis tömbhöz foglalt memóriát.

47 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)47 Flexibilis tömb műveletei  Felső( -> A:FTömb): int ■A felső határ lekérdezése  Növel( -> A : FTömb; d:int) ■Az aktuális indextípus felső határát a d értékkel növeli.  Csökkent( -> A : FTömb; d:int) ■Az aktuális indextípus felső határát a d értékkel csökkenti.

48 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)48 Flexibilis tömb megvalósítása  A megvalósításhoz válasszunk egy L konstanst.  L elemszámú dinamikussá tett tömbökből, amiket lapoknak nevezünk, állítsuk össze a nagy tömböt úgy, hogy felveszünk egy LT laptérkép tömböt, amelynek elemei lapokra mutató pointerek.

49 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)49 Flexibilis tömb megvalósítása  Ezt szemlélteti az ábra. 0 1 (N-1)/L 0 L-1... LT 0... L-1 L L-1 ((N-1)/L)L L N-1 (N-1)%L N ((N-1)%L)+1

50 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)50 Flexibilis tömb megvalósítása /* Globális elemek a flexibilis tömb megvalósításához */ #define L ??? /* lapméret */ typedef enum {false, true} bool; /* logikai típus */ typedef ??? elemtip; /* a tömb elemtípusa */ typedef elemtip *laptip; typedef laptip *lapterkeptip; typedef struct ftomb { lapterkeptip lt; /* laptérkép */ unsigned int hatar; /* aktuális indexhatár */ } ftomb; >>>

51 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)51 Flexibilis tömb megvalósítása /* A műveletek megvalósítása: */ void kiolvas(ftomb a, unsigned int i, elemtip *x) { if(i < a.hatar) { *x = a.lt[i / L][i % L]; } void modosit(ftomb a, unsigned int i, elemtip x) { if(i < a.hatar) { a.lt[i / L][i % L] = x; } >>>

52 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)52 Flexibilis tömb megvalósítása void letesit(ftomb *a, unsigned int n) { int j; if(n) { a->hatar = n; a->lt=(elemtip**)malloc( (1+((n-1)/L))*sizeof(lapterkeptip)); for(j=0; j<=((n-1) / L); ++j) { a->lt[j]=(elemtip*)malloc(L*sizeof(elemtip)); /* lapok létesítése */ } } else { a->hatar = 0; a->lt = NULL; } >>>

53 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)53 Flexibilis tömb megvalósítása void megszuntet(ftomb *a) { int j; if(a->hatar) { for(j=0; j hatar-1) / L); ++j) { free(a->lt[j]); /* lapok törlése */ } free(a->lt); a->hatar=0; } unsigned int felso(ftomb a) { return a.hatar; } >>>

54 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)54 Flexibilis tömb megvalósítása void novel(ftomb *a, unsigned int d) { int j; a->lt = (elemtip**)realloc(a->lt, (1+((a->hatar+d-1)/L))*sizeof(lapterkeptip)); for(j=(a->hatar ? ((a->hatar-1)/L)+1 : 0) ; j hatar+d-1)/L; ++j) { a->lt[j]=(elemtip*)malloc(L*sizeof(elemtip)); } a->hatar += d; } >>>

55 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)55 Flexibilis tömb megvalósítása void csokkent(ftomb *a, unsigned int d) { int j; if(d hatar) { for(j=(a->hatar-d-1)/L +1; j hatar-1)/L; ++j) { free(a->lt[j]); /* lapok törlése */ } a->hatar -= d; a->lt = (elemtip**)realloc(a->lt, (1+((a->hatar-1)/L))*sizeof(lapterkeptip)); }

56 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)56 Rendezés több szempont szerint  Problémafelvetés ■A beolvasott adatokat rendezzük több szempont szerint is egy egyszerű rendezési algoritmussal és minden rendezés után legyen kiíratás is.  Specifikáció ■Flexibilis tömbbel dolgozzunk ■Input –A tömb elemei. ■Output –A különböző szempontok szerint rendezett tömb.

57 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)57 Rendezés több szempont szerint  Algoritmustervezés: ■A fő algoritmusban csak az elemeket kell beolvasni egy végjelig, majd rendre aktivizálni kell a különböző szempontok szerinti rendezést, végül az eredményt kiíratni. ■A rendezés a beszúrórendezés lesz.

58 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)58 Beszúró rendezés  Problémafelvetés ■Rendezzük egy tömb elemeit  Specifikáció ■Input –Egy tömb melynek elemtípusán értelmezett egy rendezési reláció. ■Output –A reláció alapján rendezett tömb.

59 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)59 Beszúró rendezés  Algoritmustervezés: ■A tömböt logikailag egy már rendezett és egy még rendezetlen részre osztjuk, és a rendezetlen rész első elemét beszúrjuk a rendezett elemek közé úgy, hogy azok rendezettek maradjanak

60 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)60 Rendezés több szempont szerint /* Rendezzük névsorba illetve átlag szerint a hallgatókat! * Flexibilis tömbbel történik a megvalósítás, tehát a * névsor hosszát nem kell előre megmondani. * Készítette: Dévényi Károly, * Február 16. * Módosította: Gergely Tamás, * Augusztus 15. */ #include #define L 10 /* lapméret */ >>>

61 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)61 Rendezés több szempont szerint typedef enum {false, true} bool; /* logikai típus */ typedef struct elemtip { /* a tömb elemtípusa */ char nev[21]; float adat; } elemtip; typedef elemtip *laptip; typedef laptip *lapterkeptip; typedef struct ftomb { lapterkeptip lt; /* laptérkép */ unsigned int hatar; /* aktuális indexhatár */ } ftomb; typedef bool (*RendRelTip)(elemtip, elemtip); >>>

62 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)62 Rendezés több szempont szerint /* A műveletek megvalósítása: */ void kiolvas(ftomb a, unsigned int i, elemtip *x) { if(i < a.hatar) { *x = a.lt[i / L][i % L]; } void modosit(ftomb a, unsigned int i, elemtip x) { if(i < a.hatar) { a.lt[i / L][i % L] = x; } >>>

63 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)63 Rendezés több szempont szerint void letesit(ftomb *a, unsigned int n) { int j; if(n) { a->hatar = n; a->lt=(elemtip**)malloc( (1+((n-1)/L))*sizeof(lapterkeptip)); for(j=0; j<=((n-1) / L); ++j) { a->lt[j]=(elemtip*)malloc(L*sizeof(elemtip)); /* lapok létesítése */ } } else { a->hatar = 0; a->lt = NULL; } >>>

64 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)64 Rendezés több szempont szerint void megszuntet(ftomb *a) { int j; if(a->hatar) { for(j=0; j hatar-1) / L); ++j) { free(a->lt[j]); /* lapok törlése */ } free(a->lt); a->hatar=0; } unsigned int felso(ftomb a) { return a.hatar; } >>>

65 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)65 Rendezés több szempont szerint void novel(ftomb *a, unsigned int d) { int j; a->lt = (elemtip**)realloc(a->lt, (1+((a->hatar+d-1)/L))*sizeof(lapterkeptip)); for(j=(a->hatar ? ((a->hatar-1)/L)+1 : 0) ; j hatar+d-1)/L; ++j) { a->lt[j]=(elemtip*)malloc(L*sizeof(elemtip)); } a->hatar += d; } >>>

66 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)66 Rendezés több szempont szerint void csokkent(ftomb *a, unsigned int d) { int j; if(d hatar) { for(j=(a->hatar-d-1)/L +1; j hatar-1)/L; ++j) { free(a->lt[j]); /* lapok törlése */ } a->hatar -= d; a->lt = (elemtip**)realloc(a->lt, (1+((a->hatar-1)/L))*sizeof(lapterkeptip)); } >>>

67 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)67 Rendezés több szempont szerint void beszuroRend(ftomb t, RendRelTip kisebb) { /* A Kisebb rendezési reláció szerinti helyben rendezés */ int i,j; elemtip e,f; for(i = 1; i < felso(t); ++i) { kiolvas(t, i, &e); j = i-1; while(true) { if(j<0) break; kiolvas(t, j, &f); if(kisebb(f, e)) break; modosit(t, ((j--)+1), f); } modosit(t, j+1, e); } } /* BeszuroRend */ >>>

68 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)68 Rendezés több szempont szerint bool NevSzerint(elemtip X, elemtip Y) { /* a névsor szerinti rendezési reláció */ return strcmp(X.nev, Y.nev) <= 0; } bool AdatSzerint(elemtip X, elemtip Y) { /* az adat szerinti rendezési reláció */ return X.adat <= Y.adat; } bool CsokAdatSzerint(elemtip X, elemtip Y) { /* az adat szerint csökkenő rendezési reláció */ return X.adat >= Y.adat; } >>>

69 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)69 Rendezés több szempont szerint int main() { ftomb sor; elemtip hallg; /* beolvasáshoz */ int i; letesit(&sor, 0); /* a flexibilis tömb létesítése */ /* beolvasás */ printf("Kérem az adatsort, külön sorban név és adat!\n"); printf("A végét a * jelzi.\n"); scanf("%20[^\n]%*[^\n]", hallg.nev); getchar(); i = 0; /* az i. helyre fogunk beírni */ while(strcmp(hallg.nev, "*")) { novel(&sor, 1); /* a flexibilis tömb bővítése */ scanf("%f%*[^\n]", &hallg.adat); getchar(); modosit(sor, i++, hallg); scanf("%20[^\n]%*[^\n]", hallg.nev); getchar(); } >>>

70 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)70 Rendezés több szempont szerint beszuroRend(sor, NevSzerint); /* Rend. névsor szerint */ printf("Névsor szerint rendezve:\n"); for(i = 0; i < felso(sor); ++i) { /* Kiíratás */ kiolvas(sor, i, &hallg); printf("%6.2f %s\n", hallg.adat, hallg.nev); } beszuroRend(sor, AdatSzerint); /* Rend. adat szerint */ printf("Adat szerint rendezve:\n"); for(i = 0; i < felso(sor); ++i) { /* Kiíratás */ kiolvas(sor, i, &hallg); printf("%6.2f %s\n", hallg.adat, hallg.nev); } beszuroRend(sor, CsokAdatSzerint); /* Rendezés újra */ printf("Adat szerint csökkenő sorba rendezve:\n"); for(i = 0; i < felso(sor); ++i) { /* Kiíratás */ kiolvas(sor, i, &hallg); printf("%6.2f %s\n", hallg.adat, hallg.nev); } megszuntet(&sor); /* a flexibilis tömb törlése */ }

71 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)71 Láncok  Tekintsük azonos típusú adatelemek sorozatát.  Ha a sorozat bármely pozíciójára vonatkozó bővítés és törlés műveletet is akarunk végezni, akkor a tömbös reprezentálás nem lehet hatékony, ehelyett a sorozatnak láncolással történő reprezentálása ajánlott.  Láncoláson olyan adatszerkezetet értünk, amely a tárolandó sorozat minden elemét egy olyan rekordban (cellában) tárolja, amely a sorozat következő elemének elérését biztosító információt is tartalmazza.

72 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)72 Sorozat Láncok  Az elérési információ lehet egy pointer érték, amely a sorozat következő elemét tartalmazó cellára (dinamikus változóra) mutató pointer.  A sorozatot az első elemére mutató pointerrel adhatjuk meg. 2. Adat Elérési információ 3. Adat Elérési információ 4. Adat NULL 1. Adat Elérési információ

73 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)73 Láncok  C-ben így hozhatunk létre láncolt lista típust: typedef ??? elemtip; /* a sorozat elemtípusa */ typedef struct cellatip { elemtip adat; /* adatelem */ struct cellatip *csat; /* a következő elem cellájára */ } cellatip; typedef struct cellatip *pozicio; /* pointer */

74 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)74 Láncok  Deklaráljuk a p pointert! Lehet a következő módokon: cellatip *p; struct cellatip *p; pozicio p;  A p pointer által megmutatott cella egyes mezőire így hivatkozhatunk: ■ p->adat ■ p->csat

75 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)75 Láncok  A -> és. struktúraoperátorok a precedencia- hierarchia csúcsán állnak, és ezért nagyon szorosan kötnek.  A ++p->adat nem p -t, hanem az adat mezőt inkrementálja, mivel az alapértelmezés szerinti zárójelezés: ++(p->adat)

76 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)76 Láncok  Zárójelek használatával a kötés megváltoztatható: (++p)->adat az adat -hoz való hozzáférés előtt növeli p -t, míg (p++)->adat azt követően inkrementál.  Láncok esetén vigyázzunk ezekkel a műveletekkel, mert egyáltalán nem biztos, hogy két cellatip típusú láncelem közvetlenül egymás után helyezkedik el a memóriában!

77 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)77 Láncok  A lánc soron következő elemét a p->csat pointeren keresztül a *p->csat hozza be.

78 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)78 Láncok *p->csat++ azután inkrementálja csat -t, miután hozzáfért ahhoz, amire mutat (ekkor a lánc megszakadhat!) (*p->csat)++ azt növelné, amire csat mutat, (de ezt most nem lehet, mert ez egy struct ) *p++->csat azután inkrementálja p -t, hogy hozzáfért ahhoz, amire csat mutat (de ekkor nem biztos, hogy p továbbra is a lánc valamelyik elemére mutat).

79 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)79 Láncok  Láncok bejárására írhatunk olyan függvényt amelynek paramétere az elvégzendő művelet: typedef void (*muvelettip)(elemtip*); void bejar(pozicio lanc, muvelettip muv) { pozicio p; for(p = lanc; p != NULL; p = p->csat) { /* művelet a sorozat elemén */ muv(&(p->adat)); }

80 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)80 Típusokról C-ben  A következőkben a C típusokhoz, típusképzésekhez, deklarációkhoz tartozó néhány tudnivalót tekintünk át.

81 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)81 Struct, Union, Enum  Változódeklarációk: struct { int a, b; } vstruct; union { long long l; double d; } vunion; enum { nulla, egy, ketto, harom } venum;

82 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)82 Struct, Union, Enum  A struct, union és enum a típusdeklaráció, típusdefiníció szempontjából hasonlóan működik, így amit a következőkben a struct típusról elmondunk, az analóg módon a union és enum típusokra is érvényes.

83 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)83 Struct, Union, Enum  Ha ugyanilyen típusú változókat szeretnénk később is deklarálni akkor érdemes elnevezni a struktúrát: struct s { int a, b; } vstruct;... struct s masodik;... struct s harmadik;

84 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)84 Struct, Union, Enum  De megtehetjük azt is, hogy egyszerűen csak definiáljuk a struktúrát (változódeklaráció nélkül), és később használjuk fel: struct s { int a, b; };... struct s masodik;... struct s harmadik;

85 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)85 Struct, Union, Enum  Sőt, megtehetjük azt is, hogy egyelőre csak deklaráljuk a struktúrát, és csak később definiáljuk (de a definíció NEM maradhat el!): struct s;... struct s masodik;... struct s harmadik;... struct s { int a, b; } vstruct;

86 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)86 Struct, Union, Enum  Változódeklaráció helyett készíthetünk típusdefiníciót is: typedef struct { int a, b; } S;... S masodik; S harmadik;

87 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)87 Struct, Union, Enum  Akár így is: struct s { int a, b; } vstruct; typedef struct s S;... struct s masodik; S harmadik; s negyedik; /* ROSSZ !!! */ struct S otodik; /* ROSSZ !!! */

88 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)88 Struct, Union, Enum  Vagy így: typedef struct s { int a, b; } S;... struct s masodik; S harmadik; s negyedik; /* ROSSZ !!! */ struct S otodik; /* ROSSZ !!! */

89 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)89 Struct, Union, Enum  De adhatjuk a struktúrának és a típusnak ugyanazt a nevet is: typedef struct st { int a, b; } st;... struct st masodik; st harmadik;

90 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)90 Bonyolultabb deklarációk  A C nyelvben az összetett típusok megadásakor megismert műveleteket véges sokszor ismételhetjük.  Mivel a deklaráció nem olvasható egyszerűen balról jobbra és mivel a * művelet alacsonyabb prioritású a [] és () műveleteknél, ezért érdemes néhány példával megvilágítani a bonyolultabb eseteket.

91 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)91 Bonyolultabb deklarációk  A prioritási előírás csökkenő sorrendben ■B elemkiválasztások és fgv. ( [],., ->, () ) ■J a egyoperandusú műveletek ( -, ++, --, !, ~, &, *, sizeof ) ■B a multiplikatív műveletek ( *, /, % ) ■B az additív műveletek ( +, - ) ■B bitléptetés ( > ) ■B a kisebb-nagyobb relációs műveletek ( =, ) ■B az egyenlő-nem egyenlő relációs műveletek ( ==, != ) ■B bitenkénti 'és' művelet ( & ) ■B bitenkénti 'kizáró vagy' művelet ( ^ ) ■B bitenkénti 'vagy' művelet ( | ) ■B a logikai 'és' művelet ( && ) ■B a logikai 'vagy' művelet ( || ) ■J a feltételes művelet ( ? : ) ■J értékadó művelet ( =, +=, -=, *=, /=, %=, >>=, <<=, &=, ^=, |= ) ■B szekvencia művelet (, )

92 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)92 Bonyolultabb deklarációk  Bár a prioritási előírást a műveletek elvégzésénél vezettük be, de ugyanezt az előírást használjuk a deklarációnál is.  A műveletek elvégzésének sorrendjét zárójelek használatával befolyásolhatjuk. Ezt tehetjük a deklarációknál is. Pl: int *p /* int-re mutató pointer */ int x[10] /* tömb 10 int-ből */ int (*x)[10] /* pointer mutat egy tömbre, ami 10 int-ből áll */ int *x[10] /* tömb 10 pointerből, melyek int-re mutatnak */

93 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)93 Bonyolultabb deklarációk void (*f)(int) /* pointer egy függvényre, aminek paramétere int és nincs visszaadott értéke */ int (*f)(void) /* pointer egy függvényre, aminek nincs paramétere és a visszaadott érték típusa int */ int (*x[])(int) /* tömb, amelyik pointerekből áll. Ezek olyan függvényre mutatnak, melynek paramétere is és visszaadott értékének típusa is int. */

94 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)94 Bonyolultabb deklarációk  Lehet-e ennél bonyolultabbakat is? char (*(*f())[])() –függvény visszatér pointerrel, ami egy tömbre mutat és pointerekből áll, amelyek olyan függvényre mutatnak, aminek visszaadott értékének típusa char char (*(*x[3])())[5] –3 pointerből álló tömb. A pointerek olyan függvényre mutatnak, amely pointerrel tér vissza. Ezek 5 char -ból álló tömbre mutatnak.

95 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)95 Bonyolultabb deklarációk  Mit lehet tanácsolni, ha bonyolult deklarációt kell elkészíteni? ■Például hogyan kell deklarálni egy N elemű tömböt, amely függvényre mutató pointerekből áll. A függvény olyan pointerrel tér vissza, amely függvényre mutat, és a függvény karakterre mutató pointerrel tér vissza.  Három módszert szoktak ajánlani: ■Próbáljuk meg felírni: char *(*(*a[N])())();

96 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)96 Bonyolultabb deklarációk ■Típusdefiníciót használva építsük fel lépésenként a deklarációt. A megjegyzésekben a megfelelő angol terminologiát is bevezetjük: typedef char *pc; /* pointer to char */ typedef pc fpc(); /* function returning pointer to char */ typedef fpc *pfpc; /* pointer to... */ typedef pfpc fpfpc(); /* function returning... */ typedef fpfpc *pfpfpc; /* pointer to... */ pfpfpc a[N]; /* array of... */

97 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)97 Bonyolultabb deklarációk ■Használjuk a cdecl programot, amelyik angolról C-re és megfordítva képes deklarálni illetve a deklarációt elmagyarázni. cdecl> explain char *(*(*a[])())() declare a as array of pointer to function returning pointer to function returning pointer to char cdecl> declare a as array of pointer to function returning pointer to function returning pointer to char char *(*(*a[])())()

98 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)98 Bonyolultabb deklarációk  És ez még mind semmi, mert a függvények paramétereiről nem mondtunk semmit! A paraméterek típusa ugyanis megadható és minden paraméternek a típusa az előzőekhez hasonló bonyolultságú lehet.  Azt is szokták tanácsolni, hogy egy bonyolult deklaráció megértését kezdjük bentről kifelé.

99 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)99 Bonyolultabb deklarációk  A C nyelvben nemcsak arra van szükség, hogy egy azonosítót változóazonosítóvá vagy típusazonosítóvá deklaráljunk, hanem arra is, hogy magát a típust adjuk meg.  Ezt kell tenni függvénydeklarátoroknál a paraméterek típusának megadásakor, sizeof argumentumaként, típuskényszerítésnél.  A típus megadása szintaktikailag ugyanúgy történik, mint a változó deklarálása, csak az azonosító marad el.

100 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)100 Bonyolultabb deklarációk int /* egész */ int * /* int-re mutató pointer */ int [10] /* tömb 10 int-ből */ int (*)[10] /* pointer mutat egy tömbre, ami 10 int-ből áll */ int *[10] /* tömb 10 pointerből, melyek int-re mutatnak */ void (*)(int) /* pointer egy függvényre, melynek paramétere int és nincs visszaadott értéke */ int (*)(void) /* pointer egy függvényre, melynek nincs paramétere és a visszaadott érték típusa int */ int (*[])(int) /* tömb, amelyik pointerekből áll. Ezek olyan függvényre mutatnak, melynek paramétere is és visszaadott értékének típusa is int. */

101 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)101 Típuskényszerítés  A típuskényszerítés egy konverziós művelet, amelyet egy ()-be zárt típusmegadással írunk elő.  A prioritási előírás csökkenő sorrendben ■B elemkiválasztások és fgv. ( [],., ->, () ) ■J a egyoperandusú műveletek ( -, ++, --, !, ~, &, *, sizeof ) ■J típuskényszerítés ( () ) ■B a multiplikatív műveletek ( *, /, % ) ■B az additív műveletek ( +, - ) ■B bitléptetés ( > ) ■B a kisebb-nagyobb relációs műveletek ( =, ) ■B az egyenlő-nem egyenlő relációs műveletek ( ==, != ) ■B bitenkénti 'és' művelet ( & ) ■B bitenkénti 'kizáró vagy' művelet ( ^ ) ■B bitenkénti 'vagy' művelet ( | ) ■B a logikai 'és' művelet ( && ) ■B a logikai 'vagy' művelet ( || ) ■J a feltételes művelet ( ? : ) ■J értékadó művelet ( =, +=, -=, *=, /=, %=, >>=, <<=, &=, ^=, |= ) ■B szekvencia művelet (, )

102 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)102 Típuskényszerítés  Példa típuskényszerítésre: ■Két int tipusú változó osztása egészosztás és int eredményt ad. Ha nem egészosztást szeretnénk, akkor kényszerítsük az egyik operandust valamelyik valós típusúvá: int i = 7; j = 2; double x; x = i / j; /* x értéke 3.0 lesz */ x = (double) i / j; /* x értéke 3.5 lesz */

103 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)103 Típuskényszerítés  Példa típuskényszerítésre: ■A dinamikus változók számára leggyakrabban a malloc() függvénnyel foglalunk helyet. A függvény a malloc.h -ban van deklarálva: typedef unsigned size_t; void *malloc(size_t); void free(void *); void *realloc(void *, size_t); void *calloc(size_t, size_t);

104 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)104 Típuskényszerítés ■A függvény lefoglalja a megadott bájtszámú területet és a címét visszadja. Ha nem sikerül a tárterület lefoglalása, akkor a visszaadott érték NULL. ■A malloc() függvény alkalmazásánál típuskényszerítést kell használni. Pl. int *p; p = (int *) malloc(100 * sizeof(int));

105 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)105 Típuskényszerítés  Hasonlóan kell eljárni bonyolultabb típusok esetén: typedef struct cellatip { Elemtip adat; /* adatelem */ struct cellatip *csat; /* a következő elem cellájára */ } cellatip; typedef struct cellatip *pozicio; /* pointer típus */ pozicio p; p = (cellatip *) malloc(sizeof(cellatip));

106 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)106 Típuskényszerítés  A típuskényszerítés egy konverziós művelet, tehát nem alkalmazható mindig. Pl. ■Van egy void * p pointer. Tudom, hogy most int - re mutat. Szeretném a pointert léptetni. Lehet-e így? ((int *)p)++; Így nem lehet, de így már igen: p = (void *)((int *)p + 1); vagy egyszerűen így p += sizeof(int);

107 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)107 Az I/O alapjai  A be- és kiviteli (I/O) szolgáltatások nem részei a C nyelvnek.  Az ANSI szabvány szerint standard könyvtár áll rendelkezésre.  Ha használni akarjuk, akkor a programban szerepelnie kell a következő sornak: #include

108 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)108 Az I/O alapjai  C-ben megkülönböztetünk ■Alacsony szintű ■Magas szintű fájlkezelést.  Magas szintű fájlkezelés esetén külön beszélünk az úgynevezett standard fájlok kezeléséről.

109 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)109 Magas szintű fájlkezelés  A hordozhatóság érekében ajánlott ezt használni.  Az adatokat egy adatfolyamnak (stream) tekintjük.  A stream I/O pufferezett, vagyis az írás/olvasás fizikailag nagyobb darabokban történik.  A puffer hossza a stdio.h-ban van definiálva: ■ #define BUFSIZ _IO_BUFSIZ ahol ■ #define _G_BUFSIZ 8192 ■ #define _IO_BUFSIZ _G_BUFSIZ

110 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)110 Magas szintű fájlkezelés  A UNIX-ban 3 előre definiált stream van: ■ stdin ■ stdout ■ stderr  Mindhárom karakterfolyamnak tekinthető és a program indulásakor automatikusan úgy nyitódnak meg, hogy ■az stdin a billentyűzethez ■az stdout és a stderr a képernyőhöz rendelődik.

111 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)111 Standard fájlok kezelése  Az stdin, stdout, stderr ■magas szinten, ■szöveges módban kezelt fájlok  A fájlkezelő függvények a stdio.h -ban vannak

112 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)112 Magas szintű fájlkezelés  Természetesen a UNIX-ban szokásos átírányításokkal az eredmény adatállományba is írható, illetve az input adatok adatállományból is vehetők, de ez nem a C, hanem az operációs rendszer tulajdonsága.  Sok függvény áll rendelkezésünkre, hogy egy karakterfolyamot kezeljünk.

113 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)113 Alapvető függvények  int getchar(void) ■Makró, mely beolvas egy karaktert a stdin -ről. ■Az EOF konstans értéket adja vissza, amikor az általa éppen olvasott, bármiféle bemenet végére ért (például lenyomtuk a + d billantyűkombinációt Linux-ban) ■Implementációtól függően, de általában pufferelten olvas: –A program csak akkor kapja meg a begépelt karakter(eke)t, ha a puffer betelt vagy sorvéget (fájlvégét) nyomtunk. –Közvetlen billentyűleütés érzékelésére nem alkalmas, de nem is ez a feladata. (A közvetlen billentyűleütést csak oprendszerfüggő módon tudnánk figyelni.)

114 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)114 Alapvető függvények  char *gets(char *buf) ■Beolvas egy sort a stdin -ről a buf-ba. ■A buf egy létező és elegendő hosszú karaktertömb kell, hogy legyen, mert: –Nem ellenőrzi, hogy szabad vagy foglalt memóriaterületet ír-e felül. ■Válaszértéke –A karaktertömb címe sikeres olvasáskor. – NULL pointer sikertelen olvasáskor (hiba vagy fájlvége a sor elején).

115 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)115 Alapvető függvények ■A sor közbeni fájlvége esetén –Lezárja a sztringet a buf-ban. –A buf pointerrel tér vissza. ■Az újsor karaktert nem olvassa be, hanem '\0' karaktert tesz helyette a buf-ba (eltér az fgets() függvénytől!), ezért nem alkalmas az újsor karakter beolvasására (arra használhatjuk a getchar() makrót). ■Egy megjegyzés a gets manual oldalról: –Never use gets! –Soha ne használd a gets függvényt! –A buffer overflow súlyos biztonsági hiba lehet!

116 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)116 Alapvető függvények  int putchar(int ch) ■Makró, mely kiír egy karaktert a stdout -ra. ■A kiírt karakter kódját adja vissza sikeres művelet esetén, EOF -ot ha hiba történt. ■Nem pufferelt.

117 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)117 Alapvető függvények  int puts(const char *buf) ■A buf stringet kiírja a stdout -ra. ■A sztringvége karakter helyett újsort ír. ■Válaszértéke: –Egy nemnegatív érték sikeres végrehajtás esetén. – EOF hiba esetén.

118 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)118 Példa  A bemenet kisbetűssé alakítása: #include main() { int c; while ((c = getchar()) != EOF) { putchar(isupper(c) ? tolower(c) : c); /* putchar(tolower(c)); is jó megoldás */ }

119 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)119 Formatált I/O műveletek  int printf(char *formátum,...) ■Kinyomtatja a stdout -ra az aktuális paraméterek értékeit a formátum szövegben előírt formában. ■A visszatérési érték a kiírt karakterek száma. ■A formázó karakterlánc kétféle típusú objektumot tartalmaz: –Közönséges karaktereket, amelyeket egyszerűen a kimeneti folyamra másol. –Konverzió-specifikációkat, amelyek mindegyike a soron következő paraméter konvertálását és kiíratását írja elő.

120 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)120 Formatált I/O műveletek  Formátumbeli speciális ESCAPE karakterek: ■ \a hangjelzés ■ \n újsor ■ \r CR ■ \b backspace ■ \t vízszintes tabulátor ■ \v függőleges tabulátor ■ \f lapdobás (form-feed)

121 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)121 Formatált I/O műveletek  Formátumbeli speciális ESCAPE karakterek: ■ \" ” ■ \\ \ ■ \NNN –Az NNN oktális kódú karakter (legfeljebb 3 darab). ■ \xnn –Az nn hexadecimális kódú karakter. ■ \unnnn –Az nnnn hexadecimális kódú 16 bites Unicode karakter. ■ \Unnnnnnnn –Az nnnnnnnn hexadecimális 32 bites Unicode kódú karakter.

122 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)122 Formatált I/O műveletek  Egy konverzió-specifikáció (más néven formátumvezérlő szekvencia) általános alakja: %[flag][n[.m]][{h,l}]type (A [] közötti rész szabadon elhagyható.)

123 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)123 Formatált I/O műveletek  %[flag][n[.m]][{h,l}]type  A type egy karakter, melyet konverziós karakternek nevezünk.  A konverziós karakterek és jelentésük: ■ d,i –A paraméter decimális jelölésmódúvá alakul ( int, short, long, long long ). ■ u –A paraméter előjel nélküli decimális jelölésmódúvá alakul ( unsigned int, unsigned short, unsigned long, unsigned long long ).

124 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)124 Formatált I/O műveletek ■ o –A paraméter előjel nélküli oktális számmá konvertálódik ( unsigned int, unsigned short, unsigned long, unsigned long long ). ■ x,X –A paraméter előjel nélküli hexadecimális számmá konvertálódik ( unsigned int, unsigned short, unsigned long, unsigned long long ). ■ c –A paraméter egyetlen karakter ( char ).

125 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)125 Formatált I/O műveletek ■ f –A paramétert float -nak vagy double -nak tekinti,és a [-]mmm.nnnnnn decimális jelölésmódba konvertálja, ahol az n-ek karakterláncának hosszát a pontosság adja meg. Az alapértelmezés szerinti pontosság 6. ■ e,E –A paramétert float -nak vagy double -nak tekinti, és a [-]m.nnnnnnE[-]xx decimális jelölésmódba konvertálja, ahol a számjegyek számát a pontosság adja meg. Az alapértelmezés szerinti pontosság 6. ■ g,G – %e és %f közül a rövidebbet használja; az értéktelen nullákat elhagyja.

126 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)126 Formatált I/O műveletek ■ s –A paraméter karakterlánc (sztringre mutató pointer); a láncbeli karakterek a pontossággal megadott darabszámig vagy a nulla karakterig mindaddig nyomtatódnak. ■ p –Cím (pointer) hexadecimális formában. ■ n –Az eddig a pontig kiírt karakterek számát adja vissza a megfelelő paraméter által mutatott int változóban. ■ % –Kiírja a % karaktert. ■Ha a % -ot követő karakter nem konverziós karakter, az illető karakter nyomtatásra kerül.

127 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)127 Formatált I/O műveletek  %[flag][n[.m]][length]type  A flag hiányában a kiíratás jobbra igazítva, balról szóközökkel kitöltve történik ■ - balra igazítás. ■ + előjel kötelező kiírása. ■ ’ ’ (szóköz) kötelező előjel, + helyett szóközt ír. ■ 0 számok előtt a kitöltés a '0' karakterrel megy. ■ # –Lebegőpontosnál kötelező tizedespont. – o, x, X esetén 0, 0x, 0X kiírása nullától különböző értékek előtt.

128 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)128 Formatált I/O műveletek  %[flag][n[.m]][length]type  Az n a mezőszélességet jelenti ■Egy decimális szám, amely a minimális mezőszélességet határozza meg. (A számérték nem kezdődhet 0-val, mert azt flag-ként értelmezi.) ■Ha a szám helyén egy '*' szerepel, akkor a szélességet a következő argumentum kifejezés értéke határozza meg: printf("%*d",5,125); printf("%5d", 125);

129 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)129 Formatált I/O műveletek ■A következő argumentum értéke legalább ilyen széles, vagy szükség esetén szélesebb mezőbe nyomtatódik ki. ■Ha a konvertált argumentum kevesebb karakterből áll, mint a mezőszélesség, akkor bal oldalon (vagy, ha a balra igazítás jelző szerepel, akkor jobb oldalon) a mező kitöltődik, hogy ezáltal az előírt mezőszélesség meglegyen. ■A kitöltő karakter közönséges esetben szóköz, ill. amennyiben a számot íratunk ki jobbra igazítva, és megadtuk a 0 flag-et, akkor a '0' karakter.

130 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)130 Formatált I/O műveletek  %[flag][n[.m]][length]type  Az m a pontosságot jelenti ■Decimális szám: – i, d, o, x, X, u esetén legalább ennyi számjegyet ír ki, szükség esetén balról a '0' karakterrel kitöltve a helyet. – f, e, E, g, G esetén tizedesjegyek illetve értékes jegyek száma; az utolsó jegyet kerekíti. Ha 0, akkor a tizedespont sem kerül kiíratásra. Hiányában az alapértelmezés 6. – s esetén a sztringből kiírható karakterek maximális száma. ■Ha a szám helyén egy '*' szerepel, akkor a pontosságot a következő argumentum kifejezés értéke határozza meg.

131 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)131 Formatált I/O műveletek  %[flag][n[.m]][length]type  A length a hosszmódosító ■ hh –Az argumentumot char -ként kezeli. ■ h –Az argumentumot short -ként kezeli. ■ l, L –Az argumentumot long -ként illetve long double -ként kezeli. ■ ll –Az argumentumot long long -ként kezeli.

132 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)132 Formatált I/O műveletek  Figyeljük meg, hogy ■A printf() kerekít ■A konvertálás csonkít #include int main() { int i; double d; for(d=-2.0; d<=2.0; d+=1.0/3.0) { i=d; printf("d=%23.20lf; %5.2lf; d=%2.0lf; i=%2d;\n", d, d, d, i); }

133 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)133 Formatált I/O műveletek d= ; -2.00; d=-2; i=-2; d= ; -1.67; d=-2; i=-1; d= ; -1.33; d=-1; i=-1; d= ; -1.00; d=-1; i=-1; d= ; -0.67; d=-1; i= 0; d= ; -0.33; d=-0; i= 0; d= ; -0.00; d=-0; i= 0; d= ; 0.33; d= 0; i= 0; d= ; 0.67; d= 1; i= 0; d= ; 1.00; d= 1; i= 0; d= ; 1.33; d= 1; i= 1; d= ; 1.67; d= 2; i= 1; d= ; 2.00; d= 2; i= 1;

134 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)134 Formatált I/O műveletek  Mi történik a printf() hívásakor ? Pl.: printf("%d %d %d\n", 10, 20)  A verembe (stack) beletevődnek az argumentumok, de milyen sorrendben?  Lényeges, hogy kiolvasásnál a formátum sztring megelőzze a többi argumentumot, hiszen abból tudjuk, hogy hány és milyen típusú értékeket kell kiolvasnunk.

135 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)135 Formatált I/O műveletek  Tehát a formátum sztringnek kell a verem „tetején” lennie, ezért utolsónak kell betenni.  Tehát a paramétereket a C ■jobbról balra haladva helyezi el a veremben, ■egyre csökkenő címeken, ■végül még beteszi a visszatérési címet

136 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)136 Formatált I/O műveletek  printf("%d %d %d\n", 10, 20); "%d %d %d\n" címe Visszatérési cím

137 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)137 Formatált I/O műveletek  A függvényhívás után az argumentumokat a veremből törölni kell; de ki takarít? ■Ha a hívott printf() visszatérés előtt takarítana, akkor a fenti esetben a formátum sztring alapján még egy további (nem ide tartozó) értéket kitörölne a veremből és az egész összezavarodna. ■Tehát az argumentumokat a hívó függvény törli a visszatérés után, hisz ő tudja biztosan, hogy ténylegesen hány paramétert adott át.

138 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)138 Formatált I/O műveletek  A programozó felelőssége, hogy adott konverzió-specifikációhoz megfelelő típusú argumentumérték tartozzon: A program kimenete: #include int main() { printf("%20lld %20lld\n", (long long)2005, ); printf("%20f %20f\n", (long long)2005, ); }

139 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)139 Formatált I/O műveletek  Vagy:  A program kimenete: #include int main() { printf("%x %x %x %x\n", 1, 2, 3, 4); printf("%x %x %x %x\n", (long long)1, (long long)2, (long long)3, (long long)4); printf("%llx %llx %llx %llx\n", (long long)1, (long long)2, (long long)3, (long long)4); printf("%llx %llx %llx %llx\n", 1, 2, 3, 4); } bffd8d78bffd8df4 b7fabff a

140 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)140 printf("%x %x\n", (long long)1, (long long)2); Formatált I/O műveletek Visszatérési cím Formátumsztring címe ?? ??

141 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)141 printf("%llx %llx\n", 1, 2); Formatált I/O műveletek Visszatérési cím Formátumsztring címe 1 2 ?? ?? ??

142 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)142 Formatált I/O műveletek  int scanf(char *formátum,...) ■Beolvassa a stdin -ről a karaktereket. ■Konvertálja a megfelelő formátumra. ■Elhelyezi a paraméterlistában megadott memóriacímekre. ■A visszatérési érték a beolvasott és sikeresen eltárolt értékek száma. ■A formátumvezérlés technikája megegyezik a printf() formátumvezérlésével.

143 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)143 Formatált I/O műveletek ■A formátum string fix karaktereit sorra összeveti a stdin -ről olvasottakkal. ■A láthatatlan karaktereket egyetlen szóköznek tekinti. ■A formátumparaméterek helyén megpróbálja elvégezni a konverziót. ■Megkeresi az első még fel nem használt (azaz következő) argumentumot és arra a címre elhelyezi az eredményt.

144 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)144 Formatált I/O műveletek  Például:  Az stdin: 3 eredmény:  Akkor v1=3 v2=3 int v1, v2; scanf("%d eredmény: %d", &v1, &v2);

145 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)145 Formatált I/O műveletek  A formátum általános alakja: %[*][width][{h,l}]type  * ■Az adatmezőt beolvassa, de nem helyezi el sehova (tehát ehhez nem kell változócímet megadni)

146 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)146 Formatált I/O műveletek  %[*][width][length]type  width (szélesség) ■A konverzió során figyelembe veendő karakterek száma; hiányában addig olvas, míg logikai alapon meg nem találja a megfelelő mező végét (pl. a típushoz nem illő karaktert).

147 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)147 Formatált I/O műveletek  %[*][width][length]type  length ■ hh –A paraméter char * ■ h –A paraméter short int* ■ l –A paraméter long int* vagy double* ■ L –A paraméter long long* vagy long double*

148 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)148 Formatált I/O műveletek  %[*][width][length]type  type ■ c – width darab (ha nincs megadva, akkor 1) karakter ( char* ) ■ d,D –decimális szám ( char*,... int* ) ■ o,O –oktális szám ( char*,... int* ) ■ x,X –hexadecimális szám ( char*,... int* )

149 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)149 Formatált I/O műveletek ■ i,I – ( char*,... int* ) – 0 -val kezdődő szám oktális – 0x -el kezdődő szám hexadecimális – 0 -tól különböző egésszel kezdődő decimális szám ■ u,U –előjeltelen decimális érték ( unsigned char*, unsigned... int* ) ■ f –lebegőpontos érték ( float*,double*,long double* )

150 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)150 Formatált I/O műveletek ■ s –Karakterlánc (sztring) ( char* ) –Hosszúsága legfeljebb width, az első whitespace karakterig olvas, melyet sztringvégi null karakterrel helyettesít. ■ [karakterek] –Sztring kizárólag a megadott karakterekből ( char* ) –Hosszúsága: width, vagy az első olyan karakterig, amit nem soroltunk fel. ■ [^karakterek] –Sztring kizárólag a meg NEM adott karakterekből ( char* ) –Hosszúsága: width, vagy az első olyan karakterig, amit felsoroltunk.

151 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)151 Formatált I/O műveletek  Problémák: ■Ha egy karaktert nem tud értelmezni, akkor abbahagyja az olvasást. ■A maradékot benne hagyja az stdin -ben. ■A program nem tudja, hogy mi volt a probléma. ■Üres sztringet a %s segítségével nem tudunk beolvasni. ■ %[^\n] esetén az újsor karaktert már nem dolgozza fel. ■Ha az újsort betesszük a formátum sztringbe, akkor beolvassa a scanf, de a beolvasás végét egy újabb sorvéggel kell jeleznünk.

152 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)152 Formatált I/O műveletek ■Megtehetjük, hogy minden scanf után getchar() - okkal ellépkedünk az újsor utánig, de lehet, hogy akkor értékes karaktereken is túlmegyünk. ■Másik megoldás: scanf("%d%*[^\n]", &X); getchar();

153 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)153 Alternatív I/O  int sscanf(char *mp, char *form,…) ■A memória adott területét megpróbálja a scanf() - hez hasonlóan értelmezni és átmásolni. ■A scanf() kiváltására használhatunk sscanf() -et is, az legalább nem az stdin fájlmutatóját rontja el, hanem csak egy memóriapointert.  int sprintf(char *mp, char *form,…) ■A printf() adott memóriaterületre író változata, belső konverziók elvégzésére is használható.

154 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)154 Hozzáférés az adatállományokhoz  A már említett 3 fájl, az stdin, stdout és stderr úgy képzelhető el, mint egy folyam: ■Mi csak nyitni és zárni tudjuk a „zsilipet”, látjuk mi folyik át, de visszahozni azt már nem tudjuk. ■Vagy másképpen: mi csak egy irányban (előre) lépegethetünk a fájlban lévő elemek sorozatán, mindig csak a következő elemre.  Általánosságban viszont egy fájl tartalma megmarad, tehát akárhányszor újra ránézhetünk tettszőleges részére.

155 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)155 Hozzáférés az adatállományokhoz  Minden fájl felfogható elemek (jelen esetben karakterek) sorozataként. Ehhez a sorozathoz tartozik egy író-olvasó fej, ami a fájl értékét jelentő sorozatot két részsorozatra bontja. Tehát egy fájl minden lehetséges értéke [a 0... a i-1 ][a i... a n-1 ] alakban adható meg.  Az író-olvasó fej által kijelölt elem a második sorozat első eleme.

156 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)156 Hozzáférés az adatállományokhoz  Bármilyen művelet a fájlon (egy elem írása vagy olvasása) csak a fejen keresztül történhet.  Lehetséges elemi műveletek: ■Olvasás: kiolvassuk a fej által kijelölt elem értékét és a fej egyet továbblép. ■Írás: megváltoztatjuk a fej által kijelölt elem értékét, vagy ha az a fájl vége volt, akkor hozzáfűzzük az új elemet; a fej egyet továbblép. ■Pozícionálás: a fejet tudjuk mozgatni.

157 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)157 Hozzáférés az adatállományokhoz  Minden fájlhoz egy stdio.h -beli FILE struktúrát rendelünk hozzá.  A FILE struktúra sokféle mezőt tartalmaz (fej pozíció, puffer, stb.), ezekkel azonban nem kell (és nem is érdemes) direkt módon dolgoznunk.  E helyett függvényeket használunk, amikben a fájlhoz rendelt struktúra címe fogja a fájlt azonosítani.

158 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)158 Hozzáférés az adatállományokhoz  Ha tehát fájlokkal szeretnénk dolgozni, a következő műveletekre lesz szükségünk: ■Először a FILE típusú változóhoz hozzárendelünk egy operációs rendszerbeli adatállományt vagy eszközt: FILE *fopen(const char *path, const char *mode); ■Majd használjuk. ■Végül lezárjuk: int fclose(FILE *fp);

159 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)159 Hozzáférés az adatállományokhoz  FILE *fopen(const char *path, const char *mode) ■A path az operációs rendszerben létező fájlra való szabályos hivatkozás. ■Ha a megnyitás nem sikerült, akkor a visszatérési érték NULL ■Ha sikerült, akkor egy FILE -re mutató pointer.

160 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)160 Hozzáférés az adatállományokhoz ■A mode a megnyitás módja, ami lehet: – "r" (read): »Egy már létező fájl megnyitása olvasásra. Ha nem létezik vagy nincs rá olvasási jogunk, az hiba. – "w" (write): »Egy fájl megnyitása írásra. Ha már létezett, a régi tartalma törlődik, egyébként létre lesz hozva. Ha nincs rá írásjogunk, vagy nem tudjuk létrehozni, az hiba. – "a" (append): »Egy fájl megnyitása hozzáfűzésre. Ha már létezett, a régi tartalma megmarad, az új a végéhez fűződik. Ha nem létezett a fájl, akkor egyenértékű a "w" -vel. Ha nincs rá írásjogunk, vagy nem tudjuk létrehozni, az hiba.

161 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)161 Hozzáférés az adatállományokhoz – "r+" (read+write): »Egy már létező fájl megnyitása olvasásra és írásra. Ha nem létezik vagy nincs rá jogunk, az hiba. – "w+" (write+read): »Egy fájl megnyitása írásra és olvasásra. Ha már létezett, a régi tartalma törlődik, egyébként létre lesz hozva. Ha nincs rá jogunk, vagy nem tudjuk létrehozni, az hiba. – "a+" (append+read): »Egy fájl megnyitása hozzáfűzésre és olvasásra. Ha már létezett, a régi tartalma megmarad, az új a végéhez fűződik. Ha nem létezett a fájl, akkor egyenértékű a "w" -vel. Ha nincs rá jogunk, vagy nem tudjuk létrehozni, az hiba.

162 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)162 Hozzáférés az adatállományokhoz ■A mode bizonyos implementációkban tartalmazhatja még: – 't' (text): »Szöveges mód. – 'b' (binary): »Bináris mód. –E két módnak linux alatt nincs jelentőssége. Ha a megjelölés elmarad, a text mód az alapértelmezés.

163 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)163 Hozzáférés az adatállományokhoz  Az író-olvasó fej r, r+, w, w+ esetén a fájl elejére, a, a+ esetén a fájl végére áll.  Ha a fájlt r+, w+, a+ módok valamelyikében nyitottuk meg és váltani akarunk írás és olvasás között, akkor célszerű a puffert az fseek() vagy fflush() függvények valamelyikével a kiüríttetni.

164 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)164 Hozzáférés az adatállományokhoz  Az fopen használata:  A zárójelezésre nagyon kell vigyázni!  Biztonságosabb, ha az értékadás egy külön sorban történik meg: FILE *fp; /* fájlpointer */ if ((fp = fopen("/etc/motd", "r")) == NULL) { printf("Nem sikerült megnyitni a /etc/motd adatállományt"); exit(1); } fp = fopen("/etc/motd", "r"); if (fp == NULL) {... }

165 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)165 Hozzáférés az adatállományokhoz  Alapvető műveletek: ■ int fgetc(FILE *fp) –Egy karakter olvasása fp-ről. ■ int getc(FILE *fp) –Egy karakter olvasása fp-ről (makró). ■ int fputc(char ch, FILE *fp) –Egy karakter írása fp-re. ■ int putc(char ch, FILE *fp) –Egy karakter írása fp-re (makró).

166 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)166 Hozzáférés az adatállományokhoz  int fseek(FILE *fp, long mennyi, int honnan) ■Fájlok direkt elérése, vagyis a fej pozícionálása. ■Lépteti a fájlpointert mennyi bájtnyit. ■ honnan (viszonyítva) lehet: – SEEK_SET : a fájl elejétől. – SEEK_CUR : jelenlegi fájlpozíciótól. – SEEK_END : fájl végétől.

167 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)167 Hozzáférés az adatállományokhoz ■A fájlpointer értéke negatív nem lehet, de mutathat a fájlvégén túlra is, ekkor a rendszer addig a pozícióig nyújtja (szeméttel kiegészíti) a fájlt, és akkor is ott fogja a műveleteket végezni. ■Ha a pozicionálás sikeres volt, akkor 0-t ad vissza.

168 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)168 Hozzáférés az adatállományokhoz  char *fgets(char *buf, int n, FILE *fp) ■Egy sort (de legfeljebb n-1 karaktert) olvas be a fájlból, beleértve a sorvég karaktert is, ezt elhelyezi a buf karaktertömbbe, amelyet sztringvégi nulla karakterrel lezár. ■Visszatérési értéke: –A tömb címe (valóban haszontalan, hisz ezt mi adtuk meg paraméterként) – ha sikerült a művelet. – NULL – hiba esetén (fájl vége, olvasási hiba).

169 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)169 Hozzáférés az adatállományokhoz  int fputs(char *buf, FILE *fp) ■A buf sztring tartalmát kiírja a fájlba. ■Nem tesz a sor végére automatikusan újsort. ■Válaszértéke: – Az utolsó kiírt karakter kódja. – 0 – ha a string üres volt. – EOF – hiba esetén.

170 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)170 Hozzáférés az adatállományokhoz  int fprintf(FILE *fp, char *form,…) ■A printf() függvény fájlba író változata.  int fscanf(FILE *fp, char *form,…) ■A scanf() függvény fájlból olvasó változata.

171 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)171 Hozzáférés az adatállományokhoz  int ungetc(int c, FILE *fp) ■Visszateszi a c karaktert a fájlra úgy, hogy a legközelebbi olvasás ezt a karaktert fogja olvasni. ■Felhasználás: pl. számjegyeket olvasunk be, amikor nem számjegy karakter jött, azt visszatesszük, a számjegyeket pedig egy számmá konvertáljuk. ■Legfeljebb egy karaktert lehet visszatenni, az ungetc() többszöri egymás utáni meghívása nem megengedett.

172 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)172 Hozzáférés az adatállományokhoz  long ftell(FILE *fp) ■Lekérdezi a fej pozícióját.  int feof(FILE *fp) ■Válaszérték: –0: még nem értük el a fájl végét. –más: elértük a fájl végét.  int ferror(FILE *fp) ■Válaszérték: –0: a fájl megnyitása óta nem történt hiba. –más: hiba történt.

173 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)173 Hozzáférés az adatállományokhoz  int fread(char *buf, int rsize, int rn, FILE *fp) ■Az rsize hosszúságú csomagokból rn darabot olvas be a buf címre. ■Visszaadja a ténylegesen beolvasott csomagok számát.

174 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)174 Hozzáférés az adatállományokhoz  int fwrite(char *buf, int rsize, int rn, FILE *fp) ■Az rsize hosszúságú csomagokból rn darabot ír ki a buf címről. ■Visszaadja a ténylegesen kiírt csomagok számát.

175 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)175 Hozzáférés az adatállományokhoz  int fflush(FILE *fp) ■Kiírja a puffer tartalmát. ■Válaszértéke: –0:sikeres – EOF :sikertelen  int fclose(FILE *fp) ■Lezárja a fájlt. ■Válaszértéke: –0:sikeres – EOF :sikertelen

176 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)176 Hozzáférés az adatállományokhoz  Természetesen az előre definiált 3 streamet is kezelhetjük ezekkel a függvényekkel, pl: fprintf(stderr, "Nem működik a gépem"); fputs(stdout, "Sztring\n"); fscanf(stdin, "%s", nev); fgets(stdin, 50, sor);

177 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)177 #include main(){ FILE *fp, *fpb; int a,b; fp=fopen("probat.txt","wt"); fprintf(fp,"%d",34); fflush(fp); fclose(fp); fp = fopen("probat.txt","rt"); fscanf(fp,"%d",&a); printf("%d\n",a); fclose(fp); Hozzáférés az adatállományokhoz

178 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)178 Hozzáférés az adatállományokhoz  Az output: fpb =fopen("probab.dat","w+b"); fwrite(&a,sizeof(int),1,fpb); fseek(fpb, 0, SEEK_SET); fread(&b,sizeof(int),1,fpb); printf("%d\n",b); fclose(fpb); } 34

179 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)179 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

180 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)180 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:.c.h.i.s.o.oa.out preprocesszor C fordító assembler linker p.cp.i gcc -E p.c >p.i p.s gcc -S p.i p.o gcc -c p.s a.out gcc p.o as p.sld p.o... gcc -S p.c gcc -c p.c gcc p.c gcc p.i gcc -c p.i gcc p.s

181 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)181 A C előfeldolgozó  A C előfeldolgozó (preprocesszor) egy makroprocesszor, melyet a C fordítóprogram automatikusan meghív, mielőtt a tényleges fordításhoz hozzákezdene.  Azért nevezzük makroprocesszornak, mert lehetőségünk van úgynevezett makrók definiálására, hogy a hosszú konstrukciókat lerövidíthessük.

182 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)182 A C előfeldolgozó  A C előfeldolgozó 4 egymástól független lehetőséget kinál: ■Fájlok (általában header fájlok) bemásolása. ■Makrobővítés. (Macro expansion) ■Feltételes fordítás. (Conditional compilation) ■Sor vezérlés. (Line control)

183 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)183 A C előfeldolgozó  A C előfeldolgozó nincs tisztában a C nyelv szintaxisával, csupán egy sororientált szövegszerkesztésről van szó.  Mindig elvégzi a következő egyszerű műveleteket: ■Minden kommentet kicserél egy darab szóközre. (A /* és */ közötti részeket.) ■ \újsor karakterkombinációt (azaz sorvégi \ -t) törli. ■Az előre definiált makrókat behelyettesíti.

184 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)184 A C előfeldolgozó  Az előfeldolgozó számára szóló utasítások # - kal kezdődnek. Nem szükséges az első pozícióra írni, de a # kell legyen az első értelmes karakter a sorban.

185 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)185 Header fájlok  A header fájlok használata kettős: ■A rendszer header fájlokban az operációs rendszerrel és a szabványos könyvtárakkal való kapcsolatot definiálják. #include ■Ha nem találja a fájl -t a standard (előre definiált) helyen, akkor keresi a -I fordítási opcióval megadott könyvtárban.

186 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)186 Header fájlok ■A saját header fájlokban azok a deklarációk szerepelnek, amiket több forrásprogramunkban is fel szeretnénk használni. #include "fájl" ■Ha nem találja a fájl -t az aktuális könyvtárban, akkor keresi a -I fordítási opcióval megadott könyvtárban.

187 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)187 Header fájlok  Ha az előfeldolgozó talál egy neki szóló #include utasítást, akkor a megadott fájlt egyszerűen sorról sorra bemásolja az adott helyre, és a bemásolt rész elejéről folytatja a munkát.

188 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)188 Makrók  Az egyszerű makró egy rövidítés, amit bevezetünk és a későbbiekben használunk.  A C-ben a konstansokat például így definiáljuk:  Mindenütt, ahol mostantól kezdve a TOMB_MERET megjelenik, az előfeldolgozó helyettesíti ezt az 1020-al, tehát a C fordító már a sok 1020 értéket fogja látni. #define TOMB_MERET 1020

189 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)189 Makrók  Az egyszerű makrók értékeit be tudjuk állítani a fordító -D opciójával is.  Az egyszerű makrónál mindig ugyanazt a szöveget helyettesíti az előfeldolgozó.

190 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)190 Paraméteres makrók  Ha a makrónak paraméterei is vannak, akkor a függvényhíváshoz hasonlóan más-más paraméterekkel is meghívhatjuk, így a helyettesítés is más és más lehet.  Ha ezek után a programban szerepel a szöveg, akkor az előfeldolgozó behelyettesíti erre: #define min(X,Y) ((X)<(Y)?(X):(Y)) min(a,b) ((a)<(b)?(a):(b))

191 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)191 Előre definiált makrók  A standard előre definiált makrókat az ANSI szabvány rögzíti.  Nem standard előre definiált makrók pl. ■ unix minden UNIX rendszerben ■ m88k Motorola processzornál ■ sparc Sparc processzornál ■ sun minden SUN számítógépen ■ svr4 System V Release 4 szabványú UNIX operációs rendszerben  A makró definiciót hatástalanítani lehet az #undef -fel.

192 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)192 Feltételes fordítás  Itt is az if alapszó szolgál az egyszerű szelekció megvalósítására.  Míg a C programban szereplő if utasítás a program végrehajtása közben érvényesül, addig az előfeldolgozónál használt #if még a fordítás előtt értékelődik ki és ennek megfelelően más és más forráskód kerül lefordításra.

193 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)193 Feltételes fordítás  Miért használunk feltételes fordítást? ■A géptől és az operációs rendszertől függően más- más forráskódra van szükségünk. ■Ugyanazt a programot több célból is használni szeretnénk, pl. van benne nyomkövetés, míg a végső változatban már nincs.

194 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)194 Feltételes fordítás  A feltételes fordítás direktivái: ■ #if, #ifdef, #ifndef  Egyszerű szelekció:  Egyszerű szelekció egyébként ággal: #if kifejezés... #endif /* kifejezés */ #if kifejezés... /* text-if-true */ #else... /* text-if-false */ #endif

195 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)195 Feltételes fordítás  Például: vagy: esetleg #if defined(DEBUG) printf("%d\n", v); #endif #if DEBUG > 2 printf("%d\n", v); #endif #ifdef(DEBUG) printf("%d\n", v); #endif

196 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)196 Feltételes fordítás  Többszörös szelekció (egyébként ággal) #if kifejezes1... /* első ág */ #elif kifejezes2... /* második ág */ #elif kifejezes3... /* harmadik ág */ #else... /* negyedik ág */ #endif

197 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)197 Sor vezérlés  A C forráskód több helyekről másolodik össze. A #line direktivával megadhatjuk, hogy ez legyen most a forrássor sorszáma a könnyebb beazonosíthatóság végett. #line sorszám

198 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)198 Sor vezérlés $ cat preproc.c #define N 30 #ifdef DEBUG #define STRING "Debug" #else #define STRING "Release" #endif #line 200 main() { int unix; char tomb[N] = STRING; for(unix=N-1; unix && tomb[unix]; unix--) { tomb[unix] = 0; }

199 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)199 Sor vezérlés $ gcc -E preproc.c # 1 "preproc.c" # 1 " " # 1 "preproc.c" # 200 "preproc.c" main() { int 1; char tomb[30] = "Release"; for(1=30 -1; 1 && tomb[1]; 1 --) { tomb[1] = 0; }

200 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)200 Sor vezérlés $ gcc -DDEBUG -E preproc.c # 1 "preproc.c" # 1 " " # 1 "preproc.c" # 200 "preproc.c" main() { int 1; char tomb[30] = "Debug"; for(1=30 -1; 1 && tomb[1]; 1 --) { tomb[1] = 0; }

201 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)201 Sor vezérlés $ gcc preproc.c preproc.c: In function 'main': preproc.c:202: error: syntax error before numeric constant preproc.c:204: error: invalid lvalue in assignment preproc.c:204: error: invalid lvalue in decrement

202 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)202 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:.c.h.i.s.o.oa.out preprocesszor C fordító assembler linker p.cp.i gcc -E p.c >p.i p.s gcc -S p.i p.o gcc -c p.s a.out gcc p.o as p.sld p.o... gcc -S p.c gcc -c p.c gcc p.c gcc p.i gcc -c p.i gcc p.s

203 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)203 A C fordító  A C fordító tehát tulajdonképpen már egy preprocesszált fájlt kap, ami tisztán C nyelvi elemekből áll, és tartalmaz minden deklarációt ahhoz, hogy önmagában le lehessen fordítani.  A C fordító nem csak „szó szerint” tudja lefordítani a C programot, hanem különféle optimalizálások elvégzésére is képes.

204 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)204 A C fordító  A gcc fordítónak a –O kapcsolóval tudjuk megmondani, hogy milyen optimalizálásokat alkalmazzon: ■ -O0 : nincs optimalizálás –A C forrás minden egyes művelete le lesz fordítva assemblyre, még akkor is, ha az nyilvánvalóan felesleges. Ez általában nagyon nagy és lassú gépi kódot eredményez, viszont hibakeresésnél igen hasznos, hiszen minden egyes gépi kódú utasításról egyértelműen megmondható, hogy az eredetileg melyik C-beli művelethez tartozott.

205 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)205 A C fordító ■ -O1 : optimalizálás –A C fordító elvégzi azokat az optimalizálásokat amik mind a méretet, mind a futási időt csökkentik. ■ -O2 : optimalizálás futási időre –A C fordító az O1 –ből indulva elvégzi azokat az optimalizálásokat amik csökkentik a futási időt, de a méreten ( O1 -hez képest) csak keveset növelnek. ■ -O3 : agresszív optimalizálás futásidőre –A C fordító elvégzi azokat az futásidőre optimalizáló algoritmusokat is, amik jelentősen növelhetik a kód méretét.

206 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)206 A C fordító ■ -Os : optimalizálás méretre –A C fordító az O1 –ből indulva elvégzi azokat az optimalizálásokat amik csökkentik a kód méretét, tekintet nélkül a futási időre gyakorolt hatásuktól.  A fordítás gcc esetében nem közvetlenül gépi kódra, hanem assembly nyelvre történik.

207 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)207 Alapszavak a C nyelvben  Ismétlésképpen foglaljuk össze az alapszavakat: ■ auto break case char const continue default do double else enum extern float for goto if int long register return short signed sizeof static struct switch typedef union unsigned void volatile while

208 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)208 Alapszavak a C nyelvben  char ■Karakter típus, 1 bájt.  double ■Valós típus, 8 bájt.  float ■Valós típus, 4 bájt.  int ■Egész típus, 32 bites rendszereken 4 bájt.

209 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)209 Alapszavak a C nyelvben  long ■„hosszú”: long int (4), long long int (8), long double (8)  short ■„rövid”: short int (2)  signed ■„előjeles”: int, char  unsigned ■„előjeltelen”: int, char

210 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)210 Alapszavak a C nyelvben  enum ■Felsorolás típus képzése.  struct ■Szorzat-rekord típus képzése.  union ■Egyesített-rekord típus képzése.

211 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)211 Alapszavak a C nyelvben  typedef ■Típusképzés.  void ■Az „üres” típus.  sizeof ■Típus méretének lekérdezése.

212 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)212 Alapszavak a C nyelvben  auto ■Automatikus tárolási osztály: –A globálisan deklarált változóknak „statikus” helyet foglal a program teljes futási idejére. –A blokkokban lokálisan deklarált változóknak a veremben foglal helyet az adott blokk végrehajtásának idejére.  static ■Statikus tárolási osztály: –Az ilyen változónak mindenképpen „statikus”, vagyis állandó helyet foglal a program teljes futási idejére.

213 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)213 Alapszavak a C nyelvben  register ■Regiszter tárolási osztály: –A fordító megpróbálja mindenképpen regiszterben tartani a változót (ez nem biztos, hogy sikerül). Ez gyorsabb elérést biztosít, cserében a változónak nem lesz címe.  extern ■Külső tárolási osztály: –A fordító az ilyen változóknak itt nem foglal helyet, mert ez valahol máshol megtörténik, itt csak azt jelezzük, hogy van ilyen változó. A változóhivatkozások feloldása majd a linker feladata lesz.

214 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)214 Alapszavak a C nyelvben  const ■Ha konstansnak deklarálunk egy változót, akkor a fordítóprogram nem engedi, hogy (az inicializáláson kívül, ami ilyenkor kötelező) értéket adjunk neki. A változó értéke kerülővel azért módosítható.  volatile ■Ez a kulcsszó azt jelzi, hogy a változó értékét más is módosíthatja. Ennek az eredménye az, hogy a fordító minden egyes műveletnél használni fogja a változóhoz rendelt memóriaterületet, azaz erre a változóra nem végez optimalizálást.

215 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)215 Alapszavak a C nyelvben  if ■Az egyszerű szelekciós vezérlés kulcsszava.  else ■A szelekciós vezérlés egyébként ágának kulcsszava.

216 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)216 Alapszavak a C nyelvben  switch ■Az esetkiválasztásos szelekciós vezérlés kulcsszava.  case ■Az esetkiválasztásos szelekciós vezérlés blokkjában egy belépési pont kulcsszava.  default ■Az esetkiválasztásos szelekciós vezérlés blokkjában az egyébként fel nem sorolt esetek belépési pontja.

217 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)217 Alapszavak a C nyelvben  for ■A ciklusszervezés egyik kulcsszava, általában számlálásos ismétlésekhez.  while ■A ciklusszervezés másik kulcsszava, általában kezdő- vagy végfeltételes ismétlésekhez.  do ■A végfeltételes ciklus kezdetét jelző kulcsszó.

218 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)218 Alapszavak a C nyelvben  break ■Kiugrás az adott ciklusból vagy switch utasításból, az azt követő első utasításra.  continue ■A ciklusmag aktuális végrehajtásának befejezése, ugrás az inkrementálásra vagy a feltételkiértékelésre.  goto ■A feltétel nélküli vezérlésátadás megvalósításának kulcsszava. (Ne használjuk.)

219 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)219 Alapszavak a C nyelvben  return ■Visszatérés a függvényből a hívás helyére, és a visszatérési érték megadása.

220 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)220 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:.c.h.i.s.o.oa.out preprocesszor C fordító assembler linker p.cp.i gcc -E p.c >p.i p.s gcc -S p.i p.o gcc -c p.s a.out gcc p.o as p.sld p.o... gcc -S p.c gcc -c p.c gcc p.c gcc p.i gcc -c p.i gcc p.s

221 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)221 Az assembler  Az assembly kódot fogja gépi kóddá fordítani, és egy úgynevezett object fájlt fog létrehozni.  Egy ilyen object bináris formában tartalmazza az assembly kódból keletkezett gépi kódot, a programban található konstans értékeket (például a programban leírt számokat vagy sztringeket), illetve sok olyan technikai információt, amire szükség lesz ahhoz, hogy az object-et össze lehessen szerkeszteni más objectekkel (pl. szimbólumtábla).

222 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)222 Fordítási egységek  Mint látható, eddig a pontig minden C forrásnak „egyenes” az útja: a header fájlokat nem számolva egy C forrásból egy object keletkezik.  Eddig a pontig kivétel nélkül bármelyik helyes C forrás eljuttatható. Futtatható program azonban csak olyan forrásból készíthető, amelyben van main() függvény.

223 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)223 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:.c.h.i.s.o.oa.out preprocesszor C fordító assembler linker p.cp.i gcc -E p.c >p.i p.s gcc -S p.i p.o gcc -c p.s a.out gcc p.o as p.sld p.o... gcc -S p.c gcc -c p.c gcc p.c gcc p.i gcc -c p.i gcc p.s

224 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)224 A linker  Első megközelítésben a linker olyan object fájlból tud futtatható programot csinálni, amiben van main() függvény.  De akkor miért kell ehhez linker?  Mire jó a többi object (amiben nincs main )?  Ahhoz, hogy ezt megértsük, meg kell ismerkednünk a modulok fogalmával.

225 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)225 Modulok  A korszerű programozási nyelvek lehetővé teszik programok mellett programrendszerek nyelvi szinten történő kezelését is.  A programrendszer nem más, mint modulok hierarchiája.  A modul olyan programozási egység, amely program elemek (konstans, típus, változó, függvény) együtteséből áll.

226 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)226 Modulok  Egy modulban szereplő program elemek egy része felhasználható más modulok (programok) által, ezek képezik a modul közösségi, vagy látható részét, míg a modul többi része kívülről nem látható, ez a modul privát része.  A modulnak e két részre osztása biztosítja a felhasznált modulok stabilitását és a privát elemek védelmét.

227 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)227 Modulok  A modulok természetes egységei a fordításnak, tehát minden modul külön fordítható. (Fontos hangsúlyozni, hogy a külön fordítás nem független fordítást jelent.)  Következésképpen a modulok két formában léteznek: ■Forrásnyelvi forma. ■Lefordított forma.

228 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)228 Modulok C-ben  C-ben alapvető egységként adódik az egy forrás/object, mint legkisebb lehetséges modul.  A.o kiterjesztésű object fájl ekkor a modul „lefordított formája” lesz, a.c kiterjesztésű forrás pedig a modul privát részének nyelvi formája.  A modul közösségi részét pedig a már említett.h kiterjesztésű header fájlok valósítják meg.

229 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)229 Header fájlok  A header és forrás fájlok tehát általában párosan léteznek: ■A header fájl tartalmazza az összes olyan változó és függvény deklarációját, illetve konstans és típus definícióját, ami a modul közösségi részét képezi. Ha valaki használni akarja a modult, csak include- olnia kell ezt a header fájlt, és máris használhatja az ebben deklarált dolgokat. ■A forrás pedig tartalmazza a közösségi részben deklarált függvények definícióit, illetve a modul teljes privát részét.

230 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)230 Header fájlok  Ahhoz tehát, hogy olyan programot vagy másik modult írjunk, ami használja a modulunkat, elegendő a modulunk header fájlját ismerni.  Az adott program forrásába a megfelelő #include helyére a preprocesszor bemásolja a mi header fájlunkat, így az object szintig lefordítható lesz.

231 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)231 Modulok fordítása  Egy-egy programot vagy modult le tudunk fordítani object szintig, függetlenül attól, hogy milyen más modulokat használ.  A main() nélküli objectekkel többet már nem nagyon tehetünk, maximum össze tudjuk őket gyűjteni egy úgynevezett függvénykönyvtárban ami valójában egy olyan fájl, ami objecteket tartalmaz.  A main() függvénnyel rendelkező objectekből viszont programok készíthetők, és ez a linker feladata.

232 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)232 A Linker  Egy-egy program object-je önmagában eléggé hiányos lehet, hiszen ha egy modul valamelyik függvényét használja, annak csak a deklarációját ismeri. A függvény megvalósítása a modul object fájljában van. A linker feladata, hogy az ilyen objecteken átívelő hivatkozásokat feloldja, és egyetlen programot állítson elő sok.o fájlból.  A sok.o közül pontosan egynek tartalmaznia kell a main() függvényt, hiszen az operációs rendszer majd ezt „hívja meg” a program indításakor.

233 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)233 A C forrás fordításának folyamata p.ca.out m.a p.ip.s p.o m2.c m2.i m2.sm2.o m1.cm1.im1.sm1.o m1.h m2.h preprocesszor C fordító assembler linker archiver

234 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)234 Modulok  Látható tehát, hogy egy-egy modul több programhoz is felhasználható, gondoljunk csak például a math.h -ra. Az ebben deklarált függvények (pl.: sin() ) egy függvénykönyvtárban vannak megvalósítva. A –lm kapcsoló mondja meg a linkernek, hogy a libm.a fájlban is keresgéljen függvények után.  Meg kell jegyeznünk, hogy a modul kifejezés általában nem csupán egy.o fájlt, hanem egy vagy akár több függvénykönyvtárat is takarhat.

235 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)235 Modulok C-ben  Hogyan szokás tehát C-ben modulokat írni?  Mivel a C nyelv nem engedi például típusok újradeklarálását, viszont bonyolultabb programrendszerekben gyakran előfordul, hogy ugyanazt a header fájlt (tranzitívan) többször is includolnák ugyanabba a forrásba, ezért szokás ezt feltételes preprocesszor direktívákkal kivédeni.

236 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)236 Modulok C-ben  p.c #include #include "m.h" int main(int argc, char *argv[]) { printf("%d\n", fuggveny(argv[0])); }

237 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)237 Modulok C-ben  m.h #ifndef M_H #define M_H int fuggveny(const char*); #endif

238 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)238 Modulok C-ben  m.c #include "m.h" int fuggveny(const char *str) { int cs; for(cs=0; *str; str++) { cs^=*str; } return cs; }

239 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)239 Modulok C-ben  p.i... # 2 "p.c" 2 # 1 "m.h" 1 int fuggveny(const char*); # 3 "p.c" 2 int main(int argc, char *argv[]) { printf("%d\n", fuggveny(argv[0])); }

240 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)240 Modulok C-ben  m.i... int fuggveny(const char*); # 2 "m.c" 2 int fuggveny(const char *str) { int cs; for(cs=0; *str; str++) { cs^=*str; } return cs; }

241 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)241 Modulok C-ben  A prímszámok keresését például megírhatjuk úgy, hogy a halmaz kezelését egy külön forrásban valósítjuk meg.

242 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)242 halmaz.h /* Header fájl a halmaz modulhoz. A logikai típust most a * preprocesszor segítségével definiáljuk. * Augusztus 16. Gergely Tamás, */ #ifndef HALMAZ_H #define HALMAZ_H #ifndef BOOL #define BOOL int #define FALSE 0 #define TRUE 1 #endif #define K (8*sizeof(KisHalmaz)) typedef int KisHalmaz; typedef unsigned long int halmazelem; >>>

243 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)243 halmaz.h typedef struct halmaztip { unsigned long int n; /* Az univerzum a [0..N) */ unsigned long int m; /* A kishalmazok száma */ KisHalmaz *tar; /* A kishalmazok tömbje */ } Halmaz; Halmaz Letesit(halmazelem); void Megszuntet(Halmaz); void Uresit(Halmaz); void Bovit(Halmaz, halmazelem); void Torol(Halmaz, halmazelem); BOOL Eleme(Halmaz, halmazelem); void Egyesites(Halmaz H1, Halmaz H2, Halmaz H); void Metszet(Halmaz H1, Halmaz H2, Halmaz H); void Kulonbseg(Halmaz H1, Halmaz H2, Halmaz H); BOOL Egyenlo(Halmaz H1, Halmaz H2); BOOL Resz(Halmaz H1, Halmaz H2); BOOL Urese(Halmaz H); void Ertekadas(Halmaz H1, Halmaz H2); #endif

244 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)244 halmaz.c /* A halmaz modul függvényeinek megvalósítása. * Augusztus 16. Gergely Tamás, */ #include #include "halmaz.h" >>>

245 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)245 halmaz.c Halmaz Letesit(unsigned long int n) { Halmaz ret; ret.n = n; if(n) { ret.m = (n-1)/K + 1; ret.tar = (KisHalmaz*)malloc(ret.m * sizeof(KisHalmaz)); } else { ret.m = 0; ret.tar = NULL; } return ret; } >>>

246 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)246 halmaz.c void Megszuntet(Halmaz H) { free(H.tar); } void Uresit(Halmaz H) { long int i; for(i = 0; i < H.m; ++i) { H.tar[i] = 0; } >>>

247 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)247 halmaz.c void Bovit(Halmaz H, halmazelem x) { if(x < H.n) { H.tar[x / K] |= (1 << (x % K)); } void Torol(Halmaz H, halmazelem x) { if(x < H.n) { H.tar[x / K] &= ~(1 << (x % K)); } >>>

248 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)248 halmaz.c BOOL Eleme(Halmaz H, halmazelem x) { return (x < H.n) && (H.tar[x / K] & (1 << (x % K))); } void Egyesites(Halmaz H1, Halmaz H2, Halmaz H) { long int i; for(i = 0; i < H.m; ++i) { H.tar[i] = H1.tar[i] | H2.tar[i]; } >>>

249 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)249 halmaz.c void Metszet(Halmaz H1, Halmaz H2, Halmaz H) { long int i; for(i = 0; i < H.m; ++i) { H.tar[i] = H1.tar[i] & H2.tar[i]; } void Kulonbseg(Halmaz H1, Halmaz H2, Halmaz H) { long int i; for(i = 0; i < H.m; ++i) { H.tar[i] = H1.tar[i] & ~(H2.tar[i]); } >>>

250 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)250 halmaz.c BOOL Egyenlo(Halmaz H1, Halmaz H2) { long int i; for(i=0; (i>>

251 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)251 halmaz.c BOOL Urese(Halmaz H) { long int i; for(i = 0; (i

252 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)252 prim3.c /* * Határozzuk meg az adott N természetes számnál nem nagyobb * prímszámokat. * Készítette: Dévényi Károly, * December 6. * Módosította: Gergely Tamás, * Augusztus 16. */ #include #include "halmaz.h" #define N >>>

253 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)253 prim3.c int main() { Halmaz szita; halmazelem p, s; long int lepes, i, j; szita=Letesit(N); Bovit(szita, 2); /* a szita inicializálása */ for(i = 3; i <= N; i+=2) { Bovit(szita, i); } >>>

254 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)254 prim3.c p = 3; /* az első szitálandó prím */ while(p*p <= N) { /* P többszöröseinek kiszitálása */ lepes = 2 * p; /* lépésköz = 2*p */ s = p*p; /* s az első többszörös */ while(s <= N) { Torol(szita, s); s += lepes; } do { /* a következő prím keresése */ p += 2; } while((p < N) && (! Eleme(szita, p))); } >>>

255 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)255 prim3.c j = 0; /* a prímszámok kiíratása képernyőre */ printf("A prímszámok %ld-ig:\n", N); for(p = 2; p < N; ++p) { if(Eleme(szita, p)) { printf("%8d", p); if(++j==10) { putchar('\n'); j=0; } putchar('\n'); Megszuntet(szita); }

256 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)256 Megvalósítás elrejtése  Mire jók még a modulok?  Programrendszer készítésekor az egyes modulokat célszerű úgy tervezni, hogy a headerben ne legyenek láthatók azok a programelemek, amelyek csak a megvalósításhoz kellenek.

257 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)257 Megvalósítás elrejtése  Ennek két oka is van: ■Egyrészt ezzel biztosítani tudjuk, hogy a modult felhasználó csak azokhoz a programelemekhez tud hozzáférni, amit a műveletek szabályos használata megenged, ezzel védettséget biztosítunk a lokális elemek számára. ■Másrészt a megvalósításhoz használt elemek elrejtése az implementációs részbe azt eredményezi, hogy a megvalósítás módosítása, megváltoztatása esetén nem kell a programrendszer más modulját változtatni, pl. újrafordítani.

258 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)258 Megvalósítás elrejtése  Egyedül az adattípusok elrejtése okozhat problémát.  Ugyanis azoknak az eljárásoknak a deklarációjában, amelyek a probléma megoldását adják – tehát a headerben kell lenniük – meg kell adni a paraméterek típusát, jóllehet a típus definiálását csak a modul.c forrásában kellene megadni, mert ezek megadása már a megvalósításhoz tartozik.

259 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)259 Megvalósítás elrejtése  Adattípus megadásának elhalasztása, vagyis elrejtése a void* pointer felhasználásával megoldható.  Ezt mutatja a következő séma, amelyben az mm.h az m.h t adattípusának elrejtését mutatja.  Természetesen az mm.h -ban kell lennie olyan eljárásnak, amely t típusú dinamikus változót létesít.

260 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)260 Megvalósítás elrejtése  m.h  m.c void fgv(t *x) {... (*x)... } typedef d t; void fgv(t*);

261 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)261 Megvalósítás elrejtése  mm.h  mm.c typedef d *tt; void fgv(t x) { tt xx=x;... (*xx)... } typedef void *t; void fgv(t);

262 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)262 Megvalósítás elrejtése  Az elrejtés technikája lehetővé teszi, hogy modul tervezésekor meg tudjuk adni a header rész végleges alakját, anélkül, hogy a megvalósítás bármely részletét is ismernénk.  Ez különösen hasznos absztrakt adattípusok tervezése és megvalósítása esetén.  A függvénykönyvtárakból ráadásul csak azok az eljárások kerülnek bele a programba, amiket valóban meg is hívunk.

263 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)263 graf.h /* * Gráf megvalósítása típuselrejtéssel. Közös header fájl. * Augusztus 17. Gergely Tamás, gertom.inf.u-szeged.hu */ #ifndef GRAF_H #define GRAF_H /* Típusdefiníciók */ typedef void *graf; typedef int pont; >>>

264 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)264 graf.h graf letesit(int); int pontokszama(graf); void elbeszur(graf, pont, pont); void eltorol(graf, pont, pont); int vanel(graf, pont, pont); int kifok(graf, pont); int kielek(graf, pont, pont[]); int befok(graf, pont); int beelek(graf, pont, pont[]); void megszuntet(graf); #endif

265 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)265 graf1.c /* * Gráf megvalósítása típuselrejtéssel. * Augusztus 17. Gergely Tamás, gertom.inf.u-szeged.hu */ #include #include "graf.h" typedef struct _graft { int n; char *mx; } _graft; >>>

266 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)266 graf1.c graf letesit(int n) { _graft *ptr; ptr=(_graft*)malloc(sizeof(_graft)); if(ptr) { ptr->n =n; ptr->mx=(char*)malloc(n*n*sizeof(char)); if(!ptr->mx) { free(ptr); ptr=NULL; } else { int i, nn; for(i = 0, nn = n * n; i < nn; i++) { ptr->mx[i] = 0; } return (void*)ptr; } >>>

267 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)267 graf1.c int pontokszama(graf g) { return ((_graft*)g)->n; } void elbeszur(graf g, pont f, pont t) { if(0 n && 0 n) { ((_graft*)g)->mx[((_graft*)g)->n * f + t]=1; } void eltorol(graf g, pont f, pont t) { if(0 n && 0 n) { ((_graft*)g)->mx[((_graft*)g)->n * f + t]=0; } >>>

268 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)268 graf1.c int vanel(graf g, pont f, pont t) { return 0 n && 0 n && ((_graft*)g)->mx[((_graft*)g)->n * f + t]; } int kifok(graf g, pont p) { int i,fok=-1; if(0 n ) { for(fok=i=0; i n; i++) { fok+=((_graft*)g)->mx[((_graft*)g)->n * p + i]; } return fok; } >>>

269 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)269 graf1.c int kielek(graf g, pont p, pont l[]) { int i,fok=-1; if(0 n ) { for(fok=i=0; i n; i++) { if(((_graft*)g)->mx[((_graft*)g)->n * p + i]) { l[fok++]=i; } return fok; } >>>

270 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)270 graf1.c int befok(graf g, pont p) { int i,fok=-1; if(0 n) { for(fok=i=0; i n; i++) { fok+=((_graft*)g)->mx[((_graft*)g)->n * i + p]; } return fok; } >>>

271 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)271 graf1.c int beelek(graf g, pont p, pont l[]) { int i,fok=-1; if(0 n ) { for(fok=i=0; i n; i++) { if(((_graft*)g)->mx[((_graft*)g)->n * i + p]) { l[fok++]=i; } return fok; } void megszuntet(graf g) { if(g) { free(((_graft*)g)->mx); } free(g); }

272 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)272 graf2.c /* * Gráf megvalósítása típuselrejtéssel. * Augusztus 17. Gergely Tamás, gertom.inf.u-szeged.hu */ #include #include "graf.h" typedef struct _graft { int n; int *be; int *ki; pont *mx; } _graft; >>>

273 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)273 graf2.c graf letesit(int n) { _graft *ptr; ptr=(_graft*)malloc(sizeof(_graft)); if(ptr) { ptr->n =n; ptr->be=(int*)malloc(n*sizeof(int)); ptr->ki=(int*)malloc(n*sizeof(int)); ptr->mx=(pont*)malloc(n*n*sizeof(pont)); if(!(ptr->mx && ptr->be && ptr->ki)) { free(ptr->mx); free(ptr->be); free(ptr->ki); free(ptr); ptr=NULL; } else { int i; for(i = 0; i < n; i++) { ptr->be[i] = 0; ptr->ki[i] = 0; } return (void*)ptr; } >>>

274 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)274 graf2.c int pontokszama(graf g) { return ((_graft*)g)->n; } void elbeszur(graf g, pont f, pont t) { if(0 n && 0 n && !vanel(g, f, t)) { ((_graft*)g)->mx[ ((_graft*)g)->n * f + ((_graft*)g)->ki[f]++ ] = t; } >>>

275 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)275 graf2.c void eltorol(graf g, pont f, pont t) { int i; _graft *gg=(_graft*)g; if(0 n && 0 n) { for(i=0; (i ki[f]) && (gg->mx[gg->n * f + i] != t); i++); for(; (i ki[f]); i++) { (gg)->mx[(gg)->n * f + i] = (gg)->mx[(gg)->n * f + i + 1]; } >>>

276 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)276 graf2.c int vanel(graf g, pont f, pont t) { int i; _graft *gg=(_graft*)g; if(0 n && 0 n) { for(i=0; (i ki[f]) && (gg->mx[gg->n * f + i] != t); i++); return i ki[f]; } return 0; } int kifok(graf g, pont p) { if(0 n ) { return ((_graft*)g)->ki[p]; } return -1; } >>>

277 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)277 graf2.c int kielek(graf g, pont p, pont l[]) { int i,*ptr; if(0 n ) { for(i=0, ptr=((_graft*)g)->mx + p*((_graft*)g)->n+i; i ki[p]; i++, ptr++) { l[i]=*ptr; } return ((_graft*)g)->ki[p]; } return -1; } int befok(graf g, pont p) { if(0 n ) { return ((_graft*)g)->be[p]; } return -1; } >>>

278 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)278 graf2.c int beelek(graf g, pont p, pont l[]) { int i,*ptr; if(0 n ) { for(i=0, ptr=((_graft*)g)->mx + p*((_graft*)g)->n+i; i ki[p]; i++, ptr++) { l[i]=*ptr; } return ((_graft*)g)->be[p]; } return -1; } void megszuntet(graf g) { if(g) { free(((_graft*)g)->mx); free(((_graft*)g)->be); free(((_graft*)g)->ki); } free(g); }

279 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)279 A memóriába töltött program részei  Programkód  Csak olvasható adatterület (read-only data)  Globális változók területe  Verem  Szabad memória

280 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)280 Konstansok és változók  Mi a különbség a két deklaráció között? char t[]= "Tomb vagy pointer" char *p= "Tomb vagy pointer"  A "Tomb vagy pointer" mindkét esetben egy konstans karaktertömb, ami a program konstans szekciójában, a csak olvasható adatok között kap helyet.

281 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)281 Konstansok és változók  A t egy tömb. Amikor létrejön, a veremben vagy a globális változóknak fentartott memóriaterületen lefoglalódik a megfelelő méretű memóriaterület, és a sztring értéke a csak olvasható területről bemásolódik erre a területre.  A p egy pointer. Amikor létrejön, a veremben vagy a globális változóknak fentartott memóriaterületen lefoglalódik egy pointer számára megfelelő méretű memóriaterület, és ezen a területen eltárolódik a csak olvasható területen lévő sztring címe.

282 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)282 Konstansok és változók  Az eredmény: ■ strcpy(t, "Hello!") –A függvényhívás hatására a t területére bemásolódik a "Hello!" szöveg, azaz t felveszi ezt az értéket. ■ strcpy(p, "Hello!") –A függvényhívás hatására a p által mutatott területre bemásolódna a "Hello!" szöveg. De ez a terület csak olvasható, így futási hibát kapunk. ■Azt, hogy egy memóriaterület csak olvasható az operációs rendszer tartja számon (hardveres segítséggel).

283 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)283 Konstansok és konstansok  Mi lesz az alábbi program kimenete:  Bármilyen meglepőnek tűnik is, a program nem okoz futási hibát, és a kimenet: main() { const int c = 100; int *p; p = &c; *p *= 2; printf("%d\n", c); } 200

284 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)284 Konstansok és konstansok  A c tehát nem egy, a fordító számára szóló érték lesz, és nem is a csak olvasható memóriaterületen eltárolt változó, hanem egy valódi változó, egy kisebb megszorítással: nem szabad megváltoztatni az értékét (de nem lehetetlen). Azaz a fordítás során bármely direkt c=… alakú kifejezés hibát eredményez.  Valódi konstansokat a C előfeldolgozóval ( #define ) készíthetünk.

285 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)285 Bináris adatállományok  Világos, hogy ha egy karakterfolyamot ASCII kódrendszerben elkészítünk és ezt egy másik, szintén ASCII kódrendszerben dolgozó gépen beolvassuk, akkor ugyanúgy tudjuk értelmezni az adatállományt. (pl. UNIX, Linux, PC)

286 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)286 Bináris adatállományok  Mi a helyzet bináris adatállományok esetén?  Ennek megvizsgálásához készítsünk egy kis programot, amelyik 10 egész számot ír ki egy adatállományba és nézzük meg az eredményt több különböző rendszeren.

287 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)287 Bináris adatállományok /* Egy bináris adatállományba egész számok kiírása. * Az adatállomány nevét a parancssorból kapjuk. * Április 24. Dévényi Károly, */ #include #define DBSZAM 10 int tomb[DBSZAM]; /* innen fogunk irni */ int i; /* ciklusváltozó */ main(int argc, char **argv) { int fd; /* fájlleíró = file descriptor */ int bytedb; /* kiírt bájtok száma */ >>>

288 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)288 Bináris adatállományok if ((fd = open(argv[1], O_WRONLY)) == -1) { errno = ENOENT; perror( "Megnyitási hiha" ); exit(EXIT_FAILURE); } /* a tomb feltöltése jól látható értékekkel */ for (i = 0; i < DBSZAM; i++) { tomb[i] = i + 'a'; } if ((bytedb = write(fd, tomb, DBSZAM * sizeof(int))) == -1 ) { perror( "Írási hiba" ); exit(EXIT_FAILURE); } close(fd); printf(" Sikerült kiírni %d darab bájtot\n", bytedb); }

289 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)289 Bináris adatállományok  A Linux rendszer prompt-ját a $ jelöli (a home.cab gépen): $ gcc -o keszit keszit.c $ touch proba.bin $ keszit proba.bin Sikerült kiírni 40 darab bájtot $ a...b...c...d e...f...g...h a...i...j

290 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)290 Bináris adatállományok  A Linux rendszer prompt-ját a $ jelöli (a linux.inf gépen vagy az egyik munkaállomáson): $ gcc -o keszit keszit.c $ touch proba.bin $ keszit proba.bin Sikerült kiírni 40 darab bájtot $ a...b...c...d e...f...g...h a i...j...

291 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)291 Bináris adatállományok  A pc-n a promptot a bill> jelöli (régen, DOS alatt): bill>keszit proba.bin Sikerült kiírni 20 darab bájtot bill> a.b.c.d.e.f.g.h a 00 i.j.

292 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)292 Bináris adatállományok  Láthatjuk, hogy a három adatállomány különböző. ■A Linux és DOS közötti különbség abból adódik, hogy az int adattípus nem azonos hosszúságú a két rendszerben, de ezen könnyen lehet segíteni a pontosabb típusdefinícióval. ■A solaris.inf, illetve a többi gép közötti különbség pedig abból adódik, hogy a bájtsorrend különbözik az egyes architektúrákon.

293 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)293 Bináris adatállományok  Ha az alacsonyabb című memóriahelyekre az alacsonyabb helyiértékű bájtokat tároljuk, akkor a bájtsorrend little-endian („kis indián”, pl. a PC típusú gépek).  Ha az alacsonyabb című memóriahelyekre a magasabb helyiértékű bájtokat tároljuk, akkor a bájtsorrend big-endian („nagy indián”, pl. a solaris.inf szerver).

294 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)294 Bináris adatállományok /* Eldönti, hogy milyen a bájtsorrend a számítógépen. * Április 24. Dévényi Károly, */ #include main() { int x = 1; if (*(char *)&x == 1) { printf("little-endian\n"); } else { printf("big-endian\n"); }

295 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)295 Gyakori C hibák  while (F);  while (F) {}  for (I;F;N);  for (I;F;N) {} ■Üres ciklusmagok.  if (F);  if (F) {} ■Üres műveletek  A ; az üres kifejezésből is utasítást csinál.

296 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)296 Gyakori C hibák  Az = az értékadás, a == az összehasonlítás műveletének a jele if (a = b) {} legális utasítás sokan ezért így hasonlítanak: if (1 == x) és nem így, hogy if (x == 1) mert ha csak egy =-t írnak, akkor szól a fordító.

297 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)297 Gyakori C hibák  Ha egy típus elmarad, akkor a feltételezett típus int és nem void.  Minden utasítást a ; zár le, de nincs ; a blokk {} után.  Nem szabad összetéveszteni a logikai és bináris, vagyis a && és & illetve a || és | műveletet.  A paraméterátadás érték szerinti, vagyis bemenő módú. Ha nem ezt akarjuk, akkor az aktuális paraméterek címét kell átadni/átvenni.

298 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)298 Gyakori C hibák  A printf értékeket vár, a scanf címeket.  A scanf –nél nagyon fontos a méretmódosítók megadása.  Ha a függvénynek nincs paramétere, akkor is ott kell lenni a () -nak. Az ANSI szabvány szerint a deklaráció f(void), ha f -nek nincs paramétere.  A tömb indexelése 0 -nál kezdődik, így az n elemű tömb index tartománya 0..n-1

299 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)299 Gyakori C hibák  A többdimenziós tömb indexelése [][] -vel történik.  A C érzékeny a kis- és nagybetűkre.  "endianizmus", vagyis honnan származik a bináris adatállomány?  A pointer deklarálásánal a * -t érdemes szorosan a változóhoz írni. Ha nem ezt tesszük, hanem így int* ptr1, ptr2; akkor nem vesszük észre, hogy ptr2 nem pointer, hanem csak int.

300 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)300 Gyakori C hibák  Miért áll le hibával a következő program? struct Cellatip { Elemtip adat; /* adatelem */ struct Cellatip *csat; /* a következő */ } /* Itt lesz a főprogram */ main(int argc, char *argv[]) {... }

301 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)301 Gyakori C hibák  A ~ -t a shell dolgozza fel, tehát se nem abszolút és se nem relatív hivatkozás a data nevű adatállományra. ( getenv("HOME") )  getchar() visszaadott értéke int. Nem szabad áttenni char -ra mielőtt az EOF -al összehasonlítanánk. if ((fp=fopen("~/data", "r")) == NULL) {}

302 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)302 Egy 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);} Az eredeti programot úgy alakítjuk át, hogy az algoritmus, amit leír, ne változzon.

303 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)303 Egy C program main(l,a,n,d) char**a; { for(d=atoi(a[1])/10*80-atoi(a[2])/5-596; 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); } Kezdjük egyszerű tördeléssel, mindössze szóközöket és sorvégeket helyezünk át a programban.

304 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)304 Egy C program int main(l,a,n,d) int l; char**a; int n; int d; { for(d=atoi(a[1])/10*80-atoi(a[2])/5-596; 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); } Így már látszik, hogy régi típusú C függvényleírást használtunk. A jelzett kiegészítésekkel a program működése nem változik, hiszen a C nyelv alapértelmezett típusa az int típus.

305 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)305 Egy C program const char CLCCGZAAQBEAADAFaISADJABBA^\ SNLGAQABDAXIMBAACTBATAHDBAN\ ZcEMMCCCCAAhEIJFAEAAABAfHJE\ TBdFLDAANEfDNBPHdBcBBBEA_AL\ H E L L O, W O R L D! " int main(l,a,n,d) int l; char**a; int n; int d; { for(d=atoi(a[1])/10*80-atoi(a[2])/5-596; n=str[l++-3];) for(;n-->64;) putchar(!d+++33^l&1); } Most a programban megadott hosszú sztringet kielemjük egy külön globális változóba, hogy ne zavarjon a program megértésében.

306 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)306 Egy C program const char GAQABDAXIMBAACTBATAHDBANZcEMMCCCCAAhEIJFAEAAABAfHJET\ BdFLDAANEfDNBPHdBcBBBEA_AL H E L L O, W O R L D! " int main(l,a,n,d) int l; char**a; int n; int d; { for(d=atoi(a[1])/10*80-atoi(a[2])/5-596; n=str[l++-3];) for(;n-->64;) putchar(!d+++33^l&1); } Egy keveset elvégzünk a preprocesszor munkájából, a sztringünket kicsit összébbhúzzuk. Az értéke ezzel az átalakítással nem változik.

307 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)307 Egy C program const char GAQABDAXIMBAACTBATAHDBANZcEMMCCCCAAhEIJFAEAAABAfHJET\ BdFLDAANEfDNBPHdBcBBBEA_AL H E L L O, W O R L D! " int main(l,a,n,d) int l; char**a; int n; int d; { for(d=(atoi(a[1])/10*80)-(atoi(a[2])/5)-596; n=str[l++-3];) { for(;n-->64;) { putchar(!d+++33^l&1); } Az átláthatóság kedvéért kiteszünk pár zárójelet.

308 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)308 Egy C program const char GAQABDAXIMBAACTBATAHDBANZcEMMCCCCAAhEIJFAEAAABAfHJET\ BdFLDAANEfDNBPHdBcBBBEA_AL H E L L O, W O R L D! " int main(l,a,n,d) int l; char**a; int n; int d; { for(d=(atoi(a[1])/10*80)-(atoi(a[2])/5)-(7*80+36); n=str[l++-3];) { for(;n-->64;) { putchar(!d+++33^l&1); } Egy kicsit átalakítunk, hogy a 80 karakter széles terminál oszlopszáma jól látható legyen a kódban.

309 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)309 Egy C program const char GAQABDAXIMBAACTBATAHDBANZcEMMCCCCAAhEIJFAEAAABAfHJET\ BdFLDAANEfDNBPHdBcBBBEA_AL H E L L O, W O R L D! " int main(l,a,n,d) int l; char**a; int n; int d; { int sor=80, px, py; py=(atoi(a[1])/10)-7; px=(atoi(a[2])/5)+36; for(d=py*sor-px; n=str[l++-3];) { for(;n-->64;) { putchar(!d+++33^l&1); } A külső ciklus inicializálását egy kicsit átalakítjuk, hogy érthetőbb legyen. Látszik, hogy d -be a paraméterben kapott kétdimenziós koordináta 80 oszlopot feltételező sorfolytonossá alakított értéke kerül, méghozzá úgy, hogy az origót a 7. sor 36. oszlopába toltuk el.

310 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)310 Egy C program const char GAQABDAXIMBAACTBATAHDBANZcEMMCCCCAAhEIJFAEAAABAfHJET\ BdFLDAANEfDNBPHdBcBBBEA_AL H E L L O, W O R L D! " int main(l,a,n,d) int l; char**a; int n; int d; { int sor=80, px, py; py=(atoi(a[1])/10)-7; px=(atoi(a[2])/5)+36; for(d=py*sor-px; n=str[(l++)-3];) { for(;n-->64;) { putchar(!d+++33^l&1); } Most nézzük a sztring indexelését. Hozzávéve azt, hogy a programot 2 paraméterrel történő futtatásra tervezték, azaz az argc szerepét betöltő l értéke 3-ról indul, a ciklus egyszerűen végiglépked a sztring karakterein, egészen a 0 kódú karakterig.

311 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)311 Egy C program const char GAQABDAXIMBAACTBATAHDBANZcEMMCCCCAAhEIJFAEAAABAfHJET\ BdFLDAANEfDNBPHdBcBBBEA_AL H E L L O, W O R L D! " int main(l,a,n,d) int l; char**a; int n; int d; { int sor=80, px, py; py=(atoi(a[1])/10)-7; px=(atoi(a[2])/5)+36; for(d=py*sor-px; n=str[(l++)-3];) { while(n-->64) { putchar(!d+++33^l&1); } A belső ciklusból csak a feltételt használjuk, így az ekvivalensen átalakítható egy while ciklussá.

312 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)312 Egy C program const char GAQABDAXIMBAACTBATAHDBANZcEMMCCCCAAhEIJFAEAAABAfHJET\ BdFLDAANEfDNBPHdBcBBBEA_AL H E L L O, W O R L D! " int main(l,a,n,d) int l; char**a; int n; int d; { int sor=80, px, py; py=(atoi(a[1])/10)-7; px=(atoi(a[2])/5)+36; for(d=py*sor-px; n=str[(l++)-3];) { { putchar(!d+++33^l&1); } A belső ciklus tehát annyiszor fut le, amennyivel a sztring kiolvasott karakterének kódja nagyobb karakter kódjánál.

313 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)313 Egy C program const char GAQABDAXIMBAACTBATAHDBANZcEMMCCCCAAhEIJFAEAAABAfHJET\ BdFLDAANEfDNBPHdBcBBBEA_AL H E L L O, W O R L D! " int main(l,a,n,d) int l; char**a; int n; int d; { int sor=80, px, py; py=(atoi(a[1])/10)-7; px=(atoi(a[2])/5)+36; for(d=py*sor-px; n=str[(l++)-3];) { { putchar(((!(d++))+33)^(l&1)); } A prioritásoknak megfelelő zárójelezéssel most is láthatóvá tehetjük a kifejezés felépítését. (Ehhez persze felhasználjuk, hogy a +++ sorozatot a fordító mohó módon ++ + műveletekként értelmezi.)

314 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)314 Egy C program const char GAQABDAXIMBAACTBATAHDBANZcEMMCCCCAAhEIJFAEAAABAfHJET\ BdFLDAANEfDNBPHdBcBBBEA_AL H E L L O, W O R L D! " int main(l,a,n,d) int l; char**a; int n; int d; { int sor=80, px, py; py=(atoi(a[1])/10)-7; px=(atoi(a[2])/5)+36; for(d=py*sor-px; n=str[(l++)-3];) { { putchar(((!(d++))+'!')^(l&1)); } A sorfolytonos pozíciót jelző d változót lépésenként nö- veljük, majd egy negáció- val 0 vagy 1 értékre kon- vertáljuk, hozzáadjuk egy karakterkódhoz, majd l párosságától függően az utolsó bitjét megváltoztat- juk. Az ügyes karaktervá- lasztás miatt az eredmény 4-féle érték lehet.

315 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)315 Egy C program $./where !!!!!!!!!!! !!! !!! !!!!!!! ! !!!!!!!!!!!!!!!!! !!!!! ! ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!! !!!! ! !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!! !!!!"!! !!!!!!!!!!!!!!!!! !! ! !!!!!!!!! !! ! !!!!!!!!!!!!!!!!!!!! ! ! !!!! ! !!!!!!!!!!!!!!!!!!!!!!!!!! !!!!! !!!!!!!!!!!!! !!! !!! ! !!!!! !!!!!!!!!! ! ! ! ! !!!!!!!! !!!!! !! !!!!!! !!!! ! !!!!! !!!! !! !!!!!!!! !! !! !! ! ! $ Ez a négyféle érték:  Ha d nem nulla, akkor l párosságától függően ! vagy szóköz  Ha d nulla, akkor l párosságától függően " vagy # Vagyis a sztring karakterei felváltva a szárazföld-víz szekvenciák hosszát határozták meg, míg a d 0 értéke a speciális karakter kiírásának helyét.

316 SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)316 Kérdések, válaszok


Letölteni ppt "SZEGEDI TUDOMÁNYEGYETEM S zoftverfejlesztés Tanszék UNIVERSITAS SCIENTIARUM SZEGEDIENSIS Programozás Alapjai (2008)1 Halmaz típus  A programozásban számtalan."

Hasonló előadás


Google Hirdetések