You are on page 1of 107

Budapesti Mszaki s Gazdasgtudomnyi Egyetem

Elektronikus Eszkzk Tanszke

Pohl Lszl

A programozs alapjai

Budapest, 2010

1
Pohl Lszl, 2010

Minden jog fenntartva

Az elektronikus knyv, abban a formban, ahogy van, szabadon terjeszthet. Rszletei csak abban az esetben
jelentethetk meg az eredeti knyvtl kln, ha az idzett rszletrl egyrtelmen kiderl, hogy idzet, s
megfelel formban szerepel hivatkozs erre a mre.

2
Tartalom
I. RSZ ALAPOZS ..............................................................................................................................................8
1. A programozs ...................................................................................................................................................8
1.1 A szmtgp felptse...............................................................................................................................8
1.2 A programozs alapjai.................................................................................................................................8
2. Az algoritmusok megadsa ..............................................................................................................................10
Teafz robot ..................................................................................................................................................10
Gondolkodjunk egytt! ....................................................................................................................................12
3. Egyszer algoritmusok s kdolsuk C nyelven ..............................................................................................12
1. feladat: ......................................................................................................................................................12
2. feladat .........................................................................................................................................................13
3. feladat .........................................................................................................................................................14
Msodik megolds.......................................................................................................................................15
Gondolkodjunk egytt! ....................................................................................................................................16
Oldja meg egyedl! .........................................................................................................................................17
Az integrlt fejlesztkrnyezet ....................................................................................................................17
Program ltrehozsa ...................................................................................................................................17
Fordts, futtats, hibakeress ....................................................................................................................18
4. Hogy mkdik a fordt? .................................................................................................................................20
5. A C programok felptse ................................................................................................................................20
5.1 A szintaxis lersa ......................................................................................................................................20
5.2 Egy egyszer C program elemei.................................................................................................................21
6. Tpusok, vltozk, konstansok, mveletek ......................................................................................................24
6.1 Msodfok egyenlet gykei.......................................................................................................................24
6.2 tlag ..........................................................................................................................................................25
6.3 Fordtva......................................................................................................................................................26
Gondolkozzunk egytt! ....................................................................................................................................27
Oldja meg egyedl! .........................................................................................................................................27
7. A C utastsai ...................................................................................................................................................28
Gondolkozzunk egytt! ....................................................................................................................................32
Oldja meg egyedl! .........................................................................................................................................32
8. Egyszer fggvnyek .......................................................................................................................................32

3
Gondolkozzunk egytt! ................................................................................................................................... 34
Oldja meg egyedl!......................................................................................................................................... 34
II. RSZ: ISMERKEDS A C NYELVVEL ............................................................................................................... 35
9. Tmbk ........................................................................................................................................................... 35
Gondolkozzunk egytt! ................................................................................................................................... 36
Oldja meg egyedl!......................................................................................................................................... 36
10. Szmbrzols s az egyszer adattpusok .................................................................................................. 37
10.1. Szmbrzols ....................................................................................................................................... 37
10.2. C alaptpusok ......................................................................................................................................... 38
Gondolkozzunk egytt! ................................................................................................................................... 39
Oldja meg egyedl!......................................................................................................................................... 39
11. Bitmveletek ................................................................................................................................................. 39
Gondolkozzunk egytt! ................................................................................................................................... 40
Oldja meg egyedl!......................................................................................................................................... 40
12. Bemenet s kimenet, ASCII........................................................................................................................... 41
12.1 A karakterek ASCII kdja ......................................................................................................................... 41
12.2 getchar/putchar, gets/puts, fgets .......................................................................................................... 42
12.3 printf s scanf ......................................................................................................................................... 43
Gondolkozzunk egytt! ................................................................................................................................... 44
Oldja meg egyedl!......................................................................................................................................... 44
13. A szmtgpek felptsrl s mkdsrl ............................................................................................. 44
14. sszetett s szrmaztatott adattpusok, tpusdefinci ............................................................................... 47
14.1 sszetett s szrmaztatott tpusok ........................................................................................................ 47
14.2 Sajt tpus ltrehozsa a tpusdefinci ............................................................................................... 48
Gondolkozzunk egytt! ................................................................................................................................... 48
Oldja meg egyedl!......................................................................................................................................... 48
15. Opertorok ................................................................................................................................................... 49
15.1 Logikai rtkek s egsz szmok ............................................................................................................ 49
15.2 A C nyelv opertorai ............................................................................................................................... 49
Gondolkozzunk egytt! ................................................................................................................................... 52
Oldja meg egyedl!......................................................................................................................................... 52
16. Pointerek ...................................................................................................................................................... 53
16.1 A szmtgp memrija ........................................................................................................................ 53
16. 2 A pointer ................................................................................................................................................ 53
16.3 Pointeraritmetika.................................................................................................................................... 54

4
Gondolkozzunk egytt! ....................................................................................................................................54
Oldja meg egyedl! .........................................................................................................................................54
17. rtk s cm szerinti paramtertads; tmbk, pointerek s fggvnyek ..................................................55
17.1 Paramtertads .....................................................................................................................................55
17.2 Tmbk tadsa fggvnynek ................................................................................................................56
17.3 Tmb s pointer jra................................................................................................................................57
17.4 Pointertmb .............................................................................................................................................57
Gondolkozzunk egytt! ....................................................................................................................................58
Oldja meg egyedl! .........................................................................................................................................58
18. Dinamikus memriakezels ...........................................................................................................................58
18.1 sizeof ........................................................................................................................................................59
18.2 Tbbdimenzis dinamikus tmb ..............................................................................................................59
18.3 A lefoglalt memria bvtse...................................................................................................................60
Gondolkozzunk egytt! ....................................................................................................................................61
Oldja meg egyedl! .........................................................................................................................................61
19. Sztringek ........................................................................................................................................................61
19.1 Knyvtri sztringfggvnyek ...................................................................................................................61
19.2 Algoritmusok ...........................................................................................................................................63
Gondolkozzunk egytt! ....................................................................................................................................64
Oldja meg egyedl! .........................................................................................................................................64
20. A programozs menete .................................................................................................................................64
20.1 Programstruktra tervezse ....................................................................................................................65
20.2 Algoritmus megadsa..............................................................................................................................65
21. sszetettebb C programok kellkei ..............................................................................................................66
21.1 Tbb modulbl ll programok ...............................................................................................................66
21.2 A C programok ltalnos felptse ........................................................................................................67
21.3 Lthatsg, trolsi osztlyok.................................................................................................................67
Gondolkozzunk egytt! ....................................................................................................................................68
Oldja meg egyedl! .........................................................................................................................................68
22. A parancssor ..................................................................................................................................................69
Gondolkozzunk egytt! ....................................................................................................................................69
Oldja meg egyedl! .........................................................................................................................................69
23. Fjlkezels......................................................................................................................................................70
23.1 Binris fjlok ............................................................................................................................................70
23.2 Szveges fjlok ........................................................................................................................................71

5
23.3 Szveges fjlok s binris fjlok sszevetse .......................................................................................... 73
23.4 Szabvnyos bemenet s kimenet ............................................................................................................ 73
Gondolkozzunk egytt! ................................................................................................................................... 73
Oldja meg egyedl!......................................................................................................................................... 73
III. RSZ: HALAD PROGRAMOZS .................................................................................................................. 74
24. Dinamikus nhivatkoz adatszerkezetek 1. lncolt listk ......................................................................... 74
24.1 Egyszer lncolt lista .............................................................................................................................. 74
14.2 Lncolt lista strzsval, fggvnyekkel, beszrssal .............................................................................. 75
24.3 Kt irnyban lncolt lista ........................................................................................................................ 76
24.3 Fss lista................................................................................................................................................ 77
Gondolkozzunk egytt! ................................................................................................................................... 77
Oldja meg egyedl!......................................................................................................................................... 77
25. llapotgp (vges automata) ....................................................................................................................... 78
25.1 Kommentszr ........................................................................................................................................ 78
Gondolkozzunk egytt! ................................................................................................................................... 79
Oldja meg egyedl!......................................................................................................................................... 79
26. Rekurzi ........................................................................................................................................................ 79
26.1 A verem adatszerkezet ........................................................................................................................... 79
26.2 Fggvnyhvs ........................................................................................................................................ 80
26.3 Rekurzi .................................................................................................................................................. 81
Gondolkozzunk egytt! ................................................................................................................................... 82
Oldja meg egyedl!......................................................................................................................................... 82
27. Dinamikus nhivatkoz adatszerkezetek 2. fk ......................................................................................... 83
27.1 Binris fa ................................................................................................................................................. 83
27.2 Rendezett fa rendezfa, kiegyenslyozottsg s kiegyenslyozatlansg............................................ 84
27.3 A fabejrs tpusai .................................................................................................................................. 85
27.4 Tbb g fk ........................................................................................................................................... 85
27.5 Kt plda ................................................................................................................................................. 85
Gondolkozzunk egytt! ................................................................................................................................... 86
Oldja meg egyedl!......................................................................................................................................... 86
28. Fggvnypointer ........................................................................................................................................... 86
Gondolkozzunk egytt! ................................................................................................................................... 87
Oldja meg egyedl!......................................................................................................................................... 87
29. Keress tmbben .......................................................................................................................................... 88
Gondolkozzunk egytt! ................................................................................................................................... 89

6
Oldja meg egyedl! .........................................................................................................................................89
30. Rendezs........................................................................................................................................................89
30.1 Bubork algoritmus .................................................................................................................................89
30.2 Kzvetlen kivlasztsos rendezs ............................................................................................................90
30.3 Sllyeszt rendezs ..................................................................................................................................91
30.4 Kzvetlen beszr rendezs .....................................................................................................................91
30.5 Shell rendezs ..........................................................................................................................................92
30.6 Gyorsrendezs .........................................................................................................................................92
30.7 Szabvnyos knyvtri gyorsrendez fggvny: a qsort...........................................................................93
30.8 Lncolt lista rendezse gyorsrendez algoritmussal ...............................................................................93
Gondolkozzunk egytt! ....................................................................................................................................93
Oldja meg egyedl! .........................................................................................................................................93
31. Preprocesszor ................................................................................................................................................94
Gondolkozzunk egytt! ....................................................................................................................................95
Oldja meg egyedl! .........................................................................................................................................95
32. Bitmezk, union .............................................................................................................................................96
32.1 Struktra bitmezi ...................................................................................................................................96
32.2 Union .......................................................................................................................................................96
Gondolkozzunk egytt! ....................................................................................................................................97
Oldja meg egyedl! .........................................................................................................................................97
33. Vltoz paramterlistj fggvnyek............................................................................................................97
Gondolkozzunk egytt! ....................................................................................................................................98
Oldja meg egyedl! .........................................................................................................................................98
34. Hasznos fggvnyek a C-ben .........................................................................................................................98
Gondolkozzunk egytt! ....................................................................................................................................99
Oldja meg egyedl! .........................................................................................................................................99
35. Programozsi rdekessgek ..........................................................................................................................99
35.1 Programozs tbb szlon ........................................................................................................................99
Trgymutat ......................................................................................................................................................102

7
I. RSZ ALAPOZS
1. A programozs kli egsz szmrl beszlnk, ha pedig -127 s +127 kztti
szmnak, akkor eljeles egsz szmrl. A valsgban ltalban
ettl eltr az eljeles szmok trolsa, -128 s +127 kztti rt-
1.1 A szmtgp felptse kek vannak az eljeles bjtban, mert nem szksges 0, s a
negatv szmok nem csak az eljelben klnbznek. Az egszek,
s a tbbi tpus szmbrzolsi krdseivel ksbb rszletesen
foglalkozunk. Most elg annyit tudnunk, hogy a szmtgp
Memria Processzor Perifrik mindent bjtokban trol, legyen az egsz szm, vals szm vagy
szveg.

A szmtgpek f rszegysgei a processzor, a memria s a A processzor bekapcsols utn beolvassa a memria elejn
perifrik. A memria ltalnos trol, mely utastsokat s lv utastst. Ez ltalban egy ugr utasts, amely azt mondja
adatokat tartalmaz. A processzor beolvassa a memribl az meg, hogy hol tallja a kvetkez utastst a memriban, amit
utastsokat s az adatokat, az utastsok alapjn mveleteket vgre kell hajtania.
vgez, a mveletek eredmnyt pedig visszarja a memriba, A szmtgp elemi utastsai nagyon egyszerek azrt, hogy
valamint vezrli a perifrikat: adatokat kld szmukra s ada- az ket megvalst ramkrk minl egyszerbbek, s ezltal
tokat olvas be onnan. minl gyorsabbak lehessenek. Ha bonyolultabb utastst akarunk
adni a szmtgpnek, azt elemi utastsokbl ptjk fel. Elemi
A memria olyan, mint egy nagyon hossz tblzat, melynek utasts az az utasts, amit a szmtgp processzora kzvetle-
minden celljban egy szm van, ami csak 0 vagy 1 lehet: nl vgrehajt, teht mr nem bontjuk kisebb utastsokra.
0 1 1 1 0 0 1 0 0 0 1 0 0 1 1 Ktfle elemi utasts ltezik: ugr utasts s nem ugr utas-
Azrt csak 0 s 1, mert a szmtgpek kettes szmrendszert ts. A nem ugr utastsokat a processzor sorban egyms utn,
hasznlnak, s a kettes szmrendszerben csak ez a kt szmjegy azaz szekvencilisan hajtja vgre. A nem ugr utastsok pl. az
van. Azrt kettes szmrendszert hasznlnak, s nem pl. tzest, elemi matematikai mveletek: sszeads, kivons, szorzs, osz-
mert gy egy kapcsol elg a szm trolshoz: ha a kapcsol be ts, maradkkpzs, negls (=ellenttes eljelre alakts). Van-
van kapcsolva, az 1, ha ki van kapcsolva, az 0. Tzes szmrend- nak sszehasonlt utastsok (<, >, egyenl, nem egyenl, stb.),
szerben tz klnbz llapotot kellene megklnbztetni, ami logikai utastsok (S, VAGY, NEM), adatmozgat utastsok,
sokkal nehezebb, mint kett. Sokkal egyszerbb megllaptani, bitmveletek, stb.
hogy egy lmpa vilgt-e vagy sem, mint azt, hogy milyen ersen A processzor az adatokat beolvassa a memribl, vgrehajt-
vilgt egy tzfokozat skln. ja rajtuk az utasts(ok) ltal elrt mveletet, majd az eredmnyt
A kettes (azaz binris) szmrendszer szmjegyeit angolul visszarja a memriba.
binary digitnek, rviden bitnek nevezzk. Mivel a memriban csak egsz szmokat tudunk trolni, az
Ahhoz, hogy a memrit hatkonyan lehessen hasznlni, a elemi utastsokat is szmknt troljuk: minden utastshoz tarto-
benne trolt informcikhoz tetszleges sorrendben hozz kell, zik egy szm, ez az utasts gpi kdja. Egy utasts ltalban
hogy tudjunk frni (a msik lehetsg a sorban egyms utn tbb bjt hosszsg.
lenne). Az informcik tetszleges sorrend elrse a memri- A processzor tud adatokat fogadni a perifrikrl, s tud ada-
ban (Random Access Memory RAM) gy valsthat meg tot kldeni a perifriknak.
legegyszerbben, ha minden bitrl tudjuk, hanyadik a memria
kezdettl szmtva, s ez alapjn hivatkozunk r. A perifrik kzl szmunkra mindssze hrom lesz lnye-
Egy bit nagyon kevs informcit trol, ezrt a szmtgpek ges: a billentyzet, a kperny s a httrtr. A kpernyre nem
tervezi gy dntttek, hogy nem engedik meg minden bit cmz- fogunk rajzolni, csak szveget runk ki.
st, hanem csak bitcsoportokt, amit bjtnak neveznk, mert gy
egyszerbb az ramkrk felptse. A szmtgpekben teht 1.2 A programozs alapjai
gy vlasztjuk ki a neknk kell adatot vagy utastst, hogy
megmondjuk, hanyadik bjt a memria kezdettl szmtva. Ezt a Az 1.1 pontban bepillantottunk a szmtgpek felptsnek
sorszmot memriacmnek nevezzk. s mkdsnek alapjaiba, alacsony szint dolgokkal foglalkoz-
Egy bjt mrett gy vlasztottk meg, hogy egy karakter tunk. Az 1. fejezet htralv rszben ellenkez irnybl kzel-
(azaz bet, szmjegy, rsjegy, stb.) belefrjen. Sokfle bjtmre- tnk, s sok fontos alapfogalmat fogunk ttekinteni.
tet hasznltak: 6, 7, 8, 9 bites bjtok is lteztek. Ezek kzl ma-
napsg a 8 bites bjt szinte egyeduralkod. A knyvben ismerte- Defincik Az albbi defincikat megjegyezni nem kell. Arra
tett C nyelv szabvnya elrja, hogy csak olyan rendszerben valk, hogy ha bizonytalanok vagyunk valamiben, visszalapo-
hasznlhat a C nyelv, ahol egy bjt legalbb 8 bites, azonban zunk.
futnak C programok pl. 9 bites bjtokat hasznl rendszerekben Programozs: szmtgp-algoritmusok s adatszerkezetek
is, ezt ksbb se feledjk! megtervezse s megvalstsuk valamely programozsi nyelven.
Egy nyolcbites bjt a kvetkez szmokat trolhatja: Algoritmus: Valamely problma megoldsra alkalmas v-
00000000=0, 00000001=1, 00000010=2, 00000011=3, ges szm cselekvssor, amelyet vges szm alkalommal me-
00000100=4, 00000101=5, , 11111111=255. Azaz sszesen chanikusan megismtelve a problma megoldst kapjuk.
256 fle rtknk van (28), 0-tl 255-ig. A bjtunkat azonban Adatszerkezet: az adatelemek egy olyan vges halmaza,
rtelmezhetjk mskpp is, pldul ha azt mondjuk, hogy az els amelyben az adatelemek kztt szerkezeti sszefggsek vannak.
bit nem szmjegy, hanem eljel: ha 0, akkor pozitv szm, ha 1, Az adatelem az a legkisebb adategysg, amelyre hivatkozni lehet.
akkor negatv szm. gy azonban csak 7 bitnk marad a szmra, Programozsi nyelv: a szmtstechnikban hasznlt olyan,
azaz 0-tl 127-ig tudunk szmot trolni az eljelen kvli rszen. az ember ltal olvashat s rtelmezhet utastsok sorozata,
Ha 0255 kztti szmnak tekintjk a bjtot, akkor eljel nl- amivel kzvetlenl, vagy kzvetve (pldul: gpi kdra fordts

8
utn) kzlhetjk a szmtgppel egy adott feladat elvgzsnek Eredetileg a UNIX opercis rendszer elksztshez fejlesz-
mdjt. tettk ki, a f cl a hatkonysg, a minl tmrebben megrhat
programkd volt. Mivel nem oktatsi clra fejlesztettk ki, nem
volt cl az, hogy a nyelv egyes rszeit egymsra plve lehessen
Magyarzatok Az algoritmus defincijban ktszer is szere-
elsajttani. Tbbszr lesz olyan az anyagban, hogy elszr vala-
pel a vges sz. A cselekvsek szmnak vgesnek kell lennie, mit nem magyarzunk meg, egyszeren csak elfogadjuk, hogy ez
mert vgtelen utastst nem tudunk lerni. Vges szm ismtls: gy van, s ksbb ltjuk majd, hogy mirt.
ez ltalban egyet jelent, de ha tbbszr ismtlnk, akkor is vges
sokszor, klnben idben vgtelen ideig tartana a mvelet. Me- A programozs menete
chanikus: azt jelenti, hogy gondolkods nlkl, vagyis egy gp is
vgre tudja hajtani. Specifikci
Adatszerkezet esetben szerkezeti sszefggs pl. hogy egy
szvegben a betket sorban, egyms mellett troljuk.
A programozsi nyelv az ember szmra ttekinthet form- Tervezs
ban trtn programrst tesz lehetv, ebbl a fordtprogram
Algoritmus
kszt a gp szmra rthet gpi kdot.
Mint ltjuk, az algoritmus egy ltalnos fogalom, nem kt- vlasztsa
dik a szmtgpekhez. Pldul, ha vesznk egy lapra szerelt
knyvespolcot, ltalban van a dobozban egy paprlap, rajta Adatszerkezetek Dokumentci
brkkal, melyek az sszeszerels folyamatt, azaz az sszeszere- megvlasztsa elksztse
ls algoritmust mutatjk.
A szmtgpprogramok adatokat (informcikat) kezelnek,
dolgoznak fel. A legegyszerbb (valamire hasznlhat) program Nyelv
is kezel adatokat. Ha ki akarjuk rni a szmokat 1-tl 10-ig, akkor megvlasztsa
tudnunk kell, ppen mennyinl tartunk, ez adat. Ha csak ki aka-
runk rni egy szveget, mr ott is adatot kezelnk, mert a szveg
maga is adat. ltalban a programok komoly mennyisg adatot Kdols
kezelnek. Akkor lesz hatkony a program mkdse, ha az ada-
tokat olyan mdon troljuk, ahogy az a legkedvezbb, azaz meg- Tesztels,
felel adatszerkezete(ke)t vlasztunk. hibajavts
Program = algoritmus + adatszerkezet.
Kdols: az algoritmus s az adatszerkezet megvalstsa va-
lamely programnyelven.
Specifikci: a program feladatnak, bemeneti s kimeneti
A programozs alapjainak elsajttsa a kvetkez dol- adatainak megadsa. Ebben a knyvben sok ilyet tallunk: a
gokat jelenti: megoldand feladatok szvege specifikci. (Pl. rjon C progra-
mot, amely)
Megismernk sok fontos alapvet algoritmust, pldul
Tervezs: a feladat, azaz a specifikci ismeretben vlaszt-
ilyen a prmkeress, kivlaszts, keressek, rendezsek,
juk ki a programnyelvet (senki sem szerkesztene weblapot C-
adatszerkezet-kezelsi algoritmusok, szvegfeldolgo-
ben), az algoritmusokat s az adatszerkezeteket.
zs, rekurzv algoritmusok, vges automata.
Kdols: A kivlasztott nyelven megvalstjuk a megterve-
Megismernk nhny adatszerkezetet, pldul tmb,
zett algoritmusokat s adatszerkezeteket. Ez rszben egyszerre
struktra, fjl, lncolt listk, fk.
trtnik a tervezssel, azaz bizonyos algoritmikus ill. adatszerke-
Megtanulunk kdolni szabvnyos C nyelven. zeti krdsekben a kdols kzben dntnk.
Megismerjk a szmtgpek mkdsnek alapjait. Tesztels, hibajavts: Senki sem r hibtlan kdot, azaz
mindig van mit javtani. A hibknak kt csoportja van: szintakti-
A C nyelv sok korszer programnyelv alapja. Sok ms nyelv- kai (formai) s szemantikai (tartalmi) hibk.
hez kpest kevs nyelvi elembl pl fel, ezrt viszonylag kny- Szintaktikai hiba a formai szablyok megsrtse. Valamit
ny megtanulni. Hatkony strukturlt programok rst teszi rosszul gpelnk, lemarad egy zrjel, stb. Br a kezd progra-
lehetv. Tkletesen alkalmas arra, hogy segtsgvel megtanul- moznak sok bosszssgot okoznak a szintaktikai hibk, ezekkel
juk az algoritmusok s adatszerkezetek gyakorlati megvalstst. knny elbnni, mert a fordtprogram jelzi, hol tallhatk.
Szemantikai hiba esetn a fordtprogram nem tall hibt,
A C nyelvet az 1970-es vekben fejlesztettk ki, amikor a
mert a program formailag j, csak nem azt csinlja, amit szeret-
kperny nem volt a szmtgpek nlklzhetetlen rsze. A
szabvnyos C nyelv fggvnyknyvtra csak olyan megjelent nnk, hanem azt, amire utastottuk. Szemantikai hibra j plda a
fggvnyeket tartalmaz, amelyek szveges nyomtatn is mkd- kzismert vicc:
nek. C-ben nem tudunk rajzolni, de mg a kpernyn pozcionlni
sem, csak kls, nem szabvnyos fggvnyknyvtrak segtsg-
vel, melyek nem kpezik a tananyag rszt. Felmerlhet a krds,
hogy mirt nem egy korszer, ablakoz grafikt tmogat prog-
ramnyelvet tanulunk? Azrt, mert ez csak eltereln a figyelmn- Censored
ket a lnyegrl: az algoritmusokrl s az adatszerkezetekrl. Ne
feledjk:
programozs != kdols
Azaz a programozs nem egyenl a kdolssal. (A C nyelv-
ben a nem egyenlt !=-knt rjuk, mert nincs thzott egyenlsg- Itt teht a pciens szintaktikailag helyes algoritmust adott a
jel a billentyzeten.) Aki tud kdolni C-ben vagy ms nyelven,
doktornak, aki pontosan vgrehajtotta, amire utastst kapott, csak
mg nem tud programozni. Az fog tudni j programokat kszte-
ni, aki biztos alaptudssal rendelkezik. a pciens nem ezt szerette volna.
Ahogy emltettk, a C nyelv nagy elnye, hogy sok program- Egy program esetben nagyon fontos, hogy kiszrjk a sze-
nyelv alapja (pl. Java, C#, de pl. a php is sokat tvett belle), teht mantikai hibkat, mieltt azt valaki lesben hasznln. Ha nem
az itt megszerzett tudst jl lehet hasznlni a ksbbiekben. teszteljk megfelelen, nem is fogunk tudni arrl, hogy hibs.

9
A dokumentls clja, hogy segtsk a program megrtst.
Szlhat a felhasznlnak (hasznlati utasts), s szlhat a fejlesz-
2. Az algoritmusok megadsa
tnek. A fejleszti dokumentci tartalmazza az adatszerkezetek
s algoritmusok, fjlformtumok lerst, valamint a tesztelsnl Algoritmusok megadsra a programtervezs illetve doku-
hasznlt adatokat. Legfontosabb eleme a program megjegyzsek- mentls sorn van szksg. Alapveten kt mdon adhatunk
kel elltott forrskdja. meg algoritmusokat: szvegesen s grafikusan. Kt-kt megadsi
mdrl ejtnk pr szt.
Szveges megads: pszeudokd, programkd.
Grafikus megads: folyamatbra, struktogram.
A programkd s a pszeudokd hasonlt egymsra, erre
hamarosan tbb pldt is ltunk. F klnbsg, hogy a program-
kd megrtshez ismerni kell az adott nyelv szablyait, mg a
pszeudokd igyekszik minden programoz szmra rthet lenni.
A pszeudokd vonatkozsban nincsenek ktelez szabvnyok.
A folyamatbra s a struktogram viszonya hasonl a
pszeudokd s a programkd viszonyhoz olyan rtelemben,
hogy a struktogram rtelmezse s elksztse ignyel nmi
programozi tapasztalatot, mg a folyamatbra mindenki szmra
rthet. A folyamatbra htrnya, hogy nagyon knny vele
olyan algoritmust alkotni, ami nem alakthat kzvetlenl struk-
turlt programkdd, mg a struktogrammal lert algoritmusok
mindig strukturltak.

Teafz robot
Nzznk meg egy pldt egy feladat algoritmizlsra! Van
egy robotunk, akit szeretnnk arra utastani, hogy fzzn tet.
Hogyan utastjuk a feladatra?
1. vltozat:

Fzz tet!

Ha van olyan utastsa, hogy Fzz tet!, akkor semmi


egyb teendnk nincs, mint kiadni ezt az utastst. Ha nincs ilyen
utasts, akkor meg kell magyarznunk neki, mit is vrunk el tle.
2. vltozat:

Fzz tet! parancs:


Tlts vizet a kannba!
Kapcsold be a tzhelyet!
Tedd r a kannt!
Amg nem forr
Vrj egy percet!
Dobd bele a teatojst!
Vedd le a tzrl!
Ha kell cukor
Tedd bele!
Egybknt
Ha kell mz
Tedd bele!
Tltsd csszbe!
VGE.

Ez a teafzs algoritmusnak pszeudokdja. Amit beljebb


kezdnk, az a kvl kezdd rszhez tartozik (azaz egy blokkban
vannak). Ebben a pszeudokdban megjelenik a strukturlt
programozs mindhrom alkoteleme:
Ahol egy oszlopban kezddnek az egymst kvet
utastsok, az a szekvencia.
Az amg kezdet utastsblokk egy ciklus, ms
nven iterci. A ciklus magjban lv utasts
vagy utastsok addig ismtldnek, amg az amg
utn ll felttel igaz
Feltteles elgazs a ha kezdet utastsblokk.
Ha a ha utni llts igaz, akkor vgrehajtdik a
felttel magjban lv utasts vagy utastsok. A
feltteles elgazsnak lehet (de nem ktelez) egy

10
egybknt ga is, ami akkor hajtdik vgre, ha a Tovbbi problma, hogy mirt ezekre a rszekre bontottuk?
ha utni llts hamis. Ez a felbonts akkor j, ha a robot ismeri az sszes benne szerep-
l utastst. Ha nem ismeri, tovbb kell bontanunk az algoritmust
A fenti algoritmust folyamatbrval is megadhatjuk: egszen addig, amg olyan utastsokhoz nem rnk, amit a robot
is ismer. A robot ltal ismert utastsokat elemi utastsoknak
START nevezzk, ezekbl lehet bonyolultabb programokat kszteni.
Tegyk fel, hogy a robotunk nem ismeri a 2. vltozat utast-
sainak egy rszt! Ha ezeket felbontjuk, akkor az algoritmus
Tlts vizet a kannba! ttekinthetetlenn vlik, tl hossz lesz. Mgis muszj felbontani
az utastsokat, klnben a robot nem fogja rteni, mit akarunk
tle. Van erre is megolds: a 2. vltozatot gy hagyjuk, s a benne
Kapcsold be a tzhelyt! tallhat sszetett utastsok sztbontst kln brzoljuk.
Pldul a Tlts vizet a kannba! gy nzhet ki:
Tedd r a kannt!
Tlts vizet a kannba! parancs:
Menj a csaphoz!
Tedd al a kannt!
I Kell mg Nyisd meg a csapot!
Vrj egy percet!
melegteni? Amg nincs tele
Vrj egy msodpercet!
N Zrd el a csapot!
Dobd bele a teatojst! VGE.

Ennek a klnvlasztsnak ms elnye is van: ha tbbszr is


Vedd le a tzrl! szksg van ugyanarra a funkcira, akkor mindig csak a nevt
kell lernunk, a robot mr tudni fogja, hogy mit kell tennie. A
valdi strukturlt programok nagyon fontos tulajdonsga, hogy
gy klnvlaszthatk a funkcik. Az angol function kifejezs
I Cukor kell? funkciknt is fordthat, azonban a magyar nyelvben a fggvny
Tedd bele!
vltozata terjedt el. Hasznlatos mg az eljrs1, vagy szubrutin
elnevezs is. A C nyelv a fggvny kifejezst hasznlja, s ltni
N fogjuk, hogy a matematikai fggvnyek is valban megadhatk
ilyen formban.
N Nem biztos, hogy azonnal esznkbe jut, de a fenti algoritmust
Mz kell? elemezve gondot jelenthet, ha pl. nincs vz, vagy, mondjuk, nem
lehet megnyitni a csapot. Egy program rsa sorn fel kell kszl-
ni a vratlan helyzetekre, s a problmkat kezelni kell. Ezt hi-
I
bakezelsnek, vagy kivtelkezelsnek nevezzk. A fenti esetben
Tedd bele! pl. a kvetkezkppen jrhatunk el:

Tlts vizet a kannba! parancs:


Tltsd csszbe!
Menj a csaphoz!
Tedd al a kannt!
Ha megnyithat a csap
STOP
Nyisd meg a csapot!
Egybknt
A folyamatbrn jl ltszik a ciklus s az elgazs kztti k-
lnbsg: ciklus esetn visszaugrunk, elgazsnl pedig elre Mondd el a fnknek a problmt!
haladunk. Fejezd be a programot!
Amg nincs tele
Knnyen tudunk a folyamatbrba olyan nyilakat, azaz ugr- Ha van vz
sokat rajzolni, amelyeket a pszeudokdban, a tanult strukturlt Vrj egy msodpercet!
elemekkel nem tudnnk megvalstani. Prbljuk ki! Egybknt
Mondd el a fnknek a problmt!
Megnztk a formt, beszljnk a tartalomrl! Ha vgignzi Fejezd be a programot!
az algoritmust, valsznleg felvetdik nben, hogy nem n nem Zrd el a csapot!
gy fzne tet. Mirt nem filtert hasznlunk? Mirt a kannba VGE.
tesszk a cukrot vagy a mzet s nem a csszbe? Stb. A specifi-
kci nem rgztette ezeket a rszleteket. Egszen pontosan A folyamatbra ksztshez szksges ismeretekkel, vala-
semmit sem rgztett, csak azt, hogy a robot fzzn tet. Ez mint a struktogrammal a 20. fejezetben foglalkozunk.
alapjn akr minden zests elhagyhat lett volna, vagy tovbbi-
akkal lehetne kiegszteni. Az algoritmus ksztje hozta meg a
dntseket gy, ahogy neki tetszett.
ltalban is elmondhat, hogy a programoz dnt rengeteg
algoritmikus krdsben, a specifikci ltalban nem ad vlaszt
minden krdsre. Szksg esetn konzultlhatunk is a megbz-
val, hogy mik az elvrsai. 1
Az eljrs (procedure) kifejezst olyan esetben hasznljk, ha nincs
visszatrsi rtk. Ez a C-ben a void tpus fggvny.

11
Gondolkodjunk egytt!
3. Egyszer algoritmusok s
kdolsuk C nyelven
G2.1 Adjunk algoritmust a robotunknak rntottaksztshez!
brzoljuk az algoritmust folyamatbrval is! Vlasszunk egy
utastst, amelyet kln funkciknt (fggvnyknt) tovbbon- 1. feladat :
tunk! Egsztsk ki az algoritmust hibakezelssel!
rjuk ki a szmokat a kpernyre 1-tl 10-ig!
G2.2 A kalauz nem tudja kezelni a jegyeket a vonaton, mert a
neki adott utastsok sszekeveredtek. Segtsen neki, s rja be A megolds algoritmusa a kvetkezkpp nzhet ki:
a pszeudokd soraiba a magfelel utasts betjelt! Minden
sorba csak egy bet kerlhet, s minden bet csak egyszer Szmkir program:
hasznlhat. Minden bett fel kell hasznlnia! Jegyezd meg, hogy az aktulis szmunk 1!
Amg a szm kisebb vagy egyenl, mint 10
a) Ha nincs brlet rd ki a szmot!
b) Lyukaszd! Nveld meg a szmot eggyel!
c) VGE. VGE.
d) Szllj t a kvetkez kocsiba!
e) Amg van kezeletlen utas Ez gy jnak tnik, de ha a robotunk vgrehajtan, nem azt
f) Krd a jegyet vagy a brletet! kapnnk, amit szeretnnk:
g) Adj ptdjcsekket! Eredmny: 12345678910
Azaz kifelejtettk a szkzt a szmok kzl. Programrsnl
h) Ha nem rt a szerelvny vgre
a legaprbb rszletekre is figyelni kell, mert imperatv progra-
i) Ha van jegy
mozsi nyelvet hasznlunk, azaz a szmtgp azt, s csak azt
j) Amg nem r a szerelvny vgre
hajtja vgre, amire utastjuk, s pontosan gy, ahogy erre
k) Menj a kvetkez utashoz! utastjuk.
l) Egybknt Vannak deklaratv nyelvek is, ahol csak azt kell megmondani, mit
szeretnnk, a hogyanrl a program dnt. Ezek a nyelvek nem hasznlha-
______ tk ltalnosan, csak specilis feladatokra.
______
______ A kiegsztett algoritmus a kvetkez:
______
______ Szmkir program 2:
______ Jegyezd meg, hogy az aktulis szmunk 1! (1)
______ Amg a szm kisebb vagy egyenl, mint 10 (2)
______ rd ki a szmot! (3)
______ rj ki egy szkzt! (4)
______ Nveld meg a szmot eggyel! (5)
______ VGE.
______
Figyeljk meg, hogy ez az algoritmus az utoljra kirt 10-es
G2.3 Rajzolja fl a kvetkez algoritmus folyamatbrjt! utn is tesz egy szkzt. Ez ltalban nem problma. Ha mgis,
mdostani kell az algoritmust.

G2.4 A kvetkez folyamatbra alapjn rja fl az algoritmus Egsztse ki a programot gy, hogy az utoljra kirt szm utn
pszeudokdjt! mr ne rjon szkzt!

Gyakori, hogy az algoritmus-megadsnl, az els program-
vltozathoz hasonlan, nem jelezzk azokat a magtl rtetd
lpseket, amelyeket egybknt a programkdba belerunk.
A szmkir algoritmusban van egy szm, aminek kezdetben
egy az rtke, s folyamatosan vltozik, a ciklus minden lps-
ben eggyel n. Az olyan adatot, amelyet meg lehet vltoztatni,
vltoznak nevettk. Az olyan adatot, amelynek rtke nem
vltoztathat meg, konstansnak nevezzk. A fenti pldban
konstans az 1 s a 10. Az adat olyan informci, melyet a szm-
tgp trol. Az informci a valsg lekpezse.
A fenti algoritmus Pascal nyelven gy nz ki:

program szamkiiro (input,output);


var
szam : integer; (a)
begin
szam := 1; (1)
while szam <= 10 do begin (2)
write(szam, ); (3,4)
szam := szam + 1; (5)
end;
end.

12
A tovbbiakban csak C nyelven adjuk meg a kdot. A fenti
Ugyanez C nyelven: pldn azt akartuk szemlltetni, hogy mennyire hasonl egyms-
hoz az algoritmus s a programkd, brmilyen programnyelven is
#include <stdio.h> valstjuk meg. Ez azt jelenti, hogy aki tud programozni, annak
int main(void){ egy j nyelv elsajttsa sokkal kisebb munkjba kerl, mint
int szam; (a) alapoktl megtanulni az elst.
szam = 1; (1)
while( szam <= 10 ){ (2)
printf("%d ",szam); (3,4)
2. feladat
szam = szam + 1; (5)
} rjuk ki a pratlan szmokat a kpernyre 1-tl 21-ig!
return 0;
} A feladat megoldshoz kiindulsi alapknt felhasznlhatjuk
az 1. feladat algoritmust. Itt is folyamatosan nvekednek a kirt
A pszeudokdban s a kt programban azonos sorszm jelzi szmok, viszont nem egyesvel. Kt algoritmust is mutatunk:
az azonos jelents sorokat. Programok kztt tbb formai k-
lnbsget ltunk, de vannak hasonlsgok is. Pratlanok program 1:
Mindkt programban definilni kellett a vltozt, ezt a Jegyezd meg, hogy az aktulis szmunk 1!
rszt (a)-val jelltnk. A Pascal s a C is ersen tpusos Amg a szm kisebb vagy egyenl, mint 21
nyelv, azaz a vltozkrl meg kell mondani, hogy milyen Ha a szm nem oszthat kettvel
fajta adatok trolsra alkalmasak. Itt integer illetve int rd ki a szmot!
jelli azt, hogy egsz szmokat trolhat. Pldul PHP-ben rj ki egy szkzt!
vagy Basic-ben nem kell definilni a vltozkat, azokban brmi- Nveld meg a szmot eggyel!
lyen adat lehet. Ez egyszersti a programrst, viszont nveli a
hibalehetsget. VGE.
A pszeudokdban azzal jelltk, hogy mely utastsok
vannak egy msik utasts blokkjban, hogy beljebb Pratlanok program 2:
kezdtk (tabulltuk) ezeket a sorokat. A Pascal s a C Jegyezd meg, hogy az aktulis szmunk 1!
nyelv viszont nem rja el, hogy beljebb kezdjnk brmit, Amg a szm kisebb vagy egyenl, mint 21
vagy akr kln sorba kerljenek a dolgok, ezrt ms rd ki a szmot!
mdon kapcsolja ssze illetve vlasztja szt az utastso- rj ki egy szkzt!
kat. Az utastsok elvlasztsra mindkt nyelvben a Nveld meg a szmot kettvel!
pontosvessz (;) szolgl, mg az egy blokkba tartoz VGE.
utastsokat Pascalban a begin-end pr hatrolja, C-ben
pedig a {} kapcsos zrjel pr. C-ben nincs pontosvessz Melyik megolds helyes?
a # kezdet sorok vgn, valamint a blokk vgn sem. Mindkett helyes, mindkett j.
rtkadsra Pascalban a :=, mg C-ben az = opertor Egy problmt tbbfle, helyes mdon is meg lehet oldani.
szolgl (opertor jelentse: mveleti jel). FIGYELEM! Azt a krdst mr fel lehet tenni, hogy melyik megolds a jobb.
Az rtkads mindig jobbrl balra trtnik! Azaz nem Az els megoldsnl vgigmegynk minden szmon, s azt
j az i + 1 = i kifejezs! (Ellenkez esetben a fordt nem vizsgljuk, hogy a szm megfelel-e a kvetelmnynek, azaz
tudn, hogy egy a=b; kifejezsben a vagy b kap-e j r- pratlan-e, s ha igen, kirjuk. Az a megoldsi mdot, amikor
tket.) minden lehetsges kombincit kiprblunk, brute-force (nyers
A kirs szintaktikja egsz ms a kt nyelvben. Pascal- er) mdszernek nevezzk. Gyakran hasznlnak brute-force
ban a write fggvny vesszvel elvlasztva kapja a ki- mdszert pldul jelszk feltrsre: minden lehetsges jelszt
rand adatokat. C-ben a printf fggvny egy vgigprblnak, mg el nem jutnak az igazihoz. Nem hatkony,
formtumsztringnek nevezett, "" kz helyezett szveg- de elbb-utbb eredmnyt hoz.
gel kezddik, melyben %d jelzi, hogy itt egy egsz sz- A msodik esetben viszont kihasznljuk, hogy ismerjk a p-
mot akarunk kirni 10-es szmrendszerben (azaz decim- ratlan szmok kztti matematikai sszefggst (azaz, hogy
lisan), majd szkz, hogy szkzt akarunk kirni. A C kettvel nagyobb a kvetkez az elznl), s ezltal a ciklus
formtumsztringben kt specilis jelents karakter van, a lpsszmt a felre cskkenthetjk, s mg az oszthatsgot sem
% s a \ (fordtott per jel = back slash). Az ezek utn rt kell vizsglni.
bet vagy kifejezs specilis jelentssel br, errl a 12. fe- Lssuk a kt megoldst C nyelven:
jezetben lesz sz. Minden egyb, amit az idzjelek kz
runk, vltozatlan formban jelenik meg. (A Windows a 1.
magyar kezetes betket rosszul kezeli, ezek helyn egyb ka-
rakterek jelennek meg a kpernyn, ezrt ha ki akarunk rni va- #include <stdio.h>
lamit, kezetek nlkl tegyk!) int main(void){
A C program elejn s vgn lv rszre az 5. fejezetben int i = 1;
adunk magyarzatot, ebben a fejezetben minden progra- while( i <= 21 ){
munk gy fog kinzni: if( i % 2 == 1){
printf("%d ",i);
#include <stdio.h> }
int main(){ i = i + 1;
}
Az algoritmusnak megfelel programkd return 0;
}
return 0;
}

13
2. Ha azonban vgiggondoljuk az elz feladat brute-force
megoldst, mr nem is olyan nehz a feladat:
#include <stdio.h> Vlasszuk ki a kt szm kzl a kisebbet, mert ez
int main(void){ lehet a legnagyobb olyan rtk, ami kzs osztja
int i = 1; lehet a kt szmnak.
while( i <= 21 ){ Nzzk meg, hogy ez osztja-e mindkt szmnak.
printf("%d ",i); Ha igen, megvagyunk. Ha nem, akkor cskkentsk
i = i + 2; eggyel a szmot, s ezt vizsgljuk meg, hogy oszt-
} ja-e mindkettnek.
return 0; Ismteljk a cskkentst s a vizsglatot, amg k-
} zs osztt nem tallunk. Biztosan lesz ilyen, mert 1
minden szmnak osztja.
Az els program feltteles elgazsba ez a felttel kerlt:
rjuk le az algoritmus pszeudokdjt!
i % 2 == 1
LNKO 1 program:
Mit jelent ez? Krj be kt pozitv egsz szmot!
A dupla egyenlsgjel, azaz == opertor kt rtk egyenl-
Ha az els kisebb, mint a msodik
sgt vizsglja. Matematikban csak egyfle egyenlsgjelet
Jegyezd meg, hogy az oszt az els!
szoktunk rni, azonban kt jelentssel. C-ben megklnbztetjk
a jelentst: x=y s x==y egszen mst jelent. x=y azt jelenti, hogy Egybknt
x-nek rtkl adjuk y-t, x==y pedig azt vizsglja, hogy vajon Jegyezd meg, hogy az oszt a msodik!
egyenl-e x s y? Amg oszt nem osztja mindkt szmnak
A % opertor a C nyelvben a maradkkpzs jele. x % y Cskkentsd oszt rtkt
esetben x-et y-nal elosztva a maradkot kapjuk. Pl. 10%5==0, rd ki osztt!
11%5==1, 12%5==2, 13%5==3, 14%5==4, 15%5==0, stb. (Tz VGE.
oszthat ttel, azaz a maradk, nulla; tizenegy nem oszthat ttel,
mert a maradk egy, stb.) A % opertor csak nemnegatv eg- C nyelven:
szeken rtelmezett, teht negatv egszeken vagy valsakon nem
definilt eredmnyt ad. #include <stdio.h>
Az == ellentte a != nem egyenl opertor. int main(void){
int szam1, szam2, oszto;
Az i % 2 == 1 mvelet helyett rhatjuk, hogy i % 2 != 0 is. printf("Adj meg 2 poz. egeszt: ");
Mirt? scanf("%d%d",&szam1,&szam2);
if(szam1<szam2){
Most sszevontuk az els plda (a) s (1) elemeit: egyszerre oszto = szam1;
definiljuk a vltozt, s adunk neki kezdrtket. }
Mi trtnne, ha elfeledkeznnk a kezdrtkrl? else{
oszto = szam2;
int i; }
while( i <= 21 ){ // ajjaj! while(!(szam1%oszto==0
printf("%d ",i); && szam2%oszto==0)){
i = i + 2; oszto = oszto - 1;
} }
printf("LNKO = %d",oszto);
Ez a programrszlet hibsan mkdik, s mkdse elre ki- return 0;
szmthatatlan. Amg egy vltoz nem kap rtket, inicializlat- }
lan. A C-ben egy inicializlatlan vltoz tartalma meghatrozat-
lan, brmi lehet benne. Ezt a brmit memriaszemtnek hvjuk, A szmok beolvasshoz a scanf fggvnyt hasznljuk. A
mert minden vltoz van valahol a memriban, s amikor a fggvny hasznlata hasonlt a printf-re: egy formtumsztring
rendszer kiosztja a memrit a vltozknak, nem llt be semmi- hatrozza meg, hogy hny s milyen tpus rtket kell megadnia
lyen rtket. A vltozk rtke az lesz, ami az adott helyen ko- a felhasznlnak (vagyis annak, aki a ksz programot hasznlja),
rbban volt. ezt kveten, vesszvel elvlasztva kvetkeznek a vltozk. A
vltozk neve el egy & jelet is kell rni! A felhasznlnak sz-
kzt vagy ENTER-t kell rnia a szmok kz.
3. feladat Jegyezzk meg, hogy a scanf nem r ki semmit. Ha a %d-ken kvl
mst is runk ide, akkor a scanf azt vrja, hogy a felhasznl is berja ezt a
Az elz feladatban rvidebb s egyszerbb, radsul hat- szveget. Ha a felhasznl nem rja be, akkor hibsan mkdik. Pl. ha
konyabb is a msodik megolds, s inkbb ez jut az ember esz- scanf("Szia%d",&szam1);-t rnnk, akkor a felhasznlnak gy kellene
bernia a szmot: Szia120. Ha a felhasznl csak a 120-at rn be, a scanf
be, semmint a msik. Nzznk egy olyan esetet, amikor a brute-
ezt nem fogadn el. A scanf-rl bvebben a 12. fejezetben lesz sz.
force algoritmus a kzenfekv, s gondolkodni kell a hatko-
A while ciklus felttele ezttal jval bonyolultabb, mint ko-
nyabb megoldshoz!
rbban. A !(felttel) a felttel neglst jelenti, azaz IGAZ-bl
HAMIS-at, HAMIS-bl IGAZ-at csinl. Jelen esetben a zrjel-
rjuk ki kt pozitv egsz szm legnagyobb kzs osztjt!
ben akkor van IGAZ, ha mindkt szm oszthat az osztval,
vagyis oszt kzs osztjuk, minden ms esetben HAMIS. A
A feladat megoldshoz ismerjk az sszes algoritmikus esz-
ciklusnak viszont addig kell ismtldnie, amg oszt nem kzs
kzt s a C nyelv sszes olyan elemt, ami szksges az algorit-
osztja a kt szmnak. A !-lel jellt mveletet logikai NEM-nek
mus lekdolshoz, mgsem tnik egyszernek a feladat.
is mondjuk.

14
A zrjelben ll kt felttel kz az && opertor kerlt, en- rhat egy. Ezeket a karaktereket sszefoglal nven whitespace
nek neve logikai S kapcsolat. Az S mvelet eredmnye akkor karaktereknek nevezzk. Ennek rtelmben az if utasts blokkja
IGAZ, ha mindkt felttel IGAZ, brmelyik is HAMIS, az ered- gy is rhat pl.: {oszto=szam1;}. Azrt rtuk gy, ahogy,
mny HAMIS. hogy jobban hasonltson a pszeudokdra.
A kt megismert logikai mvelet igazsgtblja a kvetkez:
Javthatjuk az algoritmus hatkonysgt, ha elszr megnz-
A !A zk, hogy a kisebbik szm lehet-e a LNKO, s ha nem, a vizs-
glatot a kisebbik szm feltl folytatjuk. (A LNKO osztja a
HAMIS IGAZ kisebbik szmnak is, azaz lehet szm, szm/2, szm/3,
IGAZ HAMIS szm/4,, s legrosszabb esetben szm/szm=1.) Dolgozza t
a fenti algoritmust ennek figyelembevtelvel, s ksztse el a
kdot C nyelven!
A B A&&B
HAMIS HAMIS HAMIS LNKO 1 program mr tartalmazott nmi megfontolst: fellrl
IGAZ HAMIS HAMIS lefel indultunk el. Lehetne ennl butbb mdszerrel is keres-
ni a LNKO-t. Induljunk 1-tl, s menjnk a kisebbik szmig
HAMIS IGAZ HAMIS
egyesvel! Minden lpsben ellenrizzk, hogy mindkt szm
IGAZ IGAZ IGAZ kzs osztjrl van-e sz, s ha igen, jegyezzk meg az osz-
tt! A kisebbik szm elrsekor az utoljra megjegyzett oszt
A szam1%oszto==0 && szam2%oszto==0 kifejezst a LNKO. rja meg az algoritmus pszeudokdjt s C nyelv
szban gy mondhatjuk: szam1 oszthat osztval, s szam2 is megvalstst!
oszthat osztval. A htkznapi beszdben ezt
mondhatnnk: szam1 s szam2 is oszthat oszt- A while s if utastsok esetben, ha az utasts magja egyet-
val, azonban ha programot runk, nem rhatjuk gy: len utastst tartalmaz, a kapcsos zrjel elhagyhat, emiatt a
szam1 && szam2%oszto==0! fenti program rvidebben is rhat:
A C nyelvben sszesen hrom logikai mvelet van: a NEM,
valamint S mellett a harmadik a logikai VAGY kapcsolat. A #include <stdio.h>
logikai VAGY kapcsolatot C-ben || opertor jelli. Ez kt fgg- int main(void){
leges vonal, mely magyar billentyzeten a W+Alt Gr kombinci- int szam1,szam2,oszto;
val rhet el (gyakran gy brzoljk: ). Ennek igazsgtblja a printf("Adj meg 2 poz. egeszt: ");
kvetkez: scanf("%d%d",&szam1,&szam2);
if(szam1<szam2)oszto = szam1;
else oszto = szam2;
A B A||B while(!(szam1%oszto==0
HAMIS HAMIS HAMIS && szam2%oszto==0))
IGAZ HAMIS IGAZ oszto = oszto - 1;
printf("LNKO = %d",oszto);
HAMIS IGAZ IGAZ return 0;
IGAZ IGAZ IGAZ }

A VAGY kapcsolat akkor ad igazat, ha brmelyik, de akr Aki bizonytalan, nyugodtan rja ki a kapcsos zrjelet.
mindkt llts igaz. Csak akkor hamis, ha mindkt llts hamis.
Figyelem, a htkznapi letben mskpp hasznl- Msodik megolds
juk a vagy szt, pl. almt vagy krtt fogok
enni: ez azt jelenti, hogy vagy egyiket, vagy msi- Az elznl optimlisabb megoldst kapunk, ha a szmok
kat, de nem mindkettt. A logikai VAGY kapcso- prmtnyezs felbontsbl hatrozzuk meg a legnagyobb kzs
lat viszont mindkettt is megengedi. A szmts- osztt. A prmek keressnl tovbbra is megmaradunk a brute-
technika azt a vagy kapcsolatot, amikor a kt lltsbl pontosan force mdszernl.
Hatkonyabb prmkeress valsthat meg Eratoszthensz szita md-
egy IGAZ, akkor IGAZ az eredmny, KIZR VAGY kapcso- szervel, ehhez azonban trolni kell a szmokat, de legalbb a megtallt
latnak nevezi. A C nyelvben nincs ilyen logikai mvelet, de prmeket, ehhez jelenleg nem rendelkeznk elegend ismerettel.
tallkozni fogunk vele a bitmveleteknl. A mdszer a kvetkez:
a) Lnko 1-rl indul, az oszt 2-rl.
A VAGY mvelet felrhat S s NEM mveletek segtsg- b) Ha mindkt szm oszthat osztval, lnko-t megszo-
vel, az S pedig felrhat VAGY s NEM mveletek segts- rozzuk osztval, a szmokat elosztjuk osztval, s a
gvel. Ezek a De Morgan azonossgok: b) lpst ismteljk. Ha nem oszthat mindkett,
A||B !( !(A) && !(B) ), megynk tovbb c)-re.
A&&B !( !(A) || !(B) ). c) Nveljk osztt eggyel. Ha nem rtk el a kisebbik
Igazolja igazsgtbla felrsval! szmot, b)-vel folytatjuk, egybknt d)-vel.
d) Kirjuk lnko-t.
A while ciklus felttelt gy is rhattuk volna: Az imnt prmtnyezs felbontsrl volt sz. Hol vannak itt prmek?
while( szam1%oszto!=0 || szam2%oszto!=0 ) A kt szm leosztsa mindig prmekkel trtnik, mert mire pl. 10-ig
Gondolja t, mirt! jutunk, addigra leosztottuk 2-vel s 5-tel ket, gy mr nem oszthatk 10-
zel, vagy egyb sszetett szmmal. gy a gyakorlatban mindig prmekkel
osztunk.
A C-ben a mveleti jelek s a vltozk kz szabad szkzt
Pldul:
tenni, de ez nem ktelez. Az a cl, hogy a programkd minl
jobban rthet legyen az ember szmra, a fordtprogram gy is- szm1 szm2 lnko oszt
gy is megrti. A C nyelv a szkzt, tabultort, jsor jelet Kezdetben 20 30 1 2
(ENTER), s ms, kevsb hasznlt nem lthat karaktereket 2 osztja mindkett- 2010 3015 12 2
egyformn kezeli: brmelyikbl brmennyi rhat oda, ahov nek

15
2 mr csak az egyiknek 10 15 2 23 szm2=temp 20 30 30
osztja
3 csak az egyiknek 10 15 2 34 Ha ismerjk kt szm legnagyobb kzs osztjt, hogy hat-
osztja rozzuk meg a legkisebb kzs tbbszrsket?2
4 nem osztja egyik- 10 15 2 45
nek sem Gondolkodjunk egytt!
5 mindkettnek oszt- 102 153 210 5
ja
5>2, ami a kisebbik 2 3 10 5 G3.1 rjon algoritmust, amely 100 s 200 kztt kirja az sz-
szm kirjuk szes 3-mal oszthat szmot! rja fel az ehhez tartoz C nyelv
kdot! (Nem kell teljes programot rnia!)
A fenti algoritmus pszeudokdja a kvetkez lesz:
G3.2 rja fel a kvetkez mveletek igazsgtbljt! Elhagyha-
LNKO 2 program: t a zrjel?
lnko=1, oszt=2 a) A && B && C
Krj be kt pozitv egsz szmot! b) A || B || C
Ha a msodik kisebb, mint az els c) A && (B || C)
Cserld fel a kt szmot! d) (A && B) || C
Amg az els szm nagyobb vagy egyenl az osztval
Amg mindkt szm oszthat osztval G3.3 rja fel a kvetkez mveletek igazsgtbljt! Melyik a
KIZR VAGY mvelet?
Mindkt szmot oszd el osztval!
a) (A || (!B)) && ((!A) || B)
lnko-t szorozd meg osztval!
b) (A && (!B)) || ((!A) && B)
Nveld osztt eggyel!
c) !((!A) && (!B))
rd ki osztt!
d) !((!A) || (!B))
VGE.

Az algoritmus C nyelven: G3.4 rjon algoritmust pszeudokdban, amely kirja egy pozi-
tv egsz szm prmtnyezs felbontst! rja le az algoritmus
#include <stdio.h> C nyelv megvalstst is!
int main(void){ Pldul 30 prmtnyezs felbontsa:
int szam1, szam2, oszto=2, lnko=1; 30|2
printf("Adj meg 2 poz. egeszt: "); 15|3
scanf("%d%d",&szam1,&szam2); 5|5
if(szam1>szam2){ /* csere jn */ 1|
int temp=szam1;
szam1 = szam2; G3.5 rja le az sszeads algoritmusnak pszeudokdjt! (Nem
szam2 = temp; kell C kd.)
} Pl.:
while( szam1>=oszto ){ 123
while(szam1%oszto==0 +348
&& szam2%oszto==0){ ----
szam1 = szam1 / oszto; 471
szam2 = szam2 / oszto;
lnko = lnko * oszto; G3.6 A kvetkez pszeudokd egy szm faktorilist szmol-
} n ki, de van benne egy hiba. Javtsa ki a hibt! (Pl. 5 faktori-
oszto = oszto + 1; lisa: 1*2*3*4*5=120.)
}
printf("LNKO = %d",lnko); Faktorilis program:
return 0; Szorz legyen 1, Eredmny legyen 1!
} Krj be egy pozitv egsz szmot!
Amg szorz nem nagyobb a szmnl
A C kdban /* s */ kz rhatunk megjegyzseket. Ezekkel a Szorozd meg Eredmnyt a Szorzval!
fordt nem foglalkozik, neknk viszont segt a kd megrts- rd ki az Eredmnyt!
ben. A * opertor a szorzs. VGE.
A fenti kdban jdonsg a csere algoritmusa is:

Csere algoritmusa:
Tedd ideiglenes vltozba az egyik cserlend rtket! G3.7 Adja meg azt az algoritmust pszeudokdban, amely
A msik rtket tedd az egyik helyre! megszmolja, hogy egy pozitv egsz szmnak hny valdi
Az ideiglenes vltozba mentett rtket tedd a msikba! osztja van! (Valdi oszt: 1-en s nmagn kvl az sszes
VGE. oszt.) rja le az algoritmust megvalst C nyelv kdrszle-
tet!
Pldul:
szm1 szm2 temp
Kezdetben 30 20 ?
temp=szm1 30 20 30 2
LKKT=(Szam1*Szam2/LNKO). Szmbrzolsi okokbl clszer a mve-
szm1=szm2 20 20 30 letet LKKT=(Szam1/LNKO)*Szam2 formban rni.

16
G3.8 rjon kdrszletet C nyelven, amely kirja, hogy egy A kvetkez dialgusablakokat kell helyesen belltani. Fi-
pozitv egsz szm prm-e, vagy sem! A megoldsban felhasz- gyelem, knny elrontani!
nlhatja a G3.6 feladat megoldst is!

G3.9 rjon algoritmust a legkisebb kzs tbbszrs meghat-


rozsra
a) brute-force mdon!
b) prmtnyezs felbonts segtsgvel!

Oldja meg egyedl!

Az integrlt fejlesztkrnyezet

A knyelmes s gyors munka rdekben programfejlesztsre


lehetsg szerint olyan szoftvereket hasznlunk, mely egybept-
ve tartalmazza a programkd szerkesztsre alkalmas szveg-
szerkesztt, a programmodulokbl gpi kdot ltrehoz fordtt
(compiler), a gpi kd modulokbl futtathat programot ltrehoz
linkert, s a programhibk feldertst megknnyt debugger
rendszert. Az ilyen rendszereket integrlt fejlesztkrnyezetnek
(Integrated Development Environment IDE) nevezzk.
A knyvben tallhat pldk kiprblshoz brmilyen C
fordt hasznlhat, nem ktelez a bemutatott programokkal
dolgozni.
A Microsoft Visual C++ 2003 fejlesztkrnyezettel ismerke-
dnk meg rviden. A MS Visual C++ fordt Express Edition
nev, cskkentett kpessg vltozata ingyenesen letlthet a
Microsoft honlapjrl, s a vele kszlt programok tetszleges
clra felhasznlhatk. Az Express Edition tartalmazza a szmunk-
ra szksges funkcikat, hasznlata nagyon hasonl a 2003-as
vltozathoz.

Program ltrehozsa

VC++ 2003-at elindtva a kvetkez ablak fogad:

Figyeljnk, hogy Win32 Console Projectet indtsunk, s a


msodik dialgusablakban ne a Finishre kattintsunk, hanem az
Application Settings flre! Itt pipljuk
ki az Empty project opcit! Ha jl
csinltuk, akkor a jobb oldali brhoz
hasonlan, az IDE jobb oldaln tallha-
t Solution Explorer mindegyik mapp-
ja res lesz. Most
Ltre kell hozni a program projektjt. Ehhez kattintsunk a Fi- jobb klikk a Solution Explorer
le men New/Project parancsra! Source Files mappjn
Add New Item
Ne hasznljuk a New ikont! Ez egy txt fjlt hoz ltre, Vlasszuk a C++ File-t, s adjunk
amivel nem tudunk mit kezdeni, mert nem rsze a neki nevet. Ha c kiterjesztst runk
projektnek. Ha vletlenl mgis egy ilyen ablakba (valami.c), akkor a fordt nem C++
kezdtk rni a programit, ne essnk ktsgbe, hanem fjlnak fogja kezelni.
mentsk el a fjlt (c vagy cpp kiterjesztssel! teht pl.
valami.c), csukjuk be, majd a kvetkezkben lertak
szerint hozzuk ltre a projektet. Ha ez megvan, a jobb
oldali Solution Explorerben a Source Files mappra
kattintsunk jobb egrgombbal! Ezutn Add/Add
Existing Item vlasszuk ki az elmentett c vagy cpp
fjlt!

17
Fordtsi hibk

Amennyiben a programunk szintaktikai hibt tartalmazott, te-


ht valamit rosszul rtunk, esetleg lefelejtettnk egy zrjelet
vagy pontosvesszt, az erre vonatkoz hibazenetek a kperny
aljn jelennek meg. A hibazenetre kattintva a kurzor arra a sorra
ugrik, ahol a hibt elkvettk a fordt szerint, de elfordulhat,
hogy a hiba az elz sorban volt, pl. ott hagytuk le a pontosvesz-
szt. Ha tbb hibt tall a fordt, akkor mindig fllrl lefel
haladjunk ezek kijavtsban, mert gyakran elfordul, hogy a
lejjebb lert hibk nem is hibk, hanem csak egy elbb lv hiba
kvetkeztben mondja azt a fordt. Ilyen pldul akkor fordul
el, ha lehagyunk egy zrjelet.
Fordts, futtats, hibakeress Szemantikai hibk

A kvetkez lersban olyan informcik is tallhatk, me-


Miutn begpeltk a C nyelv programot, abbl futtathat lyekhez most mg nem rendelkeznk elg ismerettel, de ha ta-
programot kell kszteni (Microsoft opercis rendszerek alatt pasztaltabbak lesznk, rdemes lesz visszalapozni.
ezek .exe kiterjesztsek). A C nyelvben a programok gyakran tbb Ha sikerlt lefordtani a programot, az mg nem jelenti azt,
forrsfjlbl llnak, az is elfordulhat, hogy ezeket a modulokat ms-ms
ember kszti. A C nyelv gy tmogatja a csoportmunkt. Emiatt a felp- hogy helyesen is mkdik. Vannak olyan esetek, amikor a prog-
ts miatt a futtathat llomny ltrehozsa kt lpsbl ll: ram szintaktikailag helyes, teht le lehet fordtani, de a fordt
1. Fordts: ekkor minden egyes .c (vagy .cpp) fjlbl egy leford- tall olyan gyans rszeket, ahol hiba lehet. Ilyen esetekben
tott object fjl jn ltre (ltalban .obj kiterjesztssel). figyelmeztetst (warning) r ki. A warningokat is nzzk t, s
2. Szerkeszts (linkels): az object fjlokat, s a rendszerfggv- csak akkor hagyjuk figyelmen kvl, ha biztosak vagyunk benne,
nyeket tartalmaz .lib fjlokbl a programban hasznlt fggv- hogy j, amit rtunk.
nyeket egybeszerkeszti, s ezzel ltrehozza a futtathat progra- A kezd programoznak gyakran a szintaktikai hibk kijav-
mot.
tsa is nehz feladat, de k is r fognak jnni, hogy a szemantikai
Lehetsg van arra is, hogy tbb object fjlbl mi magunk hozzunk
ltre fggvnyknyvtrat, vagyis .lib fjlt, ezzel a krdssel azonban hibk (bugok) feldertse sokkal nehezebb, hiszen itt nem ll
ebben a jegyzetben nem foglalkozunk. rendelkezsre a fordt segtsge, nem mondja meg, hogy itt s itt
A fordtssal sszefgg parancsok a Build menben, illetve van a hiba, hanem a rendellenes mkdsbl neknk kell rjn-
az eszkztron is megtallhatk (ha a Build eszkztr be van nnk, hogy baj van. A fejlesztkrnyezet azonban nem hagy
kapcsolva). ilyen esetekben sem eszkzk nlkl.
Compile: lefordtja a .cpp fjlt, obj. fjlt hoz belle ltre. Helyezznk trspontot a programba! A trspont azt jelen-
Build Solution/Build proba2: lefordtja azokat a forrs- ti, hogy a program fut normlisan a trspontig, s ott megll.
fjlokat, melyek mdosultak a legutbbi fordts ta, Ekkor meg tudjuk nzni a vltozk aktulis rtkt, s soronknt
majd a linker ltrehozza az .exe-t. Egy Solutionn bell tovbb tudjuk futtatni a programot (vagy normlisan is tovbb
tbb program/library is lehet, a Build Solution az sszeset le- futtathatjuk). Trspontot legegyszerbben gy helyezhetnk a
fordtja, a Build proba2 csak a kivlasztott proba2 projektet. Mi programba, ha a programkd melletti szrke (VC) svon kattin-
kizrlag egyprogramos Solutiont hasznlunk, teht a fentiek tunk bal egrgombbal. Ekkor egy piros ptty jelenik meg a sor
kzl brmelyiket hasznlhatjuk. mellett.
Rebuild Solution/Rebuild proba2: a forrsfjlokat akkor is jra-
fordtja, ha nem mdosultak a legutbbi fordts ta.
Amennyiben nem rjuk t a belltsokban, a fordts a prog-
ramot tartalmaz mappa alknyvtrban jn ltre. Az alknyvtr
neve a fordts mdjtl fgg. A fels eszkztron vlaszthatunk
Debug s Release kzl, de magunk is ltrehozhatunk fordtsi
profilt.
Debug: minden optimalizci ki van kapcsolva, a kdba
kerlnek olyan rszek, melyek lehetv teszik a hibake-
resst (trspontok beptse, soronknti futtats stb.).
Emiatt ez gy kapott exe nagy s lass lesz.
Release: a vglegesnek sznt vltozat, optimalizcival
(gyorsabb programot kapunk) s a debuggolst segt
kdok nlkl: release llsban nem tudunk debuggolni,
csak ha megvltoztatjuk a konfigurcit, de akkor mr
inkbb a debug mdot hasznljuk. Start s Start Without Debugging: A Debug menben ezzel a
Ha bepillantunk a Debug s Release mappkba fordts utn, kt paranccsal indthatjuk a programot. Az elst vlasztva a
az .obj s az .exe fjlokon kvl szmos egyebet is tallunk itt. program megll az els trspontnl, a msodikat vlasztva nem
Ezekre a fjlokra a ksbb nem lesz szksgnk, teht nyugodtan veszi figyelembe egyik trspontot sem! Viszont ha a Start-ot
trlhetk. Ha jrafordtjuk a programot, ismt ltrejnnek. vlasztjuk, a program ablaka becsukdik a futs vgn, nem
A konfigurcikhoz tartoz belltsokat a Project men ltjuk, mit rt ki a programunk, mg Start Without Debugging
Properties pontjban llthatjuk be, de ugyanez a dialgusablak esetn nem csukdik be az ablak.
elhvhat a Solution Explorerben a program nevn jobb egr- Visual C++ esetn a trspontnl azt is megadhatjuk, hogy ne mindig
lljon meg ott a program, hanem csak valahanyadik odars alkalmval,
gombot nyomva, s a Propertiest vlasztva (Figyelem! Ne a vagy pedig valamifle felttel teljeslse esetn (pl. egy vltoz rtke
Solutionn, hanem a program nevn kattintsunk, klnben ms valamennyi). Ezek bellthatak a trspontra jobb egrgombbal kattint-
Properties ablak jn el!). Itt teljesen tszabhatjuk a belltsokat, va, a Breakpoint Properties menpontot vlasztva.
akr olyannyira, hogy Release zemmdban legyen olyan, mint A hibakeress megkezdse utn (pl. ha a program megll egy
alaprtelmezs szerint Debug mdban, s fordtva trspontnl) alul megjelennek a debug ablakok, ahol megnz-
hetjk s kvethetjk a vltozk rtkt. Ezek kzl az Autos a

18
rendszer ltal nknyesen kivlasztott vltozkat mutatja, a L3.2 rjon C programot, amely kirja a szmokat 1-tl 20-ig
Locals az adott fggvnyben definilt sszes vltozt, a Watch1 egyesvel! (Vagy mdostja az elz programot, vagy j pro-
pedig az ltalunk megadott vltozkat. Ezen kvl, ha az egeret jektet hoz ltre. Ha az elz projekthez ad egy msik C fjlt, akkor
valamelyik vltoz fl visszk, egy buborkban megjelenik a figyeljen arra, hogy egy projektben csak egy darab main fggvny
vltoz rtke. lehet, ezrt amelyiket most nem hasznlja, nevezze t msra!) Prbl-
A jobb als ablak Call Stack fle mg nagyon hasznos szmunkra, ja ki az IDE hibakeres szolgltatsait! Helyezzen be trspon-
mert ennek segtsgvel tudhatjuk meg, mely fggvny hvta meg az tot, s lpsenknti futtatssal figyelje a vltoz rtkt!
aktulis fggvnyt, azt melyik hvta, stb.
Nem csak vltozk, hanem kifejezsek is berhatk a Watch L3.3 A kvetkez program rjnak billentyzetrl hinyzott
ablakba, pldul t[23], *yp vagy a+b is. a pontosvessz. Segtsen neki, s tegye be a hinyz ;-ket!
Ha egy pointerrel adott tmb elemeit szeretnnk ltni, a debugger a Hasznlja a fordtprogramot a hinyz pontosvesszk megta-
+-ra kattintva csak a tmb els elemt rja ki. Ha pl. t a tmb neve, rjuk
be a Watch ablakba, hogy t,100! Ekkor a tmb 100 elemt fogja kirni.
llshoz! (Most hasznlhat copy-paste-t.)

#include <stdio.h>
int main(void){
int szam1, szam2, oszto=2, lnko=1
printf("Adj meg 2 poz. egeszt: ")
scanf("%d%d",&szam1,&szam2)
if(szam1>szam2){
int temp=szam1
szam1 = szam2
szam2 = temp
}
while( szam1>=oszto ){
while(szam1%oszto==0
&& szam2%oszto==0){
szam1 = szam1 / oszto
Trspont helyett a Run to Cursor (Futtats a Kurzorig) pa- szam2 = szam2 / oszto
rancsot is hasznlhatjuk adott helyen trtn megllsra. lnko = lnko * oszto
Ha megllt a program, tbbflekppen is tovbblptethetjk. }
A soronknti lptetsre kt lehetsg is van: oszto = oszto + 1
Step Over: vgrehajt egy sornyi programot. Ha a sorban }
fggvnyhvs trtnik, a fggvnyt is vgrehajtja. printf("LNKO = %d",lnko)
Step Into: elkezd vgrehajtani egy sor programot. Ha a return 0
sorban fggvnyhvs trtnik, beugrik a fggvnybe, s a }
kvetkez Step Over vagy Step Into utastsokkal a fgg-
vnyen bell lpegethetnk. L3.4 A C programokban a szkzk, tabultorok s az jsor
Step Out: vgrehajtja az adott fggvnyt, s visszaugrik a (ENTER) karakterek azonos jelentsek (ezeket whitespace
hvs helyre karaktereknek nevezzk). Kivtel: a # kezdet sorok, valamint
az "" kztti szvegek belseje: ezeket nem szabad ENTER-
A programok szlltsa rel darabolni. A mveleti jelek s rsjelek eltt s mgtt lehet
whitespace karakter, de szorosan egyms mell is rhatk.
A Debug s a Release mappt minden szvfjdalom nlkl t- Az L3.3-as feladatban tallhat programba tegyen be illet-
rlhetjk. Ha kell az exe, akkor azt azrt elbb msoljuk t vala- ve trljn whitespace karaktereket gy, hogy a program
hova. Amikor legkzelebb jrafordtjuk a programunkat, ezek mkdkpes maradjon!
automatikusan ismt ltrejnnek.
A projekt fknyvtrbl a .cpp s .h fjlokra van szks- 1.3.5 A javtott 1.3.3-as program mkdst kvesse
gnk. Ha a tbbit letrljk, akkor legkzelebb ismt ltre kell debuggerrel!
hoznunk a konzol alkalmazs projektet a korbban bemutatottak
szerint, majd a projekthez hozz kell adnunk a .cpp s .h fjlokat. 1.3.6 rjon programot C nyelven, amely bekr a felhasznltl
Ha teht haza akarjuk kldeni napi munknkat, akkor clsze- egy pozitv egsz szmot, s kirja az sszes osztjt!
r elszr letrlni a Debug s Release mappt, majd a marad-
kot becsomagolni (Total Commanderrel Alt+F5), s ezt csatolni a
levlhez. Ha nagyon szks a svszlessgnk, akkor csak a .cpp
s .h fjlokat tmrtsk!

L3.1 Gpelje be (ne copy-paste!), fordtsa le s futtassa az


albbi C programot! Mi trtnik, ha kezetes betket r? A
printf kezdet sort msolja be egyms utn tbbszr, s futtas-
sa jra a programot! Mi trtnik? s ha kitrli a sztringbl a \n
karakterprt?
#include <stdio.h>
int main(void){
printf("Udv, programozo!\n");
return 0;
}

19
4. Hogy mkdik a fordt? 5. A C programok felptse
Ebben a fejezetben elszr megismerkednk a nhny szinta-
Elfeldolgoz xisler mdszerrel. Ezt kveten vgignzzk a legnagyobb
nincs fjl kimenete kzs oszts programunk mdostott vltozatt, s megbeszljk
azokat a rszeket, amelyeket eddig mg nem.
Fordt
.obj ill. .o fjlok (asm)
5.1 A szintaxis lersa
Linker
futtathat llomny (.exe) Egy programozsi nyelv formai szablyainak lersra tbb-
fle megadsi mdszer ltezik. Szveges megadsra a legelterjed-
Az elfeldolgoz (preprocesszor) a kd takartst (megjegy- tebb lernyelv a Backus-Naur Form (BNF), illetve ennek to-
zsek, felesleges szkzk trlse, stb.) s a # kezdet sorok vbbfejlesztett vltozata az Extended BNF(EBNF), grafikus
feldolgozst vgzi, konstansokat s makrkat helyettest. megadsra pedig a szintaxis grf.
A fordt a C nyelven megrt kdbl a szmtgp szmra
emszthet gpi kdot kszt, melyet trgykd, n. object fjlba BNF (BackusNaur Form):
ment. A gpi kd olyan elemi utastsokbl ll sorozat, amely
mr kellen kicsi, egyszer mveleteket tartalmaz ahhoz, hogy Elemei:
azt a szmtgp processzora fel tudja dolgozni. Bellthat, hogy <szimblum> ::= kifejezs
assembly nyelv eredmnyt is produkljon. Az assembly nyelv a o <szimblum>: ::=-tl balra nemterminlis (fel-
gpi kd emberek szmra jobban fogyaszthat vltozata; az bonthat)
assembly kdban a processzor minden utastshoz rendelnek egy Kifejezs:
jl megjegyezhet nevet (pl. mov=adatmozgats, o Egy vagy tbb (terminlis vagy nemterminlis)
add=sszeads). szimblum
Egy projekt tbb .c fjt is tartalmazhat, mindegyikbl ltrejn o Egymsutnisg: tbb, szkzzel elvlasztott
egy-egy object fjl. A linker ezeket egyesti, tovbb hozzszer- szimblum
keszti a szabvnyos fggvnyek (pl. printf) gpi kdjt. gy ltre- o Vlaszts (valamelyik a felsorolsbl ll az adott
jn a futtathat llomny (Windowsban exe). helyen): |
Pl.:
<szm> ::= <szmjegy> | <szmjegy> <szm>
<szmjegy> ::= "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" |
"9"

EBNF (Extended BNF)

C-szerbb lers, tbb nyelvi elem.

szm = szmjegy , {szmjegy};


szmjegy = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9";

Szintaxis diagram

A BNF/EBNF ltvnyosabb verzija, irnytott grffal rjuk


le a nyelvet.
kezdet, vg:
terminlis szimblum: szimblum
nemterminlis szimblum: szimblum
A nem terminlis szimblum tovbb bonthat, a terminlis
nem.
szm: szmjegy

szmjegy: 0

20
5.2 Egy egyszer C program elemei /**************************************/
int legnagyobb(int szam1, int szam2){
/* A legnagyobb kzs osztt szmolja */
A msodik fejezetben beszltnk arrl, hogy a programokat // definci
clszer kisebb, ttekinthet rszekre darabolni, s egyes rszeket /**************************************/
kln megvalstani. Ez mr az egyszer programokban is gy int oszto=2,lnko=1;
van. A legnagyobb kzs oszts programunk esetn adja magt, if(szam1>szam2){ // csere jn
hogy a szmtst rdemes klnvlasztani. Ezt a vltozatot fogjuk int temp=szam1;
ttekinteni. szam1 = szam2;
Elszr lssuk a pszeudokdot! szam2 = temp;
}
LNKO 2/sztszedett program: while( szam1>=oszto ){
Krj be kt pozitv egsz szmot! while(szam1%oszto==0
Szmtsd ki a lnko-t! && szam2%oszto==0){
rd ki osztt! szam1 = szam1 / oszto;
VGE. szam2 = szam2 / oszto;
lnko = lnko * oszto;
A program gy jval egyszerbb lett: a felhasznlval val }
kommunikci lett a f feladata, a szmts egyetlen utastsra oszto = oszto + 1;
redukldott. }
return lnko;
legnagyobb fggvny: }
bemenet: kt pozitv egsz
A program futsnak eredmnye, ha a felhasznl 30-at s
kimenet: egy pozitv egsz
20-at ad meg:
lnko=1, oszt=2
Ha a msodik kisebb, mint az els Adj meg 2 poz. egeszt: 30 20
Cserld fel a kt szmot! *********
Amg az els szm nagyobb vagy egyenl az osztval LNKO = 10
Amg mindkt szm oszthat osztval *********
Mindkt szmot oszd el osztval!
lnko-t szorozd meg osztval! A forrskd magyarzata
Nveld osztt eggyel!
Add vissza osztt! Megjegyzsek A C nyelv kt megjegyzstpust tmogat.
VGE. /* */ megjegyzsek: Ez a tpus tbbsoros is lehet. Kezdett a
/* jelzi, innentl kezdve brmit runk, azt a fordt nem veszi
A fggvny viszont nem kommunikl a felhasznlval. (Ez figyelembe egszen a */ karakterprig. A /* */ pr rnzsre
a legtbb fggvny esetn igaz!) Elvgzi a legnagyobb kzs hasonlt a zrjelezshez, viszont nem az, mert nem gyazhat
oszt kiszmtst, s a kiszmtott rtket visszaadja a hvnak. egybe kt megjegyzs.
Most lssuk a programot magt! Zrjelezsnl megtehetjk, hogy ezt rjuk: y=(a+b*(c+d)*2,
a megjegyzsnl viszont /* X /* Y */ Z */ : itt Z /* mr nem rsze
/*************************************** a megjegyzsnek! Azaz mindig az els */ a megjegyzs vge.
************ //LNKO program ************ Ez akkor kellemetlen, ha szeretnnk a kd egy rszt megjegyzsbe
****************************************/ dugni, mondjuk hibakeressi clbl, s van megjegyzs ebben a rszben.
#include <stdio.h> A dolgot orvosolhatjuk a // megjegyzsek alkalmazsval.
/***************************************/ // megjegyzsek: a sor vgig tartanak. A C++ nyelvbl ut-
lag kerlt t a C-be, ezrt a rgebbi szabvny szerint mkd
int legnagyobb(); // deklarci fordtprogramok nem tmogatjk. Ahogy a pldaprogram
int legnagyobb(int,int); // prototpus msodik sorban ltszik, benne lehet a /**/ megjegyzs belsej-
// csak az egyik kell ben.

/***************************************/ #include <stdio.h> A # kezdet sorok az elfeldolgoz


int main(void){ // definci szmra adnak utastst. A #include azt kri, hogy az
/***************************************/ elfeldolgoz szrja be a programkd szvegbe, ennek a sornak
int szam1,szam2,x; a helyre, a <> kztt megadott nev fjlt. Jelen esetben az
stdio.h fjl beszrst krjk. Ha a fjl nevt <> kztt adjuk
printf("Adj meg 2 poz. egeszt: "); meg, akkor a fordt ezt a fjlt azokban a mappkban keresi,
scanf("%d%d",&szam1,&szam2); amelyek be vannak lltva a szmra.
Visual C++ 2003 esetn, alaprtelmezett belltsokkal trtn telep-
x=legnagyobb(szam1,szam2); tskor pl. a

printf("*********"); c:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\


printf("\nLNKO = %d\n*********\n",x);
mappa ilyen. Itt megtalljuk az stdio.h fjlt is. Az elre belltott include
return 0; mappk sort kibvthetjk, tovbbi mappkat adhatunk hozz. Visual
} C++-ban a Solution Explorerben jobb klikk a projekten Properties
C/C++ General Additional Include Directories listt tudjuk bvteni.

21
Ha nem egy rendszer fejlcfjlt szeretnnk beszerkeszteni,
hanem sajtot, amelyet a programunkkal egytt trolunk, azt Foglalt szavak (kulcsszavak) Olyan fenntartott szavak, ame-
idzjelek kztt kell megadnunk, gy: #include "sajat.h" lyek hasznlatt szintaktikai szablyok hatrozzk meg. Ezek
stdio.h: A STandarD Input and Output rvidtse, teht nem olyan szavak, melyek nem adhatk vltoznvnek, fggvnynv-
stdi. A .h kiterjeszts fejlcllomnyok (header fjlok) nek, stb.
fggvnyek prototpusait s konstansokat tartalmaznak. Az A C kulcsszavai: auto, break, case, char, const, continue,
stdio.h a C nyelv azon szabvnyos fggvnyeinek prototpust default, do, double, else, enum, extern, float, for, goto, if, int,
tartalmazza, melyek az adatok beolvasst s kirst vgzik. A long, register, return, short, signed, sizeof, static, struct, switch,
kpernyre rs s billentyzetrl olvass mellett ide tartozik a typedef, union, unsigned, void, volatile, while
fjlkezels is, errl ksbb lesz sz.
A C nyelv szabvnyos fggvnyknyvtra adott tma kr Fggvnyek Ahogy lttuk, az algoritmus egyes rszeit rde-
csoportostva kerltek klnbz fejlcllomnyokba. Gyakran mes kiemelni kln fggvnybe, hogy ezltal ttekinthetbb
fogjuk hasznlni az stdlib.h-t, ami a Standard Library rvidtse, kdot kapjunk, s az ismtld funkcikat csak egyszer kelljen
s sokfle fggvnyt tartalmaz, pl. memriakezelst, megvalstani. A C nyelvben maga a fprogram is fggvnybe
processzkezelst, stb. A math.h a matematikai fggvnyeket kerl, ez a main fggvny. A main fggvny paramtere void,
tartalmazza, pl. gykvons, szgfggvnyek, stb., a string.h ami azt jelenti, hogy hinyzik. A void szt elhagyhatjuk, rhatunk
szvegkezelssel, a time.h idkezelssel foglalkozik, s gy to- egyszeren int main(){}-t is.
vbb. A C programok elindtsakor mindig a main fggvny indul
el, fggetlenl attl, hogy az hol tallhat a kdban, van-e rva
Tpus A knnyebb feldolgozhatsg rdekben az azonos el ms fggvny, vagy ppen melyik forrsfjlban tallhat.
jelleg adatokat egyformn kezeljk, s tpust rendelnk hozz- A fggvny fggvnyfejbl s fggvnytrzsbl pl fel.
juk. A szmtgp memrijban minden adat bitek sorozata. Egy A fggvnyfej megadja a fggvny tpust (milyen tpus
adat tpusa azt jelenti, hogy az adatot ler bitek/bjtok sorozatt adatot ad vissza), a fggvny nevt, valamint paramtereinek
hogyan kell rtelmezni. Minden tpusra meghatrozott, hogy tpust s nevt.
mely mveletek rtelmezhetk r s mi az rtkkszletk. A fggvnytrzs tartalmazza a fggvnyt felpt utastsso-
A C-ben az adatok tpusait a kvetkez csoportokba osztjuk: rozatot, belertve ms fggvnyek meghvst is.
egyszer tpusok A fggvnydefinci maga a fggvny, azaz a fggvnyfej s
o egsz tpusok (tbbfle eljeles s eljel nlkli) a fggvnytrzs egytt.
o vals tpusok (tbbfle pontossggal) A fggvny prototpusa a majdnem ugyanaz, mint a fgg-
o karakter vnyfej pontosvesszvel lezrva, de mg a paramterek nevt
o felsorols sem kell megadni. A pldban: int legnagyobb(int,int);
szrmaztatott tpusok A fggvnydeklarci a fggvny prototpusa paramterek
o mutat nlkl. Csak a fggvny tpust s nevt tartalmazza, res para-
o tmb mterlistt adunk. A pldban: int legnagyobb();
o struktra A prototpus s deklarci jelentsge, hogy egy C prog-
o uni ram csak olyan fggvnyt tud meghvni, amelynek deklarcija
o bitmez megelzi a kdban a fggvnyhvst. A C szabvny azt ajnlja,
hogy ne a deklarci, hanem az annl tbb informcival br
Azonostk A vltozk, konstansok, fggvnyek, foglalt prototpus elzze meg a hvs helyt. Nem kell deklarci vagy
szavak (kulcsszavak) nevei azonostk. A C nyelvben az azonos- prototpus abban az esetben, ha a hvott fggvny defincija
tk (megvalstsa) megelzi a hvs helyt. Gyakran rjuk meg gy
az angol ABC kis- s nagybetibl, a programot, hogy a main fggvny a vgre kerl, ppen azrt,
szmokbl s hogy ne kelljen kln lerni a prototpust.
alhzs karakterekbl (_) A fggvny defincija msik C fjlban is lehet, mint ahol
llhatnak, szkz vagy ms karakter nem lehet bennk, s ma- hasznljuk (meghvjuk) a fggvnyt. Ilyenkor az egyes C fjlok
gyar magnhangzkat sem hasznlhatunk. Szmmal nem kez- kln is fordthatk, teht csak azt a fjlt kell jra lefordtani,
ddhetnek. A C nyelv rzkeny a betmretre (case sensitive), amelyet megvltoztattuk, gy gyorsabban ltrejn a futtathat
ezrt pl. a nev, Nev, NEV, nEv azonostk klnbzek. Foglalt llomny. (Visual C++-ban a Build parancs csak a megvltozta-
sz neve nem adhat ms azonostnak, tott fjlokat fordtja jbl, mg a Rebuild az sszeset.) A kln
lefordtott fjlokban tallhat fggvnyekbl fggvnyknyvt-
Pl. nem j vltoznevek: rat lehet ltrehozni, melyek jellemzen .lib kiterjeszts fjlokba
int int, while, llat, 4ever; kerlnek. Ilyen fggvnyknyvtrakban tallhatk a szabvnyos
fggvnyek, mint a printf, scanf s a tbbi. Fggvnyknyvtr
Pl. j vltoznevek: ltrehozst a 21. fejezetben fogjuk ltni.
int a, Macska, NEM, x81, _baba, ___, nagy_ember; A kln lefordtott, akr fggvnyknyvtrban, akr object
fjlban lv fggvnyeket a fordtprogram linker rsze szer-
Pl. j, de kerlend vltoznevek: keszti egybe.
int o, l, While; A legtbb fggvnyt gy hasznljuk, ahogy a matematikai
fggvnyeket: kap valamilyen paramtert, esetleg tbbet is, s
visszaad egy eredmnyt, pl. y=sin(x). A fenti programban a leg-
Azrt nem gpi kdban programozunk, mert rteni akarjuk a nagyobb fggvny ehhez hasonlan mkdik: kt egsz szmot
programot. Az azonostk megvlasztsnl is ezt kell szem eltt kap paramterknt, s visszaadja az eredmnyt a return utasts-
tartani, ezrt nem javasoltak a fenti azonostk. Az 0 a nullval, sal. Teht a main fggvnyben x-be az az rtk kerl, ami a leg-
az l az 1-gyel tveszthet ssze knnyen, a While hasonlt egy nagyobb fggvny return utastsa utn rt lnko vltozban van.
foglalt szra. (Termszetesen nem csak a While, hanem a tbbi A main fggvnyben is ltunk egy return-t, ami 0-t ad vissza.
foglalt szra hasonlt azonost is kerlend. Pl. nem tl olvas- Ezt a 0-t az opercis rendszer, vagy a programot elindt egyb
ms program kapja meg. A program ltal visszaadott rtket
hat ez a kd: while(While<whi1e), ahol a harmadik
nagyon ritkn hasznlja fel ms program. Az opercis rendszer-
azonostban egy egyes szmjegy tallhat)
nek visszaadott rtk sajnos ellenttes a C nyelv logikjval, a C-

22
ben ugyanis a 0 jelenti a HAMIS-at, azaz a rosszat, mg az oper- A \ segtsgvel olyan karaktereket rhatunk ki, amilyeneket
cis rendszernek akkor adunk vissza 0-t, ha a program hibtlanul egybknt nem tudnnk.
befejezdtt. A \n jsor jelet jelent, azaz a \n utni szveg j sorba kerl.
Ez a jel azrt iss fontos, mert a printf-fel kirt sor utn, ha ismt
A vltozdefinci szintaxis diagramja: kirunk valamit, az nem kerl automatikusan j sorba, ehhez be
kell rnunk a \n-t. A pldaprogramban kt sor csillag kz rtuk az
eredmnyt.
Trolsi osztly Tpusminst A \t egy tabultor karaktert r ki.
A \" egy idzjelet, a \' egy aposztrfot r ki. A \\ pedig maga
a \ karakter. Vigyzni kell teht a \ hasznlatra, mert ha pl. egy
fjl elrsi tvonalt akarjuk kirni, s ezt rjuk:
Tpus Vltoz azonost Inicializl kifejezs
printf("C:\nagy\nevek.txt");, az eredmny ez lesz:
C:
, agy
evek.txt
A kvnt eredmny elrshez printf("C:\\nagy\\nevek.txt");
A trolsi osztly (pl. static) s a tpusminst (pl. const) szksges.
megadsa nem ktelez, ezekrl a 20. fejezetben lesz majd sz. A % vltozk kiratsban segt. Lttuk mr, hogy a %d
Az eddigi pldkban s a tovbbiakban az egyszerstett vltoz- egsz szmot r ki 10-es szmrendszerben, azaz decimlisan.
defincit hasznljuk: Amikor ms adattpusokat tanulunk, megtanuljuk majd, hogy
azokhoz milyen bet(k) tartozik/nak. A % ennl tbbet is tud.
A %5d azt jelenti, hogy a kirt szm 5 helyet foglal el a kp-
Tpus Vltoz azonost Inicializl kifejezs ernyn. Ha a szm ennl rvidebb, akkor szkzket r el. Ez a
funkci akkor hasznos, ha egyms al akarunk szmokat rni
tblzatszeren. Ha a szm nem fr el 5 helyen, akkor annyi
, helyet foglal, amennyin elfr. Ha %05d-t runk, akkor a szm el
0-k kerlnek. A %+5d azt jelenti, hogy a szm el a + eljel is
int oszto=2,lnko=1; kirdik, nem csak a -. A %-5d azt jelenti, hogy a szkzk a
szm utn lesznek, nem eltte, azaz balra igaztdik. A %+-5 is
Tpus: int helyes. A %-05 esetn a 0-t nem veszi figyelembe a printf, mert a
Vltoz azonost: a, b, c szm utn rt nullk elrontank a szmot (el rva rendben van:
Inicializl kifejezs: =0 00234, de utna nem j: 23400). A %% maga a szzalkjel.

A listban a vltozk sorrendje tetszleges. Egy a lnyeg: a Ez a felsorols csak akkor r valamit, ha kiprbljuk a gyakor-
vltoz legyen definilva, mieltt elszr hasznljuk. latban is. rjon teht programot ezek kiprblsra!
A C99 eltti szabvnyokban vltozt definilni csak a blokk
elejn lehet, azaz a { utn llhatnak vltozdefincik, melyek Egy C program legmagasabb szint megadsa szintaxis
ms utastsokkal nem szakthatk meg. pl.: diagrammal:
{
preprocesszor utasts jsor
int a;
a=0; /* Vltozdefincik kztt nem vltoz deklarci
lehet ms utasts! */
vltoz definci
int b=0,c;
... fggvnydeklarci
Ez a kd a C99 eltti szabvnyok szerint hibs, az a=0; csak a fggvnydefinci
defincikat kvetheti. A C++ nyelv azonban ezt megengedi, s
ksbb a C99 szabvny is tvette. Ha kdunknak fordulni kell tpusdefinci
rgi szabvnyt tmogat fordtval is, ezt a megoldst kerljk!

Kifejezs minden, aminek rtke van (konstans, vltoz, Az egyes rszekrl ksbb lesz sz.
sszetett kifejezs, fggvnyhvs).
Opertor: mveleti utasts, mveleti jel. A C-ben sok ilyen
van, pl. +, -, *, /, %, &&, ||, <<, ++, =, ==, <, stb.
C-ben igen gazdag opertorkszlet tallhat, gy a legtbb do-
log megoldhat kifejezs utastssal.
Pldul:
c = a + b; : ez a kifejezs utasts sszeadja a-t s
b-t, az sszeget pedig c-be helyezi.
a - b; : ez is egy kifejezs, br nincs semmi rtelme.
Kiszmtja a s b klnbsgt, de az eredmnnyel nem
csinl semmit. A C-ben egy kifejezs rtke "eldobha-
t".

printf Ez a fggvny nagyon sokat tud, most megismerkednk


nhny funkcijval. Ksbb, a 12. fejezetben majd alaposan
krljrjuk a kir s beolvas fggvnyeket.
Kt specilis vezrlkaraktert hasznlhatunk a formtum-
sztringben, ezek a \ s a %.

23
6. Tpusok, vltozk, konstansok, a = 1
mveletek b = 6
c = 5

Az elz fejezetekben nhny egyszer, egsz szmokat A gyokok:


hasznl algoritmussal tallkoztunk. Most megismerkednk a C
nyelv nhny jabb elemvel: x1 = -1
a vals szmok trolsra szolgl double tpussal, x2 = -5
a for ciklussal
s nhny j opertorral, azaz mveleti jellel. Magyarzat A programban ki kell szmtanunk a diszkrimi-
nns ngyzetgykt. Ehhez az sqrt fggvnyt hasznljuk, mely-
6.1 Msodfok egyenlet gykei nek prototpusa a math.h fejlcllomnyban tallhat, ezrt ezt is
beszerkesztjk. Mindegy, hogy a beszerkesztsnl az stdio.h,
vagy a math.h van-e elbb.
Matematikbl tudjuk, hogy az 2 + + = 0 egyenlet A program sszes vltozja double tpus lesz. A vals sz-
2 4
gykeit az 1 , 2 = kplet adja. Az egyenletnek mokat a szmtgp lebegpontos formtumban trolja, ezrt a
2
akkor van vals gyke, ha a ngyzetgykjel alatt ll diszkrimi- double-t lebegpontos tpusnak is nevezik. A klnbz adatt-
nns nemnegatv. rjunk programot, amely bekri a hrom para- pusok szmtgpes megvalstsval a 10. fejezetben foglalko-
mter (a,b,c) rtkt, s kirja a gykket, ha lteznek! zunk, most csak rviden: a lebeg pont a tizedes pontra utal, amit
Az algoritmus pszeudokdja a kvetkez lesz: az angolszsz orszgokban (s a szmtstechnikban) a tizedes-
vessz helyett hasznlnak. Tzes szmrendszerben pldul a 842-t
Msodfok egyenlet program 8.42*102-knt, a 0.0456-ot 4.56*10-2-knt adhatjuk meg lebeg-
pontosan: a tizedespont az els rtkes szmjegy utn kerlt, s
Krd be a hrom paramtert!
az egszet tz megfelel hatvnyval szorozzuk. A szmtgp
Szmold ki a diszkriminnst!
kettes szmrendszert hasznl, ott termszetesen kettes szmrend-
Ha a diszkriminns nemnegatv szerben trtnik a szorzs.
Szmold ki a kt gykt a megoldkplettel! A double tpus beolvassa s kirsa az int-hez hasonlan a
rd ki a kt gykt! scanf s printf fggvnyekkel trtnik, % utn megadva a megfe-
Egybknt lel tpusazonostt. A double tpus az egyetlen olyan tpus a C-
rj ki hibazenetet! ben, ahol a scanf s a printf eltr tpusazonostt hasznl: a
VGE. scanf %lg-t, a printf %g-t. Ha valaki bizonyta-
lan, rjon mindkt helyre %lg-t, mert ezt a ford-
Az algoritmus kdja C nyelven: tk el szoktk fogadni, br nem szabvnyos,
fordtva viszont, azaz a scanf-be %g-t rva hib-
#include <stdio.h> san fog mkdni a program!
#include <math.h> A diszkriminns szmtsnl figyeljk meg, hogy a ngyzet-
re emelst szorzssal valstjuk meg. A ngyzet s a kb szm-
int main(void){ tst mindig szorzssal vgezzk! Egyb (akr nem egsz)
double a,b,c,diszkr,x1,x2; hatvnyok szmtsra a math.h-ban tallhat pow fggvny
megfelel.
printf("Masodfoku egyenlet gyokeinek" A matematikai kpletekben a szorzst gyakran nem szoktuk
" szamitasa.\n\na = "); jellni, a programban azonban ktelez!
scanf("%lg",&a); Figyeljk meg, hogy a programban b*b-4*a*c szerepel, vagy-
printf("b = "); is nem kellett zrjeleznnk gy: b*b-(4*a*c), azaz a C, a mate-
scanf("%lg",&b); matikhoz hasonlan, csak az azonos erssg, azaz azonos
printf("c = "); precedencij mveleteket rtkeli ki balrl jobbra. A szorzs
scanf("%lg",&c); precedencija nagyobb, mint a kivons, ezrt elbb rtkel-
dik ki a szorzs eredmnye, aztn a kivons. Ha ez nem felel
diszkr = b*b - 4*a*c; meg, zrjelezznk!
A hasznlt mveletek sorrendje precedencia szerint (a leger-
if( diszkr >= 0.0 ){ sebb fent):
x1 = (-b + sqrt(diszkr)) / (2*a);
+ s mint eljel
x2 = (-b - sqrt(diszkr)) / (2*a);
*, / s % szorzs s oszts jelleg mvelet
printf("\nA gyokok:\n\n"
"x1 = %g\nx2 = %g\n",x1,x2); +, - mint sszeads jelleg mvelet
} <,>, <=, >= relcis mveletek
else{ ==, != relcis mveletek
printf("Az egyenletnek nincsenek" && logikai S
" valos gyokei.\n"); || logikai VAGY
} = rtkads
return 0; A diszkr = b*b - 4*a*c mvelet esetn teht a sorrend:
} 1. b*b
2. 4*a
A programot gcc-vel fordtva linkelni kell a matematikai knyvtrat lm kap- 3. (4*a)*c
csolval.
4. (b*b)-((4*a)*c)
5. diszkr=((b*b)-((4*a)*c))
A program futsnak eredmnye:
A pldaprogramban csak oda kerlt zrjel, ahov kell. Ha
programot r, s bizonytalan, nyugodtan hasznljon zrjelet!
Masodfoku egyenlet gyokeinek szamitasa.

24
Szvegek kt sorban. A knyv kthasbos szedse miatt
nem frtek el a hossz szvegek egy sorban. A C nyelv lehetv N darab szm tlagt gy szmoljuk ki:
teszi, hogy az idzjelbe rt szvegeket, azaz a sztring konstan- =
1+2++
.
sokat tbb rszre, gy akr tbb sorba osszuk gy, hogy a kt
Azaz sszeadjuk a szmokat s elosztjuk az sszeget a darab-
(vagy tbb) rszszveg mindegyikt "-ek kz zrjuk, s a rszek
szmmal.
kz csak whitespace karaktereket (szkz, jsor, stb.) runk.
A megolds algoritmusa:
Ezeket a szvegeket az elfeldolgoz automatikusan sszefzi.
tlag program
Konstansok Eddigi programjainkban is szmos esetben tall-
koztunk konstansokkal. A szvegkonstansok (sztring konstan- Jegyezd meg, hogy a darabszm s az sszeg nulla!
sok) megadsa idzjelek kztt trtnik. Pl. "Hello World!\n". Krj a felhasznltl egy szmot!
A karakterek trolsra alkalmas char adattpusrl mg nem beszl- Amg a szm nem nulla
tnk. A sztring karakterek sorozata, melynek vgt egy specilis karakter Nveld sszeget a szmmal!
jelzi. A karakterek sorban egyms mellett helyezkednek el a memriban, Nveld darabszmot eggyel!
azaz tmbben. Errl ksbb szlunk rszletesebben. A karakter kons- Krj a felhasznltl egy szmot!
tansokat aposztrfok kztt adjuk meg: 'A', '@', stb. A specilis karakte-
rek megadsa a \ segtsgvel trtnik, gy pl. '\n', '\'', '\\', stb. Ezek egy Ha a darabszm nagyobb nullnl
karakternek szmtanak. Csak ezeknl fordulhat el, hogy az aposztrfok rd ki az sszeg s a darabszm hnyadost!
kz egynl tbb karaktert runk, de itt is csak azrt, mert ezek egynek Egybknt
szmtanak. FIGYELEM! A sztring konstanst s a karakter konstanst rd ki, hogy nincs tlag!
ne keverjk ssze, mert br rnzsre mindssze annyi a klnbsg, VGE.
hogy idzjelek vagy aposztrfok kztt vannak, egszen mshogy kezeli
ezeket a C fordt! Teht pl. az "A" s az 'A' nem helyettesthet egyms-
sal! Mint ltjuk, nincs szksg arra, hogy az sszes szmot kln-
Az int tpus egsz konstansok rsmdjban nincs semmi kln megjegyezzk, elg az sszegket.
meglep: szmjegyek sorozata, melyet eljel egszthet ki. Pl- A program C nyelven:
dul: -5, 0, 1686, stb.
Az egsz szmokat megadhatjuk nyolcas s tizenhatos szmrendszer- #include <stdio.h>
ben. Ha a konstanst nyolcas (oktlis) szmrendszerben adjuk meg, 0-
val kell kezdeni, pl. 012 (= tz), 050 (= negyven), stb. Tizenhatos (hexa- int main(void){
decimlis) szmrendszerben megadott konstans kezdete 0x vagy 0X. double szam, osszeg=0.0;
Pldul: 0x21 (= harminchrom), 0X10 (= tizenhat). 0xa2 (= szzhatvan- int N=0;
kett).
A double tpus lebegpontos konstansok a szmjegyeken printf("Adj egy szamot (vege:0): ");
kvl vagy pontot, vagy e vagy E bett tartalmaznak. Pldul: 1.2, scanf("%lg",&szam);
-4.0, 3e2, -4.1E-002, 91.4e+1, stb. Az e s E jelentse azonos, tz while(szam != 0.0){
hatvnyval val szorzst jelent, azaz pl. 3e2 jelentse 300.0, - osszeg += szam;
4.1E-002 jelentse -0.041, 91.4e+1 jelentse 914.0. Az e ill. E N++;
utn csak egsz szm llhat. Double konstans pl. a 431. (ponttal a printf("Adj egy szamot (vege:0): ");
vgn) s a .23 (ami 0.23-at jelent) is. scanf("%lg",&szam);
}
Vigyzzunk a hasznlat sorn! Mennyi double x=3/4? if(N>0)
printf("Atlag: %g\n",osszeg/N);
x-be 0.0 kerl else printf("Nincs atlag.");
return 0;
Mert 3 is s 4 is egsz, s elszr a hnyadosukat szmolja ki a }
szmtgp. Az egsz oszts eredmnye egsz szm, amit a
szmtgp nem kerekt, hanem levgja a trt rszt, azaz 0.75 Miutn megnzte a megoldst, prblja meg nllan megrni
helyett 0 van az = jobb oldaln. a programot! Ugye, hogy nem is olyan egyszer?

A szmts akkor fog 0.75-os eredmnyt adni, ha a kt rtk j opertorokA while ciklusban kt j opertorral tallko-
kzl legalbb egy lebegpontos, azaz pl. x=3.0/4.0, vagy zunk: a +=-vel s a ++-szal. Ezek a rvidebb kd rst segtik.
x=3.0/4, stb. Az osszeg += szam; jelentse: osszeg = osszeg + szam;,
vagyis az osszeg vltozban tallhat rtket nvelem meg szam-
A jelensg nem csak a konstansokat, hanem a vltozkat is mal. Minden alapmveletre ltezik ilyen opertor: +=, -=, *=, /=,
rinti. Pldul int a=3,b=4; double d=a/b; Itt ugyangy 0.0-t %=.
kapunk. A megolds ekkor az, hogy explicit (kzvetlen) t- Az N++; jelentse N = N + 1;, vagyis N rtkt nveli egy-
puskonverzit alkalmazunk, vagyis legalbb az egyik egsz gyel. A ++ opertor csak egszeken definilt, valsakon nem
vltoz el odarjuk zrjelben, hogy double. Pl.: (fordtprogramtl fgg, hogy valson mkdik-e). Ez a sor
x=(double)a/b;, vagy x=a/(double)b; A tpuskonverzi termszetesen gy is rhat: N += 1;. Ha N rtkt eggyel csk-
precedencija magasabb, mint az oszts, ezrt nem szksges kenteni akarjuk, N--;-t rhatunk. A ++-t inkremens, a ---t
gy zrjelezni: ((double)a)/b. A zrjelbe rt tpusnevet egytt dekremens opertornak is nevezzk.
tpuskonverzis opertornak nevezzk.
Nzze t a korbbi pldkat, s cserlje ki az j opertorokra a
rgieket, ahol lehet!
6.2 tlag
rjunk programot, amely elre ismeretlen mennyisg vals
szmokat kr a felhasznltl, s kirja a szmok tlagt! A
szmsorozat vgt a 0.0 rtk jelzi.

25
6.3 Fordtva while(felttel){
utastsok_a_ciklus_magjban;
lptets;
rjuk ki az sszes olyan hromjegy szmot, amely ellrl }
htra ugyanaz, mint htulrl elre! Pldul: 121, 707, 444, stb.
Ezeknek a szmoknak a formtuma ABA. Mivel hrom jegy A kt megolds teljesen azonos egymssal, brmikor helyet-
szmokrl van sz, A rtke nem lehet nulla, 1-tl 9-ig mehet. B testhet egyik a msikkal.
rtke 0-9-ig mehet.
Ktfle algoritmus tlett vetjk fel: Pldul:
1. Brute-force mdszer: 100-tl 999-ig megynk egy
ciklusban, s minden szmrl eldntjk, hogy meg- for(i=0; i<10; i++)printf("%d",i);
felel-e az elvrsoknak. Az egyes szmjegyeket a
maradkkpzs s az oszts opertorokkal nyerhet- Ez a ciklus 0-tl 9-ig rja ki a szmokat. (Ha i elri 10-et,
jk ki: ha i a ciklusvltoznk, akkor i/100 adja az i<10 hamiss vlik, mr nem fut le jbl a ciklus magja.)
els szmjegyet (egsz oszts eredmnye egsz, A Fordtva program C nyelv megvalstsa for ciklusokkal:
nincs kerekts, csonkols trtnik, gy pl.
199/100==1), i%10 pedig az utols szmjegyet ad- #include <stdio.h>
ja. Az algoritmus pszeudokdjnak s C nyelv
megvalstsnak elksztst az olvasra bzzuk. int main(void){
2. Kt egymsba gyazott ciklust hasznlunk, ahol B int A,B;
rtkt adja a bels, A rtkt a kls. for(A=1; A<10; A++){
for(B=0; B<10; B++){
A msodik algoritmus pszeudokdja a kvetkez lehet: printf("%d ",A*100+B*10+A);
}
Fordtva program }
Legyen A=1! return 0;
Amg A kisebb 10-nl }
Legyen B=0!
Amg B kisebb 10-nl A for ciklusra is igaz, hogy ha csak egy utasts van a ciklus
rd ki ABA-t! magjban, akkor a kapcsos zrjelek elhagyhatk. A fenti prog-
Nveld B-t eggyel! ramban ez az llts mindkt ciklusra igaz. (A klsre is, mert
Nveld A-t eggyel! abban csak egy msik for ciklus van, melynek rsze a printf.) A
VGE. tovbb rvidtett program ez lesz:

#include <stdio.h>
A program C nyelven:
int main(void){
#include <stdio.h>
int A,B;
for(A=1; A<10; A++)
int main(void){
for(B=0; B<10; B++)
int A,B;
printf("%d ",A*100+B*10+A);
A=1;
return 0;
while(A<10){
}
B=0;
while(B<10){
printf("%d ",A*100+B*10+A); Aki bizonytalan abban, hogy mi egy s mi nem egy utasts,
B++; inkbb zrjelezzen, abbl sosem lehet baj!
}
A++; 6.4 Vektor elforgatsa
}
return 0; rjunk programot, amely bekri a felhasznltl egy ktdi-
} menzis vals rtk vektor koordintit, valamint egy szget
fokban, s kirja a kpernyre annak a vektornak a koordintit,
A printf("%d ",A*100+B*10+A); helyett rhattuk volna, amely az eredeti vektor adott szggel trtn elforgatsnak
hogy printf("%d%d%d ",A,B,A);. eredmnye!
Nagyon gyakori, hogy egy algoritmusban egy ciklusvltozt Az elforgatott koordintkat a kvetkez kpletek adjk:
lptetnk valamettl valameddig. Mr korbban is tallkoztunk
ilyen programokkal. Sok programozsi nyelv, gy a C is rendel- xuj = xrgicos yrgisin
kezik olyan ciklusutastssal, amelyik kifejezetten ilyen ciklusok yuj = xrgisin + yrgicos
ltrehozsra szolgl: ez a for ciklus.
A C for ciklusa a kvetkez felpts: A megvalstsnl figyelnnk kell arra, hogy a math.h-ban
definilt szgfggvnyek nem fokban, hanem radinban vrjk a
for( kezdeti_bellts ; felttel ; lptets ){ szgeket, ezrt a felhasznltl kapott szget radinba kell kon-
utastsok_a_ciklus_magjban; vertlnunk a konverzi kplete:
}
rad = fok / 180
Ez a kvetkezkpp nzne ki while ciklussal:
A program C-ben gy nz ki:
kezdeti_bellts;

26
#include <stdio.h> gyis biztos nagyobb lesz a maximum mdszerrel, mert mi van akkor,
#define _USE_MATH_DEFINES // a VC++-nak kell ha a felhasznl csak ennl kisebb rtket ad meg? Ez slyos elvi hiba,
#include <math.h>
mindig igazi rtkkel inicializljunk!

int main(void){ Oldja meg egyedl!


double xregi,yregi,xuj,yuj,alfa;

printf("x="); scanf("%lg",&xregi); L6.1 rjon C programot, amely kirja a tblra a 12x12-es


printf("y="); scanf("%lg",&yregi); szorztblt! A tbla gy kezddik:
printf("alfa="); scanf("%lg",&alfa);
1 2 3 4
alfa = alfa * M_PI / 180.0; 1 1 2 3 4
2 2 4 6 8
xuj = xregi * cos(alfa) - yregi * sin(alfa); 3 3 6 9 12
yuj = xregi * sin(alfa) + yregi * cos(alfa);
4 4 8 12 16
printf("\nxuj=%g\nyuj=%g\n",xuj,yuj);
return 0;
} L6.2 rjon C programot, amely bekr a felhasznltl egy
egsz szmot, s kirja, hogy a szm tkletes-e! Tkletes
A program msodik sorban ltjuk a szm az, amely megegyezik osztinak sszegvel, az osztk
#define _USE_MATH_DEFINES kifejezst, vagyis definiljuk a kz rtve 1-et, de a szmot magt nem. Pldul
_USE_MATH_DEFINES szimblumot (lsd a 31. fejezetben). Ez 28=1+2+4+7+14.
azrt szksges, hogy elrjk a math.h-ban definilt M_PI kons-
tanst, vagyis a rtkt. A szimblum definilsa meg kell elzze Ha nllan nem megy, segtsgl az algoritmus:
a #include <math.h>-t. Ha gcc-vel fordtjuk, ne feledjk a mate-
matikai knyvtrat hozzlinkelni lm kapcsolval! Tkletes szmok program
Az sszeg legyen nulla, a szmll meg egy!
Gondolkozzunk egytt! Krj be egy egsz szmot!
Amg a szmll nem nagyobb, mint a szm fele
G6.1 rjon C programot, amely bekr a felhasznltl egy Ha a szmll a szm osztja
pozitv egsz szmot, s kirja a szm szmjegyeinek sszegt! Add szmllt az sszeghez!
Pl. 1981 1+9+8+1 = 19. Nveld szmllt eggyel!
Ha a szm egyezik az sszeggel
Ha nllan nem megy, segtsgl az algoritmus: rd ki, hogy tkletes!
Egybknt
Jegysszegz program rd ki, hogy nem tkletes!
Az sszeg legyen nulla! VGE.
Krj be egy szmot!
Amg a szm nem nulla
A szm tzzel val osztsi maradkt add az L6.3 rjon C programot, amely bekr a felhasznltl kt vals
sszeghez! szmot, s kirja, hogy bartsgosak-e! Kt szm bartsgos,
Oszd el a szmot tzzel! ha az egyik szm osztinak sszege a msikat adja, a msik
rd ki az sszeget! osztinak sszege pedig az egyiket, az osztk kz rtve 1-et,
VGE. de a szmot magt nem. Pldul: 220 s 284 bartsgos, mert
220 oszti: 1+2+4+5+10+11+20+22+44+55+110=284
G6.2 rjon C programot, amely bekr a felhasznltl hrom 284 oszti: 1+2+4+71+142=220.
vals szmot, s eldnti, hogy a hrom szm lehet-e egy h-
romszg oldala! L6.4 rjon C programot, amely vals szmokbl ll koordin-
taprokat kr be. Addig olvassa a koordintaprokat, amg a
G6.3 rjon egy teljes C programot, amely megkeresi s a szab- felhasznl mindkt koordintaknt nullt nem ad. rja ki,
vnyos kimenetre rja azt a legnagyobb hromjegy szmot, hogy a koordintk hny szzalka esett az egysg sugar
amelynek szmjegysszege megegyezik prmtnyezinek krn bellre!
sszegvel. (pl. 378=23337, ezek sszege 18, ami egyenl
a jegyek sszegvel is.) L6.5 rjon C programot, amely bekr egy pozitv egsz szmot
a felhasznltl, s a szmot fordtva rja ki a kpernyre! Pl.:
G6.4 rjon olyan algoritmust, amely egy vals szm els kt Be 12345, ki: 54321. Be 12000, Ki: 00021
tizedesjegyt egy egsz tpus vltozba teszi. gyeljen arra,
hogy a vals szm negatv is lehet, a kinyert kt tizedesjegy
viszont nemnegatv alak legyen! Pldul be: 123.456, ki: 45.
Be: -0.0987, ki: 9. Be: 3.0, ki: 0.

G6.5 rjon C programot, amely folyamatosan kr a felhaszn-


ltl vals szmokat egsz addig, amg az 0.0-t nem ad! rja ki
a felhasznl ltal adott rtkek kzl a legnagyobbat! A leg-
nagyobb meghatrozsakor ne vegye figyelembe az utoljra
megadott 0.0-t!

Tipp: az els szmot kln kell beolvasni, mert ez lesz a maximumot


trol vltoz kezdeti rtke. A maximumot trol vltoznak tilos
hasra tssel kezdrtket adni legyen mondjuk -1.0e100, mert annl

27
7. A C utastsai Trolsi egysgek defincija/deklarcija A C nyelv a
program rszeit egysgesen, trolsi egysgekben kezeli. Trte-
rlet-foglal trolsi egysgek az adatok (konstansok, vltozk),
Az elz fejezetekben megismerkedtnk a C utastsainak kdgenerl trolsi egysgek a fggvnyek. A trolsi egysge-
tbbsgvel. Most ttekintjk az sszeset, mivel nincs bellk tl ket a programban vagy kls modulban definilni kell, hasznla-
sok. tukat a kdban meg kell elzze a deklarcijuk, ami lehet maga a
A kvetkez tblzat tartalmazza a C nyelv sszes utastst: definci is. A trolsi egysgeknek tpusa van: adatok esetn:
az adatokat reprezentl bitek/bjtok sorozatt hogyan kell rtel-
Utasts Formtum mezni (egsz, lebegpontos, karakter, stb.), fggvnyek esetn:
res utasts ; vagy {} van-e visszatrsi rtkk, s ha van, azt mint adatot, hogyan kell
sszetett utasts { rtelmezni. (void: ha nincs visszatrsi rtk)
(utastsblokk) utasts1; A vltozdefincirl az 5.2. fejezetben volt sz.
utasts2; Pldul:
int a;
utastsN; double d=2.1;
} char alma=a, c=alma, x;
Trolsi egysgek tpus vltoz1[=kezdrtk] [, vlto-
(vltozk, konstansok, z2]; Kifejezs utasts Az 5.2. fejezetben beszltnk a kifejez-
fggvnyek) definci- sekrl. Emlkeztetl: Kifejezs minden, aminek rtke van
ja / deklarcija (konstans, vltoz, sszetett kifejezs, fggvnyhvs). A kifeje-
Kifejezs utasts Opertorok, fggvnyhvsok, kons- zs utasts egy kifejezs pontosvesszvel lezrva.
tansok s vltozk sorozata, ;-vel plda:
lezrva. a=1; <= ez is kifejezs utasts, lsd rtkads opertor
Feltteles elgazs if(felttel)utasts; 1; <= szintaktikusan helyes, de rtelme nincs
if(felttel)utasts1; a+2; <= szintaktikusan helyes, de rtelme nincs
else utasts2;
b=a+2;
switch(egsz tpus rtk){
x=(-b+sqrt(b*b-4.0*a*c))/(2.0*a); <= ssze-
case rtk1: utastsok; tett kifejezs
case rtk2: utastsok; A C-ben egy kifejezs rtke "eldobhat", ahogy a fenti pl-
dkban is lttuk. Ez azt jelenti, hogy egy fggvny ltal vissza-
case rtkN: utastsok; adott rtket sem kell felhasznlnunk. Pldul nyugodtan
default: utastsok;
lergatjuk egy programban, hogy
sqrt(81.0);
}
Sok rtelme nincs, hiszen a ngyzetgykt nem hasznltuk
Ciklus while(felttel)utasts;
fel. Van olyan fggvny azonban, ahol van rtelme. Pldul ilyen
for(inicializls; felttel; lpte- a printf, amely az ltala kirt karakterek szmt adja vissza, gy a
ts)utasts; kvetkez utasts rtelmes:
do utasts while(felttel); int n=printf("Ez vajon hany karakter?");
Ugr utastsok* return;
return kifejezs; Feltteles elgazs Jl ismerjk mr az if illetve if-else utas-
break;* tsokat, jdonsg viszont a switch. Tekintsk t folyamatbra
continue;* segtsgvel az utastsok mkdst!
goto cmke;*
*A ciklusban hasznlt break, a continue s a goto utastsok elkerlsvel
ltalban ttekinthetbb, karbantarthatbb kd szokott keletkezni, ppen
ezrt lehetsg szerint nem hasznljk ket.

res utasts Akkor hasznljuk, ha valahov szksges utas-


tst rni, de nem akarunk.
A ;;;; vagy a {}{}{}{} ngy res utasts.
Pldul a kvetkez kdrszlet meghatrozza azt a legkisebb
N-et, amire igaz, hogy szam<=N, ahol N=3n.
for(N=1; szam>N; N*=3);
A ciklus magja res utasts.

sszetett utasts Akkor hasznljuk, ha egynl tbb utastst


akarunk olyan helyen elhelyezni, ahol csak egy utasts llhat
(lsd: if, else, for, while magja). Tovbb, ha egyb okbl ssze
akarunk zrni utastsokat. A fggvnyek trzst ktelez Forma:
blokkba tenni.
Minden sszetett utasts elejn lehet vltozt definilni, a if(kifejezs)utasts;
vltoz a blokk vgig l. Pldul:
{ int x=5,i; if(kifejezs)utasts1;
for(i=0; i<10; i++)x+=i; else utasts2;
printf("%d\n",x);
} Ha a zrjelek kztt logikai IGAZ rtk kifejezs ll, akkor
x=10; // Fordtsi hiba: x nem ltezik a blokkon kvl vgrehajtdik az if utastsa. Ha hamis, az else utastsa hajtdik

28
vgre. Ha nincs else, akkor egybl az if-et kvet utastssal int n;
folytatdik a program. char ch;
Pldk:
if(a>b)a=b; switch(n){
if(a>b){a=b; b=0;} case 1: printf("egy\n"); break;
if(a>b)a=b; case 100: n++;
else b=a; case 101: printf("szazegy\n"); break;
Az if s az else kztt nem lehet ms utasts, csak az if default: printf("valami\n");
magjban lv utasts, vagy sszetett utasts. }
A switch utasts egy egsz tpus rtk alapjn dnti el, me-
lyik gon folytassa a program vgrehajtst. Ha n rtke 1, kirjuk, hogy egy. Ha n rtke 100, akkor meg-
nveljk eggyel, s kirjuk, hogy szazegy. Ha n rtke 101,
switch: akkor kirjuk, hogy szazegy. Ha egyik sem igaz, kirjuk, hogy
valami.
egsz
switch(n){
case case default case default:
printf("Alaprtelmezett.\n"); break;
case 2:
utasts utasts utasts utasts printf("Kirta, hogy 2, ");
n += 1;
case 3:
utasts utasts utasts utasts printf("s azt is, hogy 3.\n");
}

utasts utasts utasts utasts Most a defaultot az elejre rtuk.

scanf("%c",&ch);
switch(ch){
case 'i':
Forma: case 'I':
printf("Igen");
switch(egsz_rtk){ break;
case konstans1: utasts; utasts;utasts; case 'n':
case konstans2: utasts; utasts;utasts; case 'N':
printf("Nem");
case konstansN: utasts; utasts;utasts; break;
default: utasts; utasts;utasts; default:
case konstansN+1: utasts; utasts;utasts; printf("Nemigen");
}
case konstansM: utasts; utasts;utasts;
} A case utni rszt resen is hagyhatjuk.
A karaktereket (betk, szmjegyek, rsjelek) char tpus vl-
A switch sszehasonltja a paramterknt kapott kifejezs r- tozkban troljuk. A char tpus is egsz tpus, mert minden
tkt a case-ek utn rt konstanssal, s ha megegyezik valame- karakter egy egsz szmnak felel meg. Errl rszletesebben a 12.
lyikkel, akkor az utna megadott utastsokkal folytatdik a fejezetben lesz sz. A sztring (szveg) karakterekbl pl fel, de
program vgrehajtsa. Ha egyik konstanssal sem egyezik meg, nem egsz tpus, mert nem egy egsz rtk alkotja, hanem sok,
akkor a default utn rt utastsokkal folytatdik a mkds ezrt sztringgel nem lehet a switch-et hasznlni! A char rtkek
(olyan, mint az else az if-nl). scanf-fel trtn beolvasshoz s printf-fel trtn kirsakor a
A switch az a kivtel az utastsok kztt, amelynl nem %c formtumazonostt hasznljuk. Nem egyedi karakterek,
csak egy utasts, vagy blokk llhat a case vagy a default utn, hanem szvegek beolvassra s kirsra mst fogunk hasznlni.
hanem brmennyi.
Ha az adott case g utastsait vgrehajtotta a program, akkor CiklusokA hrom ciklusfajta kzl kettvel mr tallkoztunk,
nem az egsz switch utni utastssal folytatik a a while-lal s a for-ral. A harmadik, a do-while abban tr el az
program futsa, ahogy pl. az if-else-nl, hanem a elz ketttl, hogy htul tesztel, azaz elszr lefut a ciklus-
kvetkez case vagy default utni utastson. Ha mag, majd ellenrzi a ciklusfelttel teljeslst az utasts, s ha
azt akarjuk, hogy ne fusson r a program a kvet- az IGAZ. ismt vgrehajtja a ciklusmagot. A klnbsg annyi
kez case-re vagy a defaultra, akkor break utastssal ki kell teht, hogy htul tesztel ciklusoknl a ciklusmag legalbb egy-
lpni a switchbl. szer lefut. A while s a for ciklus ell tesztel.
Brmennyi case s egy darab default lehet, ezek sorrendje Nzzk a for ciklust:
tetszleges. Lehet a default az els, az utols (ez a leggyakoribb), H
vagy brmelyik kzbens. for :
I utasts lptets
A default elhagyhat, hasonlan az if-else-hez. inicializls kifejezs
Nem ktelez kln sorba rni a case-eket/defaultot, de az t-
tekinthet kd rdekben ersen javasolt. Pldul:
Pldk:
Szm felezse:

for(i=100; i>0; i/=2)printf("%d ",i);

29
nlhat brhol. Azt a ciklust clszer hasznlni, amelyik a legt-
sszetett kifejezs is hasznlhat mindhrom rszben. Pld- tekinthetbb kdot eredmnyezi az adott algoritmusnl.
ul rjuk ki 2 els 20 hatvnyt! Plda: rjuk ki az 1000-nl kisebb prmszmokat! Nzzk
int h, n; meg mindhrom ciklusfajtval a megoldst!
for(h=2, n=1; n<=20; n++, h*=2) Az algoritmus a kvetkez: 2-tl 1000-ig lptetnk egy vl-
printf("%d ",h); tozt egy ciklusban, s minden lpsben megvizsgljuk, hogy a
vltoz rtke prm-e. Ha prm, kirjuk. A vizsglatot ugyancsak
Az elvlasztsra a vessz opertort hasznltuk. Kt vltoz egy ciklussal vgezzk, gy egymsba gyazott ciklusokat hasz-
kapott indul rtket, s mindkettt vltoztattuk a lptetsben. nlunk.
A vesszt a C nyelv kifejezsekben opertorknt hasznlja, de a
fggvnyhvsoknl hasznlt vessz nem vessz opertor, azaz a Az ell tesztel ciklusokat hasznl algoritmus pszeudokdj-
printf("%d",a); fggvnyhvsnl a vessz nem opertor. Amikor oper-
nak elksztst az olvasra bzzuk.
tor, akkor a tbbi mveleti jelhez hasonlan hasznlhatjuk, teht rtelmes
az x=(3,4); kifejezs utasts, x-be 4 kerl: a vessz a kt operandusa
kzl a jobb oldalit adja vissza. Ebben az esetben muszj zrjelezni, For ciklussal:
mert minden opertor kzl a vessz precedencija a legkisebb. x=3,4; is
rtelmes szintaktikailag: x-be 3 kerl, a 4 meg csak gy van, nem hasz- #include <stdio.h>
nljuk semmire. Az x=(3,4)-hez hasonl rtkadst ltalban nem szoktuk
hasznlni, a vesszt elssorban a for ciklusban val elvlasztsra talltk int main(void){
ki. int i;
A kvetkez pldban a felttel s a lptets sszetett kifeje-
zs sszetett. Kt utastst tettnk a for belsejbe, ezrt ezeket {} for(i=2;i<1000;i++){
kz kell tenni, azaz sszetett utastsknt adjuk meg. A for int j,prim=1;
inicializl kifejezst resen hagytuk. for(j=2; j<i && prim==1; j++)
if(i%j==0)prim=0;
double x, y; if(prim==1)printf("%3d ",i);
... }
for(; x<100.0 && y>-2.2; x+=1.0, y-=x){ return 0;
printf("x erteke: %g\n",x); }
printf("y erteke: %g\n",y);
} While ciklussal:
Nem csak az inicializl kifejezs, hanem a for fejnek h- #include <stdio.h>
rom rsze kzl brmelyik elhagyhat.
int main(void){
int i=0; int i=2;
for(;i<n;i++)...
for(i=0;i<n;)... while(i<1000){
for(;i<n;)... int j=2,prim=1;
for(i=0;;)... while( j<i && prim==1 ){
for(;;)... if(i%j==0)prim=0;
j++;
Ahol a felttel resen maradt, ott a felttel mindig IGAZ-nak }
szmt, ami azt jelenti, hogy vgtelen ciklust kaptunk. Vgtelen if(prim==1)printf("%3d ",i);
ciklusbl pl. a return-nel ki lehet lpni, br ez a kd ttekinthet- i++;
sgt rontja. }
A while s a do-while ciklus folyamatbrja a kvetkez: return 0;
}

Do-while ciklussal:

#include <stdio.h>

int main(void){
int i=2;

do{
int j=2,prim=1;
if(j<i){
do{
if(i%j==0)prim=0;
j++;
}while( j<i && prim==1 );
}
if(prim==1)printf("%3d ",i);
i++;
Ha az utastsbl msolatot ksztnk a while ciklus el, ak- }while(i<1000);
kor a do-while mkdst kapjuk. Ha pedig a do-while ciklust return 0;
egy if belsejbe tesszk, ahol az if felttele ugyanaz, mint a ciklus }
felttele, a while mkdst kapjuk. Brmelyik ciklus hasz-

30
A kls ciklusnl nem kellett mst tennnk, mint az elejrl a 3.99999999999-et kapunk, s (int)3.99999999999 az bizony 3, s
vgre vinni a while-t, s a while helyre berni, hogy do. Ez nem 4! Szval lebegpontos szmtsoknl mindig gondoljunk a
azrt lehetsges, mert i=2-re biztosan lefut a ciklus. A bels kerektsi hibkra! Errl lesz mg sz a lebegpontos szmbr-
ciklus azonban nem futna le i=2 esetn, mert a j<i, azaz 2<2 zols kapcsn a 10. fejezetben.
felttel nem teljesl. Ha ugyangy jrnnk el, mint a kls cik-
lusnl, akkor az i%j==0 igaz volna, mert 2%2 az nulla, hiszen Ugr utastsokEzeket csak nagyon vatosan szabad hasznl-
minden szm oszthat magval. Ezrt is nem j<=i-ig ment a bels ni, mert knnyen ttekinthetetlen, mdosthatatlan programkd-
ciklus. Ezek azok az aprsgok, amelyekre gondolni kell prog- hoz juthatunk, kilgnak a strukturlt programozs eszkztrbl.
ramrs kzben, s ami csak sok gyakorlssal vlik termszetess. A break utasts hasznlata elkerlhetetlen a switch utastsban, a
A do-while megoldsba teht bekerlt egy plusz if, ami, ha return-t muszj hasznlni az rtket visszaad fggvnyekben. A
vgiggondoljuk, mindssze egyetlen egyszer jtszik szerepet, az break s continue hasznlata ciklusokban, a goto- pedig min-
i=2-nl. Minden ms esetben a while j<i felttele megakadlyoz- denhol kerlend. A returnnel is bnjunk vatosan!
za az nmagval val oszts vizsglatt. Ha elszr kirjuk, hogy A figyelmeztetsek utn nzzk rviden, mire is jk az egyes
2, utna pedig a kls ciklus 3-tl indul, akkor nem szksges az ugr utastsok!
if, ami majdnem ezerszer futna le feleslegesen. return: fggvnyekbl val kilpsre hasznljuk.
Ha mr optimalizlsrl beszlnk, nzzk meg, mit tehetnk
mg? Ha 3-rl indtjuk a prmkeresst, akkor felesleges a pros Pldul egy egsz szm abszolt rtkt szmt fggvny:
szmokat vizsglni, azok gysem prmek. Legyen teht az i++
helyett i+=2, gy i rtke 3, 5, 7, 9, lesz! Tovbbi gyorsulst int abszolut(int x){
rhetnk el, ha a bels ciklus nem i-ig, hanem i ngyzetgykig if(x<0)return -x;
megy: ha egy szmnak nincs osztja a ngyzetgykig, akkor az return x;
prm. (Mirt? Gondolja vgig!) Lehetne rni a bels ciklusba, }
hogy j<=sqrt(i), de ez azzal a kvetkezmnnyel jrna, hogy a
bels ciklus minden iterciban kiszmolja ugyanannak az i-nek A fggvny hasznlata pl.: int a=abszolut(-5); A -5 helyett
a ngyzetgykt. Szmoljuk ki teht e gykt a ciklus eltt! vltoz is lehet.
Vegyk szre, hogy mr az eredeti algoritmus is tartalmaz Kt return is szerepel a fggvnyben. Ha x negatv, a fgg-
optimalizcit: a bels ciklus vizsglja, hogy prim==1, gy ha vny x-et ad vissza, s azonnal ki is lp, teht a return x; mr
sszetett szmot tallunk, egybl befejezdik. Az algoritmus nem hajtdik vgre. ppen ezrt nem kellett odarni, hogy else
tkletesen mkdne, ha csak j<i lenne a ciklusfelttel, csak return x; (gy is lehet, de szksgtelen.)
lassabb lenne. A fenti fggvnyt egyszerbben megvalsthattuk volna a fel-
me, az optimalizlt algoritmus: tteles opertorral is: A feltteles opertor az

#include <stdio.h> if(felttel)y=valami1;


#include <math.h> else y=valami2;

int main(void){ tpus rtkadsok egyszerstsre szolgl. Klnlegessge,


int i=3; hogy ez az egyetlen hromoperandus mvelet a C-ben. A felt-
teles opertor a krdjel-kettspont, azaz ?:.
printf("2 "); Szintaxis: felttel ? kifejezs1 : kifejezs2
do{ Ha a felttel IGAZ, az opertor kifejezs1 rtkt adja ered-
int j=2,prim=1,gyok; mnyl; ha HAMIS, a kifejezs2 rtkt adja eredmnyl.
gyok=(int)(sqrt(i)+0.5); Pldul: max = a>b ? a : b;
do{ A max-ba a s b kzl a nagyobb kerl. A vltozk egszek,
if(i%j==0)prim=0; valsak, karakterek egyarnt lehetnek.
j++; Az abszolt fggvny feltteles opertorral:
}while( j<=gyok && prim==1 );
if(prim==1)printf("%3d ",i); int abszolut(int x){
i+=2; return x<0 ? -x : x;
}while(i<1000); }
return 0;
} break, continue: a kt utasts a hrom ciklusutastson bell
hasznlhat, ezen kvl a break mg a switch-ben is mkdik,
Mg nhny trkk: a gykt int-knt troljuk, mert a j<=gyok ahogy ezt a switch-nl lttuk.
mvelet gyorsabb, ha mindkett egsz, s az algoritmust tgon- A break segtsgvel kiugorhatunk a ciklusbl. Pldul:
dolva megtehetjk ezt.
gyok=(int)(sqrt(i)+0.5); utstst rtunk. Mirt? for(i=0; i<1000; i++){
Az sqrt fggvny double tpus paramtert vr s double t- printf("i=%d\n",i);
pus eredmnyt ad. A C automatikusan alakt t egsz adattpus- if(i==20)break;
bl lebegpontosba, vissza viszont nem, hiszen adatveszts lehet printf("Jok vagyunk!\n");
a kvetkezmny. (Pldul 4.7-bl 4 lesz, azaz elvsz a szm trt }
rsze, amit nem tudunk visszanyerni. Ha 4-et alaktunk 4.0-v,
akkor nyilvn nem volt adatveszts.) Az automatikus talaktst Itt rnzsre van egy ciklusunk, amely 0-tl 999-ig megy el,
implicit tpuskonverzinak nevezzk. Az (int) odarsval valjban azonban, ha a ciklusvltoz elri a 20-at, kilpnk a
jelezzk, hogy tisztban vagyunk az adatvesztssel, mgis krjk ciklusbl. Break helyett alkalmazzunk megfelel ciklusfelttelt!
az talaktst, ez az explicit tpuskonverzi, amirl mr volt sz. Ha a ciklusfelttel nagyon bonyolult lenne, hozzunk ltre egy
Mirt adunk hozz 0.5-et? Mert kerekteni szeretnnk. Lebe- segdvltozt, s azt vizsgljuk a ciklusban.
gpontos szmtsokkor erre figyeljnk! Lebegpontos szmt-
sok kzben kvantlsi s kerektsi hibk lphetnek fel. Ennek Pldul:
eredmnye lehet, hogy br pldul a pontos eredmny 4.0 lenne,

31
int seged=1;
while(seged==1){
8. Egyszer fggvnyek
if(a>b)seged=0;
i++; A program rszekre bontsnak, azaz a programszegment-
if(i==n)seged=0; ls legfontosabb eszkzei a fggvnyek. Kt f funkcijuk:
} 1. A tbbszr hasznlt programrszeket csak egyszer kell
lekdolni.
Alaktsa t az elz pldt break nlkliv (nincs szksg 2. A bonyolult algoritmusok sztbontva egyszer rszekre
segdvltozra)! ttekinthetv vlnak.
A fggvnyek ltalnos felptse:

A continue segtsgvel tugorhatjuk a ciklushtralev rszt. Bemen


Pldul: adatok
for(i=0; i<1000; i++){ Kimen
printf("i=%d\n",i); adatok
if(i==20)continue;
printf("Jok vagyunk!\n");
}

While s do-while ciklus esetn a felttelre ugrunk, for esetn


pedig a lptetsre. A pldban 20 esetn nem rjuk ki, hogy Jok
vagyunk!.
Ha tbb ciklus van egymsba gyazva, akkor a
break/continue csak a kzvetlenl befoglal ciklusra hat, teht
nem ugrik ki az sszesbl. A switch-ben lv break is csaj a
switch-bl ugrik ki. A fggvnyt tekinthetjk teht egy adatfeldolgoz egysgnek,
amely kap bemen adatokat, s ezeket felhasznlva produkl
goto: Ezzel az utastssal fggvnyen bell brhov ugorha- valamilyen eredmnyt. Vannak fggvnyek, amelyek nem kap-
tunk, fggvnyek kztt azonban nem lehet tugrani. nak bemen adatot (pldul ha szksgnk van egy
vletlenszmra, meghvjuk a rand() fggvnyt), kimen adatot
Pldul: viszont valamilyen formban mindegyik szolgltat (nem tudunk
mondani olyan rtelmes pldt, amely nem ad eredmnyt). A
#include <stdio.h> kimen adat ltalban valamilyen rtk illetve adatszerkezet,
nha a kpernyn megjelen vagy fjlba kerl informci.
int main(void){ A C nyelvben egy fggvny tetszleges szm bemen pa-
int i=0; ramterrel s egy darab visszatrsi rtkkel rendelkezhet. Ha
start: egynl tbb visszatrsi rtket kell adni, azt trkkel oldjuk meg,
printf("%d ",i); errl a 17. fejezetben lesz sz bvebben.
i++; A fggvnydefinci rszei szintaxis diagrammal:
if(i<20)goto start;
return 0;
} Trolsi osztly Tpusminst Tpus Fggvnyazonost (

A cmke C azonost, azaz az angol ABC kis- s nagybeti-


bl, szmokbl s alhzs jelekbl llhat, szmmal nem kez- Trolsi osztly Tpusminst Tpus Vltoz azonost
ddhet. A cmkt nem ktelez a sor elejre rni, de gy legalbb
ltszik. A ciklusokat a szmtgpek valjban a fentihez hasonl
,
mdon valstjk meg. A fenti kd for ciklussal:
, ) Blokk
int main(void){
int i=0;
for(i=0;i<20;i++)printf("%d ",i); Ktszer is ltjuk a trolsi osztly tpusminst tpus
return 0; azonost sorozatot. Ez nem vletlen, hiszen korbban volt rla
} sz, hogy a fggvny s a vltoz egyarnt trolsi egysg. A
fenti definciban a trolsi osztly, tpusminst s a opcio-
Az sszes ugr utasts kzl a goto hasznlata kerlend nlisan hasznlhat, s ritkbban is hasznljuk ezeket, most a
leginkbb, mert ezzel kuszlhat leginkbb ssze a kd. legfontosabb rszekkel foglalkozunk, melyek az albbi szintaxis
diagramon lthatk. A -rl azrt annyit jegyezznk meg, hogy
Gondolkozzunk egytt! ez teszi lehetv a printf s scanf fggvny szmra, hogy a
formtumsztring utn brmennyi vltozt megadhassunk. ltal-
ban nem lnk ezzel a lehetsggel, azaz a fggvnyeknek pon-
tosan annyi paramtert kell adni hvskor (aktulis param-
terek), amennyi a fggvnydefinciban feltntetnk (form-
Oldja meg egyedl!
lis paramterek).

32
A nemcserel() fggvny visszatrsi tpusa void, azaz hi-
Fggvny- Vltoz nyzik, teht nem ad vissza semmit. Az ilyen fggvnyekbe
Tpus ( Tpus ) Blokk
azonost azonost return nem szksges, de hasznlhatjuk return; formban.
, Bet-e a karakter? rjunk fggvnyt, amely a paramterknt
kapott karakterrl eldnti, hogy az bet-e, vagy brmi ms (pl.
Pldul rjunk fggvnyt, amelyparamterknt kap kt egsz szm, rsjel)! A fggvny adjon vissza egy egsz szmot, mely-
szmot, s visszaadja a szmok sszegt! nek rtke 1, ha bett kapott, s 0, ha szmot! (Vagyis 1 jelezze
az IGAZ-at s 0 a HAMIS-at!)
int osszead(int a,int b){// formlis paramterek
return a+b; Tudnivalk: a feladat szvegben nem szerepel, de ilyenkor
} mindig az angol ABC betire gondolunk, mert a magyar karakte-
rek figyelembe vtele nagyon megbonyoltan a megoldst. Az
Vagy, ha valaki kln vltozt szeretne ltrehozni az ered- angol ABC beti ugyanis egyms melletti szmokkal vannak
mnynek (nem szksges): kdolva. Errl bvebben a 12. fejezetben beszlnk. A kis- s
nagybetket ms-ms szmok jelzik.
int osszead(int a,int b){ Figyelem! A kis- s nagybetk nem szomszdosak egyms-
int c; sal. Valahogy gy helyezkednek el egymshoz kpest:
c=a+b;
return c; <egyb karakterek> A, B, C,,Y, Z<egyb ka-
} rakterek>, a, b, c, ., y, z <egyb karakterek>.

A fggvny aktivlsa (meghvsa) pldul a kvetkezkp- Megolds: ellenrizzk, hogy a vizsglt karakter benne van-e
pen trtnhet: az [A,Z] vagy az [a,z] zrt intervallumban. A fggvny C
kdja, valamint a kiprblshoz rt program:
int main(void){
int x,y,z; #include <stdio.h>
printf("3+2=%d\n",osszead(3,2));
x=5; int betu_e(char ch){
y=3; if((ch>='A' && ch<='Z') ||
z=osszead(x,y); // aktulis paramterek (ch>='a' && ch<='z'))
printf("%d+%d=%d\n",x,y,z); return 1;
return 0; return 0;
} }

Az egyik fggvnyben definilt vltozk nem lthatk a int main(void){


msik fggvnyben. Pldul ha a=3; szerepelne a main()-ben, a char ch='4';
fordt hibt jelezne, hiszen az a az osszead fggvnyben van
definilva. Ennek a kvetkezmnye az is, hogy a kt fggvny- if(betu_e(ch)==1)
ben lehetnek azonos nev vltozk, ezek kztt semmifle kap- printf("%c betu.\n",ch);
csolat nem lesz. else printf("%c nem betu.\n",ch);
A fggvny fejlcben szerepl int a, int b rnzsre olyan,
mint egy vltozdefinci. Nem csak rnzsre olyan, ez vlto- ch='w';
zdefinci! Az egyszer vltozdefincival (int c;, vagy int
x,y,z;) szemben az a klnbsg, hogy a fggvnyfejben minden if(betu_e(ch)) // egsz szm mint logikai rtk
egyes vltoz el ki kell rni a tpust, teht az int a,b hibs meg- printf("%c betu.\n",ch);
olds lenne. Az int a, int b s az int c kztti legfontosabb k- else printf("%c nem betu.\n",ch);
lnbsg, hogy az a s b azrt van a () kztt, mert szmukra
kezdrtket kell adnia a fggvny hvjnak. Azaz a fggvny return 0;
meghvsa nem ms, mint kezdrtk-ads a paramterlistn }
definilt vltozknak.
A kezdrtk-adson kvl tovbbi kapcsolat nincs a A fggvnyben nem rtunk else-t a return 0; el, mert ha tel-
fggvny hvsakor adott aktulis paramterek s a param- jeslt az if felttele, a return 1; mr kilpett a fggvnybl.
terlistn definilt vltozk, a formlis paramterek kztt. A main() fggvny egyrtelm, csak a betu_e() fggvny m-
Vagyis a kvetkez kdrszletben a main() fggvny a s b sodik meghvsa jelent jdonsgot: nem rtunk relcis opertort
vltoz eredeti rtkt fogja kirni, a fggvny nem hat vissza a a visszatrsi rtk vizsglatra. En nem hibs. A C-ben az egsz
hvs helyre. szmok hasznlhatk logikai rtkknt. A 0 logikai HAMIS, a
#include <stdio.h> nem 0 (teht brmely egsz szm, amely nem 0) pedig logikai
IGAZ. A fenti kd teht helyesen mkdik.
void nemcserel(int a,int b){ rdekes ellentmonds, hogy a sikeresen lefut main() fgg-
int c=a; a=b; b=c; vny 0-t ad vissza, ami a C-ben HAMIS-at jelent.
}
int main(void){ Betk szrse rjunk fggvnyt, amely a szabvnyos bemenet-
int a=3,b=4; rl olvas sorvge jelig, s a beolvasott szveget gy rja a szab-
nemcserel(a,b); vnyos kimenetre, hogy kiszr belle mindent, ami nem bet,
printf("a=%d, b=%d\n",a,b); azaz csak a betket rja ki! Pl. be: A 48-as forradalom 1848-ban
// eredmny: a=3, b=4 volt. Ki.: Aasforradalombanvolt
return 0;
}

33
A szabvnyos bemenet norml esetben a billentyzet, a
szabvnyos kimenet pedig a kperny.
Megolds: olvassuk be a karaktereket egy ciklusban, amg
nem jsor jelet kapunk! Minden karakterre ellenrizzk, hogy
bet-e, s ha igen, rjuk ki! A megoldsban felhasznljuk az elz
pldban ltott fggvnyt is.

rja meg az algoritmus pszeudokdjt!

A C nyelv megvalsts:

#include <stdio.h>

int betu_e(char ch){


if((ch>='A' && ch<='Z') ||
(ch>='a' && ch<='z'))
return 1;
return 0;
}

void szuro(void){
char ch;
do{
scanf("%c",&ch);
if(betu_e(ch))printf("%c",ch);
}
while(ch!='\n');
}

int main(void){
szuro();
return 0;
}

Ha kiprbljuk a programot, lthatjuk, hogy a szrt szveg csak az-


utn jelenik meg, hogy letttk a sor vgn az ENTER-t. Ennek az az
oka, hogy a scanf csak akkor kapja meg a begpelt szveget feldolgozs-
ra, amikor a felhasznl lettte az ENTER-t, s ez nem fgg a beolva-
sand adatok tpustl. A C nyelvben nincs olyan szabvnyos beolvas
fggvny, amely lehetv tenn a lettt billentyk azonnali beolvasst.

Mdostsa gy az algoritmust, hogy a szmjegyeket szrje ki a


szvegbl! Hozz kell nylni a szuro() fggvnyhez?

Gondolkozzunk egytt!

Oldja meg egyedl!

34
II. RSZ: ISMERKEDS A C NYELVVEL
9. Tmbk tmbben, hanem valamilyen dinamikus adatszerkezetben, pldul
lncolt listban vagy binris fban troljuk. Ezekrl a 24. s a 27.
fejezetben lesz sz. Ha elre ismeretlen mennyisg adatot kell
Gyakran van szksg nagyobb mennyisg adat feldolgoz- feldolgoznunk, gondoljuk meg, hogy valban szksg van-e az
sra. Az esetek egy rszben elkerlhet, hogy az adatokat elt- adatok trolsra! Az tlagszmtsnl lttuk, hogy nem mindig
roljuk, ilyen volt az tlagszmt program a 6.2. fejezetben. Ms van.
esetekben viszont muszj megjegyeznnk az adatokat. Nzzk a A tbbi tpushoz kpest (belertve a mg nem tanult tpuso-
kvetkez egyszer feladatot! kat, pldul a struktrt is) a C tmbknek van nhny furcsa,
gyakran kellemetlen tulajdonsga. A tmb nem msolhat az =
Feladat Krjnk a felhasznltl 100 darab egsz szmot, s opertorral, azaz pl. az
rjuk ki a kpernyre fordtott sorrendben!
int tomb1[100],tomb2[100];
Nem tudunk olyan trkkt kitallni, hogy a szmokat ne kell- tomb1=tomb2;
jen valamilyen mdon eltrolni. Az eddig tanultak alapjn szz
darab egsz tpus vltozra van szksgnk. Mindegyiket kln rtkads nem mkdik, a tmbelemeket egyenknt kell msolni,
definilni pl. int a,b,c,d,e,f,g,h, mdon, vagy akr int gy:
a1,a2,a3,a4,a5,a6,a7, mdon igen macers, s ha szz helyett
szzezer rtket kellene trolni, akkor egyenesen lehetetlen. for(i=0; i<100; i++)tomb1[i]=tomb2[i];
Tmb alkalmazsval tudjuk megoldani a problmt.
A tmb olyan sszetett vltoz tpus, amely a programoz l- Fggvny tpusa sem lehet tmb, azaz pl. az
tal kvnt mennyisg, azonos tpus adatot kpes trolni. C-ben
a tmb mrett a tmb ltrehozsakor szgletes zrjelben adjuk int [100] fuggveny(){
meg: int x[100];
return x;
int tomb[100]; }

Ez egy szzelem, egszek trolsra alkalmas tmb, pont fggvny nem j. Tmbt visszaadni mgis tud a fggvny, de
megfelel a feladatunk megoldsra. A tmb elemei az indexk- csak trkksen. A fggvnyek kaphatnak tmbt paramterknt,
kel rhetk el. Az index egy 0 s N-1 kztti egsz szm, ahol N azonban ezek a vltozk nem gy viselkednek, mint a tbbi ms
a tmb mrete (olyan, mint egy vektor a matematikban, csak tpusak. A fenti furcsasgok bvebb kifejtsre s magyarzat-
nem 1-tl, hanem 0-tl kezddik az elemek szmozsa). Jelen ra a 17. fejezetben kerl majd sor.
esetben N=100, azaz a tmb elemei tomb[0]tomb[99] kztti-
ek. Ez sszesen 100 darab. Aki nem hiszi, szmoljon utna! Kezdrtk tmbnek is adhat. Az elemek kezdrtkt kap-
Magyarzat: a fordt a tmb neve helyre a tmb kezdelemnek cmt helyet- csos zrjelek kztt, vesszvel elvlasztva soroljuk fel.
testi be, a keresett elem memriacmt gy szmtja ki, ha t[i]-t keressk:
t_cme+i*(egy_elem_mrete).
A feladat megoldsa tmb segtsgvel a kvetkez: Pl.: double d[3]={-2.1, 0.0, 3.7};

#include <stdio.h> A kezdrtk megadsnak van nhny specilis vltozata:


Adhatunk kevesebb rtket, mint a tmb mrete. Pl.:
int main(void){ double d[3]={-2.1, 1.0};. Ebben az esetben
int tomb[100],i; a megadott rtkek a tmb elejn lesznek, a tmb vgn
for(i=0; i<100; i++) lv elemekbe pedig nulla kezdrtk kerl (minden
scanf("%d",&tomb[i]); bjt 0 rtk lesz). Figyelem! Ha nem adunk kezdr-
for(i=99; i>=0; i--) tket egyltaln, akkor a tmb elemei kezdetben mem-
printf("%d",tomb[i]); riaszemetet tartalmaznak!
return 0; Ha kezdrtket adunk a tmbnek, a mretet nem kte-
} lez megadni. Pl.: d[]={-2.1, 0.0, 3.7};. Eb-
ben az esetben a fordt megszmolja, hogy hny rt-
Azaz az els ciklus 0-tl 99-ig feltlti a tmb elemeit, a m- ket adtunk meg, s pontosan ekkora tmbt hoz ltre.
sodik ciklus pedig 99-tl 0-ig kirja ket. Most sincs sz teht akrhny elem tmbrl, mert
olyan nem ltezik a C-ben.
Tovbbi tulajdonsgok A tmb ltrehozsakor a mretet
konstans rtkkel adjuk meg, vltozt ne hasznljunk! A C99- A sztringek trolsa karaktertmbben trtnik.
es szabvnytl kezdden a szabvny megengedi, hogy a mretet A szveget tbbek kztt. a scanf fggvny segtsgvel tud-
vltozval adjuk meg, azonban ezt a lehetsget sok fordt nem juk beolvasni (bvebben lsd a 12. fejezetben). Pl.: char
tmogatja, tbbek kztt a Visual C++ sem. Ha szoveg[100]; scanf("%s",szoveg);. (Jegyezzk meg,
platformfggetlen megoldst akarunk kszteni, akkor tmbt hogy sztring esetn nem runk & jelet a scanf-be, ez az egyet-
csak konstanssal definilunk. Ha fordtsi idben nem ismert, len kivtel!) A felhasznl ber egy szveget, leti az ENTER-t,
mekkora tmbre lesz szksg, hasznljuk dinamikus tmbt! s a szveg a szoveg nev tmbbe kerl (pontosabban a szveg-
Ezekrl a 18. fejezetben lesz sz bvebben. nek az els whitespace-ig tart rsze, tbb szavak beolvassra a
Mindig ktelez a tmbnek mretet adni! C-ben nincs gets vagy az fgets fggvny hasznlhat, lsd a 12. fejezetben).
olyan tmb, ami magtl megn, ha nagyobb tmbre van szk- Kirhatjuk pl. a printf("%s\n",szoveg); mdon.
sg. Az int tomb[]; definci nagyon slyos hiba. Ha nem ismert
elre, hogy hny adatot kell eltrolnunk, akkor az adatokat nem

35
A beolvass a pldban egy szzelem tmbbe trtnt. A fel- Azonban, az ttekinthetsg rdekben megadhatjuk csopor-
hasznl azonban valsznleg nem egy szz karakter hosszsg tostva is:
szveget fog megadni. Pldul ha a vezetknevt krdezzk, int t[3][4][2]={
nagyon sokfle szveghossz elkpzelhet. A tmb mrete nem {{34,-5},{3,20},{12,5},{-1,0}},
vltozik meg attl, hogy beletesznk valamit, mivel a tmbk {{4,77},{12,-3},{-14,3},{1,23}},
mrete a C-ben fix: akkork, amekkornak ltrehozzuk ket. A {{75,2},{10,24},{78,1},{2,7}}};
szveg mrete sem tud alkalmazkodni a tmb mrethez. Ebbl
kvetkezik, hogy a C nyelvnek valamikppen tudnia kell, hol van A kezdrtkek tbbdimenzis esetben is elhagyhatk, ekkor
a szveg vge a tmbn bell. A C nyelv kitalli kt megolds a nem belltott rtkek helyre 0 kerl (ha egyltaln nincs
kzl vlaszthattak: eltrolhattk volna a szveg hosszt egy kezdrtk, a tmb elemei nem nullzdnak, memriaszemt lesz
kln vltozban, k azonban ehelyett a szveg vgt egy speci- bennk). Pldul:
lis karakterrel, a lezr nullval jeleztk. A lezr nullt
karakterkonstansknt gy jelljk: '\0', ami nem tvesztend ssze #include <stdio.h>
a 0 szmjeggyel, mint karakterrel, ami egyszeren '0'. Ennek az a
jelentsge, hogy minden szabvnyos C fggvny, mely int main(void){
sztringekkel dolgozik, a lezr nullig dolgozza fel a szveget. int i,j,k;
Sztring kezdrtk karaktertmbnek ktfle mdon adhatunk. int t[3][4][2]={
Az els az, amit az elz oldalon lttunk: {{34}},
char tomb[20]={'S','z','i','a','!','\0'};. {{4,77},{12}},
Vegyk szre, hogy br a Szia! szveg ngy karakter, a sztring {{75},{10},{78,1}}};
a tmbben eggyel tbb helyet foglal el, mert a lezr nullnak
is ott kell lennie a vgn! for(i=0; i<3; i++){
Mivel ez a mdszer igen nehzkes, lehetsg van sztring for(j=0; j<4; j++){
konstanssal val kezdrtk adsra is: for(k=0; k<2; k++)
char tomb[20]="Szia!";. Ez a megads teljesen azonos printf("%d ",t[i][j][k]);
printf(", ");
az elzvel, azaz a lezr nulla is odakerl. Jegyezzk meg, hogy
}
sztring esetben csak kezdrtk adsakor hasznlhat az =
printf("\n");
opertor! A sztringmsolsrl a 19. fejezetben lesz sz, s ott
}
ismerkednk meg majd sok ms fontos sztringkezel algoritmus-
return 0;
sal is.
}
Tbbdimenzis tmbk Keresztrejtvnyt szeretnnk kszte-
ni, mondjuk 2030 kocka mretben (azaz vzszintesen 20, fgg-
legesen 30). Ehhez sszesen 600 karaktert kell trolnunk. Sok
Gondolkozzunk egytt!
egyforma adat, elre ismert mret tmb. A betket sorfolyto-
nosan troljuk, azaz elszr az els sor beti egyms mellett,
aztn a msodik sor beti, s gy tovbb, vagyis az egyms mel- msoljuk t egyik tmbbl a msikba az tlag alattiakat!
lett lv betk kzt egyet kell lpni, az egyms alatt lv betk
kzt pedig hszat. Az i. sorban s j. oszlopban lv bet indexe
i*20+j, ha i s j 0-tl indul. (Ha i s j 1-tl indul, (i-1)*20+(j-1) Oldja meg egyedl!
az index.) Azaz
char rejveny[600]; rejtveny[i*20+j]='A';
A C nyelv azonban biztost szmunkra ennl knyelmesebb
megoldst is, mgpedig a tbbdimenzis tmbk lehetsgt:
char rv[30][20]; rv[i][j]='A';
Az rv egy ktdimenzis tmb 30 sorral s 20 oszloppal. A
tmbt bejrhatjuk s kirhatjuk a kvetkez kddal:

for(i=0; i<30; i++){


for(j=0; j<20; j++)
printf("%c ",rv[i][j]);
printf("\n");
}

Kettnl tbb dimenzis tmbt is ltrehozhatunk a fentihez


hasonl mdon.
Az 1. fejezetben beszltnk a szmtgp memrijrl, s
lttuk, hogy az valjban bjtok egydimenzis tmbje. A C ford-
t a ktdimenzis tmbt valjban egydimenzis, sorfolytonos
alakban trolja, s pontosan gy szmtja ki a kvnt elem helyt,
ahogyan azt a rejtveny tmb esetn lttuk. A kettnl tbb di-
menzis tmbket hasonl mdon egydimenzis tmbben trolja.

Kezdrtk tbbdimenzis tmbnek az egydimenzishoz


hasonlan adhat, pl.:
int t[3][4][2]={34,-5,3,20,12,5,-1,0,4,
77,12,-3,-14,3,1,23,75,2,10,24,78,1,2,7};

36
10. Szmbrzols s az egyszer Lebegpontos szmok brzolsa A lebegpontos sz-
mokat az egszekhez hasonlan fix darabszm biten brzolja a
adattpusok szmtgp. A szmot brzol biteket kt rszre osztjuk: alapra
(mantissza) s kitevre (karakterisztika). A szmok lebegpontos
alakja: alap2kitev Az alapot gy hatrozza meg a rendszer, hogy
10.1. Szmbrzols rtke az [1,2) balrl zrt, jobbrl nylt intervallumba essen (azaz
1 lehet, 2 mr nem), a kitev pedig ebbl addik. Mivel ilyen
Egsz szmok brzolsa Az 1. fejezetben emltettk, hogy formn minden szm 1,xxxxx alak, az 1-et nem kell eltrolni. A
minden adat, amit a szmtgp trol, bjtok sorozata. Az egsz 0 nem hozhat ilyen alakba, erre egy specilis esetet definiltak.
A C nem rgzti, hogy konkrtan mi a lebegpontos szmok formtuma, azon-
szmok s karakterek ppgy, mint a lebegpontos szmok. Egy ban a gyakorlatban ltalban az IEEE 754 szabvny brzols a legelterjedtebb.
program esetn egy konkrt adattpus mindig ugyanannyi mem-
rit foglal, azaz ugyanannyi (binris) szmjegybl ll, pldul az Tpus Eljel Kitev Kitev rtkes sszesen
int tpus PC-n, 32 bites rendszerben, Visual C++-szal fordtva 32 [bit] [bit] eltols jegyek [bit]
szma [bit]
bites, vagyis 4 bjtos (a pontos szablyokat a fejezet ksbbi Fl 1 5 15 10 16
rszn talljuk). Pldul.: Egyszeres 1 8 127 23 32
Dupla 1 11 1023 52 64
00000000 00000000 00000000 00000000 = 0 Quad 1 15 16383 112 128
00000000 00000000 00000000 00000001 = 1 A PC processzora ezek kzl a az egyszeres s dupla pontossg szabvnyt is-
00000000 00000000 00000000 00000010 = 2 meri. A PC-s fordtk ltalban a float tpusnak az egyszeres pontossg, a double
00000000 00000000 00000000 00000011 = 3 s long double tpusnak a dupla pontossg lebegpontos tpust feleltetik meg.
A kitev eltols azt jelenti, hogy 2n kitev esetn n+eltols rtk kerl eltro-
lsra. Az IEEE szabvny szerint trolt vltozk esetben az eltolt kitev a csupa 0 s
01111111 11111111 11111111 11111111 = 2 147 483 647 a csupa 1 rtket nem veheti fel, ezek specilis szmok trolsra vannak fenntartva,
10000000 00000000 00000000 00000000 = -2 147 483 648 ezrt egyszeres pontossg esetn [126, 127], dupla pontossg esetn [1022, 1023]
a lehetsges kitev tartomny (n). Tzes szmrendszerben az egyszeres pontossg
tpussal brzolhat tartomny kb. 10-38-1038, a dupla pontossgval kb. 10-308-10308.
11111111 11111111 11111111 11111100 = -4 Specilis szmok:
11111111 11111111 11111111 11111101 = -3 A 0.0-t nem tudjuk addig osztani 2-vel, mg 1 s 2 kz esik, de az sem
11111111 11111111 11111111 11111110 = -2 engedhet meg, hogy egy 0.0-hoz nagyon kzel es nem 0.0 rtk jele-
11111111 11111111 11111111 11111111 = -1 ntse meg, hiszen a 0.0 a leggyakrabban hasznlt szm. A 0.0 esetn a ki-
tev, eljel s az alap egyarnt 0, azaz a 0.0 bitmintja 0x00000000.
A csupa 1 kitev, csupa 0 alap a -t jelenti (INF). Akkor kapjuk ezt, ha a
Ezzel az int tpussal teht -2 147 483 648 s 2 147 483 647 mvelet eredmnyt nem lehet brzolni az adott adattpussal, mert tl
kztti egsz szmokat tudunk trolni. Ha ennl nagyobb pozitv, nagy.
vagy kisebb negatv szmokkal kell szmolnunk, akkor az int A csupa 1 kitev, nem 0 alap jelentse: nem szm (NaN, Not a Number).
Egyb hiba. Pl. INF*0.
tpus nem megfelel, mert nem tudjuk hov rni a tovbbi szm-
jegyeket, ms tpust kell hasznlnunk, mr ha ltezik egyltaln Plda: Hogy nz ki a 6,28 egyszeres IEEE alakban?
alkalmas tpus. A C nyelv tbbfle egsz tpust is ismer, ezekkel 6,28=1,5722
hamarosan megismerkednk. eljel=0
kitev=0000 0010 (2)
A pldban lthat, hogy negatv szmoknl az els bit 1-es, eltolt kitev: 1000 0001 (129)
nemnegatvoknl pedig 0. Az azonos rtk csak eljelben k- alap: 1,1001 0001 1110 1011 1000 011 (1,57), az egszrszt (1) nem trol-
lnbz szmok kztt azonban ennl jval nagyobb a klnb- ja
sg. A magyarzat erre a furcsa brzolsra a kvetkez: tekint- a szm teht: 0100 0000 1100 1000 1111 0101 1100 0011 = 0x40c8f5c3
sk a bitmintt egyszer binris szmnak, s adjuk ssze mond- Ki is prblhatjuk az albbi kddal(csak akkor mkdik jl, ha float s
juk -3-at+3-mal! unsigned egyforma bitszm):

11111111 11111111 11111111 11111101 float f=6.28f;


printf("%x\n",*(unsigned*)&f);
+ 00000000 00000000 00000000 00000011
----------------------------------------------------- A szmtsi pontatlansg Lebegpontos szmok esetben
1 00000000 00000000 00000000 00000000 nem szabad elfelejteni, hogy a szmols nem pontos, mert az
rtkes jegyek szma korltozott.
Az eredmny egy 33 bites szm. Mivel csak 32 bitnk van,
Nzznk egy pldt tzes szmrendszerben! Ha 4 rtkes
egy bitet el kell dobni, ez pedig a legnagyobb helyirtk bit
jegy pontossgig tudjuk brzolni a szmokat, s van a k-
lesz (MSB Most Significant Bit), s a maradk 32 bitet tartjuk
vetkez kt szmunk: 8,888103, valamint 111110-4, azaz
meg, ami nem ms, mint a nulla. Brmely szmok esetn ellen-
8888 s 0,1111. Mindkt szmot tudtuk brzolni. A kett
rizhetjk, st, ha pl. -7-hez +10-et adunk, akkor +3 lesz az
ssege 8888,1111, azaz 8,8881111103. De az eredmny-
eredmny, ugyangy egy tlcsordul bittel (-10-hez adva +7-et
nek is csak 4 rtkes jegyt tudjuk trolni, teht a kiszmolt
-3-at kapunk, tlcsorduls nlkl). Az egsz szmok ilyen brzo-
eredmny 8,888103, azaz mintha az sszeads meg sem
lst kettes komplemens szmbrzolsnak nevezzk. A C
trtnt volna.
nyelv nem rja el ezt az brzolsi mdot, azonban a ma haszn-
latos szmtgpek ezt hasznljk.
Pontatlansg pldaprogrammal:
Minden mveletnl figyeljnk arra, hogy az eredmny br-
zolhat legyen a vlasztott adattpussal. Figyelem! Tilos gy //***************************************
ellenrizni a tlcsordulst, hogy #include <stdio.h>
if(a+b>2147483647)printf("Tlcsorduls);, mert #include <math.h>
ez az llts mindig hamis lesz, hiszen az sszeg //***************************************
tpusa is int, a tlcsorduls nem csak akkor tnik
el, ha egy int vltozba tesszk az sszeget, ha- //***************************************
nem a processzor eleve a tlcsordult bit nlkli int main(void){
eredmnyt adja. //***************************************
float a,b,c,x1=1.0,x2=1.0,d,y1,y2;

37
int i; long long unsigned long long 64 bit %lld (el-el-d),
for(i=0;i<20;i++,x2*=10.0F){ signed long long unsigned long long int %llu
long long int
a=1.0F; signed long long int
b=-(x1+x2);
c=x1*x2; A C szabvny szerint az adattpusok mrete kztt a kvetke-
d=b*b-4*a*c; z relci ll fenn: mret(short) mret(int) mret(long)
y1=(-b+(float)sqrt(d))/(2*a); mret(long long). Ennl tbbet nem ttelezhetnk fel! Az egyes
y2=(-b-(float)sqrt(d))/(2*a); tpusok mretre vonatkozan csak a tblzatban megadott mini-
printf("n=%d x1=%g\nx2=%g\ny1=" mlis mreteket rja el a szabvny. Az egy rubrikban lv
"%g\ny2=%g\n\n",i,x1,x2,y1,y2); elnevezsek ugyanazt jelentik. Az eljeles s eljel nlkli sz-
}
mok mindig egyforma bitszmak.
return 0; Az egsz tpusok konkrt jellemzit a limits.h-ban definilt
}
konstansok segtsgvel krdezhetjk le.
Ez a program az (x-1)(x-10n)=0 egyenlet gykeit szmolja ki. Lebegpontos tpusok A %e kitevs alakban, a %f tizedes trt
Elbb ax2+bx+c=0, azaz x2-(1+10n)+10n=0 egyenlett alaktja, alakban, a %g a leginkbb olvashat alakban rja ki, beolvassnl
majd ennek gykeit veszi az y1 / 2 ( b b 2 4 ac ) / 2a azonos jelentsek. A double tpusnl eltr a scanf s a printf
kplet segtsgvel. Ha jl szmolna, akkor a gykk 1 s 10 n formtumsztring!
volnnak, de nem ezt tapasztaljuk. n=4-nl mr lthatv vlik
egy kis hiba, 1 helyett 1.00003 a gyk, s a hiba folyamatosan n: tpus pontossg scanf printf
float 6 decimlis jegy, %e, %f, %g %e, %f, %g
n=8-nl mr 2,00294-et kapunk 1 helyett, s az eltrs gyors [1e-37,1e+37], 1e-5
temben n. A 10n gyk mindig j. Ha a float-ot double-re cserl- double 10 decimlis jegy, %le, %lf, %lg %e, %f, %g
jk, javul a pontossg, de a hiba tovbbra is fennll: n=16-ig j, [1e-37,1e+37], 1e-9
de n=17-nl 1 helyett hirtelen 0-t kapunk, s az eredmny ennyi is long double 10 decimlis jegy, %Le, %Lf, %Lg %Le, %Lf, %Lg
[1e-37,1e+37], 1e-9
marad.
A hiba oka a -b-sqrt(d) kivons. Itt ugyanis kt nagy
Mret(float) mret(double) mret(long double). A lebe-
szmot vonunk ki egymsbl, melyek kztt kicsi a klnbsg.
gpontos tpusok konkrt jellemzit a float.h-ban definilt kons-
tansok segtsgvel krdezhetjk le.
10.2. C alaptpusok azt jelenti, hogy 1 s a kvetkez brzolhat lebegpontos
rtk kztt legfeljebb ekkora a klnbsg.
void Azt jelenti, hogy hinyzik. Kt esetben hasznljuk: Lebegpontos konstansok:
Fggvny visszatrsi rtke, illetve ha nincs paramtere. float: -1.2f, 3.14F, 0.0f
Pl. int main(void){}, void kiir(int x); double: -1.2, 3.14, 0.0
Tpus nlkli pointer (lsd 16. fejezet). long double: -1.2l, 3.14L, 0.0L
Pl.: void * p = NULL;
Tpuskonverzi Kisebb pontossg tpusokrl nagyobb pon-
Egsz tpusok A printf/scanf formtumsztringben: tossgakra gond nlkl konvertlhatunk mind egsz, mind lebe-
gpontos tpusoknl, pldul int in; long lo; lo=in;
%[mdost][tpusjelz] problma nlkl mkdik. Brmely lebegpontos tpus nagyobb
pontossgnak szmt, mint brmely egsz tpus.
a kvetkez tpusjelzket hasznlhatjuk: Ha nagyobb pontossgrl szeretnnk kisebb pontossgra
o: 8-as (oktlis) szmrendszerben rja ki konvertlni, explicit tpuskonverzit kell hasznlnunk, klnben a
x,X: 16-os (hexadeximlis) szmrendszerben rja ki. Kis x fordt warningot kld. Pl. in=(int)lo;. Ugyancsak explicit
esetn kisbetket r ki, nagy X esetn nagyokat, pl. tpuskonverzi szksges, ha eljelesrl eljel nlklire vagy
0x00face12 ill. 0x00FACE12. fordtva szeretnnk konvertlni.
d,i: 10-es (decimlis) szmrendszerben rja ki eljeles Pldk:
egszknt.
int egesz=1;
u: 10-es (decimlis) szmrendszerben rja ki eljel nlkli short rovid=2;
egszknt. long hosszu=3;
Nincs tpusjelz a 2-es szmrendszerben trtn kirsra. double lebego=4.0;
A kvetkez tblzatban mindentt a d tpusjelz szerepel, de
brmelyik behelyettesthet az elzek kzl. // problma nlkl msolhat:

egesz=rovid;
nem eljeles eljel nlkli mret scanf s printf
defi-
hosszu=egesz;
nilt lebego=egesz;
eljel lebego=10; // Egszbl lebegpontos rtk lesz!
char signed char unsigned char 8 bit %c mint karakter,
%hhd ill. %hhu // adatveszts lehet:
mint szm.
short unsigned short 16 bit %hd, %hu rovid=egesz;
signed short unsigned short int rovid=hosszu;
short int
signed short int
egesz=10.3;
int unsigned 16 bit %d, %u hosszu=lebego;
signed int unsigned int
long unsigned long 32 bit %ld (el-d), lu // adatveszts lehet, de nem akarunk warningot:
signed long unsigned long int
long int rovid=(short)egesz;
signed long int rovid=(short)hosszu;

38
egesz=(int)10.3;
hosszu=(long)lebego; 11. Bitmveletek
// ahol pl. fontos lehet: Egsz szmok bitjeivel klnbz mveleteket vgezhetnk,
egesz=2;
ehhez szmos opertor ll rendelkezsre. A mveleteket kt
rovid=3; csoportba oszthatjuk: logikai s biteltols mveletekre. A szmok
lebego=egesz/rovid; // lebego rtke 0! kettes szmrendszerbeli alakjval dolgozunk.
lebego=(double)egesz/rovid; // lebego rtke 0,6666666...
A bitenknti logikai opertorok igazsgtblzatai:
Emlkeztetl: ahol kerek zrjelben megadtuk azt a tpust,
amiv t akarjuk alaktani az adatot, azt explicit (kzvetlen) A B A&B A B A|B A B A^B
tpuskonverzinak nevezzk. Ahol nem jelljk, hogy ms tpus- 0 0 0 0 0 0 0 0 0 A ~A
ra alaktjuk t az adatot, az az implicit (kzvetett) tpuskonverzi. 1 0 0 1 0 1 1 0 1 0 1
0 1 0 0 1 1 0 1 1 1 0
Gondolkozzunk egytt! 1 1 1 1 1 1 1 1 0 NEGLS
S VAGY KIZR VAGY

A bitenknti opertorok a szmok azonos helyirtk bitjei


Oldja meg egyedl! kztt mkdnek, a szmok minden egyes bitjre.
Pl.: 11&7 001011 & 000111 = 000011 3, azaz
11&7==3.
Pl.: 11|7 001011 | 000111 = 001111 15, azaz
11|7==15.
Pl.: 11^7 001011 ^ 000111 = 001100 12, azaz
11^7==12.
Pl.: ~7 ~ 000111 = 111000 8, azaz ~7==8. (Eljel
nlkli egsznl a tpus bitszmtl fgg a vgeredmny,
mert a szm elejn minden 0-bl 1 lesz.)
Bitenknti negls segtsgvel egy egsz szm mnusz egy-
szerese kettes komplemens brzolsban gy kaphat:
x==(~x+1).
A kvetkez azonossg mindig igaz: (A|B)==(A&B)+(A^B).
A bitenknti opertorok precedencija kisebb
az sszehasonlt opertoroknl, emiatt az
if(x&y==3) felttel jelentse: if(x&(y==3)), nem
pedig if((x&y)==3)!!
A rvidebb kd rsnak rdekben lteznek az rtkadst
bitmvelettel kombinl opertorok: |=, &=, ^=. Ugyangy
rtelmezettek, ahogy az aritmetikai mveleteknl lttuk: x|=y
x=x|y, x&=y x=x&y, x^=y x=x^y.

Biteltols (shiftels) opertorok


A >> balra tolja a szmot, egy bittel val eltols 2-vel val
osztsnak felel meg. Pl.: 19>>2==4. Ha a szm eljel nlkli,
vagy eljeles, de nem negatv, akkor 0 bitek lpnek be balrl, a
jobb oldalon kies bitek elvesznek. Ha a szm negatv, 1-es bitek
lpnek be balrl.
A << jobbra tolja a szmot, egy bittel val eltols 2-vel val
szorzsnak felel meg. Pl.: 19<<2==76. 0 bitek lpnek be jobbrl,
a bal oldalon kies bitek elvesznek.
Biteltolsra is lteznek sszevont rtkad opertorok, a >>=
s a <<=: x>>=y x=x>>y, x<<=y x=x<<y.
A biteltols sorn az egyik oldalon kies bi-
tek nem jnnek vissza a msik oldalon.
x<<y mvelet nem vltoztatja meg x rt-
kt. Ha vltozst akarunk, pl. gy kell: x<<=y.

Mit r ki?
int a=3,b=6;
printf("%d\t%d\t%d\t%d\n",a&b,a|b,a^b,~a);

Hny bites egy egsz? Bitmveletek segtsgvel hatrozzuk


meg, hogy hny bites egy egsz szm azon a szmtgpen, ahol
a programot futtatjk!
1-et tesznk egy vltozba, s addig toljuk balra, amg vgl
kiesik a tloldalon.

Bitszmll program:

39
Tegyl 1-at a vltozba! Pldul a felst kivesszk:
A szmll legyen nulla!
Amg a vltoz nem nulla 01101010=106, a pakolt rtk
Told balra egy bittel a vltozt! &11110000=240 (azaz 0xf0) a maszk
Nveld meg a szmllt eggyel --------------
VGE. 01100000=96 (01100000>>4)=00000110=6

//******************************************
#include <stdio.h>
#include <stdio.h>
//******************************************
int main(void){
int valtozo=1,szamlalo=0; //******************************************
while(valtozo!=0){ unsigned char bepakol(int be, int hova,
valtozo<<=1; unsigned char mod){
szamlalo++; //******************************************
} be &= 0x0f; // gy biztos csak az als 4 bit lehet nem 0
printf("%d\n",szamlalo); switch(hova){
case 0: return (mod & 0xf0) | be;
return 0; case 1: return (mod & 0x0f) | (be << 4);
} }
return 0;
rjuk t gy a programot, hogy biteltols helyett szorzst hasz- }
nl!
//******************************************
int kipakol(unsigned char pakolt, int honnan){
Pakolt egsz plda Egy feladat sorn nagyon sok 0 s 15 //******************************************
kztti egsz szmot kell trolnunk. A 0 s 15 kztti szmok switch(honnan){
elfrnek 4 biten, azonban a C nyelvben tallhat legkisebb adatt- case 0: return pakolt & 0x0f;
pus, a char is egy bjtos, azaz legalbb 8 bites. Nem szeretnnk case 1: return (pakolt & 0xf0) >> 4;
pazarolni a memrit, ezrt olyan fggvnyeket runk, amelyek }
kt darab ilyen szmot tesznek bele egy unsigned char tpus return 0;
vltozba, illetve kiveszik onnan. A fggvnyek bitmveletekkel }
dolgoznak. //******************************************
A betev fggvny jellemzi: int main(void){
Hrom paramtere van: //******************************************
o az egsz rtk, amit be kell tennie, int be1=11,be2=6;
o hov kell tennie (0: alulra, 1: fellre), unsigned char tarolo;
o a mdostand unsigned char rtk tarolo=bepakol(be1,0,0);
tarolo=bepakol(be2,1,tarolo);
Elszr a bemen rtket maszkolja 4 bitre. printf("Tarolo=%llu\n",tarolo);
Ltrehozza a pakolt rtket biteltols s maszkols se- printf("ki1=%d\n",kipakol(tarolo,0));
gtsgvel. printf("ki2=%d\n",kipakol(tarolo,1));
o Ha alulra kell tennie: return 0;
(mdostand&11110000)|bemen }
o Ha fellre kell tennie:
(mdostand&00001111)|(bemen<<4 bit)
Gondolkozzunk egytt!
Pldul fellre a 6-ot:
Hny 1-es bit van az egsz szmban?
10101010=170 a mdostand
& 00001111=15 (azaz 0x0f) a maszk Oldja meg egyedl!
---------------
00001010=10 (fell 0, alul maradt, ami volt)
| 01100000=(00000110=6 bemen)<<4
---------------
01101010=106, a pakolt rtk

A kivev fggvny jellemzi:


Kt paramtere van:
o a pakolt rtk
o honnan kell kivennie (0: alulrl, 1: fellrl),
Maszkols s biteltols segtsgvel kiveszi a szmot.
o Ha alulrl kell kivennie:
pakolt&00001111
o Ha fellrl kell kivennie:
(pakolt&11110000)>>4 bit

40
12. Bemenet s kimenet, ASCII
/******************************************/
#include <stdio.h>
/******************************************/

A fejezetben elszr a karakterek kdolsra hasznlt ASCII /******************************************/


szabvnnyal ismerkednk meg, ezt kveten megnznk nhny void magyarit(char * src){
/******************************************/
szabvnyos fggvnyt, melyekkel karaktereket illetve szvegeket unsigned i;
tudunk beolvasni illetve kirni. Vgl a printf s a scanf fggv- for(i=0;src[i];i++){
nyeket tekintjk t rszletesebben. switch(src[i]){
case '': src[i]=160; break;
case '': src[i]=130; break;
12.1 A karakterek ASCII kdja case '': src[i]=161; break;
case '': src[i]=162; break;
case '': src[i]=148; break;
A szmtgp memrija bitekbl, azaz kettes szmrendszer- case '': src[i]=139; break;
case '': src[i]=163; break;
beli szmokbl ll. Ahhoz teht, hogy szvegekkel lehessen case '': src[i]=129; break;
dolgozni, a szvegeket valamikppen szmokkal kell trolni. A case '': src[i]=251; break;
szvegekben elfordul minden karakterhez hozzrendeltek egy case '': src[i]=181; break;
case '': src[i]=144; break;
szmot. Kezdetben minden cg a sajt szm-karakter prosaival case '': src[i]=214; break;
dolgozott, ksbb a szabvnyostott ASCII (American Standard case '': src[i]=224; break;
Code for Information Interchange, ejtsd: [ski], magyarosabban case '': src[i]=153; break;
eszki) kiszortotta a tbbi varicit, s napjainkig meghatrozza case '': src[i]=138; break;
case '': src[i]=233; break;
a karakterkdolst. Csak az ASCII-re pl UNICODE illetve case '': src[i]=154; break;
ennek vltozatai (UTF-8, stb.) voltak kpesek rszben kiszortani, case '': src[i]=235; break;
azonban a C nyelv programok mg ma is zmmel ASCII-ben }
}
rdnak. }
Az ASCII szabvny 7 biten brzolja a karaktereket, azaz a 0-
127 szmokhoz rendel karaktert. A szmtartomny kt rszre /******************************************/
int main(void){
oszlik: 0 s 31 kztt tallhatk a vezrl karakterek (ezeket /******************************************/
leginkbb nyomtatk vezrlsre hasznltk), mint az jsor, kocsi char szoveg[100]="Hell vilg\n";
vissza, vzszintes s fggleges tabultor, lapdobs, escape, stb. magyarit(szoveg);
printf("%s",szoveg);
A 32-126 tartomnyban vannak a lthat karakterek, melyeket az return 0;
albbi tblzatban foglaltunk ssze. A 127-es karakter a delete. }

32-47: ! " # $ % & ' ( ) * + , - . / Figyeljk meg, hogy a szmjegyek mint ka-
48-63: 0 1 2 3 4 5 6 7 8 9 : ; < = > ? rakterek a 48-57 svban tallhatk, azaz
64-79: @ A B C D E F G H I J K L M N O '0'!=0. A sztringek vgt jelz '\0' nem egyezik
80-95: P Q R S T U V W X Y Z [ \ ] ^ _ meg az '0'-val, megegyezik viszont a 0 szm-
96-111: ` a b c d e f g h i j k l m n o mal, azaz '\0'==0!
112-127: p q r s t u v w x y z { | } ~ Mivel a 0-31 ASCII karakterek vezrlkarakterek, ezeket
nem lehet egyszeren berni sztringekbe, de az idzjel vagy
A tblzatban csak az angol ABC betit talljuk, hiszen ez aposztrof is gondot jelent. Ezek elhelyezsre a \ karakter utn rt
egy amerikai szabvny. Mi a helyzet a magyar karakterekkel? A azonost segtsgvel lehetsges. A kvetkez tblzat a C-ben
C programunkban tudunk kezetes betket rni. Ez gy lehets- hasznlhat specilis karakterkonstansokat tartalmazza:
ges, hogy br az ASCII 7 bites rendszerekre kszlt, ksbb a
legalbb 8 bites bjtokat alkalmaz szmtgpek terjedtek el, a Megads Jelents
nyolcadik bit pedig dupljra nveli a hasznlhat karakterek
szmt. A 128-255 kztti szmtartomny azonban nem szabv- \a Spol hang
nyos, sokfle kdtbla van hasznlatban. Ennek kvetkezmnye \b Backspace
az a furcsa jelensg, hogy ha Visual C++-ban runk egy progra-
mot, s abban magyar karaktereket tartalmaz szveget helye- \f Lapdobs (form feed)
znk el, akkor a konzol ablakban hibsan jelenik meg a kirt \n j sor
szveg. (printf("Hell vilg!\n"); Hell vilg!).
Egy msik kvetkezmny, hogy ha neveket rendeznk ABC \r Kocsi vissza (visszamegy a sor elejre, s az j
sorrendbe, akkor a rendezst a karakterekhez rendelt szmok szveg fellrja a rgit)
nagysga alapjn vgezzk, emiatt a magyar magnhangzk az \t Tabultor
sszes angol bet utn kerlnek. Ezzel a jelensggel ltalban \v Fggleges tabultor
nem szoktunk foglalkozni. Ha valamirt kifejezetten fontos lenne
a magyar magnhangzk helyes kezelse, sajt algoritmust kell \' Aposztrf
kszteni. Ezt az olvasra bzzuk (mire eljutunk a rendezsekig, \" Idzjel
mr minden szksges tudssal rendelkezni fog.)
A Visual C++-ban programozk szmra hasznos lehet az \\ Backslash
albbi fggvny, amely a paramterknt kapott sztringben lecse- \? Krdjel (a \ nlkl rt ? is j)
rli az kezetes magyar betket a konzol ablakban helyes vltoza-
tukra, gy a pldban lthat Hell vilg! helyesen jelenik meg. \ooo ASCII karakter nyolcas (oktlis) szmrendszer-
A fggvny mkdst nem magyarzzuk, mert mg nem min- ben megadva
dent tudunk hozz. Javasoljuk, hogy ha az olvas eljutott a 19. \xhh ASCII karakter tizenhatos (hexadecimlis)
fejezet vgig, trjen vissza ide, s rtse meg a mkdst! Addig szmrendszerben megadva
is hasznlja nyugodtan!
A fenti specilis karakterek minden sztringben hasznlhatk.
A printf s a scanf formtumsztringjben a % jel klnleges

41
karakter, ezt kveten adjuk meg a felsorolt vltoz tpust fprintf(stderr,"Hibas beolvasas!\n");
(printf-nl a %% rja ki magt a % jelet). A % jel ms esetben exit(1);
nem specilis karakter, azaz pl. a }
printf("%s","x=%d%%\n"); az x=%d%% szveget rja A getchar prja a putchar, mely a printf("%c",c);-nek
ki! felel meg: putchar('X'); putchar('\n');
putchar(ch);.
Plda rjuk ki a karakterek ASCII kdjt! ltalban kirsnl, gy a putchar-nl sem szoktunk hibt el-
lenrizni. Beolvass esetn azrt fontos, mert a felhasznl EOF-
#include <stdio.h> fal is jelezheti, hogy nem kvn tbb adatot megadni (ha Ctrl+Z-t
nyomunk a billentyzeten, amikor valamelyik beolvas fggvny
int main(void){ adatokra vr ppen, akkor ezzel EOF-ot kldnk a beolvas
int i; fggvnynek). Az EOF egybknt az End Of File, azaz fjl vge
for(i=0; i<255; i++) kifejezs rvidtse, s fjlbl olvassnl a fjlolvas fggvnyek
printf("%c=%d\t",i,i); is ezt adjk vissza. A billentyzetrl val olvass sokban hasonlt
return 0; a fjlbl val olvassra, ezrt hasznljk itt is ezt a konstanst. Az
} EOF az stdio.h-ban van definilva, hasznlathoz szksges az
stdio.h #include-dal val beszerkesztse.
A programot futtatva azt tapasztaljuk, hogy a vezrlkarakte- A scanf fggvny esetn pedig tovbbi szerepe a hibakeze-
rek egy rszt nem ltjuk, a 9 rtket pedig a 13 kveti. A 9 az lsnek, hogy amennyiben szmot prblunk beolvasni, s a fel-
jsor karakter, a '\n', a 13 pedig a kocsi vissza, azaz a '\r'. A '\r' hasznl nem szmot ad meg, a scanf fggvny hibajelzst ad
hatsra a kirs visszaugrik a sor elejre, s fellrja a korbban vissza. Ha ezzel nem trdnk, akkor a programunk hibsan fog
kirt szveget, ezrt nem ltszanak a 10-12 karakterek. (Nagy mkdni. A scanf fggvny esetn pldul gy kezelhetjk a
szmtsigny programoknl a '\r' remekl hasznlhat az elre- hibt:
halads kirsra: 1%, 2%...) int i;
Figyeljk meg, hogy int tpus vltozt jelentnk meg karak- printf("Adj meg egy egesz szamot! ");
terknt! A karaktereket trolhatjuk int-ben is, kivve, ha while(scanf("%d",&i)!=1){
sztringrl van sz. A sztringeket mindig char tmbben troljuk. fprintf(stderr,"Nem szam.\n");
scanf("%*s");
12.2 getchar/putchar, gets/puts, fgets printf("Adj meg egy egesz szamot! ");
}
A kdrszlet rdekessge a ciklusban megbj
A szabvnyos bemenetrl val beolvassra illetve rsra lta-
scanf("%*s");. A %*s azt jelenti, hogy egy sztringet olva-
lban a scanf/printf prost hasznljuk, mert ezekkel szinte minden
sunk be, de azt nem troljuk el sehol. A *-ot a tbbi adattpusnl
feladatot meg tudunk oldani, van azonban nhny specilis fgg-
is hasznlhatjuk, hasonl jelentssel: beolvassa, de nem trolja.
vny a C-ben, melyek szintn a felhasznlval trtn kommuni-
(Megjegyzs: a fenti kd az EOF-ot nem kezeli.)
kcira szolglnak.
gets/puts A gets fggvny sztring beolvassra szolgl. A
getchar/putchar Egy karaktert olvashatunk be a
scanf("%s",s); s a gets(s); kztt jelents klnbsg
scanf("%c",&c); helyett a c=getchar(); utastssal (c
van: a gets teljes sort olvas be, mg a scanf csak a kvetkez
char tpus). A kt vltozat teljesen egyenrtk, brmelyiket
whitespace karakterig olvas, ezrt a scanf-et ezen a mdon nem
hasznlhatjuk.
tudjuk nv beolvassra hasznlni. (A 12.3 alfejezetben ltjuk
A hibakezels mskppen trtnik a kt fggvny esetben. A
majd, hogy ez megoldhat a scanf-fel is.)
scanf a sikeres beolvassok szmval, vagy az EOF konstanssal
A gets hasznlata:
tr vissza. A scanf esetn gy ellenrizhetjk a beolvass sikert:
char s[100];
if(scanf("%c",&c)!=1){
gets(s);
fprintf(stderr,"Hibas beolvasas!\n");
printf("%s",s);
exit(1);
} A printf helyett hasznlhatjuk a puts fggvnyt is:
puts(s);
A scanf teht 1-et ad vissza, ha sikerlt beolvasni a karaktert.
A kt kirs kztt az az eltrs, hogy a puts tesz egy jsort a
(Az fprintf fggvny fjlba rsra szolgl, jelen esetben azonban
kirt szveg utn. (Ha printf("%s\n",s);-t hasznlunk,
nem valdi fjlba dolgozik, hanem egy fjlnak ltsz dologba, a
szabvnyos hiba kimenetre, vagyis az stderr-re, ami norml ugyanaz az eredmny.)
esetben a kperny.) Az exit(1) kilp a programbl, azaz vge a Figyeljk meg, hogy a getchar visszatrsi r-
programunknak. tke a beolvasott karakter, mg a gets a param-
A getchar esetben nincs kln paramterknt kapott clvl- terknt kapott karaktertmbbe teszi az eredmnyt!
toz s kln visszatrsi rtk, mint a scanf esetn, ezrt a hibt A gets visszatrsi rtke NULL konstans, ha nem sikerlt a
a visszatrsi rtknek kell tartalmaznia. A C nyelv kszti a beolvass:
if(gets(s)==NULL){
kvetkez trkkt alkalmazzk: a getchar nem char tpus rtket
fprintf(stderr,"Hibas beolvasas!\n");
ad vissza, hanem int-et. Ha nem trtnt hiba, akkor ez az rtk
exit(1);
berhat egy char tpus vltozba, ha azonban hiba trtnt, a
}
getchar az EOF konstanst adja vissza, melynek rtke ltalban -
1 szokott lenni. Az EOF nem char tpus rtk, teht char tpus
fgets A gets esetn problma, hogy ha a felhasznl hosszabb
vltozba nem rhat (a char c=EOF; hatsra a c-be bekerl
szveget ad meg, mint a karaktertmb mrete, akkor a gets a
egy rtk, ami mr nem az EOF, mert ha ezt kveten egy int
tmb utni memriarszre prblja meg betlteni a sztring vgt,
i=c; if(c==EOF)... utastssorozatot adunk ki, fordttl ahol valsznleg ms vltozk vannak, melyeket fellr. A msik
fgg, hogy az if felttele IGAZ-nak vagy HAMIS-nak bizonyul-e. lehetsg, hogy a programunk hibazenettel elszll. Ugyanez a
A getchar-t gy hasznlhatjuk hibaellenrzsre: problma fennll a scanf esetben is, azonban a 12.3 alfejezetben
int ch=getchar();
if(ch==EOF){

42
ltjuk majd, hogy scanf-nl korltozhat a beolvashat karakterek A szakasz tovbbi rszben lertakat nem kell tudni, ha szk-
szma. sg van r, elg fellapozni ezt a rszt, vagy megnzni a Helpben.
Az fgets fggvnyt eredetileg szveges fjlbl val beolva- Nzzk meg, hogyan hasznlhatjuk a %valami tagokat a kt fggvnyben!
printf: %[flagek][mret][.pontossg][tpushossz]tpus
ssra talltk ki, azonban hasznlhatjuk a szabvnyos bemenet A [] kztti rszek nem ktelezek.
olvassra is. Ez a fggvny szintn egy sornyi szveget olvas, Rszletek:
mint a gets, azonban van egy paramtere, mellyel megadhatjuk a tpus:
karaktertmb mrett, ahov beolvassa. Ha a felhasznl tl o d, i: eljeles egsz, a d s az i ugyanazt jelenti, azaz brhol rhatjuk a
%d helyett a %i-t
hossz szveget ad meg, az fgets nem olvassa be o u: eljel nlkli (azaz nemnegatv) egsz
a szveg vgt, hanem otthagyja egy kvetkez o o: nemnegatv rtk kirsa 8-as (oktlis) szmrendszerben
beolvass szmra. (A megadott mret teht a o x, X: nemnegatv rtk kirsa 16-os (hexadecimlis) szmrendszer-
ben. Kis x esetn kisbett, nagy X esetn nagy bett r ki, pl. %x ill.
karaktertmb mrete, az fgets ennl egy karakter- %X esetn 14-et e-nek ill. E-nek rja ki.
rel kevesebbet enged meg, mert a lezr nullnak is hagy helyet. o p: pointer kirsa hexadecimlis formban
A scanf-ben megadhat korlt viszont a karakterek szmt jelenti, o e, E: vals szm kirsa kitevs (exponencilis) alakban, pl. %e s
a scanf nem figyel a lezr nullra!) 1000.0 eredmnye: 1.000000e+003, azaz 1103; %E esetn
1.000000E+003 az eredmny.
Plda az fgets-sel trtn beolvassra: o f: vals szm kirsa fixpontos alakban, azaz 1000.0 eredmnye
char s[100]; 1000.000000.
fgets(s,100,stdin); o g, G: vals szm kirsa ltalnos (general) formban: az ember sz-
puts(s); mra legjobban olvashat formt vlasztja. 1000.0 eredmnye 1000.
o c: karakter
o s: sztring
12.3 printf s scanf o n: ez egy rdekes tpus, mert nem r ki semmit, hanem egy int * poin-
tert vr, s a mutatott int-be berja, hogy eddig a %n-ig hny karak-
tert rt ki. Pl.:
Bels formtum: ahogy a szmtgp trolja az adatokat printf("Mit sutsz kis szucs?%n "
"Sos hust sutsz, kis szucs? ",&a);
Kls formtum: ahogy az adatok az ember szmra rthe- printf("%d\n",a); eredmnye Mit sutsz kis szucs? Sos hust
tk. sutsz, kis szucs? 20.
A printf s scanf fggvnyek a kls s bels formtum k- tpushossz:
ztti talaktst vgzik. o h: egszeknl a short tpusokhoz, pl. %hd, %hx
o hh: egszeknl a char tpusok szmknt kezelshez: %hhd
Pl. a 123 az ember szmra 3 szmjegy, s a kpernyn 3 ka- o l (kis L): egszeknl a long tpusokhoz, pl. %ld, %lx
rakter brzolja. A szmtgp bel formtumban a 123 egy o ll: egszeknl a long long tpushoz (rgebbi C fordtk nem ismerik),
darab egsz szmknt, kettes szmrendszerben troldik. Ha pl. %ld, %lx
o L: valsaknl a long double tpushoz, pl. %Lf (a float s double tpu-
pldul a scanf beolvassa egy int tpus vltozba az ltalunk sokat egyarnt % e, %f ill. %g mdon rjuk ki)
megadott 123-at, akkor hrom darab karaktert kap ('1', '2', '3'), mret (a kirs minimlis szlessge):
ebbl ellltja az 1, 2 s 3 rtket ('1'-'0', '2'-'0', '3'-'0'), majd o egsz szm: ennyi karternyi helyre rja ki az rtket (szmot, bett
kiszmtja, hogy 1*100+2*10+3 a szm rtke, s ezt raktrozza vagy szveget), a tartomnyon bell jobbra igaztva. Az res rszt
alapesetben szkzkkel tlti fel. (Ezzel a mdszerrel rhet el az l-
el. Emlkezznk: az '1' ASCII kdja 49, a '0' ASCII kdja 48, a land oszlopszlessg kirs.) Ha a kirand rtk nagyobb, mint a
kett klnbsge valban 1. megadott hely, akkor nem vgja le, hanem nagyobb lesz a kirs: ak-
Ez a kt fggvny rokonfggvnyeikkel egytt (fprintf, kora, amekkora szksges. Pl. %3d s 12 eredmnye 12, vagyis 1
db szkz van eltte.
sprintf, stb.) a C legbonyolultabb fggvnyei. Paramterlistjuk is o *: paramterknt megadhat a kirand szlessg. Pl.:
olyan, amilyet nagyon ritkn hasznlunk: vltoz paramterlist- printf("%*d",3,12); eredmnye: 12, vagyis 1 db szkz
val rendelkeznek, azaz paramtereik szma s tpusa nem rgz- van eltte.
tett (lsd a 33. fejezetet). Egyszerstett prototpusuk a kvetkez: .pontossg (ms jelents az egyes tpusoknl)
o d, i, u, o, x, X: a kirt szmjegyek minimlis szma (0-kat r a szm
int printf(char formatum[],); el, ha az kisebb)
int scanf(char formatum[],); o e, E, f: a tizedespont utni szmjegyek szma, pl.
Az els paramter mindkt esetben a formtumsztring. A printf("%10.2e\n",12.789); eredmnye:
1.28e+001, egy szkz van az elejn, kt tizedes jegyre kerekt.
formtumsztring olyan sztring, mely lerja a kirand szveg, s a o g, G: az rtkes jegyek szma (ha az egsz rsz hosszabb, nem cson-
benne lv paramterek formtumt, illetve a beolvasand para- kol, pl.
mterek formtumt. printf("%2g\n",123456.789); eredmnye 123457).
A msodik paramter mindkt esetben . A hrom pont azt o s: a kirt karakterek maximlis szma (csonkol). Pl.
printf("%.4s\n","123456.789"); eredmnye: 1234
jelzi, hogy ide tetszleges szm, tetszleges tpus paramtert
flagek (tbb is hasznlhat egyszerre)
megadhatunk. A tetszleges szm 0 is lehet. o -: balra igaztja a kirt rtket. Pl. %-4dx s 12 eredmnye 12 x, az
A scanf fggvny csak beolvas, nem r ki semmit! Ha ezt x eltt 2 szkz.
rnnk: scanf("Add meg a szamot! %d",&a);, ez hibsan mkd- o +: mindenkpp r ki eljelet, pozitv szmok esetn is. Pl. %+d s 12
eredmnye +12
ne, mert a scanf nem tudja rtelmezni az Add meg a szamot, o 0: szkzk helyett 0-kal tlti fel a kirt szm eltti rszt, ha a szles-
rszt, s ezt kirni biztosan nem fogja (illeszteni prbl r, lsd sg nagyobb, mint a kirand rtk. Pl. %03d s 12 eredmnye: 012.
ksbb). A - flag esetn figyelmen kvl hagyja a fggvny. Pl. %-03d ered-
Mindkt fggvny visszatrsi rtke int. A printf visszaadja, mnye: 12 .
o #: oktlis szmnl 0-t, hexnl 0x-et vagy 0X-et r a szm el, val-
hogy hny karaktert rt ki. A scanf vagy azt adja vissza, hogy saknl mindenkpp kirja a tizedes pontot.
hny darab vltozt sikerlt beolvasnia, vagy egy specilis rt- scanf: %[*][mret][tpushossz]tpus
ket, amit az EOF nev konstans definil, mely szintn a beolvass tpus (sok hasonlsg, de sok lnyeges eltrs van a printf-hez kpest!)
o d: eljeles egsz szm 10-es (decimlis) szmrendszerben
sikertelensgt mutatja. A printf visszatrsi rtkt ltalban o i: eljeles egsz szm, 8-as, 10-es vagy 16-os szmrendszerben (12:
nem hasznljuk. decimlis, 012: oktlis, 0x12: hexa)
Figyelem! Sem a printf, sem a scanf nem tudja ellenrizni, o u: nemnegatv (eljel nlkli) decimlis egsz
hogy a programoz hny darab s milyen tpus vltozt sorolt o x: nemnegatv hexadecimlis egsz
o o: nemnegatv oktlis egsz
fel a formtumsztring utn. Mindig felttelezik, o c: karakter
hogy ott azt kapjk, amit vrnak. Ha hibsan adjuk o e, E, f, g, G: lebegpontos szm, float tpus. Az tbl brmelyiket
meg, a program akkor is lefordul, de rosszul fog hasznlhatjuk, a felhasznl brmilyen mdon berhatja a szmot,
akr kitevs alakban, akr fixpontos alakban. Fontos: a float szmok
mkdni. Ez olyan hibt is eredmnyezhet, ami beolvassa %e, %f, %g stb, a double szmok beolvassa %le, %lf,
csak idnknt jelentkezik, vagy ms platformon (gp/opercis %lg! Ha nem gy adjuk meg, a program nem fog jl mkdni! (printf
rendszer) lefordtva okoz hibt.

43
esetn a float s a double tpusnl egyarnt a %e, %f, %g alakot
hasznljuk). 13. A szmtgpek felptsrl s
o s: sztring
o p: pointer
o n: ugyanaz, mint a printf-nl, a beolvasott karakterek szmt trolja.
mkdsrl
o []: lsd lejjebb, az illesztseknl.
tpushossz Neumann elvek: A szmtgp mkdst a trolt program
o h: short egszekhez, pl. %hd
elve hatrozza meg, azaz a gp a program utastsait s az adato-
o l: long egszekhez, pl. %ld
l: double valshoz: %le, %lE. %lf, %lg, %lG (mind az t azonos je- kat egysgesen, a kzponti memriban, binris formban trolja.
lents, felcserlhet) Az ezen elv szerint mkd szmtgpek univerzlis Turing
o ll: long long egszhez (rgebbi fordtk nem ismerik) gpet valstanak meg s soros utasts-vgrehajtst alkalmaznak.
o L: long double valshoz A fenti azt jelenti, hogy a processzor az adatot is s az utastst is a memribl
mret: egsz szm, a beolvasott s konvertlt karakterek maximlis szmt olvassa be, az utastst elemzi, s az utastsnak megfelelen dolgozik tovbb.
adja. Pl. a Korbban az utastsokat kevsb rugalmas mdon troltk, pl. fixen belltottk a
scanf("%2d %2d",&a,&b); eredmnye, ha 87654-et ad meg a fel- szmtgp indtsa eltt.
hasznl: a=87, b=65 lesz. Egy kvetkez scanf kapja a 4-et. Neumann architektra: Neumann elvek alapjn felptett
*: dobjuk el a felhasznl ltal megadott rtket. A *-os beolvasshoz nem
is tartozik vltoz a paramterlistn. Pl. scanf("%*d%d",&a); ered- szmtgp, az adatokat s utastsokat ugyanazon az adatbuszon
mnye, ha 12 34-et ad meg a felhasznl: a=34, az 12-t eldobtuk. olvassa be a processzor vezrlegysge. A PC s a legtbb szm-
tgp ezt az architektrt valstja meg.
Illesztsek a scanf hasznlatval Illeszts lehetsges a %-os kifejezsen bell,
Harvard architektra: Ugyancsak Neumann elvek szerint pl
illetve azon kvl.
A %[] formtum szrt sztring beolvassra alkalmas fel, viszont az utastsokat s adatokat fizikailag elvlasztva
o %[abcd]: Addig olvassa be a szveget, amg abban olyan karakterek kezeli, kln buszon fr hozzjuk a CPU. Mikrokontrollerekben
vannak, amik a zrjelben. Pl. ha scanf("%[badluck]",s); a beolvass, igen elterjedt.
s a felhasznl azt adja meg, hogy addoda!, akkor a beolvasott
szveg add, mert az o nincs a zrjelben.
o %[A-Za-z ]: Tartomny megadsa. A-Z-ig s a-z-ig a betket, vala- A PC
mint a szkzt olvassa be. gy csak angol betkbl ll emberek ne-
vt tudjuk beolvasni, hiszen a magyar magnhangzk nincsenek ben-
Monitor Hangk.
ne az ASCII A-Z ill. a-z tartomnyban.
o %[^A-Z]: Minden, ami nem az A-Z tartomnyban van. A halmazra
nem illeszked karaktereket olvassa be. A kt vltozat nem kombi- Memria GPU PCI Express
nlhat, azaz a %[A-Z^QX] nem azt jelenti, hogy A-Z-ig illeszt, ki-
vve a Q s X, hanem azt, hogy A-Z-ig, tovbb ^ is lehet benne
(meg a Q s az X is, br ezeket tartalmazza az A-Z tartomny is). USB
o Magyar nevek beolvassa: %[^\n] mdon megadva a sor vgig ol- Memria CPU Chipset
eszkzk
vas, gy elkerlhet a gets hasznlata:
scanf("%[^\n]",nev); .
o %[]A-Z[-]: Az A-Z tartomny, plusz a [] zrjel- Httrtr
pr, s a - jel is lehet a szvegben. A ] csak az el-
s lehet a nyit zrjel utn, a pedig csak az
utols a zr zrjel eltt. A [ brhol lehet. A buszok kommunikcis csatornk, melyeken informci ramlik a szmtgp
A % formtumon kvli karakterekre pontosan illesz- egyes rszei kztt, de egyes egysgeken bell is lehetnek buszok. Szmos eltr
ked bemenetet vr a scanf. Ha nem azt kapja, akkor tpusuk ltezik.
sikertelen lesz a beolvass. A buszokon ltalban kettnl tbb eszkz tallhat, ezek kzl egyszerre
Pl. scanf("Szuletesi ev: %d",&a);. ltalban egy kld, egy pedig fogad informcikat. A buszvezrl ramkrk
Ha a felhasznl ezt rja be: Szuletesi ev: 1817, akkor a-ba bekerl dolga, hogy kivlasszk, mikor ki kommuniklhat.
1817. Megklnbztetnk soros s prhuzamos mkds buszt. Soros busznl a
o A szkz specilis: brmely whitespace karaktert helyettestheti. Pl. a bitek egymst kvetik ugyanazon a vezetken, prhuzamos busznl az ada-
"%d %d" esetn az els szm bersa utn nyugodtan thetnk EN- tok tbb vezetken haladnak egyszerre, prhuzamosan. Rgebben a lass bu-
TER-t, s gy adhatjuk meg a msodik szmot. St, akr gy is rhat- szok voltak soros felptsek, a gyors buszok pedig prhuzamosak. Manap-
tuk volna a formtumsztringet: "%d%d", ez ugyanazt jelenti. Az el- sg a lass s gyors buszok sorosak, a kzepes sebessgek prhuzamosak.
z pldban pedig a felhasznl nyugodtan rhatja kln sorba a Ennek az az oka, hogy nagy sebessgnl az egyszerre elkldtt bitek nem
Szuletesi, az ev: s az 1817-et, gy is elfogadja a scanf. egyszerre rkeznek meg a cmzetthez, mr akr nhny centimter hossz
o Ha azt akarjuk, hogy a scanf ugorjon t mindent, amit a felhasznl vezetk esetben sem. A nagysebessg soros buszok alkalmazst a modern
bert, s az els szmot olvassa be, akkor pl. scanf("%*[^0-9- ramkri technika tette lehetv. Soros buszok esetn is ltezik prhuzamo-
]%d",&a); mdon jrhatunk el. Ez gy beolvassa a negatv szmokat sts: tbb soros vezetken kldik az informcit, itt azonban bonyolult kl-
is, viszont ha a felhasznl - karaktert rt valahol nem eljelknt, ak- d s fogad ramkrk szksgesek. PCI Express busz esetn az 1, 2,
kor sikertelen lesz a beolvass. 4, 8, 16, 32 ilyen prhuzamostssal ri el a nagyobb sebessget.
o Egy sztr minden sorban angol=magyar mdon szerepelnek mon- A CPU s a memria kztt kln busz viszi az adatokat, a memriacmeket
datok. Milyen formtumsztringgel olvassuk be, ha csak a magyar s a vezrl informcikat (adatbusz, cmbusz, vezrl busz).
mondatokra van szksgnk? USB = Universal Serial Bus = ltalnos Soros Busz
Megolds: scanf("%*[^=]%[^\n]",&mondat);.
Memria s httrtr A szmtgpek f funkcija az adatfeldolgozs. Az
adatokat s a feldolgoz utastsokat valahol trolni kell. ltalban elmondhat,
hogy minl tbb informci trolsra alkalmas egy eszkz, annl lassabb. Tovbb
Gondolkozzunk egytt! ltalban gyorsabbak azok az eszkzk, melyek illkonyak, azaz elvesztik tartal-
mukat, ha megsznik az elektromos tpellts. A httrtrak nagymretek, nem
illkonyak, viszont tl lassak ahhoz, hogy a fut programot itt troljuk. A memria
s a httrtr egyarnt lehet csak olvashat, valamint rhat-olvashat.
ROM: Read Only Memory (csak olvashat memria). Minden szmtgpben
Oldja meg egyedl! tallunk ilyet. A szmtgp indulsakor az ebben tallhat programkd indtja az
opercis rendszer betltst. A PC-n ebben tallhat a BIOS (Basic Input-Output
System). Mikrokontrollereknl gyakran a mkdtet program s a konstans adatok
is ROM-ban tallhatk, s a RAM mrete nagyon kicsi. ROM-nak szoks nevezni
azokat a memrikat is, melyek nem illkonyak, azonban lehetv teszik a tartalmuk
megvltoztatst specilis krlmnyek kztt (EPROM, flash-ROM).
RAM: Random Access Memory (tetszleges elrs memria). A rvidts l-
talban vonatkozhatna a ROM-okra vagy a merevlemezre is, hiszen ott sem csak
sorban egyms utn rhetjk el az adatokat, ahogy egy mgnesszalagos trolnl,
hanem brhonnan olvashatunk vagy rhatunk. A RAM elnevezst ennek ellenre
csak az rhat-olvashat memrira hasznljuk, mely ltalban illkony, de nem
felttlenl. Legelterjedtebb a statikus RAM (SRAM) s a dinamikus RAM (DRAM).
A DRAM viszonylag lass, de a szilciumbl megvalstott celli sokkal kisebb
helyfoglalsak, mint a SRAM celli. A DRAM-ban egy kis integrlt kondenztor
trolja a bitet, melybl az elektronok elszivrognak, emiatt a segdramkrk

44
msodpercenknt sokszor kiolvassk s visszarjk a memriatartalmat, azaz friss- tani. Az opercis rendszer f feladata, hogy biztostsa ezeket a
tik az adatot. Emiatt dinamikus a dinamikus RAM. A DDR memriknl olvashat
tbb szz vagy tbb ezer MHz-es rajel becsaps, mert az egyes DRAM cellk
mveleteket a programok szmra.
Pldul az stdio.h fggvnyknyvtr fggvnyeinek zme feladatt az operci-
ennl sokkal lassabbak, mindssze nhny MHz-es, esetleg nhny tz MHz-es
s rendszer ltal biztostott fggvnyek meghvsval valstja meg.
rsi/olvassi sebessget tesznek lehetv. A nagyobb sebessget azzal rik el a
fejlesztk, hogy a mtrixban trolt RAM cellk egy teljes sort, ltalban tbb tucat, A printf fggvny gy mkdik, hogy a printf fggvny ltrehoz egy
akr tbb szz kilobitet tltenek be egyszerre egy tmeneti SRAM pufferbe (nevez- sztringet a kpernyre rand tartalommal, s ezt a sztringet tadja az oper-
hetjk akr cache-nek is), s innen mr valban lehet GHz-es sebessggel r- cis rendszernek. Az opercis rendszer jelenti meg a karaktereket a kper-
ni/olvasni. Ez azt jelenti, hogy amennyiben nem egyms utn kvetkez adatokat ny megfelel rszn. Ezrt lehet pldul, hogy az egyik opercis rendszer-
vagy utastsokat olvasunk, hanem ssze-vissza ugrlunk a memriban, durvn ben jl jelennek meg a magyar karakterek, a msikban pedig rosszul. (A %d
lecskken a programfuts sebessge. behelyettestst a printf vgzi.)
A SRAM ltalban egy 4 vagy 6 tranzisztorbl felplt flip-flop ramkr, A scanf s egyb beolvassok egy memriaterlet cmt adjk t az operci-
ugyanolyan gyors lehet, mint a processzor. A DRAM-nl 4-6-szor nagyobb helyfog- s rendszernek, ahov az beolvassa a felhasznl ltal begpelt adatokat. Az
lals miatt tmeneti trknt, vagy cache szmra hasznljk. Vannak elkpzelsek opercis rendszer nem tudja, hogy scanf, getchar, gets vagy mi egyb hvta
egy tranzisztoros (1T) RAM-ok kifejlesztsre is. A regiszterek is SRAM jelleg a fggvnyt, ezrt mindig az ENTER lenyomsig olvas, s ezutn kerl
cellkban troljk a biteket, melyeket segdramkrkkel egsztenek ki azrt, hogy vissza a vezrls a programhoz, ahol a beolvasott adatok rtelmezse s fel-
a regiszterekben lv adatokkal a processzor a lehet leggyorsabban tudjon dolgoz- dolgozsa megtrtnik.
ni. A klnfle erforrsok (fjlok, dinamikus memria) kezelse is az operci-
s rendszer dolga.
Az opercis rendszerek kszti nem ismerhetnek minden hardvert, amit a fel-
CPU Central Processing Unit (kzponti feldolgoz egy- hasznlk csatlakoztatnak a szmtgphez, ezrt a hardverek hasznlathoz szks-
sg), mikroprocesszor. A modern processzor rendkvl sszetett, ges fggvnyeket a hardverek gyrtinak kell biztostania (driver). Az opercis
eredeti hrom f rsze, a vezrl egysg, az aritmetikai s logikai rendszer az interfszt, azaz a fggvnyek deklarcijt adja meg, melyekhez illesz-
kednek a driverek fggvnyei.
egysg (Arithmetic Logic Unit ALU) s a regisztertmb, sz-
mos tovbbi rsszel egszlt ki. Ezek kzl csak a cache-t emlt- A lefordtott programrl PC-n, 32 bites Windowsban nznk egy pldt.
jk.
Vezrl egysg (Control Unit CU): Feladata az adattvitel vezrlse a #include <stdio.h>
processzor s a perifrik kztt, belertve a memrit is. Irnytja a buszo-
kat, beolvassa az utastsokat s adatokat, kirja az eredmnyeket. int minad(int a, int b, int c){
o Beolvassa az utastsregiszterbe (IR: Instruction Regiszter) a kvetkez int res;
utastst, rtelmezi a kdjt, ennek megfelelen vezrli az ALU-t, olvas if(a>b){
be adatokat, kezeli a vermet s az ugrsokat. Az utastsszmll re- if(a>c)res=b+c;
giszterben (PC: Program Counter) trolja a kvetkez utasts cmt. else res=a+b;
Norml esetben az utasts vgrehajtst kveten egy utastst lp el- }
re, ugr utastsnl pedig a megfelel cmre vltozik rtke. else if(b>c)res=a+c;
Aritmetikai s logikai egysg (Arithmetic Logic Unit ALU): Aritmetikai else res=a+b;
mveletek: +, -, *, /, %. Logikai mvelet: <, >, <=, >=, ==, !=, &, |, ^, ~. A if(res>a && a<0)res=-res;
lebegpontos mveleteket kln egysg vgzi, az FPU (Floating Point Unit). return res;
Regiszterek: ltalban 8-128 bit szles rhat-olvashat trolk, nhny }
tucat tallhat bellk a processzorban, legtbbnek egyedi neve van (pl. IR,
PC, SP, RAX, stb.). Architektrtl fggen nhny fix mret regiszter- int main(){
tmb is lehet a processzorban (xmm0, xmm1, stb.). Az ALU ltal hasznlt int x=minad(10,20,50);
regisztereket akkumultornak nevezzk. ltalban a Hny bites a szm- printf("Eredmeny=%d\n",x);
return 0;
tgp? krdsre az akkumultor mrete a vlasz.
}
Cache: a RAM messze van a processzortl, teht nagy a ksleltetsi id, ha a
gigahertzes rajeleket vesszk figyelembe. Radsul a DRAM eleve lass.
Fordtbl kinyerhet gpi kd+assembly+forrskd
Ezrt a processzor nem csak az ppen szksges adatot, hanem a kvetkez
vrhatan szksges adatokat is beolvassa az tmeneti trolba, a cache-be.
A printf formtumsztring konstansa
Gyakori, hogy ugyanaz a programkd vagy adat sokszor kerl lefuttatsra
vagy feldolgozsra. Ha ezeket a CPU a cache-ben tartja, nem kell vrakoznia
CONST SEGMENT
a RAM-ra. Az opercis rendszer a memrit hasznlja a httrtr adatainak
??_C@_0N@NIDIBBAO@Eredmeny?$DN?$CFd?6?$AA@ DB
cache-elsre, gy teht a cache szt tgabb rtelemben is hasznljuk.
'Eredmeny=%d', 0aH, 00H ;
CONST ENDS
Utastskszlet tpusok
CISC (Complex Instruction Set Computing sszetett utastskszlet fel- A kk az automatikusan generlt vltoznv. DB=Define Byte (a karaktereket
dolgozs): Az utastsok kztt szmos sszetett mveletet megvalst is egy bjtosnak fordtja, ez fordtfgg!). Aposztrfok kztt az assembly formtu-
tallhat, pl. sztringfeldolgozs. Ezeket a processzor nem kzvetlenl hajtja m konstans sztring, mely nem tartalmazza az jsor s a lezr 0 karaktereket, ezrt
vgre, hanem egyszerbb utastsokra bontja. Az utastsok nem egyforma ezek utna vannak felsorolva: 0aH a hexadecimlis 13, ami a \n kdja, s a 00H, ami
mretek. ezrt nem lehet elre tudni, hol kezddik a 10. kvetkez utasts, a 0 (ms nven '\0') kdja.
csak ha az elz 9-et beolvastuk. Sokfle cmzsi md tmogatott. Mivel az
x86-os architektra, mely CISC felpts, rendkvl elterjedt, a processzor- A main fordtsnak eredmnye
gyrtk olyan mrtkben optimalizltk a processzoraikat, hogy azok sebes-
sgben felveszik a versenyt az elvileg hatkonyabb RISC s VLIW architek- ; 16 : int x=minad(10,20,50);
trkkal. Ezt gy rtk el, hogy a berkez utastsokat RISC jelleg utast-
sokk alaktjk, s igen fejlett elgazsbecslst, valamint a kdban szerepl 0001e 6a 32 push 50 ; 00000032H
sorrendtl eltr vgrehajtsi sorrendet (Out of Order Execution) alkalmaz- 00020 6a 14 push 20 ; 00000014H
nak. Kihasznljk a CISC rendszernek azt az elnyt, hogy mivel az utast- 00022 6a 0a push 10 ; 0000000aH
sok sszetettek, kevesebb kell bellk ugyanahhoz a feladathoz, teht keve- 00024 e8 00 00 00 00 call ?minad@@YAHHHH@Z ; minad
sebbszer kell olvasni a memribl. 00029 83 c4 0c add esp, 12 ; 0000000cH
RISC (Reduced Instruction Set Computing cskkentett utastskszlet 0002c 89 45 f8 mov DWORD PTR _x$[ebp], eax
feldolgozs): Az utastsok egyszerek s egyforma mretek, a processzor
kzvetlenl vgrehajtja ket. Rgen a CISC-nl sokkal magasabb rajelek ; 17 : printf("Eredmeny=%d\n",x);
elrst tette lehetv, ma mr a CISC optimalizlsok miatt nem gy van.
VLIW (Very Long Instruction Word nagyon hossz utastssz): Fix 0002f 8b 45 f8 mov eax, DWORD PTR _x$[ebp]
nagymret utastsegysgekbl pl fel a kd, az egy egysgen bel tallha- 00032 50 push eax
t utastsokat a processzor prhuzamosan hajtja vgre. Nem vltoztatjk 00033 68 00 00 00 00 push OFFSET
meg az utastsok sorrendjt, az optimalizls teljes mrtkben a fordtra FLAT:??_C@_0N@NIDIBBAO@Eredmeny?$DN?$CFd?6?$AA@
marad, ppen ezrt sokkal ersebben ignyli a hatkony fordtt, mint a 00038 e8 00 00 00 00 call _printf
CISC, RISC rendszerek. 0003d 83 c4 08 add esp, 8
o EPIC (Explicitly Parallel Instruction Computing kzvetlenl prhu-
zamos utastskszlet feldolgozs): a VLIW Intel ltal tovbbfejlesz- ; 18 : return 0;
tett verzija, IA64
00040 33 c0 xor eax, eax

Opercis rendszerek Szmos olyan mvelet van, amit sok 00055 c3 ret 0
program ignyel, azonban nem rdemes hardveresen megvals-

45
Piros: Az utna kvetkez gpi kd memriacme a main fggvny kezdc-
mhez kpest, hexadecimlis formban megadva. A piros szmok termszetesen 00055 eb 09 jmp SHORT $L615
nincsenek benne a lefordtott kdban, csak az olvashatsgot segtik. $L616:
Zld: Ezek a tnyleges gpi kdok hexadecimlis alakban, vagyis azok a bj- 00057 8b 45 08 mov eax, DWORD PTR _a$[ebp]
tok, amik megtallhatk az exe fjlban, ha megnyitjuk, s vgigolvassuk. Minden 0005a 03 45 0c add eax, DWORD PTR _b$[ebp]
sorban egy gpi kd utasts szerepel. A fggvnyek s a sztring cme nincs 0005d 89 45 f8 mov DWORD PTR _res$[ebp], eax
behelyettestve. Felismerhetjk, hogy CISC architektrrl van sz, hiszen az $L615:
utastsok hossza klnbz. (32 bites x86 kd egybknt.)
Kk: Az assembly kd, ez a gpi kd ember szmra olvashatbb vltozata. ; 11 : if(res>a && a<0)res=-res;
A push utasts a verembe menti az rtkeket (errl lesz sz a flv ksbbi
rszn). 00060 8b 45 f8 mov eax, DWORD PTR _res$[ebp]
o rdekessg: Figyeljk meg, hogy fordtott sorrendben kerlnek az ada- 00063 3b 45 08 cmp eax, DWORD PTR _a$[ebp]
tok a verembe, emiatt a verem tetejre kerl a legels paramter. C-ben 00066 7e 0e jle SHORT $L618
vannak vltoz paramter fggvnyek, amilyen a printf vagy a scanf, 00068 83 7d 08 00 cmp DWORD PTR _a$[ebp], 0
ezeknl csak az els paramter biztos, a tbbi paramtert a 0006c 7d 08 jge SHORT $L618
formtumsztring alapjn azonostja a meghvott fggvnyt. Ha fordtva 0006e 8b 45 f8 mov eax, DWORD PTR _res$[ebp]
kerlnnek a verembe az rtkek, akkor nem tudn, hol keresse az els 00071 f7 d8 neg eax
paramtert. Ms programnyelvek, pl. a Pascal nem, gy mkdnek, azok 00073 89 45 f8 mov DWORD PTR _res$[ebp], eax
sorban teszik el a paramtereket. Ha egy C program Pascal mdon rt $L618:
fggvnyt kell hvjon, pl. az opercis rendszer egy fggvnyt, akkor a
fggvnyt Pascal tpusnak kell deklarlni. Pl.: pascal int fuggveny(int ; 12 : return res;
x, int y); Ilyesmirl nem lesz sz ebben a flvben.
00076 8b 45 f8 mov eax, DWORD PTR _res$[ebp]
call a fggvnyhvs (a paramterek a vermen kerlnek tadsra).

add esp, 12: 12-t ad az esp regiszterhez, azaz felszabadtja a paramterek
00055 c3 ret 0
ltal lefoglalt helyet a veremben. Az esp az Extended Stack Pointer rvidt-
se, ez a 32 bites veremmutat. Azrt ad hozz 12-t, mert a push utastssal
beletett 3 db 4 bjtos egsz szmot, a fggvnyparamtereket. Ezeket kive- cmp: sszehasonlt kt egsz rtket, az eredmny egy specilis flag regisz-
hetn pop-pal, de nincs szksge a paramterekre (azokat a minad fggvny terbe kerl. A flagek 1 bites rtkek. A cmp egyik paramtere konstans vagy
mr hasznlta), s gy gyorsabb. Azrt hozzad s nem elvesz, mert az x86- regiszter, ezrt kellett elbb bemsolni a-t eax-be.
os kdban a verem fejjel lefel ll, teht minl tbb adatot tesznk bele, jle: feltteles ugrs (Jump if Lower or Equal, ugorj, ha kisebb vagy egyenl).
annl kisebb az esp rtke. Ha a flag regiszter tartalma azt jelzi, hogy az sszehasonlts eredmnye <=
mov: msol utasts, jobbrl balra msol. mov DWORD PTR _x$[ebp], volt, akkor az else gra ugrik. A jle paramtere az ugrsi cm. Jelen esetben
eax: az eax akkumultor regiszter tartalmt az x vltozba teszi. A fggv- egy SHORT rtk, ami azt jelenti, hogy 1 bjt adja meg, mennyit kell ugrani.
nyek az eax regiszterben adjk vissza az egsz tpus visszatrsi rtket. Ennek a bjtnak az rtke addik az IC utastsszmll regiszter rtkhez.
o A kvetkez sorban az x-bl kerl vissza az adat eax-be. Ez nem azrt jmp: felttel nlkli ugrs (Jump) a megadott (relatv) cmre.
van, mert a mov tmozgatta, teht vissza kell tenni, hanem mert debug A visszatrsi rtk az eax-be kerl.
zemmdban lett lefordtva a program, s ekkor a fordt semmit sem
optimalizl, minden C kdot megvalst, teht nem trdik azzal, hogy sszefoglalva
felesleges mveletet vgez.
A printf hvs eltti push-nl felismerhetjk a formtumsztring memriac- A memriban az adatok s utastsok bjtok sorozataknt jelennek meg, rn-
mt. zsre nem lehet megmondani, hogy mi micsoda. Ugyanazt a memriatartalmat
xor eax,eax: Ha valamit magval hozunk xor kapcsolatba, akkor 0-t kapunk. utastsknt, egsz szmknt vagy lebegpontos szmknt kezelve teljesen ms
eredmnyt kapunk.
Assemblyben minden aritmetikai s logikai mvelet esetben az els para-
Pldul a 2 206 009 344 egsz szm (hexa: 83 7D 08 00) lebegpontos szm-
mter csak regiszter lehet, s az eredmny az els paramterbe kerl. Jelen
knt -7.43592e-037, gpi kdban pedig a cmp DWORD PTR _a$[ebp], 0 utasts
esetben a C nyelv ^= mvelett valstja meg, korbban pedig az add a +=-t.
kdja.
ret 0: Itt a 0 nem a visszaadott rtk, ez abbl is ltszik, hogy a kd mindsz-
A vgrehajthat fjl (pl. exe) eleje fix felpts, gy indtskor az opercis
sze egy bjt. A visszaadott rtk az eax-be kerl.
rendszer tudja, hol van az els utasts illetve az adatok.
A minad fggvny:

; 4 : int res;
; 5 : if(a>b){

0001e 8b 45 08 mov eax, DWORD PTR _a$[ebp]


00021 3b 45 0c cmp eax, DWORD PTR _b$[ebp]
00024 7e 1e jle SHORT $L612

; 6 : if(a>c)res=b+c;

00026 8b 45 08 mov eax, DWORD PTR _a$[ebp]


00029 3b 45 10 cmp eax, DWORD PTR _c$[ebp]
0002c 7e 0b jle SHORT $L613
0002e 8b 45 0c mov eax, DWORD PTR _b$[ebp]
00031 03 45 10 add eax, DWORD PTR _c$[ebp]
00034 89 45 f8 mov DWORD PTR _res$[ebp], eax

; 7 : else res=a+b;

00037 eb 09 jmp SHORT $L614


$L613:
00039 8b 45 08 mov eax, DWORD PTR _a$[ebp]
0003c 03 45 0c add eax, DWORD PTR _b$[ebp]
0003f 89 45 f8 mov DWORD PTR _res$[ebp], eax
$L614:

; 8 : }
; 9 : else if(b>c)res=a+c;

00042 eb 1c jmp SHORT $L615


$L612:
00044 8b 45 0c mov eax, DWORD PTR _b$[ebp]
00047 3b 45 10 cmp eax, DWORD PTR _c$[ebp]
0004a 7e 0b jle SHORT $L616
0004c 8b 45 08 mov eax, DWORD PTR _a$[ebp]
0004f 03 45 10 add eax, DWORD PTR _c$[ebp]
00052 89 45 f8 mov DWORD PTR _res$[ebp], eax

; 10 : else res=a+b;

46
14. sszetett s szrmaztatott adat- printf("x1=%g\nx2=%g\n",x.x1,x.x2);
return 0;
tpusok, tpusdefinci }
A programban a struktra defincija gy nzett ki:
A 10. fejezetben megismerkedtnk a C egyszer adattpusai- struct par{ double x1,x2; };
val (void, char, egsz tpusok, lebegpontos tpusok). Vannak
azonban olyan adattpusok, melyek ezekbl az elemi tpusokbl de gyakran rjuk gy, tbb sorra bontva:
vagy ms sszetett tpusokbl plnek fel (tmb, struktra,
union) illetve ezekbl szrmaznak (enum, bitmez, pointer, fgg- struct par{
vny). A C nyelv lehetv teszi sajt adattpusok ltrehozst is. double x1,x2;
};
14.1 sszetett s szrmaztatott tpusok
Struktra helyett hasznlhattunk volna ktelem tmbt?
Tmb A 9. fejezetben mr megismerkedtnk ezzel az adatt- Nem. Magyarzat a pointerekkel foglalkoz rszben lesz.
pussal. Egyfajta tpus, szomszdosan elhelyezked elemek
halmaza a tmb. Egy tmbtpust elemeinek tpusa s elemeinek Kaphat kezdrtket: struct par x={7.1, -4.2};
szma hatroz meg. A tmbnek legalbb 1 eleme kell legyen. A
tmb elemei a sorszmuk segtsgvel rhetk el, a kezdelem A struktra klnbz tpus vltozkat is magba foglalhat:
sorszma 0. Elemei szrmaztatott illetve sszetett tpusak is
lehetnek. struct korcs{
double x1,x2;
int a;
elemtpus tmbazonost [ mret ] inicializls char t[10];
};

Msolhat = opertorral. (Emlkezznk, a tmb nem! De ha a


Struktra Tetszleges tpus, szomszdosan elhelyezked struktrban van tmb, akkor a struktrval egytt msolhat!
elemek halmaza a struktra. A struktrnak legalbb egy eleme Magyarzat a pointerekkel foglalkoz rszben.)
kell legyen. Az elemek (tagvltozk) az egyedi nevk segtsg-
vel rhetk el. Elemei szrmaztatott tpusak is lehetnek. struct korcs a,b;
a=b;

struct tpuscmke { deklarcis lista } vltozazonost lista Fggvny tvehet paramterknt struktrt, s vissza is tudja
adni.

A struktra jl hasznlhat pldul abban az esetben, ha egy struct korcs proba(struct korcs a){
fggvnynek tbb rtket kell visszaadnia. Nzzk pldul a if(a.t[3]=='N')a.x1=a.x2;
msodfok egyenlet megoldst: else a.x2=a.x1;
return a;
#include <stdio.h> }
#include <stdlib.h>
#include <math.h> Nem csak struktrban lehet tmb, tmbben is lehet strukt-
ra:
struct par{ double x1,x2; };
int main(){
struct par gyok(double a,double b, struct korcs kutyu[100];
double c){ int i;
double d = b * b - 4 * a * c; for(i=0; i<100; i++)kutyu[i].a=0;
struct par x; }

if(d < 0){ Union Tetszleges tpus, egymst tfed elemek halmaza a
fprintf(stderr, union. A unionnak legalbb egy eleme kell legyen. Az elemek
"Negativ diszkriminans.\n"); (tagvltozk) az egyedi nevk segtsgvel rhetk el. Elemei
exit(1); szrmaztatott tpusak is lehetnek. Ritkn hasznljuk. Bvebben
} a 32. fejezetben szlunk a unionrl.
d = sqrt(d);
x.x1=(-b+d)/(2.0*a); union tpuscmke { deklarcis lista } vltozazonost lista
x.x2=(-b-d)/(2.0*a);
return x;
} Felsorolt tpus (enum) Egsz (int) tpus konstansok csopor-
tos defincijt teszi lehetv.
int main(){
struct par x;

x=gyok(1.0,7.0,10.0);
printf("a=1, b=7, c=10.\n");
printf("Az egyenlet gyokei:\n");

47
typedef eredeti_tpus j_nv;
enum Tpuscmke {
Itt az eredeti tpus tbb rszbl is llhat, az j nv egyszavas
C azonost.
Azonost = Egsz szm } vltozazonost lista
Pldul:
,
typedef int egesz;
Megads: enum azonost {konstansok};
typedef unsigned char uchar;
Pl.: enum lampa{piros,pirossarga,zold,sarga}
akt=zold; typedef egesz inttomb[100]; // tmb tpus
Pl.: enum {Zold,Tok,Makk,Piros}szin=makk; typedef double dtomb[33]; // tmb tpus
Pl.: enum irany{fel,le,jobbra,balra}; typedef struct{
Pl.: enum het{hetfo,kedd,szerda,csutortok=-1, char nev[100];
pentek}; double ertek;
Pl.: enum prim{ketto=2,harom,ot=5,tizenhet=17, } ember; // struktra tpus
tizenharom=13, k2=2}; typedef FILE * PFILE; // fjlpointer tpus
typedef double (*fvp)(double); // fggvnypointer tpus
Ha nem adunk meg rtket, a konstansok rtke egyesvel n,
az indulrtk pedig 0. A pldkban hetfo=0, kedd=1, szerda=2, egesz a=3;
csutortok=-1, pentek=0. Az enum konstansok azonostk, teht uchar c;
nem lehet pl. ilyen nev vltoz vagy msik konstans, mert a inttomb t1,t2; // 2 db 100 elem egszeket trol tmb
nevk tkzne. PFILE fp=fopen("szoveg.txt","wt");
Plda hasznlatra: rjunk fggvnyt, amely egy kzlekedsi fvp gyok=sqrt;
lmpt a kvetkez llapotba vlt (piros pirossrga, pirossrga double gyokketto=gyok(2);
zld, zld srga, srga piros). A lmpa llapott ember Peter,Pal;
enummal adjuk meg! strcpy(Peter.nev,"Peter");
Peter.ertek=3.5;
#include <stdio.h>
A pointerekrl, fggvnypointerekrl a 16. s 38. fejezetben
enum lampa {piros, pirossarga, zold, sarga};
beszlnk bvebben.
enum lampa valt(enum lampa be){
switch(be){ Gondolkozzunk egytt!
case piros: return pirossarga;
case pirossarga: return zold;
case zold: return sarga;
case sarga: return piros; Oldja meg egyedl!
}
}

Bitmez Struktra vagy union int vagy unsigned int tpus


tagvltozibl ltalunk megadott bitszm egsz rtkeket alakt-
hatunk, ezltal takarkosabb memriahasznlatot elrve. A meg-
adott bitszm nem lehet nagyobb, mint az adott rendszerben
hasznlhat int/unsigned mrete. Bvebben lsd a 32. fejezetben.

Pointer vagy mutat Egy adott tpus pointer hivatkozst


tartalmaz egy, a pointer tpusval megegyez tpus elemre.
(Azaz a pointer egy vltoz memriacmt tartalmazza.) A poin-
ter tpusa egyszer s szrmaztatott tpus is lehet. Bvebben lsd
a 16. fejezetben.

Fggvny A fggvnytpus meghatrozott tpus visszatrsi


rtk fggvnyt r le. A fggvnytpust a visszatrsi rtknek
tpusa, valamint a paramtereinek szma s tpusa rja le. A 28.
fejezetben, a fggvnypointerek kapcsn vilgosabb vlik majd
a fggvnytpus rtelme.

14.2 Sajt tpus ltrehozsa a tpusde-


finci

typedef tpuslers tpusazonost lista

Sajt tpusnevet a kvetkez mdon hozhatunk ltre:

48
15. Opertorok Logikai rtk mint egsz A logikai mveletek eredmnye
egsz szmknt hasznlhat. A logikai mvelet eredmnye 0, ha
HAMIS s 1, ha IGAZ. Pldul:
Ebben a fejezetben sszefoglaljuk a C nyelv opertorait, azaz
mveleti jeleit, elbb azonban rviden szlunk a logikai rtkek int a=(2>3),b=(2<3);
s az egsz szmok kapcsolatrl. Az opertorokat sszefoglal printf("%d,%d\n",a,b); // 0,1
rszben megismteljk a mr tanult opertorok legfontosabb
tulajdonsgait, gy az olvas ksbb mindent megtall egy he- Gyakran hasznlunk olyan fggvnyeket, melyek logikai r-
lyen. tket adnak vissza. Nzznk kt pldt ezek elksztsre! Az
els megvizsglja, hogy hrom vals szm lehet-e egy hromszg
15.1 Logikai rtkek s egsz szmok oldala:

int hszog(double a, double b, double c){


Egsz mint logikai rtk A C nyelvben az egsz szmoknak if(a>=b+c)return 0;
logikai jelentse van: ha a szm nem nulla, az IGAZ-at jelent, ha if(b>=a+c)return 0;
nulla, az HAMIS-at. Ez a tulajdonsg kihasznlhat logikai vizs- if(c>=a+b)return 0;
glatoknl. Pl.: return 1;
}
for(i=100; i>0; i--)...
if(hszog(3.0, 4.0, 5.0))printf("Lehet hromszg");
helyett azonos jelentssel rhat, hogy
A msodik eldnti a paramterknt tvett karakterrl, hogy
for(i=100; i; i--)... (1) bet-e:

Egy sztringet kirhatunk karakterenknt gy: int betu_e(char ch){


if(ch>='A' && ch<='Z')return 1;
char s[100]="Mndn egr szereti a sajtot"; if(ch>='a' && ch<='z')return 1;
for(i=0; s[i]!=0; i++)putchar(s[i]); return 0;
}
A felttelvizsglatban szerepl !=0 helyett rhatjuk, hogy '\0',
gy: char s[100]="Lenni, vagy nem lenni?";
int n,i;
for(i=n=0; s[i]!=0; i++)if(betu_e(s[i])n++;
for(i=0; s[i]!='\0'; i++)putchar(s[i]); printf("%d db bet volt a szvegben.\n",n);

A kt megolds egyenrtk, mindenki a neki szimpatikusat A betu_e fggvny csak az angol ABC betit vizsglja. Eg-
vlassza! sztsk ki gy, hogy a magyar betkkel is boldoguljon!
Viszont mivel a char is egsz tpus (akrcsak az enum vagy
a pointer), itt is hasznlhat a rvidebb felrs: A C nyelv szabvnyos knyvtrban megtalljuk azt a fgg-
vnyt, amely ellenrzi, hogy egy karakter bet-e. Ennek neve
for(i=0; s[i]; i++)putchar(s[i]); (2) isalpha. Hasznlata ugyanaz, mint a betu_e fggvny:

A logikai rtkeken alkalmazhat logikai mveletek egsze- for(i=n=0; s[i]!=0; i++)


ken is alkalmazhatk. Pldul if(isalpha(s[i])n++;

int a,b; Az isalpha mellett tovbbi karaktervizsgl fggvnyek is


... rendelkezsre llnak, ezek kzl a fontosabbak:
if(a==0 && b!=0)... isalnum: ha bet vagy szmjegy
isupper: ha nagybet
helyett islower: ha kisbet
isspace: ha whitespace karakter
if(!a && b)... Ezek a fggvnyek a ctype.h fejlc beptsvel vlnak elr-
hetv. Ugyancsak a ctype.h-ban tallhat kt tovbbi hasznos
is rhat. Ha a-ban 0 van, akkor az logikai HAMIS, amibl a ! fggvny, a toupper s a tolower. Mindkt fggvny egy karak-
opertor logikai IGAZ-at csinl, azaz !a akkor igaz, ha a==0. tert vr paramterknt, s visszatrsi rtkk ugyancsak egy
Az i>0 helyre teht rhat i, az s[i]!=0 helyre rhat s[i], az karakter: a tolower esetben, ha a bemen karakter nagybet volt,
a==0 helyre rhat !a s b!=0 helyre rhat b, akkor annak kisbet vltozatt adja vissza, minden ms esetben
azonban ezek hasznlatt mgis clszer ke- az eredeti karaktert kapjuk. A toupper esetben pedig a kisbett
rlni, mert a kdot nehezebben olvashatv cserli nagyra.
teszi. Azrt szerepel mgis ebben a knyvben, Pldul:
mert a C programoznak fel kell ismernie ms kdjban.
A pointerekrl csak a kvetkez fejezetben lesz sz, azonban char s[100]="Mndn egr szereti a sajtot";
ide kvnkozik, hogy pointerek esetn is gyakran hasznljk ezt a for(i=0; s[i]!=0; i++)
megoldst, melyet azonban pointereknl is clszer kerlni. Az putchar(toupper(s[i]));
if(!fp) helyett teht rjunk if(fp!=NULL)-t, az if(p) helyett
if(p!=NULL)-t, mert gy sokkal olvashatbb a kd. A NULL
konstans nevt is rjuk ki, ne hasznljunk helyette 0-t, ugyancsak 15.2 A C nyelv opertorai
ttekinthetsgi okbl!
Az opertorokat kifejezsekben hasznljuk.
Egy opertor jellemzi:

49
Milyen OPERANDUSAI vannak Opertor Funkci Plda
o hny darab ==, != logikai mveletek if(3!=2)puts("OK");
& bitenknti S (AND) if((x&1)==0)puts("Pros");
o milyen tpus ^ bitenknti KIZR VAGY (XOR) if((a^a)!=0)puts("o_o");
Milyen az eredmny tpusa/rtkkszlete | bitenknti VAGY (OR) a=a|1;
o mint az operandusok && logikai S if(ch>='a' && ch<='z')
o eltr tpus (pl. relcis opertorok) || logikai VAGY if(ch=='N' || ch=='n')
Operandusok kirtkelsi sorrendje ?: feltteles opertor max=a>b?a:b;
=, +=, -=,
asszociativits (csoportosthatsg, pl.: (a+b)+c *=, /=,
a+(b+c) ugyanaz (br szmtsi pontossg miatt itt is le- %=,
rtkad opertorok a=3; b+=c; a|=1; x<<=1;
het gond, pl. ha b s c egyforma, a pedig hozzjuk kpest &=, ^=,
nagyon kicsi). |=, <<=,
>>=
F HATS: milyen rtket szolgltat a kifejezs a kir- , vessz opertor c=(a=d, j=0, x);
tkels utn? * 1 bjt nem biztos, hogy 8 bit!
Van-e egyb hatsa a mveletnek MELLKHATS
Mi a viszonya a tbbi opertorhoz egy sszetett kifeje- A mvelet tpusa Ha egy ktoperandus opertort eltr
zsben PRECEDENCIA tpus adatokon alkalmazunk, akkor a pontatlanabb tpus rtk
A mvelet elvgzse sorn trtnik-e valamilyen automa- pontosabb tpusv konvertldik, s a mvelet eredmnye is
tikus tpuskonverzi? pontosabb tpus lesz. Brmelyik lebegpontos tpus pontosabb-
Pldul az rtkads mvelete: nak szmt brmelyik egsz tpusnl.
a=b Pldul 3/2 eredmnye 1, mert kt egsz osztsi eredmnye is
ez gy nem utasts, hanem egy ktoperandus mvelet egsz, viszont 3.0/2, vagy 3/2.0 eredmnye 1.5, mert az egyik
eredmnye lesz rtke lesz teht ez egy kifejezs operandus double tpus.
ltalnosan: balrtk = jobbrtk (lvalue = rvalue)
o Mi lehet jobbrtk? Brmi, aminek rtke van. Precedencia (kirtkelsi sorrend) A mveletek rangja,
o Mi lehet balrtk? Brmi, aminek rtk adhat (rhat erssge. A fenti tblzat egy rcsban tallhat mveletek
adatterletet cmez). Pl. vltoz, pointer kifejezs egyforma precedencijak. (Akkor is, ha tbb sorba vannak
Az rtkad opertor mkdse: rva!) Matematikbl jl ismerjk a dolgot.
rvalue kirtkelse
lvalue kirtkelse A kirtkels irnya ltalban balrl jobbra, kivve az egy-
operandus mveletek, tovbb az rtkadsok s a feltteles
az lvalue=rvalue kifejezs rtke a kirtkelt rvalue rt-
opertor.
ke lesz ez a F HATS
MELLKHATSKNT rvalue rtke az lvalue ltal
Pldk a precedencia s kirtkelsi irny rtelmezsre
cmzett adatterletre msoldik.
Kvetkezmny: a=b=c=1 esetn a kirtkels a fenti a*=b=c+d-e*f+g;
szablyok szerint c=1 kirtkelse utn mr is szolgl-
hat rvalue-knt s gy tovbb. Sorrend:
e*f
Az opertorok tbbsge nem hasznlhat sszetett adattpu- c+d
sokon (tmb, struktra, union), de az ezekben trolt egyszer (c+d)-(e*f)
tpus vltozkon igen. Pldul: ((c+d)-(e*f))+g
b=(((c+d)-(e*f))+g)
int t1[100],t2[100],t3[100],i; a*=(b=(((c+d)-(e*f))+g))
(a*=(b=(((c+d)-(e*f))+g)))
t1=t2; // HIBS
t3=t1+t2; // HIBS
Legmagasabb precedencija a szorzsnak van a kifeje-
for(i=0;i<100;i++)t1[i]=t2[i]; // HELYES
zsben, ezrt ez hajtdik vgre elszr.
for(i=0;i<100;i++)
Az additv mveletek (sszeads, kivons) egyforma
t1[i]=t2[i]+t3[i]; // HELYES
precedencijak, k kvetkeznek. Kzttk a kirtkels
irnya dnt, ami balrl jobbra trtnik. Elszr c+d, majd
A C nyelv opertorait sszegz tblzat:
ehhez addik a szorzat, vgl g is.
Opertor Funkci Plda Az rtkadsok maradtak. Ezek jobbrl balra rtkeld-
++, -- vltoz nvelse/cskkentse 1-gyel(post) i++, j nek ki, ezrt elbb b-be kerl a kiszmolt eredmny, majd
[] tmb indexelse t[i]=9; a szorzdik ezzel, s kerl a-ba.
zrjelezs, fggvnyhvs
()
. struktratag elrse
printf("Hello wilg\n"); Vgl azrt kerlt zrjelbe az egsz, mert ennek is van
ember.sorszam=3;
-> pointerrel mutatott struktra tagjnak if(gyoker->bal==NULL)
rtke.
elrse
sizeof tpus vagy vltoz mrete bjtban* sizeof(double) if(!-*p)puts("WoW");
++, -- vltoz nvelse/cskkentse 1-gyel(pre) ++i, --j
& vltoz cme scanf("%c",&ch);
* pointer ltal mutatott vltoz *p=3; Egyoperandus kifejezsek: jobbrl balra.
+, - eljel *p=+3; n=-5;
~ bitenknti negls a=~b; Sorrend:
! logikai NEM if(!(a>b))puts("a<=b"); *p
(tpus) tpuskonverzis opertor int x=(int)3.14;
-(*p)
*, /, % szorzs, oszts, maradkkpzs x=(y*2/3)%5;
+, - sszeads, kivons a=b+c-d;
!( -(*p))
<<, >> biteltols if(1<<4==16)puts("OK"); (!( -(*p)))
<, <=, >,
logikai mveletek if(3>2)puts("OK");
>= p egy pointer, *p az ltala mutatott rtk.

50
vesszk a -1-szerest a-t konvertlja t, mivel a tpuskonverzis opertor
logikai negls: ha 0 volt, akkor IGAZ lesz belle, ha precedencija magasabb, mint az oszts opertor.
nem 0 volt, akkor HAMIS lesz belle maradkkpzs (%): kizrlag nemnegatv egszeken r-
telmezett, s a kt operandusnak osztsi maradkt adja.
while(*p++);
Kt szm akkor oszthat egymssal, ha osztsi marad-
A p pointer kezdetben egy sztring elejre mutat, keressk a kuk 0, azaz a%b==0.
sztringet lezr 0-t. Mivel ++ posztinkremens, ennek a legna- x=(a+b)/c*d s x=(a+b)/(c*d) nem ugyanazt jelenti, hi-
gyobb a precedencija. szen a multiplikatv opertorok percedencija azonos, az
els kifejezs teht gy is rhat: x=((a+b)/c)*d
Sorrend:
p++ Logikai opertorok &&, ||, !
*(p++) A logikai opertorok igazsgtblzatai:
(*(p++)) A B A&&B A B A||B
HAMIS HAMIS HAMIS HAMIS HAMIS HAMIS A !A
IGAZ HAMIS HAMIS IGAZ HAMIS IGAZ HAMIS IGAZ
p++ utlag nveli meg a p pointer rtkt, azaz a *p++ HAMIS IGAZ HAMIS HAMIS IGAZ IGAZ IGAZ HAMIS
mg az eredeti p ltal mutatott rtket adja. IGAZ IGAZ IGAZ IGAZ IGAZ IGAZ TAGADS
Ha vget rt a ciklus, akkor p a lezr 0 utni karakterre S VAGY
mutat, mert az utols ++ mg megtrtnik. De Morgan azonossgok: !A&&!B == !(A||B), ill.
A mveletek teht a kvetkezk: !A||!B == !(A&&B). Ellenrizze!
o p++ jelzi, hogy p pointer rtkt majd ksbb meg A ill. B a leggyakrabban valamely sszehasonlt oper-
kell nvelni. torral (==, !=, <, <=, >, >=) megadott kifejezs.
o vesszk a p ltal mutatott rtket A C nyelvben az egsz szmok logikai rtkknt kezelhe-
o ha ez 0, akkor a ciklus vget r, ha nem 0, akkor is- tk: 0==HAMIS, 1==IGAZ. Pl.: 1&&3 IGAZ, 0&&3
mtldik a ciklus, mindkt esetben vgrehajtdik a HAMIS, 0||3 IGAZ, 0||0 HAMIS, !0 IGAZ, !-1 HAMIS.
kvetkez mvelet: A C nyelvben a logikai mveletek eredmnye egsz
o p rtke megn eggyel szmknt kezelhet. A logikai mvelet mindig 0-t vagy 1-
A ciklus magjban res utasts ll. et ad. Pl.
int x;
Mellkhatsok kirtkelse A C szabvny nem definilja a x=3>1; x==1
mellkhatsok kirtkelsi sorrendjt, ezrt soha x=3<1; x==0
ne alkalmazzunk ktrtelm kifejezst! Pldul x=3&&1; x==1
az x=i++ + i; kifejezs rtke nem definilt,
fordtfgg, nem tudhatjuk, hogy a msodik i Mit r ki?
mr megnvelt, vagy mg az eredeti! int a=3,b=6;
A ++, --, rtkadsok, () fggvnyhvs opertoroknak van printf("%d\t%d\t%d\t%d\n",a&&b,a||b,!a,!!a);
mellkhatsa.
Az && s a || opertor rvidzr tulajdonsggal br. Ez
Lptet opertorok ++, -- azt jelenti, hogy ha az opertor bal oldaln
Egsz tpus vltozkon (ide rtve a pointert is) hasznlhat, ll kifejezsbl egyrtelm, hogy mi a
a vltoz rtkt nveli illetve cskkenti eggyel. Kt vltozata logikai rtk, akkor a jobb oldal nem rt-
van: a preinkremens / predekremens s a posztinkremens / keldik ki. SOHA NE LEGYENEK
posztdekremens. MELLKAHTSSAL BR SSZETETT KIFEJE-
1. Pre: ++a ill. --b. ZSEK AZ OPERANDUSOK!!
Pl.: int a=7,b=3, c; c=++a; Az utasts lefutsa utn a o A||B esetn ha A==IGAZ, nem szmt B rtke, az
s c rtke egyarnt 8 lesz, mert a nvels a (++a) rtk- eredmny IGAZ.
nek felhasznlsa eltt trtnik. o A&&B esetn ha A==HAMIS, nem szmt B rtke,
2. Poszt: a++ ill. b--. az eredmny HAMIS.
Pl.: int a=7,b=3, c; c=a++; Az utasts lefutsa utn a o Pl.: if((x=a/2)&&(y=b/2) utastsban ha a rtke 0,
rtke 8, c rtke 7 lesz, mert a nvels az (a++) rtk- akkor y-ba nem kerl bele b/2.
nek felhasznlsa utn trtnik. o Hasznos pl.: if(a!=0 && b/a>3), vagy if(p!=NULL
&& p->ertek<7.1) esetben.
Multiplikatv opertorok *, /, % A rvidzr tulajdonsg miatt az && ill. || opertorok kir-
szorzs (*): semmi klns tkelsi pontot (sequence point) is jelentenek, lsd k-
oszts (/): figyelni kell arra, hogy ha mindkt operandusa sbb!
egsz tpus, akkor az eredmny is egsz tpus lesz.
Bitmveletek &, |, ^, ~, <<, >>
Pldul double d=4/5; eredmnyekpp d rtke 0.0! Egsz tpus rtkeken rtelmezettek, a szmok kettes szm-
Ugyanis 4 s 5 egsz (ha itt egsz tpus vltoz lenne, rendszerbeli alakjval dolgozunk.
ugyanez volna a helyzet), az oszts eredmnye egsz, az- A bitenknti logikai opertorok igazsgtblzatai:
az 0. Ezt kveten az = opertor automatikus tpuskon- A B A&B A B A|B A B A^B
verzival a 0 egsz szmbl 0.0 double rtket hoz ltre. 0 0 0 0 0 0 0 0 0 A ~A
1 0 0 1 0 1 1 0 1 0 1
Helyesen gy rhattuk volna: double d=4.0/5.0;, illetve
0 1 0 0 1 1 0 1 1 1 0
elg, ha az egyik operandus vals, pl.: double d=4.0/5;. 1 1 1 1 1 1 1 1 0 NEGLS
Ha nem konstansokat hasznlunk, akkor explicit tpus- S VAGY KIZR VAGY
konverzi szksges: int a=4, b=5; double A bitenknti opertorok a szmok azonos helyirtk
d=(double)a/b;. Itt a (double) tpuskonverzis opertor az bitjei kztt mkdnek, a szmok minden egyes bitjre.

51
o Pl.: 11&7 001011 & 000111 = 000011 3, azaz o ||, &&: ((k=i++) || (j=-i)) k-ba i eredeti rtke ke-
11&7==3. rl mindenkpp. Ha i eredeti rtke 0, akkor j-be -1
o Pl.: 11|7 001011 | 000111 = 001111 15, azaz kerl, mert a ++ nvels a bal oldal kirtkelse utn,
11|7==15. a jobb oldal kirtkelse eltt trtnik. Ha i eredeti r-
o Pl.: 11^7 001011 ^ 000111 = 001100 12, azaz tke nem 0, akkor biztos, hogy a || mvelet eredm-
11^7==12. nye IGAZ, teht a rvidzr miatt a j=-i kifejezs nem
o Pl.: ~7 ~ 000111 = 111000 -8, azaz ~7==-8. rtkeldik ki, azaz j rtke nem vltozik.
(Eljel nlkli egsznl a tpus bitszmtl fgg a o ?: : x= i++ ? i+1 :i-1; a felttel IGAZ vagy HA-
vgeredmny, mert a szm elejn minden 0-bl 1 MIS volta i eredeti rtke alapjn dl el, i rtke ez-
lesz.) utn megn, s a kifejezs rtke a meghatrozott fel-
A kvetkez azonossg mindig igaz: ttelnek megfelelen i+1-et vagy i-1-et ad vissza. Ha
(A|B)==(A&B)+(A^B). i kezdetben 0, akkor x-be 0 kerl, egyb esetben pe-
A bitenknti opertorok precedencija ki- dig az eredeti i+2.
sebb az sszehasonlt opertoroknl,
emiatt az if(x&y==3) felttel jelentse:
if(x&(y==3)), nem pedig if((x&y)==3)!! Gondolkozzunk egytt!
Biteltols (shiftels) opertorok:
o A >> balra tolja a szmot, egy bittel val eltols 2-vel
val osztsnak felel meg. Pl.: 19>>2==4. Ha a szm
eljel nlkli, vagy eljeles, de nem negatv, akkor 0 Oldja meg egyedl!
bitek lpnek be balrl, a jobb oldalon kies bitek el-
vesznek. Ha a szm negatv, 1-es bitek lpnek be bal-
rl.
o A << jobbra tolja a szmot, egy bittel val eltols 2-
vel val szorzsnak felel meg. Pl.: 19<<2==76. 0 bi-
tek lpnek be jobbrl, a bal oldalon kies bitek el-
vesznek.
o Az egyik oldalon kies bitek nem jnnek vissza a m-
sik oldalon.
o x<<y mvelet nem vltoztatja meg x rtkt. Ha vl-
tozst akarunk, pl. gy kell: x<<=y.

Mit r ki?
int a=3,b=6;
printf("%d\t%d\t%d\t%d\n",a&b,a|b,a^b,~a);

Feltteles opertor ?:
Kt rszbl ll, hrom operandusa van: felttel-kifejezs ?
igaz-kifejezs : hamis-kifejezs
Ha a felttel IGAZ, az opertor igaz-kifejezs rtkt adja
vissza, ha HAMIS, hamis-kifejezs rtkt.
Az if(a>b)c=a; else c=b; utasts gy rhat egyszerbben:
c=a>b?a:b;.

Vessz opertor A vesszt (,) ltalban nem opertorknt


hasznljuk, pldul a vltozdefincinl (int x,y;) nem opertor,
a fggvnyhvsnl (fgets(s,100,fp);) nem opertor, ezekben az
esetekben nem garantlt a balrl jobbra kirtkels, s nem is
kirtkelsi pont a vessz.
Leggyakrabban a for ciklus fejben hasznljuk opertorknt:

for(i=0, j=1; i<n; i++, j<<=1)


printf("2 %u. hatvnya=%u\n,i,j);.

A vessz a legkisebb precedencij opertor, mg az rtk-


adsnl is kisebb. Mint minden opertornak, ennek is van rtke:
a jobb oldali kifejezs rtke. Pl.: x=(3,4); x-be 4 kerl. Pl.:
x=(i=0,j=1); itt x-be 1 kerl. A vessz opertor kirtkelsi pont.

Kirtkelsi pont (sequence point) Mikor kerlnek kirtke-


lsre a kifejezsek?
Utasts vgn: a ;-nl vagy }-nl.
Fggvnyhvs eltt az sszes paramter kirtkeldik.
if, while, switch () kztt.
Nhny opertornl megtrtnik a kirtkels, azaz ezek
hasznlatakor garantlt a mellkhatsok megtrtnte az
opertor kirtkelse kzben:
o vessz: (i=j+2,k=i) k-ba garantltan j+2 kerl.

52
16. Pointerek egy konstans, ha hasznlni szeretnnk, a programba be kell szer-
keszteni valamelyik szabvnyos fejlcfjlt (pl. stdio.h, stdlib.h).

16.1 A szmtgp memrija Fggvnypointer: egy fggvny els utastsnak cmre


mutat. Ksbb bvebben is foglalkozunk vele. Ha nem hangs-
UT (jmp) lyozzuk, akkor a tovbbiakban adatpointerekrl lesz sz.

Rendszerterlet Vltoz memriacme: A fenti brn lthatjuk, hogy minden


adat van valahol a memriban. A vltoz nevbl a cmkpz
(&) opertorral kaphatjuk meg a vltoz cmt:

UT UT UT UT UT UT UT UT int x,*p;
UT UT UT UT UT p=&x;
AD AD AD AD AD AD AD AD AD AD
AD AD
Pointer ltal mutatott rtk: Indirekci opertorral kapjuk.
UT UT UT UT AD AD AD Ha p a pointer *p az ltala mutatott rtket jelenti.
Rendszerterlet
int n,*p;
p=&n;
A memrit tekintsk egy egydimenzis tmbnek, melynek // Az albbi kt rtkads ugyanaz
az egyes bjtjait a MEMRIA[i] mdon indexelve rhetjk el n=8;
(nincs ilyen tmb a C-ben, a pointerek azonban pontosan gy *p=8;
viselkednek).
A fenti bra abban segt, hogy el tudjuk kpzelni egy szm- Kezdrtk pointernek: int n,*p=&n;. Itt ltszlag a
tgp memrijnak tartalmt. Korbban mr lttunk gpi kdot, pointer ltal mutatott rtk kap rtket, de nem ez a helyzet: a
ez alapjn nem nehz felismerni az utastsokat reprezentl UT pointernek gy adhatunk kezdrtket, amikor definiljuk.
cellkat. Az AD cellk adatokat (vltozk, konstansok) jelente-
nek. A Rendszerterlet lehet egyrszt az opercis rendszer ada- Tmb s pointer: Egy tmb neve az index opertor ([]) nl-
tait s utastsait trol memriarsz, msrszt a rendes memria kl egy pointer a tmb els (azaz 0 index) elemre.
cmtartomnyban ms, memria jelleg perifrik is megjelen- int t[100],*p;
hetnek, gy pldul a videokrtya memrija kzvetlenl cmez- // Az albbi kt rtkads ugyanaz
het ebben a cmtartomnyban, pedig az valjban a videokr- p=t;
tyn tallhat. (Ez az oka annak, hogy 32 bites Windows alatt p=&t[0];
max. 3 GB memrit lt az opercis rendszer, a maradk 1 GB a // Az albbi kt rtkads ugyanaz
videokrtya memrijnak cmtartomnya). p=t+5;
A memriatrkp egy-egy cellja egy-egy bjtot reprezentl, p=&t[5];
br a valsgban ltalban sokkal tbb utasts vagy adat tallha-
t egytt. Lthat, hogy nincs minden terleten adat vagy utas- Pointer mint tmb: Pointerre alkalmazva az index opertort
ts, ezekkel a terletekkel rszben a programunk, rszben az tmbknt kezelhetjk a mutatott memrit. Fontos: ha olyan
opercis rendszer gazdlkodik. Pldul dinamikus memriafog- memrit akarunk hasznlni, ahol nincs tnylegesen adat, futs-
lals esetn az opercis rendszer ebbl ad annyi bjtot, amennyit idej programhibt kapunk. Az ilyen hibk feldertse nem kny-
krnk tle (mr persze ha rendelkezsre ll a kvnt mennyi- ny.
sg). int t[100],*p=t,n;
A memria elejn gyakran ROM tallhat, ahol az els utas-
ts ltalban egy ugrs a rendszerindt programra. // Az albbi kt rtkads ugyanaz

t[6]=9;
16. 2 A pointer p[6]=9;

Memriacm egy egsz szm, amely kijelli a memria va- // Az albbi kt rtkads ugyanaz
lahnyadik bjtjt.
p=t+5;
Pointer (mutat) olyan vltoz, amelyik memriacmet tar- p=&t[5];
talmaz.
// Az albbi kt rtkads ugyanaz
Pointer tpusa: amilyen tpus adatra vagy fggvnyre mutat // (p a tmb 5-s index elemre mutat)
a pointer.
t[6]=9;
Pointer ltrehozsa az indirekci opertorral (*) trtnik. p[1]=9;

int-re mutat tpusos pointer: int * p; // egy int cmt kapja


A * brhov rhat: int* p; int *p; int*p;
p=&n;
Tpus nlkli pointer: void * p; (ejtsd: void csillag).
// Az albbi hrom rtkads ugyanaz
NULL pointer: a memria 0. bjtjra mutat. A memria 0.
bjtja nem tartozik a programhoz, ezrt ott nem tallhat a prog- n=8;
ram kdja vagy adata. Egy pointer rtkt akkor lltjuk NULL- *p=8;
ra, ha jelezni akarjuk, hogy a pointer nincs belltva. A NULL p[0]=8;

53
// A kvetkez rtkads hibs: Gondolkozzunk egytt!

p[1]=8; // HIBS! p 1 db int rtkre


// mutat, az utna kvetkez
// memriahely mr ms adatot Oldja meg egyedl!
// vagy utastst tartalmaz,
// valamit fllrunk, mit nem
// lenne szabad.

Tbb pointer definilsa: Tipikus hiba: int* a,b;


Itt csak a lesz pointer, b egy int tpus vltoz. Helyesen gy
kellett volna megadni:
int *a,*b; // Persze az int* a,*b; is
// helyes, csak becsaps.
Termszetesen ez a megolds is hasznlhat:
typedef int * pint;
pint a,b;

16.3 Pointeraritmetika
Mivel a pointerek eljel nlkli egsz szmokat trolnak (a
memriacmet), logikus, hogy matematikai mveleteket is lehes-
sen vgezni ezekkel. A pointerek sajtossgai miatt azonban csak
nhny ilyen mvelet megengedett.
Pointer s egsz szm sszeadsa vagy kivonsa:
int t[20],*p=t+10;
*(p-2)=6; // azaz t[8]=6;
*(p+3)=6; // azaz t[13]=6;
FONTOS! A pointerhez adott egsz
szm nem kzvetlenl addik a poin-
terben trolt memriacmhez, hanem
gy, hogy a pointert tmbcmnek tekintve
az egsz szmban meghatrozott index
tmbelem cmt kapjuk. Pl.:
int t[20],*p=t+10;
printf("p=%u, p+1=%u,p+2=%u\n",p,p+1
,p+2);
A kirs eredmnye adott gpen (a konkrt szmok
mindenkinl msok lehetnek): p=1244792, p+1=1244796,
p+2=1244800. Azaz a memriacm az int bjtban kifeje-
zett mretvel ntt (int* pointerrl van sz), jelen esetben
4-gyel, mikzben 1-gyel ntt a pointerhez adott egsz
szm.
Pointer nvelse vagy cskkentse ++ ill. opertorral.
int t[20],*p,i;
// A kvetkez kt sor ugyanazt teszi
for(p=t;p<t+20;p++)*p=0;
for(i=0;i<20;i++)t[i]=0;
A kt megolds kzl a tmbset (azaz a msodikat)
ajnlott hasznlni, mert
1) ez ttekinthetbb kdot eredmnyez
2) A fordt jobban tudja optimalizlni, hatkonyabb k-
dot kszt.
Kt pointer klnbsge
int t[20],*p,*q;
p=t+3, q=t+17;
printf("q-p==%d, t-p=%d\n",q-p,t-p);
Eredmny: q-p==14, t-p=-3

54
17. rtk s cm szerinti paramter- A fggvnyben a s b helyett mindenhol *a ill. *b szere-
pel. Ugyanis most a s b mr nem int tpus vltozk, ha-
tads; tmbk, pointerek s nem int-re mutat pointerek, az ltaluk cmzett vltozt
pedig az indirekci opertor segtsgvel rhetjk el.
fggvnyek A csere fggvny hvsa megvltozott: csere(a,b) helyre
csere(&a,&b) kerlt. Az & cmkpz opertor a kt vl-
toz cmt adja. Ne felejtsk odarni, ellenkez esetben az
17.1 Paramtertads a pointerbe 2, a b pointerbe pedig 5 kerl, s a csere
fggvny a memria 2. s 5. bjtjn lv int tpusnak te-
Mit r ki az albbi program? kintett (amgy ki tudja, hogy valjban mi van ott, adat
egyltaln, vagy utasts) rtket prblja megvltoztatni.
#include <stdio.h> Ez valsznleg nem fog sikerlni neki, s elszll a prog-
ramunk.
void csere(int a,int b){
int c=a; A C-ben gy valsthat meg a cm szerinti paramtert-
a=b; ads.
b=c; Vegyk szre, hogy a scanf fggvnybe pon-
} tosan a cm szerinti paramtertads miatt kell &
jelet rni a vltozk neve el, hiszen a scanf meg-
int main(void){ vltoztatja a vltozk rtkt. Ha sztringet olva-
int x=2,y=5; sunk be, akkor nem rjuk oda az & jelet, mert a sztringet trol
csere(x,y); karaktertmb neve a szgletes zrjelek nlkl a tmb kezdele-
printf("x=%d, y=%d\n",x,y); mnek cmt jelenti, teht abban az esetben mr eleve rendelke-
return 0; zsre ll a cm. Azonban a kvetkez mdon
} visszacsempszhetjk az & jelet:

Azt rja ki, hogy x=2, y=5. Mirt, hiszen a csere fggvny char s[100];
megcserli az rtkeket, nem? scanf("%s",s);
Nem. Emlkezznk vissza, mit mondtunk a fggvnyek pa-
ramtereirl! A paramterknt definilt vltozk (a,b) mindssze helyett rhatjuk:
abban klnbznek az egyszer vltozktl (c,x,y), hogy kezd-
rtkknt kapjk azt az rtket, amivel a fggvnyt meghvjuk. scanf("%s",&s[0]);
Vagyis a-ba bekerl 2, b-be pedig 5. A fggvny helyesen mk-
dik, s valban felcserli a s b rtkt, azonban ez semmi mdon Utbbit a gyakorlatban nem hasznljuk, csak rdekessgkp-
nem hat vissza x-re s y-ra. pen kerlt ide.
Ezt gy mondjuk, hogy a C nyelvben rtk szerinti param-
tertads trtnik. rjon fggvnyt, mely paramterknt veszi t egy kocka vals
Tudunk-e rni mgis olyan fggvnyt, amely felcserl kt r- tpus rtkkel megadott lhosszsgt, s paramtersoron
tket? visszaadja a kocka fellett s trfogatt!
Igen, most, hogy tanultuk a pointereket, mr tudunk. Ha
ugyanis a fggvny nem a vltozt, hanem annak cmt kapja Tipp: a fellet s a trfogat paramtersoros adand vissza, nem
paramterknt, akkor a cm msoldik be a a paramterknt pedig visszatrsi rtkknt (azaz returnnel), teht a fggvny-
definilt pointer vltozba, a cm pedig tovbbra is az eredeti nek hrom paramtere lesz, egy double rtk az lhossznak, s
vltozra mutat. Igaz, hogy az eredeti vltoz a hv fggvny- kt double tpus pointer: a felletnek s a trfogatnak.
ben van, de ez minket egyltaln nem zavar, jogunk van megvl-
toztatni annak rtkt. Pointer rtknek megvltoztatsa fggvnyben Mi a hely-
Nzzk a mdostott programot! zet akkor, ha egy pointert kell visszaadnunk paramtersoron?
Ekkor pointerre mutat pointert kap a fggvnynk.
#include <stdio.h> rjunk fggvnyt, mely paramterknt kap egy egszekbl l-
l tmbt s egy egsz rtket, s logikai IGAZ vagy HAMIS
void csere(int * a,int * b){ rtket ad vissza attl fggen, hogy megtallhat-e a tmbben az
int c=*a; egsz rtk. Adja vissza paramtersoron a megtallt elem cmt,
*a=*b; vagy ha nincs a tmbben, NULL pointert!
*b=c;
} #include <stdio.h>
int main(void){ int keres(int t[],int n,int mit,int **p){
int x=2,y=5; int i;
csere(&x,&y); for(i=0; i<n; i++)
printf("x=%d, y=%d\n",x,y); if(t[i]==mit){
return 0; *p=t+i; // vagy &t[i]
} return 1; // IGAZ
}
Ez mr valban felcserli x s y rtkt, azaz x=5, y=2 rdik *p=NULL;
ki. return 0; // HAMIS
Figyeljk meg a vltozsokat: }
A fggvny fejbe int * a s int * b kerlt, azaz a fgg-
vny pointereket vesz t, a s b pedig int-re mutat poin- int main(void){
ter. int tomb[]={3,6,3,5,2,3,0,6,-5,92};

55
int *cim; int c,t[3];
int mit=-1; return a; // Ez rendben van, a egy
scanf("%d",&mit); // kls vltozra mutat
if(keres(tomb,10,mit,&cim)) return &b; // TILOS!
printf("Megvan, t[%d]==%d\n" return &c; // TILOS!
,cim-tomb,*cim); return t; // TILOS!
else printf("Nincs meg.\n"); return t+2; // TILOS!
return 0; return &t[2]; // TILOS!
} }

Megjegyzs: a feladat megoldsa csak a keres fggvny. A int main(void){


#include-ot s a main-t csak a jobb rthetsg rdekben rtuk int x,*p;
ide. p=mitilos(&x,3);
Az int ** p egy egszekre mutat pointerre mutat pointer. A *p=3; // Emiatt tilos, ami tilos.
pointert ebbl *p mdon nyerhetjk ki, **p-vel pedig az egsz return 0;
rtket. }
A keres meghvsa utn cim-be kerl a megtallt elem cme.
A cim-tomb adja a megtallt elem indext, de csak akkor, ha a Termszetesen a a fggvnyben lv return-k kzl csak az
cm a tomb valamelyik elemre mutat (ha keres IGAZ rtket ad els fog lefutni, a tbbi nem, mivel a return azonnali kiugrst
vissza, akkor ez a helyzet). eredmnyez a fggvnybl.
Ha a feladat gy szlt volna, hogy visszatrsi rtkknt adja A fenti program szintaktiakilag helyes, mg a TILOS! sorok
a megtallt elem cmt, vagy ha nincs meg, NULL-t adjon, vala- is jk, hiszen pl. a return &c; visszaadja a c vltoz cmt, ami
mivel egyszerbb megoldst kapunk: egy egsz szm. A program akkor vlik hibss, ha a megsemmi-
slt vltozbl akarunk olvasni, vagy rni akarjuk, azaz *p-t vagy
#include <stdio.h> p[i]-t runk. Mrpedig nehz lenne elkpzelni olyan letszer
esetet, amikor a fggvny pointert ad vissza, de a mutatott cmen
int * keres2(int t[],int n, int mit){ lv vltozhoz nem akarunk hozzfrni.
int i;
for(i=0; i<n; i++)
if(t[i]==mit)
17.2 Tmbk tadsa fggvnynek
return t+i; // vagy &t[i]
return NULL; Annak, hogy a tmb szgletes zrjelek nlkli neve a tmb
} kezdelemnek cmt jelenti, lett egy rdekes kvetkezmnye: a
tmbk cm szerint kerlnek tadsra a fggvnyeknek.
int main(void){ rjunk fggvnyt, amely paramterknt kap egy tmbt, s
int tomb[]={3,6,3,5,2,3,0,6,-5,92}; visszaadja a tmb elemeinek sszegt!
int *cim;
int mit=-1; #include <stdio.h>
scanf("%d",&mit);
if(cim=keres2(tomb,10,mit)) double osszegzo(double t[],unsigned n){
printf("Megvan, t[%d]==%d\n" double sum=0.0;
,cim-tomb,*cim); unsigned i;
else printf("Nincs meg.\n"); for(i=0;i<n;i++)sum+=t[i];
return 0; return sum;
} }

A fenti programban igyekeztnk rossz pldt mutatni, mg- int main(void){


hozz a main fggvny if-jnek fejben. A kultrlt, br mg double tomb[5]={9.1,-1.3,6,.1,-4};
mindig sszetett megolds ez lett volna: double ossz=osszegzo(tomb,5);
printf("ossz=%g\n",ossz);
if((cim=keres2(tomb,10,mit))!=NULL) return 0;
}
A cim-be bekerl a visszaadott pointer, majd ellenrizzk, A megoldsban azt ltjuk, hogy a paramterknt kap egy
hogy ez NULL-e. A pointer egy egsz szm, a NULL pointer tmbt utastst gy rtelmeztk, hogy a tmb mellett az elem-
pedig a 0 szmnak felel meg, ami logikai HAMIS, ezrt mkdik szmot is tadjuk. Ez szksges, hiszen ms mdon nem tudjuk
jl az els vltozat is. kiderteni, hny elem a tmb. rhattunk volna olyan fggvnyt,
amely csak az 5 elem tmbkre mkdik, akkor nem kellett
Pointert visszaad fggvny Ahogy a pldban lttuk, a volna az elemszm, de a feladat nem ezt rta el.
fggvny pointert is vissza tud adni. Nagyon A paramtersoron ezt ltjuk: double t[]. A tmbknl azt be-
fontos tudnunk azonban, hogy egy fggvnyben szltk, hogy tilos mret nlkli tmbt definilni, itt viszont
a vltozk megsemmislnek, amikor a fgg- pont ezt ltjuk. A dolgot ktflekppen is meg lehet magyarzni:
vny futsa befejezdtt: a hely felszabadul, a 1. A fggvnyparamterek kezdrtkknt kapjk azt az r-
rendszer ms vltozkat tehet ide. Ez azrt fontos, tket, amivel meghvtuk a fggvnyt, s itt is errl van
mert TILOS A FGGVNY LOKLIS VLTOZJNAK sz. Mrpedig a tmbknl is lttunk olyat, hogy nem ad-
CMT VISSZAADNI. tunk mretet, mert adtunk kezdrtket, s a fordt meg-
szmolta az elemek szmt, ez alapjn hozta ltre a tm-
#include <stdio.h> bt. Ez a magyarzat azonban tves, itt ugyanis nem
jn ltre j tmb a megadott mrettel. Lssuk az igazi
int * mitilos(int *a,int b){ magyarzatot:

56
2. A double t[]; definci pointert hoz ltre. Rgen a C for(i=0;i<3;i++)
nyelvben valban lehetett gy pointert ltrehozni a para- be.k[i]/=hossz;
mterlistn kvl is, de ppen a flrevezet jellsmd return be;
miatt a legtbb fordt ezt a formtumot mr nem enged- }
lyezi. A t teht egy pointer, amely a tmb
els elemre mutat, s a pointereknl lt- int main(void){
tuk, hogy a pointerek mg indexet rva koordinata x={6.0, 3.1, 4.5}, y;
tmbknt hasznlhatk. Az sszegez int i;
fggvnyt rhattuk volna gy is, teljesen ugyanazt jelenti:
y=normal(x);
double osszegzo(double * t,unsigned n){ for(i=0; i<3; i++)
double sum=0.0; printf("x[%d]=%10g, y[%d]=%10g\n"
unsigned i; ,i,x.k[i],i,y.k[i]);
for(i=0;i<n;i++)sum+=t[i]; return 0;
return sum; }
}
17.3 Tmb s pointer jra
A kt megolds kzl brmelyiket vlaszthatjuk, de javasolt
az indexes megolds, mert azon jobban ltszik, hogy tmbt
A tmbk s pointerek kapcsolatrl sokat beszltnk mr,
adunk t, nem egy-egy elemet.
nhny tovbbi dologra hvnnk fel a figyelmet:
Mivel a tmb cmt adjuk t, az elemeirl nem kszl mso-
lat. Ha teht megvltoztatjuk egy paramterknt kapott tmb A tmbnv hozz van rgztve a tmbhz, azaz a
elemeit, akkor az eredeti tmbt vltoztatjuk. tmbnv mint pointer nem vltoztathat meg:
double t1[10],t2[10],*p;
rjunk fggvnyt, amely nullzza a paramterknt tvett, el-
p=t1; // Helyes.
jel nlkli egszeket tartalmaz tmb sszes elemt!
p[5]=3.14; // Helyes.
t2=p; // HIBS! T2 mint pointer
void nullaz(unsigned t[],unsigned n){
// nem vltoztathat meg.
unsigned i;
t2=t1;// HIBS! T2 mint pointer
for(i=0;i<n;i++)t[i]=0;
// nem vltoztathat meg.
}
t1++; // HIBS! T1 mint pointer
// nem vltoztathat meg.
A felcserlhetsget mg egy pldval igazoljuk. A csere
p++; // Helyes.
fggvny gy is kinzhetne:
Emlkezznk a sztringeknl tanultakra! Itt lthat, mirt
void csere(int * a,int * b){ nem msolhat a sztring (vagy brmely tmb) az = oper-
int c=a[0]; torral: mert a tmb neve egy rgztett
a[0]=b[0]; (konstans) pointer, teht a t2=t1 msols-
b[0]=c; nl pointert prblunk msolni, nem pedig
} magt a tmbt. Ha a tmb struktrban
van, akkor mr nincs gond, hisz a struktra neve nem po-
s persze a paramterlistn is lehetne int a[], int b[]. Ez a inter, azaz lehet msolni.
megolds azonban mgsem javasolt, hiszen itt nem tmbkkel Ha struktrban pointer van, ami egy tmbre mutat, s
dolgozunk, s ahogy sokszor elhangzott mr: nagyon fontos, a struktrt tmsoljuk = opertorral, akkor csak a pointer
hogy jl olvashat kdot rjunk. msoldik, a tmb nem. Ez logikus, hiszen a fordt nem
tudja, hogy mire mutat a pointernk, mutat-e egyltaln
Tmb a struktrban A 14.1 fejezetben lttuk, hogy strukt- brmi rtelmesre. A tmb nevvel nincs ilyen problma,
rban lehet tmb. Mi a helyzet, ha ezt a struktrt egy fggvny az mindig a tmbre mutat.
kapja paramterknt, vagy fggvny adja vissza visszatrsi
rtkknt? 17.4 pointertmb
A struktrban lv tmb tmsoldik, akr paramterrl,
akr visszatrsi rtkrl van sz, ebben az esetben teht nem a Pointerekbl is hozhatunk ltre tmbt. Pl.:
tmb cme msoldik, hanem a tartalma. Termszetesen ez azt is
jelenti, hogy a struktrban tadott tmb megvltoztatsa a hvs int a,b,c,d;
helyn nem okoz vltozst. int *t[4]={&a,&b,&c,&d};
Az albbi programban egy hromdimenzis vektor *t[1]=5; // azaz b=5
normlst vgezzk. A fggvny beler a struktra tmbjbe, ez **t=9; // azaz a=9
azonban nem okoz vltozst az eredeti adatban: t[1]=&d;
*t[1]=5; // azaz d=5
#include <stdio.h>
#include <math.h> Sztringpointerek tmbje:
typedef struct {double k[3];} koordinata; char *s[]={"Htf","Kedd","Szerda"},ch;
koordinata normal(koordinata be){ printf("%s\n",s[2]);
double hossz=0.0; s[2]="Vasrnap"; // pointermsols!!!
int i; printf("%s\n",s[2]);
for(i=0;i<3;i++) ch=s[0][3]; // f bet a "Htf"-bl
hossz += be.k[i] * be.k[i]; s[0][3]='X'; // TILOS! A "Htf"
hossz=sqrt(hossz); // sztring konstans

57
strcpy(s[1],"Szombat"); // TILOS! A
// "Kedd" sztring konstans
18. Dinamikus memriakezels
A "Htf" s a tbbi sztring konstans csak olvashat, belerni Eddig, ha nagyobb mennyisg adatot troltunk, tmbket
ezekbe nem szabad, ltalban a program elszll, ha megksrel- hasznltunk. Igen gyakran azonban fordtsi idben nem lehet
jk. A r mutat pointer megvltoztathat, gy kerlt oda a "Va- elre tudni, hogy mennyi adatot kell majd feldolgozni. Kt eset
srnap". van.
Ebben az esetben minden sztringhez akkora memriafogyasz- Az egyik, ha azt tudjuk mondani, hogy ennyi hely bizto-
ts tartozhat, amekkort a sztring ignyel. A ktdimenzis karak- san elg lesz. Pldul sztringek beolvassnl mst nem
tertmb hasonlt a pointertmbhz, de fontos klnbsgek van- is nagyon tudunk csinlni, legfeljebb ha rendkvl meg-
nak: bonyoltjuk a programunkat.
A msik eset, ha saccolni sem tudunk.
char s[][20]={"Htf","Kedd","Szerda"},ch; Mondhatnnk erre, hogy akkor foglaljunk pl. 100 milli ele-
printf("%s\n",s[2]); m tmbt. Ez egyrszt nem gazdasgos, hiszen mi van akkor, ha
s[2]="Vasrnap"; // TILOS! s[2] konstans az esetek tlnyom tbbsgben ennl sokkal kevesebb hely kell?
// pointer Flslegesen foglaln a programunk a rendszer
printf("%s\n",s[2]); erforrsait. Msrszt viszont mi van, ha nem
ch=s[0][3]; // f bet a "Htf"-bl elegend a 100 milli sem? (Elre ismeretlen
s[0][3]='X'; // Helyes. mennyisg adatnak nagymret tmbt lefoglal-
strcpy(s[1],"Szombat"); // Helyes. ni igen slyos hiba.)
A megolds, ha a memrit nem elre krjk, hanem a prog-
Minden sztringhez egy-egy 20 elem karaktertmb tartozik, ram futsa kzben, az aktulis ignyeinknek megfelelen (dina-
teht tbb helyet foglalunk, mint ehhez a tartalomhoz szksges, mikusan) foglaljuk le, s ha mr nincs r szksg, felszabadtjuk.
viszont a tartalom megvltoztathat. Az ignyelt memrit az opercis rendszer biztostja a rendelke-
zsre ll szabad memria terhre. Ehhez a C nyelvben kt me-
Gondolkozzunk egytt! mriafoglal fggvny ll rendelkezsre: a malloc s a calloc. A
kt fggvny kztti klnbsgek a kvetkezk:
A malloc-nak egy paramtere van: hny bjtot szeretnnk
lefoglalni. Ezzel szemben a calloc-nak kt paramtere
Oldja meg egyedl! van, s a kett szorzata adja a kvnt bjtszmot.
A malloc ltal lefoglalt memriaterlet memriaszeme-
tet tartalmaz, azaz a dinamikusan lefoglalt vltoz kez-
deti rtke brmi lehet, ahogyan ezt az egyszer, nem di-
namikus vltozknl is megszoktuk. A calloc ezzel szem-
ben a lefoglalt terlet minden bjtjt kinullzza.
Ms klnbsg nincs, a hasznlat s a felszabadts ugyanaz
mindkt esetben. A fggvnyek visszatrsi rtke egy void*
tpus pointer a lefoglalt memriaterletre, vagy ha nem sikerlt
lefoglalni (nincs a kvnt nagysg sszefgg memriaterlet az
opercis rendszer birtokban), akkor NULL pointer. A dinami-
kus memria kezelshez szksges fggvnyek hasznlathoz
szerkesszk a programunkhoz az stdlib.h fejlcllomnyt!
A lefoglalt dinamikus memrit ktelez felszabadtani a
free fggvnnyel!
Plda: a felhasznltl bekrt mret, double elem dinami-
kus tmb ltrehozsa, elemeinek feltltse az index rtkvel,
kirs fordtott sorrendben, majd a memria felszabadtsa.

#include <stdio.h>
#include <stdlib.h>

int main(void){
unsigned m,i;
double * t;
printf("Mekkora tomb kell? ");
scanf("%u",&m);

// memriafoglals

t=(double*)malloc(m*sizeof(double));
if(t==NULL){
puts("Sikertelen allokalas.");
exit(1);
}

// Innentl gy hasznljuk, mint


// egy kznsges tmbt.

for(i=0;i<meret;i++)t[i]=i;

58
for(i=meret-1;i+1!=0;i--)
printf("%g ",t[i]); Itt teht m a pointermretet adja, n pedig a tnyleges tmbm-
ret.
// felszabadts, ha mr nem kell

free(t);
18.2 Tbbdimenzis dinamikus tmb
return 0;
} Dinamikus foglalssal csak egydimenzis tmbt hozha-
tunk ltre. Ha tbbdimenzisra van szksg, akkor tbb lehet-
A malloc helyett calloc-ot hasznlva: sg ll elttnk. Pl. szksgnk van egy M soros, N oszlopos
ktdimenzis tmbre:
t=(double*)calloc(m,sizeof(double)); Lefoglalunk egy M*N mret egydimenzis tmbt, az i.
sor j. oszlopban lv elemet t[i*N+j] mdon rhetjk el.
Figyeljk meg, hogy vessz kerlt a csillag helyre! A t[i][j] mdon val cmzshez elbb egy M mret po-
A visszaadott void* pointert double* tpusv konvertljuk. intertmbt foglalunk, majd M darab N mret tmbt az
Ez a konvertls a valsgban nem csinl semmit, hiszen gy is- elemeknek, s a pointertmb egy egy-eleme ezekre a so-
gy is ugyanazt a memriacmet jelenti. Azt a clt szolglja, hogy rokra mutat.
tudassuk a fordtval: valban nem void*-knt, hanem double*-
knt akarjuk hasznlni a cmet, teht ne adjon hibazenetet (pon- 0 1 2 N-1
tosabban warningot). 0
A lefoglalst s felszabadtst kivve a lefoglalt vltozt 1
0 1 2 N-1
ugyangy hasznlhatjuk, mint egy nemdinamikus tmbt, illetve 2
pointerrel mutatott vltozt, tadhatjuk pl. fggvnynek is.
0 1 2 N-1
M-1

18.1 sizeof 0 1 2 N-1

Egy adattpus vagy vltoz mrett a sizeof opertor adja.


(A tbbi opertortl eltren ez szveges opertor. A C-ben Egy mik mdszer a t[i][j] mdon val cmzshez: el-
szveges opertor mg a tpuskonverzis opertor: (int)a.) Azt szr szintn egy M mret pointertmbt foglalunk, majd
mondja meg, hogy az adott adat hny bjtos (1 bjt nem biztos, egy darab M*N mret tmbt az elemeknek. A pointer-
hogy 8 bites). A char tpus mindig 1 bjt, teht a sizeof(char) tmb egy-egy eleme ezen a tmbn bell N elemenknt
mindig 1-et ad. A sizeof opertor fordtsi idben kerl kirtke- eltolva mutat az elemekre. Ez a megolds hasonlt legjob-
lsre, teht a lefordtott programba mr a konkrt mretek lesznek ban a nemdinamikus tbbdimenzis tmbk mkdsre.
behelyettestve. Minden tpus mrete egsz bjtszm, teht nincs
pl. 1,5 bjtos vltoz. 0 1 2 N-1 N N+1 N+2 2N-1 2N (M-1)N MN

double d; 0

int t[30]; 1

int meret=sizeof(d); // vltoz mrett 2

// is nzhetjk

meret=sizeof(double);// tpus mrett M-1

// is nzhetjk
meret=sizeof(t); // hny bjtot Plda Krjk a felhasznltl a ktdimenzis tmb mrett,
// foglal a tmb hozzuk ltre, tltsk fel adatokkal, majd rjuk ki, vgl trljk!
meret=sizeof t; // hny bjtot
// foglal a tmb 1. vltozat:
meret=sizeof(t)/sizeof(int);
// hny elem a tmb (int a tmb tpusa) #include <stdio.h>
#include <stdlib.h>
Ha tpusra alkalmazzuk a sizeof-ot, akkor a tpust kerek zr- void hibaellenorzo(void * p){
jelek kz kell tenni, ha vltozra ill. kifejezsre, akkor a kifeje- if(p==NULL){
zst nem kell zrjelek kz tenni, de szabad. A sizeof nem hasz- fprintf(stderr
,"Sikertelen allokacio.\n");
nlhat inkomplet tpusra, vagy defincira (pl: sizeof(int []). exit(1);
Nagyon fontos! A sizeof nem tudja megl- }
laptani a fggvnynek tadott tmb mrett, }
mivel a fggvny nem a tmbt, csak annak
int main(void){
cmt veszi t! Ezrt adtuk t mindig a tmb int M,N,i,j;
mrett is a fggvnynek. A sizeof kirtkelse mindig fordtsi double ** tomb;
idben trtnik, azaz a lefordtott programba mr a konkrt rt-
// Mretek bekrse
kek kerlnek be.
double summa(double [] t,unsigned n){ printf("M=");
int m=sizeof(t)/sizeof(double); scanf("%d",&M);
double s=0.0; printf("N=");
scanf("%d",&N);
if(m==n)
printf("Ez ltalban nem igaz!"); // pointertmb foglalsa
for(i=0;i<n;i++)s+=t[i];
tomb=(double**)calloc(M,sizeof(double*));
return s; hibaellenorzo(tomb);
}

59
// sorok foglalsa
18.3 A lefoglalt memria bvtse
for(i=0; i<M; i++){
tomb[i]=(double*)calloc(N,sizeof(double));
hibaellenorzo(tomb[i]); A bemutatatott pldban megkrdeztk a felhasznlt, mek-
} kora tmbre lesz szksge, s ekkort foglaltunk. Gyakori azon-
ban, hogy egyltaln nem tudjuk elre, hogy mennyi elemre lesz
// hasznlat
szksg. Az eddig megismert eszkzk segtsgvel kell megol-
for(i=0; i<M; i++) danunk a problmt.
for(j=0; j<N; j++)
tomb[i][j]=0.1*i*j;
Meg lehet-e nyjtani a lefoglalt memrit? Nem.
for(i=0; i<M; i++){
for(j=0; j<N; j++) Ha nem elegend a lefoglalt dinamikus tmb, a kvetkez
printf("%9g ",tomb[i][j]);
printf("\n");
mdszerrel tudjuk megnvelni a mrett:
} t pointer mutat a dinamikus tmbre, melynek M a mrete.
N mret helyre lenne szksgnk.
// sorok felszabadtsa
Lefoglalunk egy N mret helyet, melyre v pointerrel mu-
for(i=0; i<M; i++)free(tomb[i]); tatunk.
tmsoljuk az elemeket a t tmbbl a v tmbbe.
// pointertmb felszabadtsa
Felszabadtjuk t tmbt, s t pointert v tmbre lltjuk.
free(tomb);
#include <stdio.h>
return 0;
} #include <stdlib.h>

2. vltozat: // ha kisebb az j tmb, akkor csak ennyi


// elemet msolunk t a rgibl
int main(void){ double*ujrafoglal(double *t,int M,int N){
int M,N,i,j; double * v;
double ** tomb; unsigned i, min = M<N ? M : N;
// Mretek bekrse
v=(double*)calloc(N,sizeof(double));
printf("M="); if(v==NULL)return NULL;
scanf("%d",&M);
printf("N="); for(i=0;i<min;i++)v[i]=t[i];
scanf("%d",&N); free(t);
return v;
// pointertmb foglalsa
}
tomb=(double**)calloc(M,sizeof(double*));
hibaellenorzo(tomb); void hiba(char * s){
fprintf(stderr,%s\n,s);
// sorok foglalsa
exit(1);
! tomb[0]=(double*)calloc(M*N,sizeof(double)); }
! hibaellenorzo(tomb[0]);
! for(i=0; i<M; i++)
! tomb[i]=tomb[0]+N*i;
int main(void){
double * t;
// hasznlat
t=(double*)malloc(100*sizeof(double));
for(i=0; i<M; i++)
for(j=0; j<N; j++) if(t==NULL)hiba("Memoriafoglalas");
tomb[i][j]=0.1*i*j;
// megnveljk 200 elemre
for(i=0; i<M; i++){
for(j=0; j<N; j++)
printf("%9g ",tomb[i][j]); t=ujrafoglal(t,100,200);
printf("\n"); if(t==NULL)hiba("Memoriafoglalas");
}

// sorok felszabadtsa // lecskkentjk 50 elemre

! free(tomb[0]); t=ujrafoglal(t,200,50);
if(t==NULL)hiba("Memoriafoglalas");
// pointertmb felszabadtsa

free(tomb); free(t);
return 0;
return 0;
} }

A kt vltozat a kt brnak megfelel, klnbsg a felkilt- Ltezik egy C fggvny, a realloc, amely ugyanezt teszi. A
jellel jelzett sorokban van. fenti program realloc-os vltozata:
A hibaellenorzo fggvny csak azt vizsglja, hogy a pointer
NULL-e, brmilyen pointertpust hasznlhatunk. Mivel tbbfle #include <stdio.h>
tpussal is meghvjuk, a legclszerbb tpus nlkli pointert meg- #include <stdlib.h>
adni paramterknt.
void hiba(char * s){
fprintf(stderr,%s\n,s);

60
}
exit(1);
19. Sztringek
int main(void){ A tmbkkel foglalkoz fejezetben megismerkedtnk a
double * t; sztringek felptsvel (karaktersorozat egy tmbben, melynek
t=(double*)malloc(100*sizeof(double)); vgt a nulla rtk karakter jelzi). Most megnzzk a knyvtri
if(t==NULL)hiba("Memoriafoglalas"); sztringkezel fggvnyek kzl a fontosabbakat s nhny
sztringalgoritmust.
// megnveljk 200 elemre

t=(double*)realloc(t,200);
19.1 Knyvtri sztringfggvnyek
if(t==NULL)hiba("Memoriafoglalas");
A sztringekkel kapcsolatosan leggyakrabban szksges fel-
// lecskkentjk 50 elemre adatok s az ezeket vgrehajt knyvtri fggvnyek a kvetke-
zk:
t=(double*)realloc(t,50); hossz megllaptsa: strlen
if(t==NULL)hiba("Memoriafoglalas"); msols: sprintf, strcpy
sszefzs: sprintf, strcat
free(t); sszehasonlts: strcmp
return 0; sztring szmm alaktsa: sscanf, atoi, atof, atol
} szm sztringg alaktsa: sprintf
keress sztringen bell: strstr, strchr
A mdszer htrnyai:
ideiglenesen tbbletmemrit ignyel sprintf, sscanf A jl ismert prrintf s scanf fggvnyek
hosszadalmas az eredeti tmb tmsolsa stringbe dolgoz vltozatai. A sprintf a kperny helyett az els
Ezek a htrnyok kikszblhetk nhivatkoz adatszerke- paramtereknt kapott karaktertmbbe rja a szveget, a sscanf
zetek alkalmazsval, melyekrl a 24. s 27. fejezetben lesz sz. pedig a billentyzet helyett az els paramterknt kapott
sztringbl olvassa ki az rtkeket.
A kvetkez pldaprogram igyekszik felvillantani a kt fgg-
Gondolkozzunk egytt! vny lehetsgeit.

#include <stdio.h>

void kiir(int a,int b,char*t,char*s){


Oldja meg egyedl! printf("t=%s\na=%d\nb=%d\ns=%s\n\n",t,a,b,s);
}

int main(void){
char t[]="65 ember osszjovedelme 877323 Ft.";
char s[40];
int a,b,i;

sscanf(t,"%d%s%*s%d",&a,s,&b);
kiir(a,b,t,s);

sscanf(t+25,"%d%s",&b,s);
kiir(a,b,t,s);

sprintf(t+4,"%s+%d szia!",s,a+b+3);
kiir(a,b,t,s);

printf("A t tomb tartalma:\n");


for(i=0;i<sizeof(t);i++)
printf("t[%2d] = %3d = \'%c\'\n",
i,t[i],t[i]);
return 0;
}

A kd ttekinthetsgnek javtsa rdekben a ngy vltoz


kpernyre val kirst kln fggvnybe tettk.
A sscanf(t,"%d%s%*s%d",&a,s,&b); a t tmbbl olvas h-
rom rtket: az a vltozba kerl a 65, az s vltozba az ember,
a %*s-ben a * azt jelzi, hogy a kvetkez szt tugorjuk, nem
olvassuk be sehov, gy a b vltozba a 877323 kerl. Az els
kirs eredmnye teht:

t=65 ember osszjovedelme 877323 Ft.


a=65
b=877323
s=ember

A sscanf(t+25,"%d%s",&b,s); utastsban bemeneti sztring-


knt t+25 szerepel, vagyis a t pointerhez 25-t adunk, ami a t
tmb 25. elemnek cmt jelenti. A sscanf fggvny szmra ez a
7323 Ft. tartalm tmbt jelenti bemenetknt, ebbl fog olvas-

61
ni. Egy egsz szmot s egy sztringet olvasunk teht, gy a kirs osztssal kapunk. A karaktertmbnl az osztsra azrt nem volt
eredmnye: szksg, mert a char tpus mrete definci szerint 1 bjt, azaz
sizeof(char)==1. Termszetesen helyes lenne a program akkor is,
t=65 ember osszjovedelme 877323 Ft. ha gy rnnk: i<sizeof(t)/sizeof(char).
a=65
b=7323 strlen, strcpy, strcat, strcmp, strchr, strstr, strncpy Egy
s=Ft. pldaprogramon keresztl mutatjuk be ezek hasznlatt:

A sprintf(t+4,"%s+%d szia!",s,a+b+3); utastssal lecserl- #include <stdio.h>


#include <string.h>
jk az eredeti sztringet a t tmbben. Bemenete a t+4, azaz a t
tmb elejn lv 65 e rszt nem bntjuk, utna kerl az j int main(){
kirs. Az eredmny: char t[100];
char t1[]="Egy meg egy";
char t2[]=" az ketto.";
t=65 eFt.+7391 szia! printf("%d\n",strlen(t1)); // NEM szmolja a
a=65 // lezr 0-t!
b=7323 strcpy(t,t1);
puts(t);
s=Ft. strcat(t,t2);
puts(t);
rdekes megnzni a t tmb teljes tartalmt is, amit egy cik- strcpy(t1,"Harry");
strcpy(t2,"Ron");
lussal runk ki, elbb a karakter ASCII kdjt, aztn magt a strcpy(t,"Hermione");
karaktert aposztrfok kztt. if(strcmp(t1,t2)<0)printf("%s<%s\n",t1,t2);
else printf("%s>=%s\n",t1,t2);
A t tomb tartalma: if(strcmp(t1,t)>0)printf("%s>%s\n",t1,t);
else printf("%s<=%s\n",t1,t);
t[ 0] = 54 = '6' if(strcmp(t1,t)==0)printf("%s==%s\n",t2,t);
t[ 1] = 53 = '5' else printf("%s!=%s\n",t2,t);
t[ 2] = 32 = ' ' if(strchr(t,'o')==NULL)
printf("%s nem tartalmaz \'o\'-t\n",t);
t[ 3] = 101 = 'e' if(strstr(t,"on")==NULL)
t[ 4] = 70 = 'F' printf("%s nem tartalmaz \"on\"-t\n",t);
t[ 5] = 116 = 't' else printf("%s tartalmaz \"on\"-t: %s\n",t,
t[ 6] = 46 = '.' strstr(t,"on"));
strncpy(t1,"Beckham",2);
t[ 7] = 43 = '+' puts(t1);
t[ 8] = 55 = '7' return 0;
t[ 9] = 51 = '3' }
t[10] = 57 = '9'
t[11] = 49 = '1' A kpernyn ez jelenik meg:
t[12] = 32 = ' '
t[13] = 115 = 's' 11
t[14] = 122 = 'z' Egy meg egy
t[15] = 105 = 'i' Egy meg egy az ketto.
t[16] = 97 = 'a' Harry<Ron
t[17] = 33 = '!' Harry<=Hermione
t[18] = 0 = ' ' Ron!=Hermione
t[19] = 108 = 'l' Hermione tartalmaz "on"-t: one
t[20] = 109 = 'm' Berry
t[21] = 101 = 'e'
t[22] = 32 = ' ' strlen(t1): a t1 sztring hosszt adja, a lezr 0-t nem
t[23] = 56 = '8' szmolja bele
t[24] = 55 = '7' strcpy(t,t1): tmsolja t-be t1-et, ugyanaz, mint a
t[25] = 55 = '7' sprintf(t,%s,t1);, brmelyik megoldst hasznlhatjuk.
t[26] = 51 = '3' (Az rtkads irnya itt is jobbrl balra, ahogy az = ope-
t[27] = 50 = '2' rtornl.)
t[28] = 51 = '3' strcat(t,t2): t vghez fzi t1-et. Az sszefzs a sprintf
t[29] = 32 = ' ' segtsgvel is megoldhat, de a forrs s
t[30] = 70 = 'F' a cl tmb nem lehet ugyanaz, azaz a
t[31] = 116 = 't' sprintf(t,%s%s,t,t2); hibs! A fenti
t[32] = 46 = '.' programban a kvnt eredmnyt gy kap-
t[33] = 0 = ' ' juk sprintf hasznlatval: sprintf(t,%s%s,t1,t2);.

Figyeljk meg, hogy a 65 eFt.+7391 szia! szveget a lezr Magyarzat: a sprintf fggvny a tmbk cmt veszi t, s nem ellenrzi,
nulla kveti, majd az eredeti sztring megmaradt rsze. hogy van-e tfeds a tmbk kztt, egyszeren elkezdi belerni a cl
tmbbe azt, amire a formtumsztringje utastja. Ha a forrs s a cl ugyan-
A sizeof(t) a tmb mrett adja bjtban. Ha egy int tmbt az, akkor azzal, hogy a clba beler, a forrst is mdostja, ami problms
akarnnk vgigjrni, a ciklus gy nzne ki: lehet, pldul ha fellrja a forrs lezr nulljt egyb karakterrel.
strcmp(t1,t2): sszehasonltja t1-et s t2-t.
int egesz[]={6,2,77,21,4},i;
for(i=0; i < sizeof(egesz)/sizeof(int); i++)
o Ha egyformk, 0 a visszatrsi rtke.
printf("egesz[%d] = %d\n",i,egesz[i]); o Ha t1<t2, azaz ABC-ben elbb van, akkor a fggvny
negatv rtket ad vissza (nem definilt, hogy mit, a
A sizeof(egesz) ugyanis a tmb mrett adja lnyeg, hogy negatv).
bjtokban, neknk viszont az elemszmra van o Ha t1>t2, akkor pozitvat.
szksgnk, amit .egy elem mretvel val

62
strchr(t,ch); megnzi, hogy t tartalmazza-e a ch karaktert. mny nlkl el lehet hagyni. Ha a fggvny rja vletlenl meg-
Ha nem, akkor NULL pointert ad vissza. Ha tartalmazza, vltoztatn a sztringet, a const miatt a fordt hibazenetet adna.
akkor az els megtallt karakter cmt a t-n bell. A fggvny hasznlatt semmiben nem befolysolja.
strstr(t1,t2): megnzi, hogy t1 tartalmazza-e a t2 szve-
get. Ha nem, akkor NULL pointert ad vissza. Ha tartal- strcpy A kvetkez algoritmusunk a sztringmsols. Ennek
mazza, akkor az els megtallt rszsztring cmt a t1-en ngy vltozatt is megadjuk:
bell.
char * x_strcpy_1(char * ki,const char * be){
strncpy(t1,t2,n): t2-bl n db karaktert msol t1-be. Ha n int i;
kisebb, mint a sztring hossza, akkor nem msolja t a le- for(i=0; be[i]!=0; i++)ki[i]=be[i];
zr 0-t, ennek a kvetkezmnye, amit a pldaprogram ki[i]=0; // lezr!
mutat: az els kt karakter fellrdik a Beckham els return ki;
}
kt betjvel, a Harry tbbi rsze ott marad, a kir
fggvny (jelen esetben a puts, de a printf is ugyangy vi- char * x_strcpy_2(char * ki,const char * be){
selkedne) pedig mindig a lezr 0-ig rja ki a szveget. int i;
for(i=0; (ki[i]=be[i])!=0; i++);
Ha n nagyobb, mint a msoland szveg hossza, akkor a return ki;
szveg vge utn nulla bjtokkal tltdik fel a tmb n-ig. }
Tovbbi fggvnyek llnak rendelkezsre a string.h-ban, sok
char * x_strcpy_3(char * ki,const char * be){
fggvnynek van n-es vltozata az strncpy mintjra (pl. strncmp int i;
az els n karaktert hasonltja ssze). Amit clszer megjegyezni, for(i=0; ki[i]=be[i]; i++);
az az strlen, strcpy s strcat. A tbbit szksg esetn megtalljuk return ki;
}
a Helpben.
char * x_strcpy_4(char * ki,const char * be){
Sztring-szm s szm-sztring talaktsok Lttuk mr az while(*ki++=*be++);
talaktst a sscanf s az sprintf segtsgvel. A sztringbl szm- return ki;
}
m alaktshoz rendelkezsre ll nhny specilis fggvny is, az
atoi, atof, atol. mindhrom bemenete egy sztring, visszatrsi Az elstl a negyedikig haladva egyre tbb C trkkt haszn-
rtkk pedig int, double illetve long. Hasznlatukhoz az stdlib.h
lunk. Elg, ha az els vltozatot meg tudjuk rni, a tbbit csak
beszerkesztse szksges. Pl.:
rdekessg kedvrt kzltk.
char t[]="65 ember osszjovedelme 877323 Ft.";
Az elsben a lezr nullt nem msoljuk t, mert vget r a
int a; ciklus, ezrt ezt oda kell biggyeszteni a sztring vgre. A tbbi-
a=atoi(t); ben a msols a ciklus felttelben van, s csak a lezr nulla
tmsolst kveten nzzk meg, hogy mit is msoltunk.
Az a-ba 65 kerl. Ha a bemeneti sztring szmknt nem rtel- A negyedik vltozat a be pointer ltal mutatott rtket a ki po-
mezhet, a fggvnyek nullt adnak vissza. Ezt az esetet nem inter ltal mutatott cmre msolja, ezt kveten mindkt pointer
lehet megklnbztetni attl, ha tnyleg nulla van a bemen rtkt megnveli eggyel.
sztringben, emiatt a hibakezels problms. A fggvnyek az els
olyan karakterig olvasnak, ami nem lehet az adott tpus szm strcat Sztringek sszefzse:
rsze, pl. a -45.21x az atoi s az atol szmra -45, az atof sz-
mra -45.21 (a scanf, sscanf stb is ugyangy mkdik). char * x_strcat_1(char * beki,const char * be2){
Hibakezelsre alkalmasabb a sscanf: int i,j;
for(i=0; beki[i]!=0; i++);
for(j=0; (beki[i]=be2[j])!=0; i++,j++);
if(sscanf(t+25,"%d%s",&b,s)!=2){ return beki;
fprintf(stderr,"Hibas bemeno adat.\n"); }
exit(1);
} char * x_strcat_2(char * beki,const char * be2){
strcpy(beki+strlen(beki),be2);
Kt rtket szeretnnk beolvasni, ha ez nem sikerl, akkor baj return beki;
}
van.
char * x_strcat_3(char * beki,const char * be2){
19.2 Algoritmusok char *p=beki;
while(*p++);
p--; // vissza a lezr 0-ra
while(*p++=*be2++);
rjuk meg magunk a knyvtri sztringkezel fggvnyeket! return beki;
Nem mindet persze, de nhnyat. }

strlen Figyeljk meg az els vltozatban, hogy kt kln indexet


hasznltunk a kt sztringhez! A 2-3 fggvnyvltozat ezttal is
size_t x_strlen(const char *s){ csak rdekessg.
size_t i;
for(i=0; s[i]!=0; i++); strcmp
return i;
} int x_strcmp(const char *a,const char *b){
int i;
for(i=0; a[i]!=0 && b[i]!=0 && a[i]==b[i]; i++);
Az x_strlen ugyanazt teszi, mint az strlen. Visszatrsi tpusa if(a[i]<b[i])return -1;
size_t, ami egy typedef segtsgvel definilt szabvnyos tpus, if(a[i]>b[i])return 1;
return 0;
sok szabvnyos fggvny hasznlja mretmegadsra. Hasznlha- }
tunk helyette int-et vagy unsigned-et, ha az jobban tetszik.
A paramter tpusban szerepl const azt jelenti, hogy a A ciklus addig megy, mg valamelyik sztring vget nem r,
fggvny nem vltoztatja meg az s tmb tartalmt, ezt kvetkez- vagy amg a kt sztring egyforma.

63
Ha a kt sztring egyforma, akkor a[i] s b[i] egyarnt a lez-
r nulln fog llni, azaz ekkor sem a[i]<b[i], sem a[i]>b[i] nem
20. A programozs menete
teljesl, teht a fggvny 0-t ad vissza.
Ha a kt sztring klnbzik, akkor az els klnbz karakter Nagyobb programok ksztsekor nem clszer gy eljrni,
alapjn dntjk el, hogy melyik van elbb az ABC-ben. hogy az ember lel a gp el s elkezd kdolni. A program felp-
Ha az sszehasonlts gy r vget, hogy az egyik sztring a tst meg kell tervezni, a kszts folyamatt pedig dokumentlni
msik eleje, vagyis pl. a=Konyha, b=Konyhaablak, akkor a kell, hogy a ksbbiekben knny legyen karbantartani illetve
rvidebb sztring [i] eleme a lezr nulla, mg a msik sztring fejleszteni a szoftvert. Az is gyakori, hogy tbb programoz
esetben egy nem 0 rtk van ott (a pldban 'a'), ezt hasonltjuk dolgozik ugyanazon szoftver klnbz rszein. Belthatjuk,
ssze. hogy a program megtervezse s a feladatok elzetes felosztsa
nlkl az egyttmkds lehetetlen lenne. Ebben s a kvetkez
Mi van akkor, ha az egyik sztring a msik eleje, s a hosszab- fejezetben a nagyobb programok ksztshez kapcsold dol-
bik egy kezetes magyar magnhangzval folytatdik? Ugyan- gokrl lesz sz.
gy rendezi-e a szvegeket, ha a char eljeles illetve eljel Emlkeztetl a programozs menett bemutat brnk az 1.
nlkli az adott rendszerben? fejezetbl, illetve az egyes lpsek bvtett lersa:

sszefsls Vgl nzznk egy olyan pldt, amire nincs Specifikci


knyvtri fggvny:
rjunk fggvnyt, amely paramterknt kap kt sztringet s Tervezs
ezeket sszefsli gy, hogy az eredmnybe felvltva kerljenek
be a karakterek a kt forrsbl, amg lehet, aztn a hosszabbik Algoritmus
sztring maradk karakterei kvetkezzenek egyms utn! Az vlasztsa
eredmny karaktertmbt szintn paramterknt kapja a fgg-
vny. Pl.: be: 0123456789 s abcdef, ki:
Adatszerkezetek Dokumentci
0a1b2c3d4e5f6789.
Mieltt megnzi a megoldst, prblja meg egyedl megol- megvlasztsa elksztse
dani a feladatot!
A kt sztring eltr hossza miatt nem lehet egy indexszel
Nyelv
megoldani a feladatot. Sokfle helyes algoritmus ltezik, az
albbi ezek kzl csak egy. megvlasztsa

void fesul(char ki[],char be1[],char be2[]){


int i=0,j=0,k=0; Kdols
while(be1[i]!=0 || be2[j]!=0){
if(be1[i]!=0)ki[k++]=be1[i++];
if(be2[j]!=0)ki[k++]=be2[j++]; Tesztels,
} hibajavts
ki[k]=0; // lezr
}
Specifikci: a program feladatnak rszletes definilsa,
A ciklus akkor r vget, ha mindkt bemen sztring vgre belertve a bemeneti s kimeneti adatok formtumt.
rtnk. i s j rtkt csak akkor nveljk, ha mg nem vagyunk a Algoritmus vlasztsa: a program felptsnek megter-
be1 ill. a be2 vgn. A ki[k++]=be1[i++]; sztszedve gy rhat: vezse a program megrshoz szksges rszletessggel.
{ ki[k]=be1[i]; k++; i++; }, mivel a ++ mindkt esetben Fontos szempont a hatkonysg (mveletvgzs, elvi kor-
posztinkremens, azaz a kifejezs kirtkelse utn nvelik a ltok, memriaigny futs kzben), a program mrete, a
vltoz rtkt. programfejleszts sebessge.
Adatszerkezet megvlasztsa: a feladathoz leginkbb
rjon fggvnyt, amely egy sztringet kap paramterknt, me- megfelel struktra megtervezse (pl. tmb, lista, fa?)
lyet sajt helyn megfordt (azaz nem hasznl msik tmbt Nyelv megvlasztsa: Mindig a feladatnak leginkbb
vagy egyb adatszerkezetet a megfordtott vagy az eredeti megfelel nyelvet vlasszuk. Pl. website fejlesztshez al-
sztring ideiglenes trolsra)! kalmasabb a php, mint a C.
Kdols, tesztels, hibajavts: ezek a lpsek egymst
vltogatjk. Nagy programoknl jellemz, hogy hibakere-
sssel tbb id megy el, mint a programozs sszes tbbi
Gondolkozzunk egytt! tevkenysgvel egyttvve.
Dokumentci elksztse:
o Programozi (fejleszti) dokumentci: fontos,
hogy ksbb javtani, bvteni lehessen a programot,
Oldja meg egyedl! s erre ne csak a program eredeti rja legyen kpes,
hanem ms programoz is.

A fejleszti dokumentci legfontosabb eszkze ma-


ga a jl kommentezett, vilgos, ttekinthet struktr-
j forrskd. Rengeteg idt lehet megtakartani, ha
nem kell elmlyedni a forrskdban, s megprblni
kitallni, hogy mit is jelentett a c vltoz?, mert a
kommentekre pillantva msodpercek alatt behatrol-
hat a keresett programrsz, s beszdes vltoz- s
fggvnynevek alapjn ezen bell is knny tjko-
zdni. (Az egy-kt bets vltoznv is lehet beszdes.

64
i,j,k a ciklus futvltozja, n a darabszm, x,y koordi- Kt algoritmus megadsi mddal ismerkednk meg rszlete-
ntk, fp az egy szem megnyitott fjl, ezek teljesen sebben: a folyamatbrval s a struktogrammal.
egyrtelmek, ha konzekvensen hasznljuk az elne-
vezseket.) Folyamatbra A szveges lersnl knnyebben ttekinthet
a grafikus algoritmusbrzols. Ennek egyik legjobb eszkze a
A dokumentci ksztshez nagy segtsget nyjt a folyamatbra. A legegyszerbb folyamatbrk mindssze kt
Doxygen program, mely a C kdban elhelyezett spe- elemet hasznlnak: a mveletet s a dntst, melyek segtsgvel
cilis felpts megjegyzsek segtsgvel kszt do- minden algoritmus lerhat. A gyakorlatban ennl bvebb elem-
kumentcit. kszletekkel is dolgoznak az egyes funkcik jobb elklntse
rdekben. Az albb lista tovbbi elemekkel bvthet, szmunk-
A programozi dokumentci rsze a forrskd mel- ra azonban ez is bven elegend.
lett a specifikci, adatszerkezetek (belertve a fjlok
formtumt), s az algoritmusok lersa, diagramok.
Mindaz, ami ahhoz szksges, hogy valaki gyorsan Start, stop: START STOP
ttekintst szerezzen a programrl, s aztn knnyen
eligazodjon a rszletekben.
o Tesztelsi dokumentci: ha elkszlt a program,
vagy annak valamely modulja, akkor azt tesztelni, Mvelet:
kell, hogy feldertsk az esetleges hibkat. A tesztel-
si dokumentciban fel kell tntetni, hogy milyen
tesztadatokkal vizsgltuk a szoftvert, milyen hibkat
talltunk, s javtottunk. Ksbbi hibakeressek sorn Adatbevitel, kirs (I/O):
hasznos lesz akr kiindul adatnak, akr azrt, hogy
segtsen, mit nem kell mr tesztelni.
o Felhasznli dokumentci: magyarul hasznlati
utasts. A program bonyolultsgtl fgg ennek sz- Dnts:
szetettsge. Tartalmazza a szoftver funkciit, a be- s
kimeneti adatok, fjlok formtumait, melyekkel a fel-
hasznl a programmal kommunikl, a korltokat, Csatlakozs (mshol folytatdik az bra): 2
ismert hibk jegyzkt, a szoftver ltal tmasztott
hardver s szoftver kvetelmnyeket, a fejleszt elr-
hetsgt. Kls csatlakozs: 3
20.1 Programstruktra tervezse
Egy nagymret, sok ezer soros programot nem kezdhetnk Plda: n! kiszmtsa szorzssal.
el gy rni, hogy van egy homlyos elkpzels a fejnkben arrl,
hogy is fog felplni a program, mert ennek szinte biztosan az
1
lesz a kvetkezmnye, hogy oda jutunk: a legjobb lenne elrl
kezdeni az egszet, annyira kusza s nehzkes, amit alkottunk. START
Meg kell tervezni a programot: tervezs kzben hamar kiderlnek N
i<=n
az elzetes elkpzelsnkben rejl legnagyobb strukturlis hibk,
n beolv.
melyek ilyenkor mg egyszeren javthatk. A tervezs sorn I
ktfle mdszert hasznlunk:
i++ j kir
top-down (fellrl lefel) tervezs: A specifikci alap- i=j=1
jn meghatrozzuk a program f rszeit (pl. felhasznli
fellet, 3D grafikus motor, mestersges intelligencia, j*=i STOP
hangkezels, hlzatkezels, stb.), tisztzzuk, hogy me- 1
lyik rsz mit csinl (=specifikcit ksztnk a rszek-
hez), majd az egyes rszeket bontjuk kisebb rszekre, a
kisebb rszeket specifikljuk, s gy tovbb. Addig bont- Folyamatbra segtsgvel knny jl ttekinthet algorit-
juk a feladatot, amg azt nem tudjuk mondani: Ezen a must rajzolni, azonban miutn megrajzoltuk az algoritmust, kny-
blokkon bell minden feladat vilgos, szksgtelen to- nyen azt tallhatjuk, hogy strukturlt mdon nem valsthat
vbb bontani. meg, mert olyan ugrsok vannak benne, amit a struktrlt utast-
bottom-up (alulrl felfel) tervezs: Ha egy adott sok (feltteles elgazs, ciklus) nem tmogat. Pldul, ha a fenti
blokkban vilgos a feladat, teht sztbontssal nem jutunk brt gy alaktannk t:
mr sehov, akkor nekillunk elemi rszekbl sszerakni 1
a blokkot. Az elemi rszek lehetnek utastsok (ciklus, START
feltteles elgazs stb.), fggvnyek, objektumok, ms l- i++
tal fejlesztett blokkok. A bottom-up tervezs nem is min-
dig vlik el a kdolstl, hiszen a kdols sorn ltalban n beolv.
ugyanazok az alapegysgek, mint a bottom-up tervezs- i<=n
N
nl. j kir
i=0, j=1 I

20.2 Algoritmus megadsa j*=i


1 STOP

65
Ez az algoritmus mkdkpes, azonban hogy valstannk
meg ezt a tanult C eszkzkkel strukturlt mdon? Az algoritmus
21. sszetettebb C programok kell-
megvltoztatsa nlkl sehogy. A goto utasts segtsgvel kei
persze megvalsthat, de annak nem megengedett a hasznlata
pont azrt, mert strukturlatlan, s kvethetetlenn teszi a kdot.

Struktogram A struktogram (struktradiagram) szintn az 21.1 Tbb modulbl ll programok


algoritmusok grafikus brzolsra val, de csak strukturlt
megoldsokat enged meg. Kevsb szemlletes, mint a folyamat- Nagyobb programoknl clszer nem egy forrsfjlt hasznl-
bra, azonban hasznosabb, ha le is akarjuk kdolni az algorit- ni, hanem tbb fjlra bontani a programot. Ez szmos elnnyel
must. A struktogram elemei egymshoz csatlakoz tglalapok. jr:
A fordt forrsfjlonknt kln-kln fordt. Ha csak
Tevkenysg: egy forrsfjlt mdostunk, akkor csak ezt kell ismt le-
fordtani.
A nagy programokat gyakran tbb fejleszt kszti, mind-
Felttel egyikk a sajt forrsfjljain dolgozik.
Vlaszts
I N Egy adott funkcihoz tartoz programrszek kerlnek egy
fjlba, gy hamarabb megtallhat a keresett kdrszlet.
Tevkeny- Tevkeny- A C nyelvben egy fggvny csak akkor hasznlhat, ha a
sg1 sg2 deklarcijt a fordtprogram mr megtallta az adott forrsl-
lomny lefordtsakor. Ha kln modulba tesszk a fggvnyek
egy rsznek defincijt (azaz forrskdjt), akkor szksg van
Ell tesztel ciklus Felttel arra, hogy a msik modul rendelkezsre bocsssuk a deklarci-
kat. Erre a clra hasznljuk a fejlc llomnyokat.
Ciklusmag
Plda rjunk C fggvnyt, mely paramterknt kt eljel
nlkli egszt vesz t, s visszaadja a kt szm legnagyobb kzs
osztjt! Egsztsk ki teljes programm, amely teszteli a fgg-
Htul tesztel ciklus vny helyes mkdst! A fggvnyt tegyk kln modulba!
Ciklusmag
lnko.h:

#ifndef LNKO_H
Felttel
#define LNKO_H

unsigned lnko(unsigned a, unsigned b);


Plda: n! kiszmtsa szorzssal.
#endif
n beolvassa
A fejlcfjl a deklarcin kvl a preprocesszornak szl fel-
i=j=0 tteles fordtsi utastsokat is tartalmaz. Ezek azt a clt szolgl-
jk, hogy a fejlcfjl tartalmt a fordt csak egyszer fordtsa bele
i<=n egy adott forrsfjlba. Norml esetben egyszer szerepel egy
fejlcllomny beszerkesztse egy fjlban, azonban gyakran
i++ elfordul, hogy az egyik fejlcllomnyt beszerkeszti egy msik,
j*=i s a forrsfjlban erre nem figyelve mindkettt beszerkesztjk.
Ami viszont valdi problmt okozhat: ha az egyik fejlcbe
j kirsa beszerkesztjk a msikat, a msikba pedig az egyiket. Ha ez ellen
nem vdekeznk a fenti mdon, akkor a fordt nem tudja lefor-
dtani a kdot, mert ez egy vgtelen rekurzi.
A struktogram tglalapjai nem felttlenl egyforma szless- Ha a #ifndef utn megadott szimblum (LNKO_H) mr defi-
gek, pl. a ciklus magjban lehetne feltteles elgazs, annak az nilva van, akkor a fordt nem szerkeszti be a #endif-ig tart
igaz gn egy msik ciklus, stb. rszt, ha mg nincs definilva, akkor beszerkeszti. A kvetkez
sorban definiljuk (a #define-nal definilt konstansok s makrk
esetben is ugyangy vizsglhat a szimblum ltezse.)

lnko.c:

#include "lnko.h"

unsigned lnko(unsigned a, unsigned b){


unsigned i=a<b?a:b;
for(;i>1;i--)
if(a%i==0 && b%i==0)return i;
return 1;
}

66
A fejlcfjl nevt "" kztt adtuk meg, mert a programunk hasznlni veszlyes. Br globlis vltozt hasznlni knyelmes-
mappjban tallhat, nem pedig a rendszer mappban. Itt jelen nek tnhet (nem kell paramtert tadni a fggvnynek), a globlis
esetben ez a beszerkeszts el is hagyhat, azonban clszer gy vltozk ttekinthetetlenn s rugalmatlann teszik a program
rnunk a programjainkat, mert ha a fejlcben deklarljuk az sz- felptst. Ha egy vltozt brmely fggvny megvltoztathat,
szes fggvnyt, akkor a forrsllomnyban nem kell arra figyel- akkor knnyen elveszthetjk a fonalat, s csak hosszas keresg-
nnk, hogy az egyik fggvnyben hasznlt fggvny megelzze a ls utn derthetjk fel, melyik fggvny is vltoztatta meg sz-
msikat. munkra kellemetlen mdon. A globlis vltozkkal operl prog-
ram ksbb csak nehzkesen bvthet.
main.c:
Fggvnydeklarci, fggvnydefinci Lsd az 5.2 fejezet-
#include <stdio.h> ben.
#include "lnko.h"
Plda
int main(void){
printf("lnko(273,865)=%u\n" #include <stdio.h>
,lnko(273,865));
printf("lnko(342,88395)=%u\n" #define INT_KIIR(a) printf("%d\n",a)
,lnko(342,88395));
printf("lnko(97842834,762321)=%u\n" #include <stdlib.h>
,lnko(97842834,762321));
printf("lnko(8192,6144)=%u\n" void valtoztat(int);
,lnko(8192,6144));
printf("lnko(836525,43210)=%u\n" int x;
,lnko(836525,43210));
return 0; extern int y;
}
int main(void){
gy hasznljuk az lnko-t, mint a knyvtri fggvnyeket. int a=0,b;
A C fordtval futtathat programokon kvl ltrehozhatunk x=y;
fggvnyknyvtrakat is. Visual C-ben ehhez Library Projectet INT_KIIR(x);
kell indtani. A knyvtr projekt ugyanolyan .c s .h fjlokbl ll, valtoztat(a);
mint a futtathat programok projektjei, de nincs main fggvny. INT_KIIR(x);
A fordts utn ltrejv .lib fjlt hozz kell adni az azt hasznl return 0;
program linker belltsainak megfelel sorhoz. (A szabvnyos }
fggvnyeket (printf, fopen, sqrt stb.) ugyanilyen lib fjlok tar-
talmazzk.) A fggvnyek hasznlathoz szksg van a deklar- int y=21;
cikat tartalmaz fejlcllomny (elksztsre s) beszerkeszt-
sre. void valtoztat(int y){
x=y;
}
21.2 A C programok ltalnos felptse
Az INT_KIIR egy fggvnyszer makr, mivel a
Egy C program a kvetkez rszekbl plhet fel: preprocesszor dolgozza fel, nincs pontosvessz a vgn.
fejlcfjlok beszerkesztse Az x vltoz kezdrtke 0, mert globlis, a b vltoz kezd-
preprocesszor konstansok, makrk defincija rtke memriaszemt, mert loklis.
globlis vltozk, konstansok A #include sorok nem felttlenl a fjl elejn vannak. Oda
globlis tpusdefincik tesszk, ahov be akarjuk szrni a megadott fjl tartalmt (ad
fggvnydeklarcik absurdum mg fggvnyen bell is lehet specilis esetben).
fggvnydefincik A main fggvny eltt szerepel a valtoztat fggvny s az y
Ezek kzl brmelyik elhagyhat, ha nincs r szksg. Sor- vltoz deklarcija. Ezeket a main utn definiljuk. A deklarci-
rendjk nem kttt, akr vegyesen is alkalmazhatk. ban ha akarjuk, elhagyhatjuk a paramtervltoz nevt, csak a
tpust adjuk meg. Az extern kulcssz globlis vltoz deklarl-
Fejlcfjlok beszerkesztse A #include kezdet sorok, lsd az st teszi lehetv, azaz egy mshol definilt globlis vltoz
5.2 fejezetben. ltezst jelenti be. ltalban a mshol egy msik forrsfjlban
van, erre utal az external=kls szbl ered trolsi osztly.
Preprocesszor konstansok, makrk defincija A #define Loklis vltoz esetn nem hasznlhatjuk az extern trolsi osz-
kezdet sorok, lsd a 31. fejezetben. tlyt.
A valtoztat fggvny defincijban szerepel egy loklis y
Globlis vltozk, konstansok, tpusdefincik Vltozkat, nev vltoz defincija. A loklis vltoz eltakarja a globlisat,
konstansokat, tpusokat lehet definilni fggvnyen kvl is. azaz ebben a fggvnyben nem rhet el a globlis vltoz, de
Ebben az esetben ezek globlisak lesznek, azaz brmely ezt ms problmt a dolog nem okoz.
kvet fggvnyben hasznlhatk. Hasznlhatk tovbb a defi-
ncit megelzen vagy msik forrsfjlban is, ha eltte szerepel 21.3 Lthatsg, trolsi osztlyok
a deklarcijuk.
A globlis vltozk kezdrtke nulla, ha nem adunk kezd-
Az albbiakban, ha fjlrl vagy forrsfjlrl beszlnk, azt a
rtket. (Emlkezznk, hogy a fggvnyben definilt, azaz loklis
fjlt rtjk alatta, ami kijn a preprocesszorbl, s a fordthoz
vltoz esetn memriaszemt volt!)
kerl. Azaz a #include-dal beszerkesztett fjlok
Korbbi programjainkban kerltk a globlis vltozk hasz-
vge nem jelenti a fjl vgt.
nlatt, s a jvben is kerlni fogjuk, mert globlis vltozt

67
// kap rtket!
if(x>0)i++;
Lokalits A fggvnyen kvl definilt vltozok a globlis return i;
vltozk, a fggvnyen bell definilt vltozk a loklis vltozk. }

int main(){
Lthatsg A globlis vltozk a defincitl a fjl vgig auto int a=3; // = int a=3;
lthatk, a loklis vltozk az azokat definil blokk vgig, azaz register int b=5;
a blokkot lezr }-ig. auto int c; // memriaszemt kezdrtk
Loklis vltoz nem csak a fggvny elejn, hanem brmely register int d; // memriaszemt kezdrtk
extern int glob; // csak deklarci
{} blokk elejn (a C99 szabvnytl mr nem csak az elejn) static int st; // 0 kezdrtk
definilhatk. Pldul if(x>y){int a=x; x=y; y=a; }. Ebben az {
esetben az a vltoz csak az if-et lezr }-ig l, utna megsemmi- int x; // auto vltoz, a blokk vgig l
}
sl, s persze nem is lthat. // itt mr nem rhatjuk, hogy x=3;,
// mert a blokk utn vagyunk
lettartam Mikor jn ltre a vltoz s meddig ltezik. Az }
auto s register vltozk definilsuktl a blokk vgig lnek; a int glob; // msik forrsfjlbl is elrhet
globlis, statikus s extern vltozk a program mkdse alatt // extern-nel, 0 kezdrtk
mindvgig lnek; a dinamikus vltozk a lefoglalsuktl a felsza-
badtsukig, de legksbb a program vgig lnek.
Gondolkozzunk egytt!
A trolsi osztly a vltozk ill. fggvnyek trolsi mdjt
hatrozza meg. Ngy nevestett trolsi osztly van a C-ben:
auto, register, static, extern.
auto, register: ezek csak loklis vltozk lehetnek. Ha Oldja meg egyedl!
egy loklis vltoznl nincs megadva, a fordt dnti el,
hogy a kett kzl melyiket vlasztja. (Egybknt ha
lib ksztse is
register-t adunk meg, a fordt akkor is automatikuss de-
finilhatja a vltozt.) Az auto s register vltozk a
blokk/fggvny vgig lnek, ott megsemmislnek, kez-
drtkk brmi lehet (memriaszemt). A register vlto-
zt a fordt a processzor valamelyik regiszterben pr-
blja elhelyezni, ezltal gyors hozzfrst biztostva.
static: fggvny s vltoz is lehet. Vltoz esetben
mst jelent, ha loklis vltozra adjuk meg, s mst, ha
globlisra. Ha statikus vltoznak nem adunk kezdrt-
ket, akkor 0 lesz.
o Ha egy loklis vltoz statikus, akkor a vltoz meg-
rzi az rtkt a fggvny kt meghvsa kztt.
Olyan, mintha egy globlis vltozt hasznlnnk, ami
ms fggvnybl nem lthat. A megadott kezdrt-
kt csak a fggvny els meghvsakor kapja meg,
ksbb ezzel nem rdik fell (a lenti pldban a
szamol fggvny ltal visszaadott rtk minden olyan
hvsnl eggyel nagyobb, amikor x>0).
o Ha egy globlis vltoz statikus, az nem rhet el m-
sik forrsfjlbl extern segtsgvel.
o A fggvnyek mindig globlisak. Ha egy fggvny
statikus, akkor nem rhet el msik forrsfjlbl a
deklarci megadsval.
extern: ugyanazt a clt szolglja, mint a fggvnynl a
deklarci. Teht gy lehet vltozt deklarlni gy, hogy
az adott helyen nem definiljuk. Loklis vltozra nem
hivatkozhatunk extern-nel (a lenti programban nem rhat-
tuk volna extern int glob; helyett, hogy extern int a;).

#include <stdio.h>

// csak ebben a forrsfjlban elrhet, 0 kezdrtk


static int sta_glo;

// ez csak deklarci, kell definci, ami


// msik fjlban is lehet
extern int kulso;

static void sta_fv(){


printf("Csak itt elrhet.\n");
}

extern void ext_fv(); // = ext_fv();

int szamol(register int x){


static int i=0; // Ha nem adunk kezdrtket,
// akkor is biztosan 0.
// Csak az els hvsnl

68
22. A parancssor
Gondolkozzunk egytt!
Amikor a C nyelv megszletett, mg nem lteztek grafikus
fellet opercis rendszerek, csak szvegesek. Ezekben teljesen
termszetes volt a programok parancssori paramterrel val
indtsa. Ez a lehetsg ma is megvan, br ritkbban hasznljuk. Oldja meg egyedl!
A C nyelv a main fggvny paramtereiknt tudja tvenni a
parancssori paramtereket.

Pl. mkdir p /home/laci/sajtok/gouda

A fenti unix program ltrehozza a megadott mappt, a p-vel


jelezzk, hogy ha a teljes tvonal nem ltezik, akkor hozza ltre a
hinyz mappkat is.
Prbljuk meg elkszteni a program C vltozatt!

mkdir.c els vltozat:

int main(void){
...
return 0;
}

Ez nem ltja a parancssori paramtereket.

mkdir.c msodik vltozat:

int main(int db){


printf("A paramterek szma: %d\n",db);
...
return 0;
}

Ez mr tudja, hogy hny paramtert adtunk meg, de azt mg


nem, hogy mik a paramterek.

mkdir.c harmadik vltozat:

int main(int db,char * parameterek[]){


int i;
printf("A program neve: %s\n",parameterek[0]);
for(i=1;i<db;i++)
printf("A %d. paramter: %s\n",i,parameterek[i]);
...
return 0;
}

Ez a vltozat kezeli a parancssori paramtereket. A pldban


szerepl paramterekkel meghvva db rtke 3 lesz, a
parameterek tmb pedig:

0 "mkdir"
[1 ] "-p"
2 "/home/laci/sajtok/gouda"

Mivel a 0 index paramter a program neve, db mindig leg-


albb 1. A main vltozinak neve brmi lehet, gyakran argc-nek
hvjk a darabszmot s argv-nek a pointertmbt. Ha szmot
krnk parancssori paramterknt, a program azt is sztring for-
mban kapja. A sztringbl pl. a sscanf fggvny segtsgvel
tudunk szmot nyerni (az atof, atoi, atol fggvnyek is hasznl-
hatk).
Nhny C fordt tovbbi main formtumot is megenged. a
Visual C az albbit:

int main(int argc,char *argv[],char *envp[]);

Az envp az opercis rendszer n. krnyezeti vltozit tar-


talmazza, a tmb vgt NULL pointer jelzi.

69
23. Fjlkezels Ha nem sikerlt megnyitni egy fjlt valamirt (pl. nem ltez
fjlt akarunk olvasni, vagy nem rhat meghajtra akarunk fjlt
rsra nyitni), akkor fp rtke NULL lesz.
A fjlok arra szolglnak, hogy vltozink tartalmt a szm- Miutn vgeztnk a fjl rsval, be kell zrni azt az fclose
tgp kikapcsolsa utn is megrizhessk, illetve hogy msok fggvny segtsgvel. Az fclose egy paramtert kap: a megnyi-
ltal elmentett adatokat feldolgozhassunk,msok ltal ksztett tott fjl fjlpointert. Tilos egy mr bezrt fjlra ismt meghvni
programokat futtathassunk. Ezekben ugyanolyan bjtokat tro- az fclose fggvnyt!
lunk, mint a memria tartalma. Nem kell teht mst tenni, mint a
memria tartalmt vltoztats nlkl a httrtrra msolni, illetve
onnan beolvasni. A C szabvnyos fggvnyeivel ez nagyon egy-
23.1 Binris fjlok
szer.
A C nyelv ktfle magas szint fjlkezelst tmogat: egy l- Fjl binris olvassa az fread fggvnnyel, rsa az fwrite
talnos fjlt s egy specilis fjlkezelst. fggvnnyel trtnik. A kt fggvny paramterezse s visszat-
Az ltalnos fjlkezelst binris fjlkezelsnek nevezzk. rsi rtke ugyanaz.
Ha egy fjlt binrisan kezelnk, akkor a fjlkezel fggvnynek Els paramter: a kirand/olvasand adat memriacme.
egy memriacmet adunk, s egy egsz szmot, mely megmond- Msodik paramter: egy adat (egy tmbelem) mrete.
ja, hogy hny bjtot szeretnnk beolvasni vagy kirni. Harmadik paramter: a tmb elemszma (nem tmbnl
A specilis fjlkezels alatt azt rtjk, hogy a nyelv ismeri az 1).
adott fjltpus bels felptst, azt teht a programoznak nem Negyedik paramter: a fjlpointer.
kell. A C nyelvben tmogatott specilis fjl a szveges fjl. Ms Visszatrsi rtk: hny darab tmbelemet sikerlt kir-
programnyelvek (pl. php) tmogatja pldul a jpg, png, stb grafi- ni/beolvasni. Ha ismeretlen mret fjlt olvasunk be, ak-
kus llomnyokat, a zip archvumokat, stb. A C sajnos nem ilyen kor ezt hasznlhatjuk annak vizsglatra, hogy elrtk-e a
bkez, br lteznek kls fejleszts knyvtrak ezen fjltpu- fjl vgt.
sok tmogatsra. A msodik s harmadik paramter szorzata a tmb mrett
Brhogyan is kezeljk a fjlt, azt meg kell nyitni hasznlat adja bjtokba, hasonlt lttunk a calloc fggvnynl, ott azonban
eltt, amit az fopen fggvnnyel tehetnk, s be kell zrni, ami az a kt paramter fordtott sorrendben szerepelt: elbb az elem-
fclose fggvny dolga. szm, aztn egy elem mrete. Ilyen az, amikor kt ember kszt el
Az fopen prototpusa: egy programozsi nyelvet ;-).
FILE *fopen(const char *filename, const char *mode);
Pldaprogram:
A fggvny teht egy pointert ad vissza, melynek tpusa FI- #include <stdio.h>
LE *. A FILE egy struktratpus, amely az stdio.h-ban van defi- #include <stdlib.h>
nilva. A struktrban tallhatk azok az adatok, melyek segts-
void hiba(char * s){
gvel a szabvnyos fggvnyek a fjllal dolgozni tudnak. Sz- fprintf(stderr,%s\n,s);
munkra nincs jelentsge a struktra tartalmnak. Annyi a dol- exit(1);
gunk, hogy az fopen ltal visszaadott pointert odaadjuk a fjlbl }
olvas vagy oda r fggvnyeknek, melyek a fjlpointer alapjn typedef struct{
tudjk, mely fjllal kell dolgozniuk. char nev[40],cim[100];
Az fopen els paramtere a fjl nevt tartalmaz sztring, me- double egyenleg;
}elofizeto;
lyet konstansknt vagy karaktertmbben egyarnt megadhatunk.
A fjl neve elrsi tvonalat is tartalmazhat. Ha nem adjuk meg, int main(void){
az aktulis mappban keresi a fjlt. char szoveg[100]="Nyaktekerszetimellfekvenc.";
double t[20];
Az fopen msodik paramtere szintn sztring, a fjl megnyi- int x=3;
tsnak mdja. A md els karaktere w, r vagy a, jelentse elofizeto jozsi={"Jzsi","Hd alatt",2300};
write read ill. append azaz rni, olvasni vagy hozzrni elofizeto et[30];
akarunk-e a fjlhoz. Msodik karaktere b vagy t: binary
//fjlnyits
vagy text. A t elhagyhat, teht pl. a "wt" s a "w" ugyanazt
jelenti. Ha rsra nyitjuk meg a fjlt, akkor a fjl FILE * fp=fopen("progalapjai.xyz","wb");
korbbi tartalma elvsz, ha hozzrsra, akkor a if(fp==NULL)
hiba("Fajlnyitas.");
korbbi tartalom megmarad, s rskor az eddigi
rsz utn kerl az j tartalom! //fjlrs
A msodik paramter esetn tovbbi lehetsgek is vannak, ezek ismerete nem
ktelez: if(fwrite(szoveg,1,100,fp)!=100)
"w+", "r+", "a+" is hasznlhat (azaz "w+t", "w+b" stb.). Itt a + azt je- hiba("Nem irta ki jol a char tombot.");
lenti, hogy a fjlt rhatjuk s olvashatjuk is egyszerre. A hrom vltozat if(fwrite(t,sizeof(double),20,fp)!=20)
kztt az a klnbsg, hogy a w+ letrli a fjlt, ha ltezett korbban, s hiba("Nem irta ki jol a double tombot.");
a megnyitott res fjl elejn llunk; r+ esetn szintn a fjl elejn l- if(fwrite(&x,sizeof(int),1,fp)!=1)
lunk, viszont nem trldik a korbbi tartalom; a+ esetn nem trldik a hiba("Nem irta ki jol az int-et.");
tartalom, s a fjl vgn llunk. if(fwrite(&jozsi,sizeof(elofizeto),1,fp)!=1)
A "w+", "r+", "a+" opcikat akkor tudjuk kihasznlni, ha tudunk mozogni hiba("Nem irta ki jol jozsit.");
a fjlban. A rewind fggvnnyel a fjl elejre mozoghatunk. Pontosabb if(fwrite(et,sizeof(elofizeto),30,fp)!=30)
pozcionlst tesz lehetv az fseek fggvny. Pl.: fseek(fp, n, hiba("Nem irta ki jol az elofizeto tombot.");
SEEK_SET); Els paramtere a fjlpointer, msodik, hogy hny bjtnyit
akarunk mozogni, harmadik paramtere hrom konstans lehet: //fjlzrs, fjlnyits
SEEK_SET, SEEK_CUR s SEEK_END. SEEK_SET esetn a fjl elejtl
mozgunk, SEEK_CUR esetn a jelenlegi helytl, SEEK_END esetn a fjl fclose(fp);
vgtl. Az n rtke negatv is lehet, ekkor a megadott helytl ennyi bjtot fp=fopen("progalapjai.xyz","rb");
mozgunk visszafel. Az n long int tpus rtk, ami 32 bites rendszerben if(fp==NULL)
ltalban 32 bites, ami maximum 2 GB-os tartomny elrst teszi lehet- hiba("Fajlnyitas 2.");
v, nagy fjloknl erre figyeljnk!
//fjlolvass
Az ftell fggvny megmondja, hogy a fjl elejtl hny bjtra vagyunk je-
lenleg. Ez is long tpus rtket ad vissza, teht 2 GB fltt nem mkdik
if(fread(szoveg,1,100,fp)!=100)
32 bites long tpus esetn.

70
hiba("Nem olvasta be jol a char tombot."); (Binris fjlok esetben tisztban kell lenni az adatok trolsi mdjval, ha k-
if(fread(t,sizeof(double),20,fp)!=20) lnbz rendszerek kztt akarjuk tvinni az adatokat. Pldul az Intel/AMD
hiba("Nem olvasta be jol a double tombot."); processzorok az egy bjtnl nagyobb adattpusok bjtjait fordtott sorrendben
if(fread(&x,sizeof(int),1,fp)!=1) troljk. Errl meggyzdhetnk, ha lefuttatjuk az albbi kdot:
hiba("Nem olvasta be jol az int-et.");
if(fread(&jozsi,sizeof(elofizeto),1,fp)!=1) #include <stdio.h>
hiba("Nem olvasta be jol jozsit.");
if(fread(et,sizeof(elofizeto),30,fp)!=30) int main(void){
hiba("Nem olvasta be jol az elofiz tombot."); int a=0x04030201;
char * p=(char*)&a;
//fjlzrs printf("%x,%x,%x,%x\n",p[0],p[1],p[2],p[3]);
return 0;
fclose(fp); }
return 0;
} Intel architektrn az eredmny: 1,2,3,4. Pl. Motorola architektrn viszont
4,3,2,1.)
A pldaprogram hibakezelstl megcsupasztott vltozata (ez A szveges fjlok htrnya, hogy elssorban a beolvassuk
ttekinthetbb, de a gyakorlatban fontos a hibakezels, ne hagy- sokkal nehzkesebb, mint a binris fjlok. Ha binris fjlba
juk el!): mentnk egy egsz szmot, az mindig ugyanannyi bjtot foglal,
mg szveges formban nem ez a helyzet: a 3 s a -21342131
#include <stdio.h> egyarnt belefr egy 32 vagy tbb bites int-be, viszont lthatan
az elbbi egy bjtot (karaktert), utbbi viszont 9 bjtot foglal
typedef struct{
char nev[40],cim[100]; szveges formban. Ha egy karaktertmbt runk ki binris fjl-
double egyenleg; ba, az mindig ugyanolyan hossz, ha egy sztringet runk ki sz-
}elofizeto; veges fjlba, az nem egyforma hossz.
int main(void){ Tovbbi gond, hogy mivel a szveges fjlt brki brmilyen
char szoveg[100]="Nyaktekerszetimellfekvenc."; szvegszerkesztvel szerkesztheti, fel kell kszlni arra, hogy a
double t[20]; beolvasott fjl nem pont olyan, mint a kirt: a felhasznl esetleg
int x=3;
elofizeto jozsi={"Jzsi","Hd alatt",2300};
kt szkzt rt az adatok kz egy helyett, stb.
elofizeto et[30]; A szveges fjlok kezelse mindenkinek ismers lesz, mert a
kpernyre r s a billentyzetrl olvas fggvnyekhez nagyon
//fjlnyits
hasonl fggvnyeket hasznlhatunk.
FILE * fp=fopen("progalapjai.xyz","wb"); A .c ill. .h kiterjeszts forrsllomnyok ppgy szveges
fjlok, mint a .html vagy a .php fjlok.
//fjlrs

fwrite(szoveg,1,100,fp); A fggvnyek
fwrite(t,sizeof(double),20,fp); fprintf: a printf s az sprintf rokona, szveget r szveges
fwrite(&x,sizeof(int),1,fp); fjlba. Els paramtere a megnyitott fjl fjlpointere, ezt kveti a
fwrite(&jozsi,sizeof(elofizeto),1,fp);
fwrite(et,sizeof(elofizeto),30,fp); formtumsztring, majd a formtumsztringben jelzett vltozk
illetve konstansok.
//fjlzrs, fjlnyits fputs: a puts fjlba r vltozata. Kt paramtere van: a ki-
fclose(fp);
rand sztring s a fjlpointer. A puts-sel ellenttben az fputs nem
fp=fopen("progalapjai.xyz","rb"); r ki jsort a sztring vgn.
fputc: a putchar fjlba r vltozata. Kt paramtere van: a
//fjlolvass kirand karakter s a fjlpointer.
fread(szoveg,1,100,fp); Pldul: rjunk programot, amely kirja a hellovilag.c nev
fread(t,sizeof(double),20,fp); fjlba a Hello vilag! szveget kir C programot!
fread(&x,sizeof(int),1,fp);
fread(&jozsi,sizeof(elofizeto),1,fp); #include <stdio.h>
fread(et,sizeof(elofizeto),30,fp);

//fjlzrs int main(void){


FILE * fp=fopen("hellovilag.c","wt");
fclose(fp); if(fp!=NULL){
return 0; fprintf(fp,"#include <stdio.h>\n\n");
} fprintf(fp,"int main(void){\n");
fputs(" printf(\"Hello vilag!\");\n",fp);
fputc('}',fp);
Lthat, hogy egy bonyolult struktrt is egyszeren kirt s fputc('\n',fp);
beolvasott. Szveges fjl esetn az adattagokat kln-kln ki fclose(fp);
kellett volna rni/be kellett volna olvasni. A binris fjlban az }
else{
adatok abban a binris formban kerlnek kirsra, ahogy a sz- fprintf(stderr,"Sikertelen fajlnyitsa.\n");
mtgp memrijban megtallhatk, teht az gy ltrejtt fjl }
ltalban nem olvashat szvegszerkeszt programmal. return 0;
}
Ezzel a mdszerrel a szveges fjlok is olvashatk, pldul
karakterenknt. Ebben az esetben persze neknk kell figyelnnk
Fordtsa s futtassa le a programot, majd keresse meg a ltre-
pldul az jsor karakterekre, s ha a szveges fjlban szmok is
jtt hellovilag.c-t!
vannak, akkor neknk kell a kls formtum (karakterekbl
ll) szmot bels formtumra (binrisra) alaktani.
fscanf: a scanf s az sscanf rokona, szveget olvas szveges
fjlbl. Els paramtere a megnyitott fjl fjlpointere, ezt kveti a
23.2 Szveges fjlok formtumsztring, majd a formtumsztringben jelzett vltozk
cmei.
A szveges fjlok, ahogy nevnk is mondja, szvegeket tar- fgets: a gets fjlbl olvas vltozata. Hrom paramtere van a
talmaznak. Brmely szvegszerkesztvel megnyithatk, s k- 12.2 fejezetben rottaknak megfelelen: a cl karaktertmb cme,
lnbz szmtgp-architektrk kztt hordozhatk. a karaktertmb mrete s a fjlpointer.

71
fgetc: a getchar fjlbl olvas vltozata. Egy paramtere van:
a fjlpointer, visszatrsi rtke a beolvasott karakter, vagy EOF,
ha nem sikerlt az olvass.
Pldul rjunk programot, amely beolvassa a hellovilag.c
fjl tartalmt, s kirja a kpernyre!

#include <stdlib.h>
Csv-be mentve a kvetkez szveges fjlt kapjuk:
void hiba(const char * s){
fprintf(stderr,"%s",s); Gipsz Jakab;Trutty Vilma;1848.03.15;+36-30-112345678
exit(1); Gipsz Jakabn;Mocsri Vipera;1988.01.03;+36-30-112345678
}

int main(void){ Feladat: rjuk ki azon a szemlyek nevt, akik mrciusban


FILE * fp=fopen("hellovilag.c","rt"); szlettek, anyjuk msodik neve (ami valsznleg a keresztneve)
char s[100];
int ch; pedig V-vel kezddik!

if(fp!=NULL){ Ha a szveges fjlunk ilyen sszetett sorokat tartalmaz, akkor


if(fgets(s,100,fp)==NULL)
hiba("1. sor hianyzik");
nem rdemes az fscanf-fel bajldni, jobban jrunk, ha soronknt
printf("%s",s); olvassuk, s a sort mint sztringet dolgozzuk fel.
if(fgets(s,100,fp)==NULL)
hiba("2. sor hianyzik"); #include <stdio.h>
printf("%s",s); #include <stdlib.h>
if(fscanf(fp,"%s",s)!=1)
hiba("int hianyzik"); void hiba(const char * s){
printf("%s ",s); fprintf(stderr,"%s",s);
if(fscanf(fp,"%s",s)!=1) exit(1);
hiba("main(void){ hianyzik"); }
printf("%s",s);
if(fgets(s,100,fp)==NULL) // A forrs sztringet szepartor karakterek osztjk
hiba("ujsor jel hianyzik (1)"); // oszlopokra.
printf("%s",s); // az ENTER-t olvassa // Az oszlopadik oszlopot tmsolja a cl tmbbe
if(fgets(s,100,fp)==NULL) int get_oszlop(const char * forras
hiba("4. sor hianyzik"); ,char szeparator,int oszlop,char * cel){
printf("%s",s); int n,i,j;
if((ch=fgetc(fp))==EOF)
hiba("} hianyzik"); // az n. oszlop elejnek megkeresse
putchar(ch);
if((ch=fgetc(fp))==EOF) for(i=n=0; forras[i]!=0 && n<oszlop; i++)
hiba("ujsor jel hianyzik (2)"); if(forras[i]==szeparator)n++;
putchar(ch); // az ENTER-t olvassa if(n!=oszlop)return 0; // nincs n. oszlop
}
else{ // tmsols a cl tmbbe
fprintf(stderr,"Sikertelen fajlnyitsa.\n");
} for(j=0; forras[i]!=0 && forras[i]!=szeparator;
return 0; i++,j++)cel[j]=forras[i];
} cel[j]=0;
return 1;
}
Mindhrom fggvny hasznlatt be szerettk volna mutatni,
ahogy az elz pldban is, de egyszerbben is megoldhattuk
volna a feladatot, pl. gy: int main(void){
FILE * fp=fopen("emberek.csv","rt");
int main(void){ char s[400],t1[100],t2[100];
FILE * fp=fopen("hellovilag.c","rt");
char s[100]; if(fp==NULL)hiba("Sikertelen fajlnyitsa.\n");

if(fp!=NULL){ // soronknt olvasunk


while(fgets(s,100,fp)!=NULL)printf("%s",s);
} while(fgets(s,400,fp)!=NULL){
else{
fprintf(stderr,"Sikertelen fajlnyitsa.\n"); // t1-be az anyja neve, t2-be a keresztnv
}
return 0; if( get_oszlop(s,';',1,t1)
} && get_oszlop(t1,' ',1,t2) ){

// Ha a keresztnv V-vel kezddik,


Excel fjl feldolgozsa Magyar nyelv Excellel ksztettnk // t1-be teszi a szletsi dtumot
egy tblzatot, melyben a kvetkez adatoszlopok szerepelnek:
if(t2[0]=='V' && get_oszlop(s,';',2,t1)){
Nv int ev,honap,nap;
Anyja neve
Szletsi v.hnap.nap, pl.: 1848.03.15 // Ha mrciusi, kirja

Telefonszm if(sscanf(t1,"%d.%d.%d"
A tblzatot elmentjk az emberek.csv fjlba. (A magyar ,&ev,&honap,&nap)==3 && honap==3){
Excel pontosvesszvel tagolt fjlt hoz ltre, mg az angol vessz- get_oszlop(s,';',0,t2);
printf("%s\n",t2);
vel tagoltat, ahogy a csv nevbl is kvetkezik: comma separated }
values vesszvel elvlasztott rtkek.) }
}
}
return 0;
}

72
A get_oszlop fggvny a forrs sztringbl a cl sztringbe m- tabb: elmletileg brmilyen karakter elfordulhat benne (akr
solja azt a rszt, amely a szepartor karakter oszlop-adik s osz- soremels is), mi legyen az elvlaszt karakter? Binris fjl ese-
lop+1-edik elfordulsa kztt tallhat. Ha nincs benne oszlop- tn a sztringekkel sincs semmi gond, ahogy a fenti pldban
szor a szepartor, HAMIS visszatrsi rtkkel jelzi ezt. Helyesen szerepel: elmentjk az egsz tmbt, azt a rszt is, ahol mr vget
kezeli azt az esetet is, amikor van oszlop darab oszlop, de ez az rt a sztring. Ezzel ugyan tbb helyet foglalunk, de cserbe na-
utols, utna nincs szepartor. gyon egyszer a kezels.
A main fggvnyben egy while ciklus olvassa az embe- Szveges fjl s binris fjl kztti dntsnl mindig az adott
rek.csv sorait a fjl vgig. A feldolgozs sorn vgig figyelnk feladatnak legjobban megfelel formtumot vlasszuk!
a hibkra. Ha egy sor hibs, azaz nincs benne annyi oszlop,
amennyi kell, a kvetkez sorra lpnk. 23.4 Szabvnyos bemenet s kimenet
A get_oszlop fggvnnyel kiolvassuk t1-be az 1-es oszlopot,
azaz az anyja nevt, s abbl kiolvassuk a msodik nevet a t2-be.
Ez azrt lehetsges, mert az oszlopokat pontosvessz, a neveket A program szabvnyos bemenete alaprtelmezs szerint a bil-
pedig szkz vlasztja el egymstl. lentyzet, kimenete a kperny, de ez tirnythat.
Pl.: programom.exe > kimenet.txt
Az oszlopokat 0-tl szmozzuk, ha gondolja, trhatja a prog- Ltezik hrom olyan szabvnyos globlis vltoz, amely sz-
ramot gy, hogy 1-tl szmoljon. Mit kell ehhez vltoztatni? veges fjlknt viselkedik:
stdin // standard input
Figyeljk meg, hogy a get_oszlop(s,';',1,t1) && stdout // standard output
stderr // standard error
get_oszlop(t1,' ',1,t2) kifejezsben kihasznljuk az && opertor
mindkt specilis tulajdonsgt: a rvidzrat s azt, hogy kirt- Ezek kzl az stdin olvashat, az stdout s stderr rhat a
kelsi pont. A rvidzr azt jelenti, hogy ha az els get_oszlop szvegfjl-kezel fggvnyekkel.
hvs HAMIS-sal tr vissza, a msodik hvs nem trtnik meg, Megnyitni, bezrni ezeket nem kell s nem is szabad.
mert HAMIS && BRMI eredmnye biztosan HAMIS. Kirt- Hasznlat pl.:
kelsi pont azt jelenti, hogy az && eltti kifejezs, azaz a fgg- fprintf(stdout,"Hogy hivnak? ");
vnyhvs biztosan megtrtnik, mieltt az && utni kifejezs, if(fgets(s,100,stdin)==NULL){
azaz a msodik fggvnyhvs megtrtnne. Ez azrt fontos, mert fprintf(stderr,"Sikertelen beolvass.");
a msodik fggvnyhvs azt a tmbt hasznlja, amit az els exit(1);
}
ellltott. Kirtkelsi pontknt nem mkd opertorok eset- fprintf(stdout,"%s\n",s);
ben ez nem garantlt, azaz ha pl. int x=get_oszlop(s,';',1,t1) +
get_oszlop(t1,' ',1,t2); utastst rnnk, akkor lehetsges, hogy a A szabvnyos kimenet s a szabvnyos hibakimenet kln-
msodik fggvnyhvs elbb trtnne, mint az els, ami gy kln tirnythat.
hibs bemeneti tmbt kapna.
Az sscanf visszatrsi rtke a sikeresen beolvasott vltozk Gondolkozzunk egytt!
szma, ami itt hrom kell legyen. Ebben az if-ben is kihasznljuk
az && specilis tulajdonsgait.

23.3 Szveges fjlok s binris fjlok Oldja meg egyedl!


sszevetse
A szveges fjl elnye, hogy platformfggetlen: teljesen ms
szmtgp architektrn is ugyangy olvashat. Ha a fenti bin-
ris fjlos pldt 32 bites s 16 bites opercis rendszer alatt is
lefordtjuk, akkor egyik esetben 32 bites az egsz szm, a msik
esetben 16 bites. Ha az egyik rendszerben elmentett fjlt a msik-
ban akarjuk olvasni, gondjaink lesznek emiatt. A szveges fjllal
nincs ilyen problma.
A szveges fjl elnye, hogy minden gpen van egyszer
szvegszerkeszt program, mellyel a felhasznl mdostani
tudja a fjl tartalmt.
A szveges fjl htrnya, hogy minden gpen van egyszer
szvegszerkeszt program, mellyel a felhasznl mdostani
tudja a fjl tartalmt. Emiatt beolvasskor mindig figyelni kell
arra, hogy helyes-e a fjl tartalma. Binris fjlnl nyugodtan lehet
felttelezni, hogy minden adat a helyn van.
A binris fjl elnye, hogy mivel nem kell konvertlni kls
s bels formtum kztt, jval gyorsabban rhat/olvashat,
mint a szveges.
A binris fjl elnye, hogy tmbk, struktrk nagyon egy-
szeren rhatk s olvashatk. Szveges fjlba kzvetlenl csak
alaptpusokat tudunk rni, teht a tmbk elemeit egyenknt (pl.
ciklussal), a struktrkat tagonknt.
A szveges fjl htrnya, hogy beolvassa nagyon macers,
binris fjlnl egy adattpus mindig ugyanakkora helyet foglal.
Ha egy egsz szmot szveges formtumban runk ki, akkor az
lehet pl. 2, vagy lehet pl. -87649829 is. Elbbi 1 karakternyi
helyet foglal, utbbi 10-et. A sztringek helyzete mg bonyolul-

73
III. RSZ: HALAD PROGRAMOZS
24. Dinamikus nhivatkoz adat- Teht mindig lesz szabad pointernk, amivel mutathatunk a
kvetkez adatra.
szerkezetek 1. lncolt listk A struktrban lv pointer ugyanolyan struktrkra mutat,
mint sajt maga nhivatkoz adatszerkezet.
Az ilyen felptsnek az egyszer bvthetsgen tlmenen
Sok adatot feldolgoz programok esetben a feladat jellegtl ms elnyei is vannak:
fggen a kvetkez esetek fordulhatnak el: Ha a lista kzepre akarunk j adatot betenni, akkor csak
Az adatok eltrolsra nincs szksg, mert egyszer v- kt pointert kell tlltani, mg ha pl. egy tmb kzepre
gigolvasva az adatokat a kvnt eredmnyre jutunk. Pl- szeretnnk beszrni, a beszrs utni sszes adatot eggyel
dul ha meg kell szmolni a bemenetrl rkez szveg- htrbb kell msolni.
ben a kisbetket. Ha egynl tbb pointer van a struktrban, nagyon vlto-
Ha a program lefordtsnak idpontjban tudjuk, hogy zatos adatszerkezeteket hozhatunk ltre.
pontosan vagy maximum mennyi adatra szmthatunk, A htrny, hogy ha a lista valamelyik elemt szeretnnk
amit el is kell trolni, akkor tmbt alkalmazhatunk. Pl- megkapni, ahhoz vgig kell jrni a lista elejtl az sszes elemet,
dul konstans sztring; az ts lott nyerszmai, hrom- nem lehet egyszeren sorszm alapjn kiolvasni, mint egy tmb-
dimenzis vektorok s mveleteik, stb. nl.
Ha egy program futsa sorn az adatok beolvassa eltt
tudjuk meg, hogy pontosan vagy maximum mennyi adat- Mintafeladat rjon programot szabvnyos C nyelven, amely
ra szmthatunk, amit el is kell trolni, akkor dinamikus beolvassa egy skbeli poligon cscsainak vals rtk koordint-
tmbt hasznlunk. Pldul kt tetszleges mtrix szorz- it a szabvnyos bemenetrl, majd rja ki a slyponttl jobbra
st elvgz fggvny az eredmnyt egy dinamikus tmb- tallhat koordintkat! A koordintasorozat vgt a 0.0 0.0
ben adja vissza. koordintapr jelzi. A koordintkat szkz vlasztja el egyms-
Ha nem tudjuk elre, mennyi adattal kell majd dolgoz- tl.
nunk, vagy ms okbl egyszerbb, ha mindig az ignye- #include <stdio.h>
inknek megfelel mennyisg memrit tartunk lefoglal- #include <stdlib.h>
va. Pldul ismeretlen mennyisg mrsi adat feldolgo- typedef struct koordinata{
zsa. double x,y;
A memriakezels sszes C eszkzt megismertk mr ko- struct koordinata *next; // a kv. elemre mutat
} koord;
rbban, teht az ismeretlen mennyisg adat eltrolst ezekkel
az eszkzkkel kell megoldanunk. int main(){
Az egyik lehetsges megolds, hogy lefoglalunk egy dinami- koord *start=NULL,*p; // starttl indul a lista
kus tmbt, majd ha betelik, foglalunk egy nagyobbat, ahov double x,y;
unsigned db=0;
tmsoljuk a kicsit, s aztn letrljk az eredetit. Ezzel az a
problma, hogy sok felesleges adatmozgatssal jr, s amg // A lista ltrehozsa
mindkt tmb ltezik, sok felesleges memrit foglalunk. (A
scanf("%lg %lg",&x,&y);
realloc fggvny ugyanezt teszi.) while(x!=0.0 || y!=0.0){
A msik megolds, hogy egyenknt foglalunk memrit az koord *uj=(koord*)malloc(sizeof(koord));
rkez adatoknak. A memria lefoglalsa a malloc/calloc fgg- if(uj==NULL)return 1;
uj->x=x;
vnyek valamelyikvel trtnik, melyek visszaadjk a lefoglalt uj->y=y;
terlet cmt. Ezt a cmet meg kell jegyeznnk, hogy megtalljuk uj->next=start; // a lista elejre fzzk az
a lefoglalt memriaterletet. Ez azt jelenti, hogy ha ezerszer // jat, az = akkor is j, ha res a lista
start=uj;
foglalunk helyet, ezer cmet kell trolnunk, ha tzezerszer fogla- db++;
lunk, akkor tzezret Vagyis ugyangy nem tudjuk, mennyi scanf("%lg %lg",&x,&y);
cmet kell trolnunk, mint ahogy azt sem, hogy mennyi adatot, }
viszont ez a kt szm megegyezik. Megolds: troljuk struktr-
// A koordintk sszegzse
ban egy adatot s egy cmet. A struktrban trolt pointer nem
sajt magra mutat, hanem a kvetkez adatra. for(x=y=0.0, p=start; p!=NULL; p=p->next){
x+=p->x;
y+=p->y;
24.1 Egyszer lncolt lista }
x/=db; y/=db; // ez a slypont, br y-ra
// igazbl nincs is szksg

// a slyponttl jobbra esk kirsa

troland troland troland for(p=start; p!=NULL; p=p->next){


adat adat adat if(p->x>x)printf("(%g,%g)\n",p->x,p->y);
pointer
}
pointer pointer NULL // a lista trlse

if(start!=NULL){
Kezdetben csak egy pointernk van, aztn lefoglalunk egy for(p=start, start=start->next;
struktrt, s eltroljuk benne a beolvasott adatot. A pointert erre start!=NULL; p=start, start=start->next)
lltjuk. A struktra pointert NULL-ra lltjuk jelezve, hogy itt a free(p);
free(p);
lista vge. Amikor lefoglalunk egy jabb adatot, ezt a pointert az }
j adatra lltjuk, s az j adat pointere lesz NULL. return 0;
}

74
pointere pedig az adott elem utni elem lesz. Ez megvalsthat,
A fenti kdban j nyelvi elem a nyl opertor (->). Ez az de a dolgunkat leegyszersthetjk gynevezett strzsa (dummy)
opertor egy pointer ltal mutatott struktra valamelyik adattagjt elem(ek) alkalmazsval a lista egyik, vagy mindkt vgn.
adja. Pldul az uj->x a (*uj).x helyett kerlt a kdba, azzal A strzsa olyan elem, amely nem tartalmaz hasznos adatot,
tkletesen azonos jelents. A *uj azrt zrjelezend, mert a . gy ha a lista elejn ll, akkor el biztos nem kell beszrni sem-
precedencija magasabb, mint az indirekci opertor (*). Mivel mit, ha pedig a vgn ll, akkor utna nem kell beszrni. Ha kt
ez egy gyakori mvelet a C nyelvben, a nyelv kszti gy lttk strzsa van, akkor csak olyan beszrsra kell megrni a beszr
jnak, hogy a ngy karakter (kt zrjel, * s .) helyett csak kt fggvnyt, ami kt elem kz szr be.
karakter kelljen a mvelethez (mnusz: - s nagyobb: >). A kvetkez pldaprogramban a lista mindkt vgn strzsa
A struktratpus ltrehozsakor a struktrn bell nem hasz- ll. A kt strzst nem dinamikusan foglalt struktra alkotja
nlhatjuk a koord tpust, hiszen a nv ksbb szerepel a kdban, (lehetne dinamikus is).
ezrt itt mg struct koordinata tpust adunk meg. Ksbb azonban Elem beszrsa a listba a kvetkezkppen trtnik:
mr hasznlhat a rvidebb vltozat (termszetesen a hosszabb
is). adat adat adat adat
Megjegyzs: a struktrn bell ltrehozhatunk nmagra mu-
tat pointert, hiszen az csak egy pointer, de nem hozhatunk ltre pointer pointer pointer pointer

struct koordinata tpus vltozt, mert az azt jelenten, hogy


azon bell is van egy ilyen struktra, meg azon bell is, meg azon lemarad adat el adat el
lemarad
bell is A rekurzv definci nem megengedett. pointer pointer
A koordintkat ideiglenes vltozkba tesszk el, s csak ak-
kor foglalunk j memrit, ha nem az adatsor vgt jelz 0,0
prra bukkantunk. Az jonnan lefoglalt struktrba bemsoljuk a Megkeressk azt az elemet, amely el szeretnnk beszrni az
koordintkat, majd a next pointert a lista kezdelemre lltjuk j elemet. Ezrt el, mert ha rendezett listt akarunk pteni,
(res listnl NULL pointer: a lista vgt a NULL pointer jelzi, akkor gy talljuk meg a beszrs helyt, hogy addig megynk a
gyhogy ez gy teljesen j), a kezdelem pedig ettl kezdve az listn, mg meg nem talljuk az els olyan elemet, amelynek
jonnan lefoglalt struktra lesz, azaz a lista elejre fztk be az j kulcsa nagyobb (vagy kisebb, ha cskken a lista), mint a besz-
elemet, ms szval az elemek fordtott sorrendben kerltek a rand elem kulcsa. (Kulcs=az az adat, amely szerint rendezzk
listba a beolvasshoz kpest. a listt.) Egy irnyban lncolt listn viszont csak valamely elem
Ha ez gondot okoz, megoldhat, hogy a lista a beolvass sor- el tudunk beszrni, ezrt hasznlunk egy lemarad segdpoin-
rendjvel azonos sorrend legyen, ehhez azonban egy jabb tert. (Egy mozg pointerrel is megoldhat, de nem ezt a megol-
segdvltoz kell, ami a lista vgre mutat, s a kd is valamivel dst vlasztottuk.)
bonyolultabb lesz. Ennek megvalstst az olvasra bzzuk.
Ugyancsak lehetsg, hogy a listt valamilyen felttelnek Feladat rjon szabvnyos C programot, amely a szabvnyos
megfelelen ne a beolvass sorrendjben, hanem ms sorrendben bemenetrl olvassa be lakosok adatait: nv, irnytszm, cm. A
ptsk fel, pldul a kulcsnak vlasztott elem nvekv vagy lakosok szma elre nem ismert. rja ki a lakosok adatait irny-
cskken sorrendjben. Erre ltunk pldt a kvetkez szakasz- tszm szerint nvekv sorrendben, azonos irnytszm esetn
ban. pedig cm szerinti ABC sorrendben (a program az angol ABC
A fenti pldban a listt for ciklussal jrjuk be. A bejrs ha- betire mkdjn helyesen). Az irnytszm ngy- vagy tje-
sonlt egy tmb elemeinek vgigjrshoz: a ciklusvltoz ezttal gy.
pointer, amit a kezdelemre lltunk. A ciklus vge, ha NULL //************************************************
pointerhez rnk, a lptets a ciklusvltoz kvetkez elemre #include <stdio.h>
mozgatst jelenti. #include <stdlib.h>
#include <string.h>
A lista trlse ignyel nmi tgondolst: a segdvltoz mu- //************************************************
tasson a lista kezdelemre, a kezdelem pedig lpjen a kvetke-
zre. Ekkor trlhetjk a segdvltoz ltal mutatottat, gy a lista //************************************************
valban egy elemmel rvidebb lesz. Ezt addig folytatjuk, mg van typedef struct _lakos{
//************************************************
elem a listban. Amire figyelni kell, hogy unsigned irszam;
NULL->next a program azonnali elszllst okozza, teht ezrt char cim[150];
van az if(start!=NULL), s ezrt van a ciklus utn az utols char nev[60];
struct _lakos * next;
free. } lakos;

//************************************************
void hiba(char t[]){
14.2 Lncolt lista strzsval, fggv- //************************************************
printf("Hiba: %s\n",t);
nyekkel, beszrssal }
exit(1);

Az elz plda a lehet legegyszerbb esetet mutatta be. Ha //************************************************


void beszur(lakos * start,const lakos * puj){
bonyolultabb a listakezels, clszer minden mveletnek kln /* Az j elem azrt pointer, mert gy kevesebb adatot
fggvnyt ltrehozni. kell mozgatni, nem kell eltrolni a struktrt a
Ha az egyszer listaptsnl bonyolultabb mveletek is van- stack-en, csak a cmt. A startrl felttelezzk,
hogy nem NULL, mert van strzsa.
nak, pldul beszrs vagy elemcsere, akkor mskpp kell eljrni, */
ha a lista belsejben kell vltoztatni, a lista elejn kell vltoztatni //************************************************
vagy a lista vgn kell vltoztatni. lakos * lemarad=start,*ptemp;
Ha a lista elejre szrunk, a start pointert is meg kell vltoz- start=start->next;
// a start pointer a main-ben lv start
tatni, a meglv listnak viszont nem kell elemt megvltoztatni. // msolata, megvltoztathat visszahats nlkl
Ha a lista vgre szrunk, az j elem pointere NULL lesz, a lista
utols elemnek pointere pedig az j elem cme. Ha kzbe sz- // megkeressk, hov kell beszrni
runk, akkor a lista egy elemnek pointere vltozik, az j elem while(start->next!=NULL //start nem a vgstrzsn

75
&& (start->irszam < puj->irszam
// irnytszm szerint nvekv sorrend 24.3 Kt irnyban lncolt lista
|| (start->irszam == puj->irszam
// azonos irnytszm esetn...
&& strcmp(start->cim,puj->cim)<0))){
// cm szerint nvekv sorrend
lemarad=start; troland troland troland troland
start=start->next; adat adat adat adat
}
NULL pointer pointer pointer
// memriafoglals s beszrs
pointer pointer pointer NULL
ptemp=(lakos*)malloc(sizeof(lakos));
if(ptemp==NULL)hiba("Memoriafoglalas.");
*ptemp=*puj; // a teljes struktra tmsolsa, Ha egynl tbb pointer van a struktrban, akkor sokfle
// a tmbkkel egytt!!! adatszerkezetet tudunk kialaktani. Egyik lehetsg a kt irnyban
ptemp->next=start; lncolt lista.
lemarad->next=ptemp; // ez a kt rtkads
// beszrta lemarad s strat kz
Elnyk:
} Mindkt irnyban tudunk lpkedni az elemek kztt. gy
pldul a gyorsrendez algoritmus hasznlhat lesz kt
//************************************************
void kiir(const lakos * start){
irnyban lncolt listn is, mg az egyirnyn nem.
//************************************************ Nincs szksg a lemarad pointerre, ezltal knnyebb a
for(start=start->next; start->next!=NULL; beszrs vagy a csere.
start=start->next)
printf("Nev: %s\nCim: %u, %s\n\n",
Htrny:
start->nev,start->irszam,start->cim); Tbb pointert kell belltani.
} Nagyobb helyfoglals.
//************************************************ A kvetkez pldban nem bonyoltjuk a listt, ahogy az el-
void torol(lakos * start){ z pldban, egyszeren egy egsz szm lesz a listaelemekben. A
//************************************************ listakezel fggvnyek sort kiegsztjk egy cserl s egy
lakos * lemarad=start->next;
for(start=start->next->next; start->next!=NULL;
keres fggvnnyel.
lemarad=start, start=start->next)
free(lemarad); #include <stdio.h>
} #include <stdlib.h>

//************************************************ //************************************************
const unsigned MaxIranyitoszam=100000; typedef struct _szam{
//************************************************ //************************************************
int n;
//************************************************ struct _szam *prev,*next;
int main(void){ } szam;
//************************************************
lakos strazsa2={MaxIranyitoszam,"","",NULL} //************************************************
,strazsa1={0,"","",&strazsa2}; void hiba(char t[]){
lakos temp={0,"","",NULL}; //************************************************
int jovolt=1; // logikai rtk, ha hiba a printf("Hiba: %s\n",t);
// beolvassnl vagy vge, 0 lesz exit(1);
char s[100]; }

do{ //************************************************
printf("Iranyitoszam: "); void beszur(szam * start,int n){
if(fgets(s,100,stdin)==NULL)jovolt=0; //************************************************
if(jovolt && sscanf(s,"%u",&temp.irszam)!=1) szam * p=NULL;
jovolt=0; for(start=start->next;
if(temp.irszam>=MaxIranyitoszam start->next!=NULL && start->n < n;
|| temp.irszam<1000) start=start->next);
jovolt=0; p=(szam*)malloc(sizeof(szam));
if(jovolt){ if(p==NULL)hiba("malloc sikertelen");
printf("Cim: "); // befzs
if(fgets(temp.cim,150,stdin)==NULL) p->n=n;
jovolt=0; p->prev=start->prev;
} p->next=start;
if(jovolt){ start->prev->next=p;
printf("Nev: "); start->prev=p;
if(fgets(temp.cim,150,stdin)==NULL) }
jovolt=0;
}
if(jovolt)beszur(&strazsa1,&temp); //************************************************
}while(jovolt); void csere(szam * p1,szam * p2){
kiir(&strazsa1); // megcserl a listban kt elemet
torol(&strazsa1); //************************************************
return 0; if(p1==p2)return; // ha szomszdosak:
} if( p1->next==p2 || p1->prev==p2 ){
if(p1->prev==p2){ // pointerek megcserlse
szam *temp=p1;
rdekessg a kt strzsa: nem dinamikus vltozk. A tnyle- p1=p2;
ges listt ezek kz szrjuk be. Start pointerre nincs szksg, p2=temp;
mert a kezdelem a strazsa1, ennek a next elemtl lpkedve }
p1->next=p2->next; // mindig rajzoljunk!
eljuthatunk a lista vgig. // figyeljnk a sorrendre is!
Minden fggvny figyel arra, hogy a strzsk adatt ne hasz- p2->prev=p1->prev;
nlja, s ne prblja felszabadtani. p2->next=p1;
p1->prev=p2;
p2->prev->next=p2;
p1->next->prev=p1;
}

76
else{ // nem szomszdos
// bonyolult => segdpointereket hasznlunk 24.3 Fss lista
szam * szomszed1=p1->prev;
szam * szomszed2=p1->next;
szam * szomszed3=p2->prev; Itt az elemek mr nem mind sorban egyms utn kvetkez-
szam * szomszed4=p2->next; nek, azaz gyorsabban megtallhatjuk a keresett elemet. Ktfle
szomszed1->next=p2; struktra kell a trolshoz:
szomszed2->prev=p2;
szomszed3->next=p1; Amelyik a fs szrt trolja. Ennek tartalma: kulcs, po-
szomszed4->prev=p1; inter a kvetkez szr elemre, pointer az els fog elemre.
p2->prev=szomszed1;
p2->next=szomszed2;
Amelyik a tnyleges adatokat trolja: kznsges lncolt
p1->prev=szomszed3; lista elem.
p1->next=szomszed4;
}
} kulcs kulcs kulcs

pointer pointer pointer NULL


//************************************************
void torol(szam * start){ pointer NULL pointer
//************************************************
szam * p=start->next;
if(p->next==NULL)return;
for(p=p->next ;p->next!=NULL; p=p->next) troland troland
free(p->prev); adat adat
free(p->prev);
p->prev=start; // a kt strzsa egymsra mutat, pointer NULL
// gy korrekt a trls
start->next=p;
} troland
adat
//************************************************
void kiir(szam * start){ NULL
//************************************************
for(start=start->next; start->next!=NULL;
start=start->next) A fss listhoz nem nznk pt/bont kdot, csak bejrst.
printf("%d\n",start->n);
}
A listban telefonknyvet trolunk, a szrban a kulcselemek a
vezetknv kezdbeti, ABC sorrendben. A fogakban az adatok
//************************************************ szintn ABC sorrendben vannak.
szam * keres(szam * start,int n){
//************************************************ //************************************************
for(start=start->next; start->next!=NULL; typedef struct _fogelem{
start=start->next) //************************************************
if(start->n==n)return start; char nev[50];
return NULL; char cim[150];
} char telefonszam[30];
struct _fogelem * next;
} fogelem;
//************************************************
int main(){ //************************************************
//************************************************ typedef struct _nyelelem{
szam strazsa1,strazsa2; //************************************************
int n; char kulcs;
szam *p1=NULL,*p2=NULL; struct _nyelelem * pkovnyel;
fogelem * pfog;
// A kt strzsa lncba fzse } nyelelem;
strazsa1.prev=strazsa2.next=NULL; //************************************************
strazsa1.next=&strazsa2;
fogelem * keres1(nyelelem * start,char keresett[]){
strazsa2.prev=&strazsa1;
//************************************************
fogelem * pfog;
// beolvass nyelelem * pnyel;
// addig megynk, mg meg nem talljuk
while(scanf("%d",&n)==1&&n!=0) // a keresett kezdbett
beszur(&strazsa1,n); for(pnyel=start; start->pkovnyel!=NULL
&& start->kulcs<keresett[0];
// fggvnyek kiprblsa start=start->pkovnyel);
// ha nem talljuk, NULL-t adunk vissza
p1=keres(&strazsa1,3); if(start->kulcs != keresett[0])return NULL;
p2=keres(&strazsa1,6); //innentl kznsges lncolt listn megynk
if(p1!=NULL && p2!=NULL)csere(p1,p2); //ha for(pfog=start->pfog; pfog->next!=NULL &&
// valamelyik szm nincs a listban, nem cserlhet
strcmp(pfog->nev,keresett)<0; pfog=pfog->next);
kiir(&strazsa1);
// vagy megtalltuk, vagy nincs a listban
torol(&strazsa1);
return strcmp(pfog->nev,keresett)==0 ? pfog
return 0; : NULL;
} }

Ha magunk runk listakezelst, nem kell, hogy kznl tart- Gondolkozzunk egytt!
sunk valami mintakdot a beszrs vagy a csere fggvnyhez. A
szksges pointermsolsokat knnyedn kitallhatjuk, ha rajzo-
lunk, mghozz folyamatosan: mindig rajzoljuk be a pointerek
aktulis llapott!
Oldja meg egyedl!

77
25. llapotgp (vges automata) viszont nem / jtt, akkor mg mindig a megjegyzsben
vagyunk. Akkor viszont nem kellett volna kijnni a cik-
lusbl
Elfordulnak olyan feladatok, amikor nagyobb mennyisg
adatot kell feldolgoznunk, de nincs szksg az adatok trolsra, int main(void){
viszont a korbban berkezett adatok befolysoljk, hogy az adott int ch; // a getchar int-et ad vissza
while((ch=getchar())!=EOF){
lpsben mit kell tennnk az aktulis adattal. if(ch=='/'){
Ilyen pldul, amikor egy ismeretlen hosszsg szveg r- ch=getchar();
kezik hozzk, s ebbl a szvegbl valamit ki kell szrnnk, vagy if(ch=='*'){
while((ch=getchar())!=EOF && ch!='*');
valamit ki kell cserlnnk msvalamire. // ha EOF jtt => vge
A szvegfeldolgozsnl is jobban ignyli az llapotgpes // ha '/' jtt, vge a megjegyzsnek
megvalstst sok vals idej algoritmus, pldul egy mrm- // ha ms jtt, mg mindig a
// megjegyzsben vagyunk
szert vezrl szoftver. }
Feladat: a szoftver lltsa be a termosztt hmrsklett! else if(ch!=EOF){
Vrja meg, mg stabilizldik a hmrsklet! Adjon a m- putchar('/');
putchar(ch);
rend eszkzre egysgugrs jelet, s msodpercenknt n }
darab mrst vgezve rgztse a vlaszt mindaddig, mg a }
kimeneten be nem ll a stabil llapot! Ezutn ismtelje else putchar(ch);
meg a mrst ms hmrskleten! }
}
A fenti esetben kt bizonytalan tnyez is van: mennyi id
alatt ll be a hmrsklet, s mennyi id alatt ll be a vlasz? Itt most elakadtunk, de persze tovbbi bvszkedssel elr-
A kvetkez llapotokat vehetjk fel:
hetjk, hogy mkdjn a dolog.
A Kezdeti llapot, parancs kiadsa j hmrsklet bellt-
sra (csak egy lpsnyit vagyunk ebben az llapotban)
2. prblkozs Tovbbi problma, hogy egy csom helyen
B Figyeljk a hmrskletet, mg stabil nem lesz. Mindad- olvastunk be, s ez gy nehzkess s ttekinthetetlenn teszi a
dig ebben az llapotban maradunk, amg a hmrsklet
kdot. Megoldhat, hogy csak egyszer kelljen beolvasni? Van-e
vltozik. A stabilitst pldul gy definiljuk, hogy a leg-
valami szisztematikusabb mdszer a megoldsra?
utols szz mrs eredmnyt eltroljuk, s ha nincs 0,1
A megolds termszetesen az llapotgp.
Celsiusnl nagyobb eltrs a legalacsonyabb s legmaga-
Az, hogy a kvetkez beolvasott karakterrel mit kell ten-
sabb hmrsklet kztt, akkor stabilnak tekintjk
ni, attl fgg, hogy a korbbi karakterek mik voltak. Kez-
C Radja az egysgugrs gerjesztst (csak egy lpsnyit va-
detben pldul ki kell rni a karaktereket, ha viszont most
gyunk ebben az llapotban)
megjegyzsben vagyunk, akkor nem szabad kirni a k-
D Addig maradunk ebben az llapotban, mg a kimeneti jel
vetkez karaktert.
nem stabilizldik, kzben fjlban rgztjk a mrsi
Hozzunk ltre egy vltozt, melynek segtsgvel azt tart-
eredmnyeket.
juk nyilvn, hogy mit kell tennnk a kvetkez karakter-
A fenti llapotgpet egy temez hvja, mondjuk msodper-
cenknt tzszer, vagy amilyen srn akarjuk mrni az rtkeket. rel. A vltoz rtke jelzi, hogy norml kir helyzetben
vagyunk, vagy esetleg megjegyzsben. Ez a vltoz le-
Tbb hmrsklet esetn az egsz llapotgp egy ciklus belsej-
hetne mondjuk egy egsz szm. Ha rtke 1, akkor nor-
ben lesz, ami minden menetben ms belltand hmrskletet s
ml llapotban vagyunk, ha pedig 2, akkor megjegyzs-
mrsi eredmnyeket trol fjlnevet biztost.
ben.
Jobban olvashat kdot kapunk, ha nem szmokkal jelez-
25.1 Kommentszr zk a program llapotait, hanem konstansokkal, melyek
neve jelzi az llapotot. Erre a clra tkletes az enum t-
Nzznk konkrt pldt llapotgpes feladatra! pus!
Plda: Olvassunk be a szabvnyos bemenetrl egy C progra- Vannak mg tovbbi llapotaink is. Megjegyzsbe csak
mot, s rjuk gy a szabvnyos kimenetre, hogy a benne tallhat akkor kerlnk, ha egymst kveti egy /* pros, nmag-
/* */ megjegyzseket trljk! Egyszerstsknt felttelezzk, ban egyik sem elg. Megjegyzsbl kikerlni is csak */
hogy a programban lv sztring konstansok nem tartalmaznak /* prossal lehet. A / utn teht mg egyet kell olvasnunk,
vagy */ prost. A szveg vgt EOF jelzi. de ezt gy akarjuk megtenni, hogy a kdban csak egyszer
Nem tudjuk, milyen hossz egy sor szerepeljen a beolvass. Legyen egy olyan llapotunk is,
nem olvashatunk tmbbe egy sort. amelyik a / jel rkezse utn *-ot vr, s egy olyan, ame-
Karakterenknt olvassunk! lyik * utn /-t!
Nem kell eltrolni az adatokat, rgtn ki lehet rni a beolva-
sott karaktert, ha biztosak vagyunk benne, hogy nem megjegyzs Ezek alapjn felrunk egy llapottblt:
rsze.
llapot * / egyb
1. prblkozs Essnk neki, mint majom a farknak! Prbl- norml norml csillagra vr norml
junk kitallni valami megoldst! csillagra vr megjegyzs csillagra vr norml
Pldul elkezdnk gondolkodni: megjegyzs perre vr megjegyzs megjegyzs
A karaktereket egyenknt olvassuk egy while ciklusban. perre vr perre vr norml megjegyzs
Ok, de ha / jtt, akkor meg kell nzni, hogy a kvetke-
z *-e! (Ha nem, rjuk ki a karaktert!) rjuk fel emell a tevkenysgtblt is!
Ha *, akkor megjegyzsben vagyunk, teht innentl
egsz a kvetkez *-ig nem rjuk ki a karaktereket, azaz llapot * / egyb
olvassunk a kvetkez *-ig! (s kzben figyeljk, hogy norml msol nem msol msol
jtt-e EOF, mert ht ki tudja?) csillagra vr nem msol elz / kirsa, elz /
Ha * jtt, akkor nzzk meg, hogy /-e a kvetkez! Ha nem msol kirsa, msol
igen, akkor ez utn megint ki kell rni a karaktereket. Ha

78
megjegyzs nem msol nem msol
perre vr nem msol nem msol
nem msol
nem msol
26. Rekurzi
A tblzatoknl ltvnyosabb az llapotgrf felrajzolsa:
egyb / msol
egyb / nem msol 26.1 A verem adatszerkezet

normal komment A verem (stack) olyan adatszerkezet, melybl az utoljra be-


'*' / nem msol
tett adatot tudjuk kivenni elszr. A verem kifejezs elg szem-
'/' / nem msol egyb / msol '*' / nem msol egyb / nem msol lletes: ha egy valdi verembe dolgokat doblunk, akkor az jon-
nan bedobott legfellre kerl, teht ha ki akarunk venni valamit,
'/' / nem msol
akkor fordtott sorrendben vehetjk ki a trgyakat, mint ahogy
cs_var p_var
bedobtuk.

'/' / putchar('/') '*' / nem msol

llapottbla alapjn knnyebb a kdols, s jobban ltszik


belle, mely llapotok sszevonhatk, tovbb sok llapot esetn
a grf kvethetetlenn vlik.
Az lapottbla+tevkenysgtbla, vagy az llapotgrf alapjn
a program lekdolsa egyszer, mechanikusan vgezhet feladat.

#include <stdio.h>
typedef enum {normal,komment,cs_var,p_var} allapotok;
// allapotgepes modellhez

int main(void){
int ch;
allapotok allapot=normal;

while((ch=getchar())!=EOF){
switch (allapot){
case normal:
if(ch!='/')putchar(ch);
A veremnek kt utastsa van: bedob (push) s kivesz (pop).
else allapot=cs_var; A C nyelvben nincs verem tpus, ha ilyenre van szksgnk,
break; neknk kell megvalstani. Vermet ltrehozhatunk pldul tmb
case cs_var:
if(ch=='*')allapot=komment;
vagy lncolt lista segtsgvel. Ha tmbt hasznlunk, egysze-
else{ rbb a kd, viszont a verem fix helyet foglal, s ha betelik,akkor
putchar('/'); nem tudunk tbb elemet beletenni. Lncolt lista esetn a verem
if(ch!='/'){ helyfoglalsa a belepakolt adatok mretvel arnyos, s csak a
putchar(ch);
allapot=normal; szmtgp memrijnak mrete korltoz, cserbe valamivel
} bonyolultabb a hozz tartoz kd.
} Nzznk egy nagyon egyszer verem megvalstst:
break;
case komment:
if(ch=='*')allapot=p_var; #include <stdio.h>
break;
case p_var: int t_verem[100], n=0;
if(ch=='/')allapot=normal;
else if(ch!='*')allapot=komment;
break; void push(int uj) { t_verem[n++]=uj; }
} int pop() { return t_verem[--n]; }
}
}
int main(void){
push(5);
Gondolkozzunk egytt! push(13);
push(8);
printf("%d\n", pop() ); // 8
printf("%d\n", pop() ); // 13
printf("%d\n", pop() ); // 5
Oldja meg egyedl! return 0;
}

A veremben egsz rtkeket trolhatunk.

Egsztse ki a fenti programot veremtlcsorduls ill. alulcsor-


duls elleni vdelemmel, azaz ne engedje, hogy teli verembe
rjunk ill. res verembl elemet vegynk ki! Alaktsa t gy a
programot, hogy az ne hasznljon globlis vltozt!

Ksztsen double rtkek trolsra alkalmas vermet lncolt


listval! Egyirny listt hasznljon strzsa nlkl! Az j
elemet a lista elejhez fzze!

79
26.2 Fggvnyhvs ; 11 : y=masodfok(2, 6, 3, x);

00025 8b 45 ec mov eax,DWORD PTR _x$[ebp]


A legtbb szmtgpen verem segtsgvel trtnik 00028 50 push eax
a paramterek tadsa a fggvnyeknek. 00029 6a 03 push 3
a visszatrsi rtkek visszaadsa. 0002b 6a 06 push 6
0002d 6a 02 push 2
a loklis vltozk trolsa. 0002f e8 00 00 00 00 call _masodfok
a fggvnybl val visszatrs cmnek trolsa. 00034 83 c4 10 add esp,16 ; 00000010H
Minden lefordtott programnak van egy sajt verme, melyben 00037 89 45 f8 mov DWORD PTR _y$[ebp],eax
tetszleges tpus adatokat trolhat. Visual C++-ban lefordtott
Az x vltoz az eax regiszterbe kerl, innen a push a program vermbe helyezi
programok esetn 1 MB az alaprtelmezett stack mret, melyet a (csak konstansokat vagy regiszter rtkeket lehet a verembe tenni, vltozkat
Properties - Configuration Properties - Linker - System - Stack kzvetlenl nem), ezutn a hrom konstans rtk kvetkezik: fordtott sorrendben
Reserve Size helyen mdosthatunk. kerlnek a verembe, mint ahogy a paramterlistban szerepelnek.
A call utasts a verem tetejre helyezi az t kvet utasts cmt, azaz a visz-
szatrsi cmet, s utna a fggvnyre ugrik.
Ksztsen double s int rtkek kzs trolsra alkalmas Visszatrve a fggvnybl az add esp,16 16-ot ad a veremmutat regiszterhez,
vermet! Ezt gy valstsa meg, hogy ksbb knny legyen azaz trli belle a ngy paramtert, majd az eax regiszterben lv visszatrsi
gy kiegszteni a kdot, hogy ms tpus adatokat is el tud- rtket y-ba msolja.
Lssuk a masodfok fggvnyt!
junk trolni!
Tipp: hasznljon unsigned char elem tmbt a stack megvalstshoz! Minden
; COMDAT _masodfok
adattpusnak legyek sajt push/pop fggvnye, pl. push_int, pop_double! A push
_TEXT SEGMENT
fggvnyben hozzon ltre egy unsigned char * tpus pointert, mellyel mutasson
_res$ = -8 ; size = 4
a bemen adatra, pl.: (double be){unsigned char *p=(unsigned char *)&be;},
_a$ = 8 ; size = 4
s a pointer ltal mutatott tmbbl msolja a bjtokat a stack tmbjbe (a
pldban sizeof(double) darab bjt msoland).
_b$ = 12 ; size = 4 1
_c$ = 16 ; size = 4
_x$ = 20 ; size = 4
Egy fggvnyhez tartoz veremrszlet pldul a _masodfok PROC NEAR ; COMDAT
kvetkezkppen nzhet ki: ; 3 : int masodfok(int a, int b, int c, int x){

00000 55 push ebp


loklis vltoz 00001 8b ec mov ebp, esp
00003 81 ec cc 00 00 00 sub esp,204 ; 000000ccH
00009 53 push ebx
0000a 56 push esi 2
loklis vltoz 0000b 57 push edi
0000c 8d bd 34 ff ff ff lea edi,DWORD PTR[ebp-204]
visszatrsi cm 00012 b9 33 00 00 00 mov ecx,51 ; 00000033H
00017 b8 cc cc cc cc mov eax,-858993460; ccccccccH
visszatrsi rtk/cme 0001c f3 ab rep stosd

paramter 1 ; 4 : int res = a*x*x;

0001e 8b 45 08 mov eax,DWORD PTR _a$[ebp]


00021 0f af 45 14 imul eax,DWORD PTR _x$[ebp]
paramter n 00025 0f af 45 14 imul eax,DWORD PTR _x$[ebp]
00029 89 45 f8 mov DWORD PTR _res$[ebp],eax

; 5 : res += b*x+c; 3
A paramtereket a hv teszi bele, mghozz fordtott
0002c 8b 45 0c mov eax,DWORD PTR _b$[ebp]
sorrendben. Ez azrt szksges, mert ha vltoz paramterszm 0002f 0f af 45 14 imul eax,DWORD PTR _x$[ebp]
fggvnyt hvunk (pl. printf, scanf, stb.), a fggny az els 00033 03 45 10 add eax,DWORD PTR _c$[ebp]
paramter alapjn tudja, hogy hny s milyen tpus rtkkel 00036 03 45 f8 add eax,DWORD PTR _res$[ebp]
00039 89 45 f8 mov DWORD PTR _res$[ebp],eax
hvtk meg.
A visszatrsi rtk/cm, s a szaggatott krvonala magyarzatra szorul: a
; 6 : return res;
paramteek s visszatrsi rtkek tadsi mdjrl a fordt dnt, ez sokflekpp
mkdhet. A Visual C++ abban az esetben, ha a visszatrsi rtk elfr egy-kt 0003c 8b 45 f8 mov eax,DWORD PTR _res$[ebp]
regiszterben, akkor nem a veremben adja vissza, hanem a processzor valamelyik
regiszterben. Ha a visszatrsi rtk egy nagyobb struktra, akkor a hv fggvny ; 7 : }
ltrehoz egy ideiglenes loklis vltozt a visszatrsi rtknek, s a verembe ennek
cmt helyezi el. Ms fordt viszont dolgozhat gy, hogy a visszetrsi rtk nem 0003f 5f pop edi
ideiglenes vltozban van, hanem kzvetlenl a veremben. 00040 5e pop esi 4
00041 5b pop ebx
Pldaprogram A kvetkez pldaprogram egy msodfok polinom rtkt 00042 8b e5 mov esp, ebp
szmtja ki: 00044 5d pop ebp
00045 c3 ret 0
#include <stdio.h> _masodfok ENDP
_TEXT ENDS
int masodfok(int a, int b, int c, int x){
int res = a*x*x;
res += b*x+c; Az 1-essel jelzett rszben konstansokat definil az assembly, ebbl nem lesz
return res; gpi kd, csak az assembly kd olvashatsgt segti. A konstansok azt mondjk
} meg, hogy a verem ebp munkaregiszternek rtkhez kpest (melybe a 2-es rsz
elejn az esp, azaz a verem tetejt jelz regiszter rtke kerl) hny bjtnyira
int main(void){ tallhat az adott loklis vltoz. (Az x86-os rendszerekben a verem lefel n.)
int y,x=5; A 2-es rszben a fggvny ltal hasznlt s megrzend regiszterek mentse
y=masodfok(2, 6, 3, x); trtnik. A fggvny hasznlja ezeken kvl az eax-et ill. az ecx-et, ezeket azonban
printf("%d\n", y); nem kell trolni, mert munkaregiszterek.
return 0; A 3. rszben a matematikai mveletek vgrehajtsa trtnik.
} A 4. rszben elszr az eax regiszterbe msoldik a res vltoz (az eax-ben ke-
rl visszaadsra a visszatrsi rtk), majd visszatltdnek a 2-es rszben elmentett
regiszterek, vgl a ret utasts visszaugrik a hvs helyre, mikzben trli a
Nzzk meg a lefordtott gpi kdot!
visszatrsi cmet a verembl az esp regiszter nvelsvel.
Elszr a main egy rszlete:

80
26.3 Rekurzi
Rekurzv az a fggvny, amely kzvetlenl vagy kzvetve v v=1
visszartk return=1
nmagt hvja. visszacm visszacm
n=1 n=1
Ha egy fggvny sajt magt hvja, azt nrekurzinak ne- v v v v=2

vezzk. visszartk
visszacm
visszartk visszartk
visszacm visszacm
return=2
visszacm

Ha a fggvnyek egy csoportja klcsnsen egymst hvja, v


n=2
v
n=2
v
n=2
v
n=2
v v=6
azt klcsns rekurzinak nevezzk. (Vagyis A fggvny hvja visszartk
visszacm
visszartk
visszacm
visszartk visszartk visszartk
visszacm visszacm visszacm
return=6
visszacm
B fggvnyt, B fggvny pedig A-t, de ez kiterjeszthet C, D, v
n=3
v
n=3
v
n=3
v
n=3
v
n=3
v
n=3
v v=24
E fggvnyekre is.) visszartk visszartk
visszacm visszacm
visszartk
visszacm
visszartk visszartk visszartk visszartk
visszacm visszacm visszacm visszacm
return=24
visszacm
Rekurzival tbb olyan problma megoldhat egyszeren, n=4 n=4 n=4 n=4 n=4 n=4 n=4 n=4

mely rekurzi nlkl csak nagy nehzsgek rn. A binris fkkal A fakt fggvny elejn, a { utn A fakt fggvny vgn, a } eltt
foglalkoz 26. fejezetben szmos rekurzv fggvnnyel tallkozni
fogunk.
A faktorilis kiszmthat ciklussal is, gy:
A rekurzv fggvnyhvs gondolata nagyon hasonl a mate-
matikbl ismert teljes indukcis bizonytsi mdszerhez: az int fakt(int n){
lltst beltjuk 1-re, majd n-1 alapjn n-re. Az egyik legegysze- int i,s=1;
rbb rekurzv definci a faktorilis: 1 faktorilisa 1, n faktori- for(i=1; i<=n; i++) s*=i;
return s;
lisa (n-1)!*n. }
A rekurzv fggvnyek termszetesen nem a vgtelensgig
hvjk sajt magukat, mindig van egy lellsi felttel, azaz a A kt megolds nagyjbl ugyanolyan hossz, ugyanolyan
rekurzv fggvnyeknek szksges kellke a feltteles elgazs. bonyolult. Melyiket vlasszuk? Ha egy feladat
Nzzk meg konkrtan a faktorilis pldjt! ciklussal val megoldsa hasonl bonyolultsg,
mint a rekurzv megolds, akkor a ciklust rde-
#include <stdio.h>
mes vlasztani, mert az ltalban gyorsabb s
int fakt(int n){ kevesebb memrit hasznl.
int v;
v = (n<2) ? 1 : n*fakt(n-1);
return v; rjuk ki egy tmb elemeit fordtott sorrendben! me a rekurzv
} s a ciklusos megolds:
int main(void){ void ford1(int t[],int n){
printf("4 faktorialisa=%d\n",fakt(4)); if(n>0){
} ford1(t+1,n-1);
printf("%d",t[0]);
Itt a lellsi felttel az n<2 IGAZ esete, mert ekkor a fgg- }
}
vny 1-et ad vissza. Ha n>=2, akkor n*fakt(n-1), ami rekurzv
fggvnyhvs. void ford2(int t[],int n){
Hogyan kpzeljk el a fejnkben a rekurzv fggvnyhvst? int i;
for(i=n-1;i>=0;i--)
me, a faktorilis plda kifejtett vltozata: printf("%d",t[i]);
}
#include <stdio.h>

int fakt_1(int n_1){ Ha egy 1000 elem tmbt szeretnnk gy kirni, az els
int v_1; megolds 32 bites rendszerben 100012=12000 bjtnyi helyet
v_1 = 1; foglal a verembl, mg a msodik mindssze 16
return v_1;
} bjtot. Vigyzni kell a rekurzi mlysgre, mert
nagy mlysg esetn a verem betelik, s a
int fakt_2(int n_2){ program elszll.
int v_2;
v_2 = (n_2<2) ? 1 : n_2*fakt_1(n_2-1);
return v_2; Fibonacci sorozat A Fibonacci sorozat els kt eleme 1, a
} tbbi eleme pedig az t megelz kt elem sszege, azaz: 1, 1, 2,
int fakt_3(int n_3){
3, 5, 8,13, 21 Mivel a sorozatot eleve rekurzv defincival
int v_3; adjuk meg, nyilvnval a rekurzv megolds. Emellett megnz-
v_3 = (n_3<2) ? 1 : n_3*fakt_2(n_3-1); zk a ciklussal val megoldst is. A kvetkez fggvnyek a
return v_3; sorozat n. elemnek rtkt adjk:
}

int fakt_4(int n_4){ int fibo1(int n){


int v_4; if(n<3)return 1;
v_4 = (n_4<2) ? 1 : n_4*fakt_3(n_4-1); return fibo1(n-2)+fibo1(n-1);
return v_4; }
}
int fibo2(int n){
int main(void){ int a, b, i;
printf("4 faktorialisa=%d\n",fakt_4(4)); for(i=2,a=b=1; i<n; i++){
} int c=b;
b+=a;
a=c;
Kvesse vgig fejben a program mkdst! }
Lthat, hogy ha a fakt fggvny magt hvja, akkor nem r- return b;
}
dik fell az n vagy a v vltoz, mert minden hvskor j keletke-
zett a veremben, valahogy gy:
Prbljuk ki mindkt fggvnyt pl. 30-cal meghvni! A
rekurzv fggvny tbb msodprcig fut, mg a ciklusos fggvny

81
nagyon gyorsan befejezdik. A rekurzi mlysge ezttal nem Elegnsabb megolds adhat rekurzival. A kvetkez md-
okoz problmt, mert a mlysg mindssze 30. Akkor mirt ilyen szer a szm szmjegyeit fordtott sorrendben adja, viszont nem
lass a rekurzi? Mert alacsony n rtk esetn is rengetegszer kell tudnunk, hny jegy a szm: 835%10==5, 835/10==83,
hvja nmagt, ugyanis ha vgiggondoljuk a mkdst, az n. 83%10==3, 83/10=8, 8%10==8, 8/10==0. Fordtott sorrendben
Fibinacci szmot 1+1+1+1+1+1++1 mdon szmtja ki, azaz a nem rhatjuk ki a szmjegyeket. Ha pl. lncolt listval eltroljuk a
fibo1 fggvny tbbszr hvdik, mint amennyi szm szmjegyeit, akkor ersen tlbonyoltottuk a megoldst.
az ltala visszaadott rtk. Teht hiba adja Tmbt nem hasznlhatunk, mert nem ismerjk elre a jegyek
magt egy feladat rekurzv megoldsa, nem szmt azaz a tmb mrett, fix mret megadsa elvi hiba lenne.
biztos, hogy az a legjobb. Rekurzv fggvnnyel viszont knny megfordtani a sorrendet:
Az eddigi pldkban mindig adtunk megoldst ciklussal s
rekurzival egyarnt. Mindig ltezik mindkt megolds? Igen, Rekurzv fggvny (szm, szmrendszer)
azonban nem biztos, hogy hasonl bonyolultsg. Rekurzv fggvny(szm eleje, azaz szm/szmrendszer)
Minden ciklus megvalsthat rekurzival. Az talakts rd ki: utols szmjegy, azaz szm%szmrendszer
nagyon egyszer: VGE.

Ciklus fggvny: void szamrendszer(int x,int n){


if(x<n)printf("%d",x);
Amg felttel igaz else{
Ciklusmag szamrendszer( x/n, n );
printf("%d", x%n );
VGE. }
}
Rekurzv fggvny:
Ha felttel igaz A rekurzit gyakran a Hanoi tornyai jtkon keresztl szoktk bemutatni. A
trtnet gy szl, hogy egy rdon 64 db egyre cskken mret korong tallhat,
Ciklusmag melyeket Brahma szerzeteseinek t kell raknia a mellette lv rdra gy, hogy
Rekurzv fggvny naponta egy korongot mozgathatnak, s sosem kerlhet kisebb korongra na-
VGE. gyobb. Segtsgl egy harmadik oszlop is felhasznlhat. Feladat: rjon C
fggvnyt, amely kirja az A oszloprl B oszlopra trtn pakols lpseit n
korong esetn! (64-gyel nem rdemes prblkozni, mert a lpsek szma 2n-1.)
Minden rekurzi megvalsthat ciklussal. Elmletben. A Az algoritmusnak utnanzhet az interneten.
gyakorlatban azonban a ciklussal trtn megvalsts nagyon
bonyolult lehet, sok segdvltozt ignyelhet. Rekurzival
pldul nagyon egyszer a fabejrs, lsd a kvetkez fejezetben.
Prblja megvalstani rekurzi nlkl brmelyiket!
Egy msik rekurzv algoritmus, ami rekurzi nlkl nagyon bonyolult, a
felletkitlts (flood fill): egy pixelekbl ll kpen egy adott szn, ms sznekkel
hatrolt terletet ms sznre szeretnnk festeni.
Algoritmus:

Flood fill fggvny(x, y, cserlend szn, j szn)


Ez a kp a Wikimedia Commonsbl szrmazik.
Ha pixel(x,y)!=cserlend szn
return
pixel(x,y)=j szn
Flood fill(x-1, y, cserlend szn, j szn) Gondolkozzunk egytt!
Flood fill(x+1, y, cserlend szn, j szn)
Flood fill(x, y-1, cserlend szn, j szn)
Flood fill(x, y+1, cserlend szn, j szn)
VGE.
Oldja meg egyedl!
A cserlend s az j szn nem lehet azonos.
Meg tudja oldani rekurzi nlkl?

Kirs ms szmrendszerben rjon fggvnyt, amely kt


pozitv egsz szmot kap paramterknt, s az elst a msodikkal
megadott szmrendszerben rja ki! A szmrendszer 2-10 kztt
lehet.
Meg kell hatroznunk a szm szmjegyeit, s ezeket egyms
utn kirni.
Pldul ki szeretnnk rni a 835-t 10-es szmrendszerben.
Az els szmjegyet megkapjuk, ha elosztjuk 100-zal (egsz osz-
ts): 835/100==8, majd levonjuk a 8*100-at, kapunk 35-t. Ezt
10-zel osztjuk, stb. A problma ezzel a megoldssal, hogy tud-
nunk kell elre, hny jegy a szm, mert ebbl tudjuk meg, hogy
10 melyik hatvnyval kell osztanunk. Egy ciklussal meghatroz-
hat a kvnt hatvny. (A 00000835 stlus eredmnyt ad ez a
hatvny biztosan elg lesz tpus megolds kerlend, mert elvi
hibs).

void szamrendszer(int x,int n){


int temp=x,oszt;
for(oszt=1; temp!=0; temp/=n, oszt*=n);
for(oszt/=n; x!=0; x%=oszt, oszt/=n)
printf("%d",x/oszt);
}

82
27. Dinamikus nhivatkoz adat- 27.1 Binris fa
szerkezetek 2. fk Egy fa akkor binris, azaz ktg, ha egy szlnek legfeljebb
kt gyermeke lehet. Az elnevezsnek teht semmi kze a binris
A fa olyan grf, melyben nincs hurok, azaz a grf minden szmokhoz.
csompontjhoz (node) csak egy ton lehet eljutni. Az adatszer- A binris fa az informatikban nhivatkoz adatszerkezet. A
kezetknt hasznlt fk irnytott grfok, azaz csak fentrl lefel fa csompontjai struktrk, melyek a csompontban trolt adatok
lehet haladni. mellett kt pointert tartalmaznak: a bal illetve a jobb oldali gyer-
mek cmt. Ha nincs gyermek az adott irnyban, a pointer rtke
NULL.
adatok

*bal *jobb

adatok adatok

*bal NULL *bal *jobb

adatok adatok adatok

NULL *jobb *bal *jobb NULL NULL


Br ez az alakzat rnzsre inkbb gykrre hasonlt. Ha feje
tetejre lltannk, akkor lenne belle fa. Nem a fa az egyetlen, adatok adatok adatok

ami akkor mutatja meg valdi arct, ha a feje tetejre lltjuk. Az NULL NULL NULL NULL NULL NULL
albbi A zldsgkertsz cm kpet Giuseppe Arcimboldo festette.
Morse kd A kvetkez pldaprogram felpt egy Morse
kdokat trol binris ft, majd dekdol egy Morse kddal meg-
adott szveget.
A Morse kd megadsa BNF lerssal:
<sor> ::= " " <kd> "\n"
<kd> ::= <egykd> | <kd> " " <egykd>
<egykd> ::= <karakter> <morse>
<morse> ::= <alap> | <morse> <alap>
<alap> ::= "." | "_"
Pldul: A._ E. I.. M__ O___ P.__. S... T_
Z__..
A Morse kd utn szkz van, a sort lezr soremels eltt
szintn van szkz!
A visszafejtend szveg formtuma:
<sor> ::= " " <kd> "\n"
<kd> ::= < morse> | < kd> " " < morse> | < kd> " "
<morse> ::= <alap> | <morse> <alap>
<alap> ::= "." | "_"
Pldul: ... __.. .. ._ __.. .. _ ._ ... _
___ .__.
A Morse karaktereket szkz vlasztja el egymstl. Ha egy-
nl tbb szkz van kt karakter kztt, akkor ezek a kimeneten
is megjelennek, mint szavakat elvlaszt szkzk. A sort lezr
jsor karakter eltt kell legyen szkz.
//**************************************************
#include <stdio.h>
A fa tetejn lv kiindul elemet gykr elemnek nevezzk. #include <stdlib.h>
//**************************************************
Kt csompont tvolsga azt jelenti, hogy hny msik cso-
mponton keresztl lehet eljutni hozz. Mivel irnytott grfrl //**************************************************
van sz, nem lehet brmely csompontbl brmelyikbe eljutni. typedef struct dat{
Egy elem azon a szinten van, amennyi a gykrtl val t- //**************************************************
char betu;
volsga. (A gykr teht a 0. szinten van.) A fenti brn az egy struct dat *pont,*vonal;
szinten lv elemeket valban egy szintre rajzoltuk, de ez nem }Morse,*MP;
ktelez.
//**************************************************
Azokat az elemeket, melyek kztt egy szint a klnbsg s void hiba(char t[]){
kapcsolatban vannak egymssal, szlnek illetve gyermeknek //**************************************************
nevezzk. Minden gyermeknek egy szlje van, egy szlnek fprintf(stderr,"Hiba: %s\n",t);
exit(1);
brmennyi gyermeke lehet. A fa levele olyan elem, melynek }
nincs gyermeke.
A fk rekurzv felptsek, mert brmely csompontot kiv- //**************************************************
lasztva azt tekinthetjk egy fa gykernek. Fban keresni pl. gy void delfa(MP gyoker){
//**************************************************
lehet rekurzvan, hogy megnzzk a gykr elemet: ezt keressk- if(gyoker==NULL)return;
e. Ha nem, akkor minden gyermeket gykrnek tekintve megis- delfa(gyoker->pont);
mteljk az eljrst, mg van gyermek vagy meg nem talltuk a delfa(gyoker->vonal);
free(gyoker);
keresett elemet. }

83
//************************************************** //**************************************************
MP feltolt(MP gyoker){ int main(void){
//************************************************** //**************************************************
int c,aktbetu=0; MP gyoker=NULL;
MP futo; gyoker=feltolt(gyoker);
keres(gyoker);
delfa(gyoker); delfa(gyoker);
gyoker=(MP)malloc(sizeof(Morse)); return 0;
if(gyoker==NULL)hiba("Elfogyott a memria"); }
gyoker->pont=gyoker->vonal=0;
gyoker->betu=0;
Az elem adata az a karakter, melyet a gykrbl az tvonal-
futo=gyoker; nak megfelel pont-vonal kombinci ad. A bal s jobb pointere-
ket ezttal pont-nak illetve vonal-nak nevezzk.
printf("Kerem a definiciot!\n");
while((c=toupper(getchar()))!=EOF && c!='\n'){
A delfa fggvny rekurzv felpts: Elszr trli a gyerme-
switch(c){ keit (azok is az gyermekeiket, stb.), majd sajt magt, gy a fa
case '.':{ minden eleme trldik. A rekurzi lellsi felttele, hogy a kapott
if(futo->pont==NULL){ gykr NULL pointer-e. Ez egy kellemes felttel, mert gy nyu-
futo->pont=(MP)malloc(sizeof(Morse));
if(futo->pont==NULL) godtan meghvhatja magt a fggvny a jobb s bal rszfra, nem
hiba("Elfogyott a memria"); kell vizsglnia, hogy ott NULL pointer van-e.
futo=futo->pont; A fa feltltst vgz feltolt ill. a keresst vgz keres fgg-
futo->betu=0;
futo->pont=futo->vonal=NULL; vny viszont ciklust hasznl. Meg tudn oldani rekurzival is?
}
else futo=futo->pont;
break; 27.2 Rendezett fa rendezfa, kiegyen-
}
case '_':{ slyozottsg s kiegyenslyozatlansg
if(futo->vonal==NULL){
futo->vonal=(MP)malloc(sizeof(Morse));
if(futo->vonal==NULL) A binris ft leggyakrabban gy ptjk fel, hogy abban az
hiba("Elfogyott a memria"); elemek valamilyen szempont szerint rendezve legyenek.
futo=futo->vonal;
futo->betu=0;
Pldul egy egsz elemeket tartalmaz fba a folyamatosan
futo->pont=futo->vonal=NULL; rkez elemeket gy ptjk be, hogy a gykrelemtl balra csak
} nla kisebb, tle jobbra csak nagyobb rtkek kerljenek, s ez az
else futo=futo->vonal; llts brmely elemre igaz: tle balra csak kisebbek, tle jobbra
break;
} csak nagyobbak vannak.
default:{ Legyen a bemen szmsor: 13, 7, 19, 3, 5, 23, 17, 31. Az
futo->betu=aktbetu; ezekbl felpl rendezfa a kvetkez:
if(isalnum(c))aktbetu=c;
else aktbetu=0;
futo=gyoker; 13 13 13
}
} 7 7 19 13
}
return gyoker; 13 7 19
}
7 19
//************************************************** 3 13
void keres(MP gyoker){
//************************************************** 3 23 7 19
int c;
MP futo=gyoker; 5 13
int jo=1; 3
7 19
printf("Kerem a megfejtendo kodot!\n"); 5
while((c=toupper(getchar()))!=EOF && c!='\n'){
switch(c){ 3 17 23
case '.':{ 13
if(jo){ 5
if(futo->pont!=NULL)futo=futo->pont; 7 19
else jo=0;
} 3 17 23
break;
}
case '_':{ 5 31
if(jo){
if(futo->vonal!=NULL)futo=futo->vonal; Az els elem (13) lesz a fa gykere.
else jo=0; A 7 tle balra kerl, mert kisebb nla.
}
break;
A 19 a gykrtl jobbra kerl, mert nagyobb nla.
} A 3 a gykrtl balra kerl, mert kisebb nla. Ott mr van
default:{ elem, ezrt tovbbi szintet kell ltrehozni a 3 szmra. A
if(futo->betu&&jo)putchar(futo->betu);
else if(c==' ')putchar(' ');
3 kisebb az 5-nl, ezrt tle balra kerl.
else putchar('?'); Az 5 a gykrtl balra kerl, mert kisebb nla, a 7-tl bal-
futo=gyoker; ra kerl, mert kisebb nla. A 3-tl jobbra kerl, mert na-
jo=1;
}
gyobb nla.
}
} Vegyk szre, hogy amennyiben ugyanezek
}
a szmok ms sorrendben rkeztek volna,
egszen ms ft kaptunk volna!
Mirt j a rendezett fa? Az inorder bejrsnl megltjuk.

84
Milyen ft kaptunk volna, ha az elemek nvekv sorrendben egyszerbb kdot eredmnye, mint a ciklussal val megvalsts.
rkeznek? 3, 5, 7, 13, 17, 19, (Prbljuk meg kirni egy rendezett fbl az elemeket nvekv
Gykr: 3 tle jobbra 5 tle jobbra 7 tle jobbra sorrendben ciklus segtsgvel! s rekurzvan?) Rekurzi esetn
13 Ha felrajzoljuk, ltjuk, hogy ez gyakorlatilag egy egyszere- a rekurzi mlysge megegyezik a fa mlysgvel, azaz az eme-
sen lncolt lista. letek szmval. Kiegyenslyozott fa esetn ez az elemszm kettes
Ha az eredeti fban akarunk eljutni a legtvolabbi elemig, ak- alap logaritmusval arnyos, vagyis nem nagy. (0. szint: 1 elem,
kor a gykrtl hrmat kell lpni. A lncolt lista-szeren kapcso- 1. szint 2, elem, 2. szint: 4 elem, 3. szint: 8 elem). A sebessge
ld binris fa esetben viszont a legtvolabbi elem ht lpsre pedig a ciklusnak sem nagyobb.
van a gykrtl. Nyilvnvalan az a hatkonyabb, ha kevesebb Lncolt lista is bejrhat rekurzvan, de ott ez a megolds ke-
lpsben lehet eljutni a legtvolabbi elemhez, ez pedig kiegyen- rlend, mivel a rekurzimlysg megegyezik az elemszmmal.
slyozott fval rhet el. A kiegyenslyozottsg azt jelenti, hogy
brmely elemtl balra s jobbra is nagyjbl ugyanannyi elem 27.4 Tbb g fk
legyen. A lncolt lista-szer felpts szlssgesen kiegyens-
lyozatlan eset. Az elemek trendezsvel utlag ki lehet egyens-
lyozni a ft, ennek megvalstsval azonban nem foglalkozunk. Kis mdostssal a ktg fra alkalmazott algoritmusok s
adatszerkezetek alkalmasak tbb g fk kezelsre is.
27.3 A fabejrs tpusai Pl.: 3 g fa:

Aszerint, hogy a fa gykrelemnek tartalmt mikor dolgoz- typedef struct _elem3{


int adat;
zuk fel a kt g feldolgozshoz kpest, hromfle bejrstpust struct _elem3 *bal,*kozep,*jobb;
klnbztetnk meg: }elem3;

Preorder bejrs Pl. n g fa:

Preorder fabejr fggvny typedef struct _elemn{


int adat;
elem feldolgozsa unsigned n;
egyik g bejrsa struct _elemn **t; // n elem din. pointertmb
msik g bejrsa }elemn;

Ezt a bejrst pldul akkor hasznljuk, ha a fa elemeit fjlba Ezek bejrsa ugyangy trtnhet rekurzv fggvnnyel, mint
akarjuk menteni, majd onnan visszaolvasva az eredeti ft akarjuk a binris f.
visszakapni. A fenti ft 13, 7, 3, 5, 19, 17, 23, 31 sorrendben rja
ki. Ez ugyan nem egyezik a szmok eredeti sorrendjvel, de Pl.
//**************************************************
lthatjuk, hogy ha ebbl ptnk rendezft, ugyanazt kapjuk int osszead(elem3 * gyoker){
vissza. //**************************************************
if(gyoker==NULL)return 0;
return osszead(gyoker->bal)
Inorder bejrs +osszead(gyoker->kozep)
+osszead(gyoker->jobb);
Inorder fabejr fggvny }
egyik g bejrsa
elem feldolgozsa ill.
msik g bejrsa //**************************************************
int osszead(elemn * gyoker){
A fenti fban, ha egyik g=bal, msik g=jobb, akkor 3, 5, 7, //**************************************************
int sum=0,i;
13, 17, 19, 23, 31 sorrendben kapjuk az elemeket, azaz nvekv if(gyoker==NULL)return 0;
sorrendben. Ha egyik g=jobb, msik g=bal, akkor pedig ellen- for(i=0; i<gyoker->n; i++)
kez, azaz cskken sorrendben. gy kell eljrni teht, ha az sum+=osszead(gyoker->t[i]);
elemekre sorrendben van szksg. return sum;
}

Postorder bejrs
27.5 Kt plda
Postorder fabejr fggvny
egyik g bejrsa 1. plda Adottak a kvetkez defincik:
msik g bejrsa
typedef struct bf {
elem feldolgozsa double ertek;
struct bf *bmut, *jmut;
Ez a bejrs hasznlatos a fa trlsekor. } bifa, *pbifa;
Elfordulhat, hogy olyan megoldst alkalmazunk, amelyet
nem lehet egyrtelmen besorolni a hrom vltozat kz. Ksztsen egy olyan szabvnyos ANSI C fggvnyt, amely
meghatrozza az ilyen elemekbl ll binris fban trolt rtkek
Rekurzi s bejrs A rekurzi kapcsn megemltettk, hogy sszegt. Az adatszerkezet "vgt" a megfelel mutat NULL
alkalmazst mindig meg kell fontolni: rtke jelzi. A fggvny bemen paramtere a fa gykerre muta-
Elnysebb-e a ciklussal val megolds a rekurzvnl? t pointer, visszatrsi rtke a fenti mdon meghatrozott rtk
Nem tl mly-e a rekurzi, s ezltal nem telik-e be a ve- legyen! Vlasszon megfelel paramtereket! Trekedjen gyors
rem? megoldsra!
Binris fkrl azt mondhatjuk, hogy ha a fa kiegyenslyozott,
akkor egyrtelmen rdemes hasznlni a rekurzit, mert jval

85
Egy lehetsges megolds:
28. Fggvnypointer
double osszegez(pbifa gyoker){
return gyoker!=NULL ? gyoker->ertek+ A fggvnyek kdja a memriban tallhat, csakgy, mint a
osszegez(gyoker->bmut)+
osszegez(gyoker->jmut) vltozk, teht meg lehet mondani azt a memriacmet, ahol az
: 0.0; adott fggvny kezddik. A C nyelvben definilhatk olyan
} pointerek, melyek fggvnyek cmeit troljk. Ezeket a pointere-
ket hasonlan kezelhetjk, mint az adatpointereket, pldul tm-
2. plda Adott a kvetkez definci: bt szervezhetnk bellk vagy tadhatjuk fggvnynek param-
terknt.
typedef struct mf {
double adat; A kvetkez pldban ltrehozunk egy olyan tmbt, mely-
unsigned m; nek elemei double visszatrsi rtk, egy double paramterrel
struct mf **p; rendelkez fggvnyek cmei. Ezutn feltltjk a tmbt ngy
} magufa, *pmagufa;
fggvnnyel, melyek a math.h-ban tallhatk. Termszetesen
sajt fggvnyeket is hasznlhatnnk. Az utols sorban meghv-
Ksztsen egy olyan C fggvnyt, amely meghatrozza, egy juk a tmb n-1-edik elemt.
ilyen magufa tpus elemekbl ll fa n-edik szintjn tallhat
adat-ok sszegt! Egy csompont p mezje egy m elem dinami-
#include <stdio.h>
kus tmbre mutat, amelyben a csompont gyerekeire mutat #include <math.h>
pointereket troljuk. Ha egy elemnek nincs gyereke, p NULL
pointer. A fggvny bemen paramtere a fa gykerre mutat int main(void){
double (*t[4])(double),d;
pointer, valamint n, azaz a keresett szint. Visszatrsi rtke az n- int n;
edik szinten trolt adatok sszege legyen! Nem hasznlhat glob-
lis vltozt! t[0]=sin;
t[1]=cos;
t[2]=exp;
Egy lehetsges megolds: t[3]=tan;

double adatosszeg(pmagufa p,int n){ printf("Kerek egy valos szamot: ");


double s=0.0; scanf("%lg",&d);
unsigned i; printf("Mit szamoljak?\n1. sin\n");
if(!p)return 0; printf("2. cos\n3. exp\n4. tan\n");
if(n==0)return p->adat; scanf("%d",&n);
for(i=0; i<p->m; i++)
s+=adatosszeg(p->p[i],n-1); if(n<1||n>4)return;
return s;
} printf("Eredmeny: %g\n",t[n-1](d));

return 0;
}
Gondolkozzunk egytt!
Egyszer menvezrelt program Megkrdezzk a felhaszn-
ltl, hogy sszeadni, kivonni, szorozni vagy osztani szeretne-e,
s ennek megfelelen vlasztunk fggvnyt. A program knnyen
Oldja meg egyedl! bvthet tovbbi fggvnyekkel. Ha a felhasznl rossz szmot
r be, a program ismt kirja a ment. Ha nem szmot r be (hiba-
kezels), vagy a 0 menpontot vlasztja, a program kilp.

#include <stdio.h>

void osszead(double a,double b){


printf("Osszeg: %g\n",a+b);
}

void kivon(double a,double b){


printf("Kulonbseg: %g\n",a-b);
}

void szoroz(double a,double b){


printf("Szorzat: %g\n",a*b);
}

void menukiir(void){
printf("\n0 Kilep\n");
printf("1 Osszead\n");
printf("2 Kivon\n");
printf("3 Szoroz\n");
printf("\n");
}

int main(void){
void (*t[3])(double,double)={osszead,kivon,szoroz};
int n;
double a,b;

menukiir();
while(scanf("%d",&n)==1 && n!=0){
if(n>0 && n<4){
printf("Kerek ket szamot ,-vel elvalasztva: ");
scanf("%lg,%lg",&a,&b);
t[n-1](a,b);

86
}
menukiir(); double x2(double x){
} return x*x;
}
return 0;
} int main(void){
printf("I(sin[0,1])=%g\n",integral(0,1,1e-8,sin));
printf("I(x2[0,1])=%g\n",integral(0,1, 1e-8,x2));
Integrlszmts tglalap formulval A kvetkez plda azt return 0;
mutatja be, hogyan rhatunk fggvnyt, amely tetszleges, egy- }
vltozs (vals) fggvny integrljt szmtja ki tglalap formu-
lval. A teglalap fggvny fv fggvny integrljt szmtja ki Az integral fggvny szmtja ki fv fggvny integrljt [a,b] intervallumon.
[a,b] intervallumon, az intervallumot n egyenl rszre osztja. Az integrlsnl hasznlt x irny feloszts ebben az esetben nem egyenletes, mint a
korbbi, tglalap formult hasznl esetben, hanem ahol a fggvny hullmosabb,
ott srbb a feloszts, ahol pedig egyenletesebb, ott ritkbb.
#include <stdio.h> Ezt gy rjk el, hogy els lpsben kiszmtjuk az integrl kzelt sszegt
#include <math.h> kevs (16) pontra a tglalap formulval (mg az integral fggvnyben), majd (mr a
finomitas fggvnyben) vesszk az intervallum als s fels felt, s kiszmtjuk
double teglalap(double a,double b,int n,double azok integrljt is, ugyancsak 16-16 osztponttal. A kt flre kapott integrl sszege
(*fv)(double)){ egy pontosabb kzeltst, ad, mert ktszer annyi osztpontot hasznltunk.
double dx=(b-a)/n,sum=0; Megnzzk, hogy az j s az elz integrlkzelt sszeg mennyire tr el
int i; egymstl. Ha az eltrs a hiba vltozban magadottnl kisebb, akkor nem szmo-
for(i=1;i<n;i++)sum+=fv(a+dx*i); lunk tovbb. Ha nagyobb, akkor a kt oldalon kln-kln szmoltatunk egy ponto-
return (sum+0.5*(fv(a)+fv(b)))*dx; sabb eredmnyt. Ha az egyik oldalon a kvetkez lpesben elg pontos eredmnyt
} kapunk, a msik oldalon viszont nem, akkor a kt oldalon eltr felbontshoz
fogunk jutni.
double x2(double x){ A rekurzv hvs teht megll, ha elrtk a kvnt pontossgot. Elfordulhat,
return x*x; hogy ezt sosem tudjuk elrni (szmtsi hibk miatt), ezrt bevezettnk egy korlto-
} zst: ha 20-nl nagyobb mlysgre lenne szksg, akkor is lell a folyamat.

int main(void){
printf("I(sin[0,1])=%g\n",teglalap(0,1,100,sin));
printf("I(x2[0,1])=%g\n",teglalap(0,1,100,x2));
return 0; Gondolkozzunk egytt!
}

A teglalap fggvny negyedik paramtere teht egy olyan


fggvny cme, amelynek mind a paramtere, mind a visszatrsi Oldja meg egyedl!
rtke double tpus. A paramterknt tadott fggvnyt gy
hvjuk meg, mintha egyszer fggvny volna, nem pointer.
A fggvnynek tadott fggvnypointer hasznlatt korbban
lthattuk a qsort esetben. A qsort paramterknt kapta az ssze-
hasonlt fggvnyt.
A fv(a+dx*i) helyett (*fv)(a+dx*i) alakban is hasznlhat a
fggvnypointer, a kt megolds ekvivalens egymssal. A pointe-
res rsmd a korbbi s a ksbbi pldkban is hasznlhat, de a
fggvny rsmd egyszerbb, ezrt ennl maradunk.

Integrlszmts adaptv finomtssal Az albbi plda fggvnypointert s


rekurzit egyarnt tartalmaz.

#include <stdio.h>
#include <math.h>

double teglalap(double a,double b,int n


,double (*fv)(double)){
double dx=(b-a)/n,sum=0;
int i;
for(i=1;i<n;i++)sum+=fv(a+dx*i);
return (sum+0.5*(fv(a)+fv(b)))*dx;
}

double finomitas(double a,double b,double hiba


,double (*fv)(double),double elozo,int szint){
double kozep=(a+b)*0.5;
double bal=teglalap(a,kozep,16,fv);
double jobb=teglalap(kozep,b,16,fv);
double uj=bal+jobb;

if(szint>20)return uj; // ha tl nagy lenne a


// rekurzi mlysge, nem megynk tovbb
if(fabs((uj-elozo)/uj)<hiba)return uj; // ha ksz
hiba*=0.5;
return finomitas(a,kozep,hiba,fv,bal,szint+1)
+finomitas(kozep,b,hiba,fv,jobb,szint+1);
}

double integral(double a,double b,double hiba


,double (*fv)(double)){
return finomitas(a,b,hiba,fv
,teglalap(a,b,16,fv),1);
}

87
29. Keress tmbben Start

Igen Nincs a tmbben


t[0]>=keresett? t[0]>keresett? Igen
Kt eset lehetsges: ha a tmb rendezve van a keresett adat Megtalltuk
Nem
szerint, s ha rendezetlen. Ha rendezetlen, akkor csak egyet tehe- Nem Vge

tnk: elindulunk a tmb elejrl (vagy vgrl) s minden elemet t[utols]<=kere


Igen
t[utols]<keres Nincs a tmbben
Igen
megvizsglunk, hogy az-e a keresett. Ennek a trivilis mdszer- sett?
Nem
ett?
nek is van tudomnyos neve: lineris keressnek nevezzk. min=0, max=utols

Lineris keress Keressnk meg egy double tmbben egy med=(min+max)/2


rtket, s adjuk vissza az indext! Ha nincs a tmbben, -1-et
adjunk vissza! min==med?
Nincs a tmbben
Igen
Nem
int linkeres(double t[],int db,double mit){ Megtalltuk
int i; t[med]==kerese
Igen
tt?
for(i=0;i<db;i++) Nem
if(t[i]==mit)
t[med]<keresett min=med
return i; ?
Igen
return -1;
} Nem
max=med

Binris keress Abban az esetben, ha a tmb rendezett a A feladat ugyanaz, mint a lineris keressnl. A fenti algorit-
keressi kulcs szerint, a lineris keressnl gyorsabban is megta- mus megvalstva:
llhatjuk a kvnt elemet. a leghatkonyabb keressi mdszer a
binris vagy ms nven logaritmikus keress, melyet a kvet- int binkeres(double t[],int db,double mit){
kezplda szemlltet. int min=0,max=db-1,med=(min+max)/2;
Keressk 19-et az albbi tmbben: if(t[min]>mit)return -1;
if(t[min]==mit)return min;
2 3 5 7 11 13 17 19 23 29 31 37 if(t[max]<mit)return -1;
if(t[max]==mit)return max;

while(med!=min && t[med]!=mit){


2 37 if(t[med]<mit)min=med;
else max=med;
med=(min+max)/2;
min max }
return t[med]==mit ? med : -1;
2 13 37 }

min med max Keressi id: O(log2n)

13 37 Binris keresst valst meg a bsearch szabvnyos knyvtri


fggvny, mely az stdlib.h-ban tallhat.
min=med max
void bsearch(
13 23 37 void *key,
void *base,
size_t nelem,
min med max size_t width,
int (*fcmp)(const void *elem1,const void *elem2)
13 23 );

min max=med
key: a keresett elemet trol vltoz cme
base: a tmb cme
13 17 23 nelem: elemszm
width: egy elem mrete
min max fcmp: kt tmbelemet sszehasonlt fggvny cme
med

17 23
Az sszehasonlt fggvny ugyanolyan, mint amilyet a qsort
is hasznl, lsd a 30.7 fejezetben.
min=med max #include <stdio.h>
#include <stdlib.h>
17 19 23
int hasonlit(const void *p1, const void *p2){
double *d1=(double*)p1;
min max double *d2=(double*)p2;
med if(*d1<*d2)return -1;
Azaz: a min s max indexek kezdetben a tmb kt szln ll- if(*d1>*d2)return 1;
return 0;
nak, majd minden lpsben felezdik kztk a tvolsg, krlke- }
rtik a keresett elemet. A keress ideje log2n nagysgrend, ahol n
a tmb szmossga. (Lineris keressnl n/2 nagysgrend). int main(void){
double t[]={2,3,5,7,11,13,17,19,23,27,31,37};
A logaritmikus (binris) keress folyamatbrja a kvetkez: size_t n=sizeof(t)/sizeof(double);
double mit=19,*p;
p=(double*)bsearch(&mit,t,n,sizeof(double),
hasonlit);

88
30. Rendezs
if(p==NULL)printf("Nincs\n");
else printf("Megvan: t[%u]=%g\n",p-t,*p);
return 0;
}
Rendezett adatsorban keresni lnyegesen gyorsabb, mint ren-
dezetlenben, ezt lttuk az elz fejezetben. A rendezsnl fontos
Gondolkozzunk egytt! szempont, hogy az algoritmus a lehetsgekhez kpest gyors
legyen, s minl kevesebb ideiglenes memrit foglaljon, azaz az
adatokat a sajt helykn rendezze.
Ebben a fejezetben elszr tmbk rendezsre nznk meg
nhny algoritmust, vgl bemutatjuk a gyorsrendez algoritmus
Oldja meg egyedl!
kt irnyban lncolt listn mkd vltozatt is.
A rendezalgoritmusok egyikre sem lehet ltalnossgban
kijelenteni, hogy mindig ez vagy az a leggyorsabb. Pldul a
winchesteren lv adatok rendezsre egsz ms algoritmusok
hatkonyak, mint a memriban lv adatok rendezsre, vagyis
az algoritmus hatkonysga fgg a hardver krnyezettl is.
Egy tmb elemeit sorba rendezni nem rdgtl val dolog,
brki, aki az eddigi rszeket nagyjbl megrtette s tudja hasz-
nlni, kpes rni ilyet.

rjon fl cdulkra 5-10 klnbz egsz szmot, keverje ssze


a paprokat, s aztn rakja nvekv sorba! A sorba raksnl
gyeljen arra, hogy a szmtgp nem ltja egyszerre az sszes
rtket, csak 1-2 kivlasztottat, teht n se lssa egyszerre az
sszeset, csak azokat, amelyekre az ujjval mutat! Cserlgesse
addig a cetliket, amg azok helyes sorrendbe nem kerlnek!

Az algoritmusokat double elem tmbk rendezsre alkal-


mas C fggvnyekkel valstjuk meg. Az algoritmust egy konkrt
tmb rendezsvel is bemutatjuk, rdemes elszr ezt megnzni,
s csak ezutn a programkdot. Mivel a tmb rendezse nagy
helyet foglal az oldalon, az adott rendezshez kapcsold alfeje-
zeten bell klnbz helyeken jelenik meg.

30.1 Bubork algoritmus


Egyszer algoritmus, de nem nagyon szeretjk, mert nem tl
hatkony.
Mkds:
1. Vesznk kt szomszdos tmbelemet, s sszehasonlt-
juk. Ha a sorrendjk nem megfelel (azaz nvekv sor-
ba val rendezsnl nem a kisebb van elbb), akkor
megcserljk az elemeket.
2. Egy elemmel tovbb lpnk, s gy vgezzk el az 1.
lpsben mondottakat (teht az elz lpsben sszeha-
sonltott kt elem kzl a msodikat hasonltjuk most a
kvetkez tmbelemmel, lsd az brt)
3. Ezt ismteljk, amg a tmb vgre nem rnk. Ekkor
az biztos, hogy a legnagyobb tmbelem eljutott a tmb
vgre. (Ms elemek is kzelebb kerlhettek a vgs
helykhz.)
4. Ismteljk az eljrst a tmb elejtl. Most elg az
utols eltti helyig menni, s gy a msodik legnagyobb
tmbelem az utols eltti helyig bugyborkol.
5. n-1-szer megismtelve a vgigbugyborkoltatst a tmb
rendezett vlik.

//*************************************************
void buborek(double t[],int db){
//*************************************************
int i,j;

for(i=0;i<db-1;i++){
for(j=0;j<db-1-i;j++){
if(t[j]>t[j+1]){
double temp=t[j]; // csere
t[j]=t[j+1];
t[j+1]=temp;
}
}
}

89
}
Az algoritmus sebessge nmileg javthat, ha figyeljk, 30.2 Kzvetlen kivlasztsos rendezs
hogy volt-e csere egy vgigbugyborkoltats alatt. Ha nem, akkor
a tmb rendezett, teht szksgtelen folytatni a rendezst: Mkds:
1. Jegyezzk meg, hogy a tmb els eleme helyre akar-
//************************************************** juk betenni a tmb legkisebb elemt!
void buborek_jav(double t[],int db){
//************************************************** 2. Keressk meg a legkisebb elemet! Elszr felttelez-
int i,j,csere=1; zk, hogy az els elem a legkisebb, s ezzel hasonltjuk
ssze sorra a tmb elemeit.
for(i=0; i<db-1 && csere!=0; i++){
csere=0;
3. Ha tallunk kisebbet, akkor ettl kezdve ezzel hasonl-
for(j=0;j<db-1-i;j++){ tunk.
if(t[j]>t[j+1]){ 4. Ismteljk a 3. lpst a tmb vgig! gy megtalltuk a
double temp=t[j]; // csere
t[j]=t[j+1];
legkisebbet.
t[j+1]=temp; 5. Cserljk ki a megjegyzett elemet a legkisebbre, ha
csere=1; nem a megjegyzett volt a legkisebb!
} 6. Jegyezzk meg, hogy az elzleg megjegyzett utni
}
} tmbelem helyre akarjuk becserlni a maradk tmb-
} bl a legkisebbet, s ismteljk a lpseket a 2.-tl, mg
a megjegyzett tmbelem az utols nem lesz!
5 23 13 31 29 3 7 17 2 37 19 11 7. A tmb rendezett.

5 23 13 31 29 3 7 17 2 37 19 11 hov?
5 23
5 23 az eddigi
legkisebbel
23 13 hasonlt
5 13

13 23 5 31

5 29
23 31
j legkisebb
5 3
van

31 29 3 7

3 17
29 31
j legkisebb
3 2
van
31 3 2 37

2 19
3 31
2 11
5 23 13 31 29 3 7 17 2 37 19 11
5 23 13 31 29 3 7 17 2 37 19 11

5 13 23 29 3 7 17 2 31 19 11 37
2 23 13 31 29 3 7 17 5 37 19 11

rendezetlen rendezett

5 13 23 3 7 17 2 29 19 11 31 37 2 3 13 31 29 23 7 17 5 37 19 11

rendezett 2 3 5 31 29 23 7 17 13 37 19 11
rendezetlen

5 13 3 7 17 2 23 19 11 29 31 37
2 3 5 7 29 23 31 17 13 37 19 11

rendezetlen rendezett
rendezett rendezetlen
2 3 5 7 11 13 17 19 23 29 31 37

2 3 5 7 11 13 17 19 23 29 31 37
Bubork rendezs:
sszehasonltsok szma: Kzvetlen kivlasztsos rendezs:
worst case: O(n2) sszehasonltsok szma:
best case: n-1 = O(n) worst case: O(n2)
Cserk szma: best case: O(n2) // rosszabb, mint bubork
worst case: O(n2) Cserk szma:
best case: 0 worst case: n-1 = O(n) // jobb, mint bubork
Javtott bubork rendezs: best case: 0
Ugyanaz, mint a bubork, de a vrhat lpsszm kisebb

90
//************************************************** t[j] = t[j-1];
void kozvetlen(double t[],int db){ t[j-1] = temp;
//************************************************** }
int i,j,minindex; }

for(i=0;i<db-1;i++){ // i: hova
minindex=i; sszehasonltsok szma:
for(j=i+1; j<db; j++) worst case: O(n2)
if( t[j]<t[minindex] ) minindex=j; best case: n-1 = O(n)
if(minindex!=i){
double temp=t[minindex]; // csere
Cserk szma:
t[minindex]=t[i]; worst case: O(n2)
t[i]=temp; best case: 2*(n-1) = O(n)
}
}
} 30.4 Kzvetlen beszr rendezs
30.3 Sllyeszt rendezs A sllyeszt rendezs javtott vltozata.
Mkds:
Mkds: 1. Binris keresssel megkeressk a tmb mr rendezett
1. A tmb els kt elemt megfelel sorrendbe tesszk. rszn a nem rendezett rsz els elemnek helyt. Az
2. Most a tmb eleje rendezetten tartalmaz elemeket. elemet ideiglenes vltozba kivesszk.
3. A kvetkez tmbelemet addig cserlgetjk lefel, 2. A beszrs helytl az elemeket eggyel feljebb mozgat-
amg a nla eggyel kisebb index elem nla nagyobb. juk. (Figyeljk meg, hogy a t[j]=t[j-1] msolsnl j r-
Ekkor ismt rendezett lesz a tmb eleje, csak eggyel tke cskken a ciklusban. Ha nne, ugyanazzal az
tbb elem van ezen a rszen, mint elbb. elemmel rnnk fell az sszes elemet a rendezett rsz
4. A 3. lpst ismteljk egsz addig, amg van olyan vgig.)
tmbelem, amit nem sllyesztettnk a helyre. 3. Az ideiglenes vltozbl betesszk az elemet a helyre.
5. A tmb rendezett. 4. Addig ismteljk 1-3-ig, mg a tmb rendezett nem
lesz.
5 23 13 31 29 3 7 17 2 37 19 11 gy az sszehasonltsok szma jval kevesebb lehet, a cserk
szma viszont vltozatlan.
5 23
5 23 13 31 29 3 7 17 2 37 19 11
5 23 13

3 5 13 23 29 31 7 17 2 37 19 11
5 13 23

5 13 23 31 rendezett rendezetlen
3 5 13 23 29 31 7
5 13 23 31 29

temp
5 13 23 29 31
3 5 13 23 29 31 7 temp
5 13 23 29 31 3

3 5 7 13 23 29 31
5 13 23 29 3 31
temp

5 13 23 3 29 31
2 3 5 7 11 13 17 19 23 29 31 37

5 13 3 23 29 31 //**************************************************
void beszuro(double t[],int db){
//**************************************************
5 3 13 23 29 31 int i,j;

for (i=1; i<db; i++){


int min=0, max=i-1, med;
3 5 13 23 29 31 double temp=t[i];

while(min<=max){ // bin keres


rendezett rendezetlen med=(min+max)/2;
if(temp<t[med]) max=med-1;
else min=med+1;
2 3 5 7 11 13 17 19 23 29 31 37
}
for(j=i; j>min; j--) t[j]=t[j-1]; // eltol
//************************************************** t[min]=temp;
void sullyeszto(double t[],int db){ }
//************************************************** }
int i, j;

for(i=1; i < db; i++)


for(j=i; j > 0 && t[j-1] > t[j]; j--){
double temp = t[j]; // csere Kzvetlen beszr rendezs:

91
sszehasonltsok szma: int i,j,dist;
worst case: O(n*log2n) // jobb, mint az elzek for(dist=(db+1)/3; dist>0; dist=(dist+1)/3){
best case: O(n*log2n) for(i=dist; i<db; i+=dist)// sllyeszt rend.
Cserk szma: if(t[i]<t[i-dist]){
double temp=t[i];
worst case: O(n2) // a kzvetlen kivlaszts jobb for(j=i-dist;j>=0&&t[j]>temp;j-=dist)
best case: 2*(n-1) = O(n) t[j+dist]=t[j];
t[j+dist]=temp;
}
30.5 Shell rendezs }
}

Donald Shell dolgozta ki. Cl: az elemek mielbb vgleges


helyk kzelbe jussanak. 30.6 Gyorsrendezs
Mkds:
1. Bontsuk a tmbt sok kevs elembl ll rsztmbre! A Shell algoritmushoz hasonlan ez is gyorsan a vgleges he-
(Pl. 3 elem rsztmbkre.) A rsztmbket nem lye kzelbe viszi az elemeket.
szomszdos elemek alkotjk, hanem egymstl nagy, Mkds:
egyenl tvolsgra lv elemek. 1. Tippeljk meg, mennyi lehet a tmb kzps eleme
2. Rendezzk az elemeket az egyes rsztmbkn bell! (medin)! (Pontosan nem tudjuk, mert ahhoz rendezni
(Pl. n/3 db tmbt rendeznk gy.) A rendezshez gya- kne a tmbt.) Az adattpustl fggen ez lehet pl. a
korlatilag brmilyen megfelel algoritmus hasznlhat, kt szls adat tlaga, vagy valamelyik szls adat. (Pl.
a mintakdban sllyeszt rendezs szerepel. sztringtmb esetn nehz lenne tlagot szmolni)
3. A rsztmbk rendezse kevs mozgatssal jrt, de az 2. A medinnl kisebb elemeket dobljuk a tmb elej-
elemek nagyot ugrottak a majdani vgs helyk fel. re, a medinnl nagyobbakat pedig a tmb vgre! (Az-
4. Most az elznl srbb rsztmbket jelljnk ki (a az a kt fltmb nem lesz rendezett, csak az lesz biztos,
mintakdban hromszorosra srtjk a rsztmbket, a hogy az als felben minden elem kisebb lesz, mint
rajzon csak ktszeresre, mert gy jobban lthat, mit brmelyik elem a fels felben.)
csinlunk.) 3. A sztdobls a kvetkezkpp trtnik:
5. Rendezzk az j rsztmbket a 2. pontban rtak sze- a. Induljunk balrl, s keressk meg az els olyan
rint. elemet, amelyik nagyobb a medinnl, teht a
6. Ismteljk a 4-5 lpseket addig, amg egyetlen rsz- tmb rossz oldaln van.
tmbnk nem lesz, azaz maga a teljes tmb. Ha ezt b. Induljunk jobbrl, s keressk meg az els olyan
rendezzk, sokkal kevesebb mozgatsra lesz szksg, elemet, amelyik kisebb a medinnl, teht a tmb
mintha az eredeti tmbt rendeztk volna a sllyeszt rossz oldaln van.
algoritmussal. c. Ha a bal elem balra van a jobb elemtl, cserljk
meg ket, s ismteljk az a-b lpseket innen to-
5 23 13 31 29 3 7 17 2 37 19 11 vbbindulva.
d. Ha a bal elem jobbra van a jobb elemtl, akkor a
2 23 13 31 5 3 7 17 29 37 19 11
tmb elemei szt vannak vlasztva.
2 23 13 31 5 3 7 17 29 37 19 11 4. Ismteljk az 1-4 lpseket a kt rsztmbre! (A 4. pont
miatt rekurzv a folyamat.)
2 3 13 31 5 23 7 17 29 37 19 11 5. Addig meny a folyamat, amg egyelem tmbkig nem
jutunk. Ekkor befejezzk, mert ksz a rendezs.
2 3 13 31 5 23 7 17 29 37 19 11
23 13 31 3 7 17 2 37 19 11
2 3 7 31 5 23 13 17 29 37 19 11
5 23 13 31 29 3 7 17 2 37 19 11 med=15
2 3 7 31 5 23 13 17 29 37 19 11 bal jobb
5 11 13 31 29 3 7 17 2 37 19 23
2 3 7 11 5 23 13 17 29 37 19 31
bal jobb
2 3 7 11 5 23 13 17 29 37 19 31
5 11 13 2 29 3 7 17 31 37 19 23

2 3 5 11 7 23 13 17 19 37 29 31 bal jobb
5 11 13 2 7 3 29 17 31 37 19 23
2 3 5 11 7 17 13 23 19 31 29 37
jobb bal
2 3 5 11 7 17 13 23 19 31 29 37 med=6 med=26
5 11 13 2 7 3 29 17 31 37 19 23

2 3 5 7 11 13 17 19 23 29 31 37 5 3 13 2 7 11 23 17 31 37 19 29

5 3 2 13 7 11 23 17 19 37 31 29
Shell rendezs:
sszehasonltsok szma: 5 3 2 13 7 11 23 17 19 37 31 29
worst case: O(nA) , A=1,21,5
2 3 5 11 7 13 19 17 23 29 31 37
best case: O(nA)
Cserk szma: 2 3 5 11 7 13 19 17 23 29 31 37
worst case: O(nA) , A=1,21,5 2 3 5 7 11 13 17 19 23 29 31 37
best case: 0
2 3 5 7 11 13 17 19 23 29 31 37
//************************************************** //**************************************************
void Shell(double t[],int db){ void gyros(double t[],int db){
//************************************************** //**************************************************

92
int bal=0, jobb=db-1;
double med=(t[bal]+t[jobb])/2; // nem idelis int hasonlit2(const void *a, const void *b){
hallgato *x=(hallgato*)a;
if(db<2)return; // rekurzi stop hallgato *y=(hallgato*)b;
do{ if(x->atlag < y->atlag)return -1;
while(t[bal]<med)bal++; if(x->atlag == y->atlag)return 0;
while(t[jobb]>med)jobb--; return 1;
if(jobb>=bal){ }
double temp=t[bal]; // csere
t[bal]=t[jobb]; qsort(t,100,sizeof(hallgato),hasonlit1);
t[jobb]=temp; qsort(t,100,sizeof(hallgato),hasonlit2);
bal++; jobb--;
}
}while(jobb>=bal); Az els rendezs nv szerint teszi sorba a tmbt, a msodik
if(jobb>0)gyros(t,jobb+1); pedig tlag szerint.
if(bal<db-1)gyros(t+bal,db-bal);
}

sszehasonltsok szma: 30.8 Lncolt lista rendezse gyorsrende-


worst case: O(n2)
best case: O(n*log2n)
z algoritmussal
tlag: O(n*log2n)
Cserk szma: Az sszes olyan rendez algoritmust t lehet rni dupln ln-
worst case: O(n2) colt listra, ahol nem ugrlunk a tmbben, hanem szomszdos
best case: 0 elemeket vesznk. Egyirnyban lncolt lista esetn kvetelmny
tlag: O(n*log2n) mg, hogy csak elre kelljen haladni az elemek kztt.
Egyirny lista rendezsre alkalmas az eddigi algoritmu-
sok kzl: bubork, kzvetlen beszrs
Ktirny lista rendezsre alkalmas ezen fell mg: a
30.7 Szabvnyos knyvtri gyorsrende- sllyeszt, gyorsrendezs
z fggvny: a qsort A kzvetlen beszr nem volt j a binris keress miatt. A
Shell csak nagyon nehzkesen lenne hasznlhat, inkbb ne
prblkozzunk vele.
Az stdlib.h-ban tallhat a
void qsort( Gyorsrendezs listn:
void *base,
size_t nelem,
size_t width, //**************************************************
int (*fcmp)(const void *elem1,const void *elem2) typedef struct _szam{
); //**************************************************
int n;
prototpus tmbrendez fggvny. struct _szam *prev,*next;
base: a tmb cme } szam;
nelem: elemszm
width: egy elem mrete //**************************************************
void csere(szam * p1,szam * p2);
fcmp: kt tmbelemet sszehasonlt fggvny cme //**************************************************

Pl.: //**************************************************
void lista_qsort(szam * elso,szam * utolso){
//**************************************************
double t[7]={863, -37, 54, 9520, -3.14, 25, 9999.99}; szam *bal=elso, *jobb=utolso;
qsort( t, 7, sizeof(double), hasonlit ); int med=(elso->n+utolso->n)/2;
int hasonlit(const void *a, const void *b){ if(elso==utolso)return; // rekurzi stop
double *ia=(double*)a; do{
double *ib=(double*)b; while(bal->n<med)bal=bal->next;
if(*ia<*ib)return -1; // <0 while(jobb->n>med)jobb=jobb->prev;
if(*ia==*ib)return 0; // ==0 if(jobb->n>=bal->n){
return 1; // >0 szam * temp;
} csere(bal,jobb);
temp=bal; bal=jobb; jobb=temp;
A hasonlt fggvny visszatrsi rtke <0 egsz szm, ha if(bal!=jobb)bal=bal->next;
if(bal!=jobb)jobb=jobb->prev;
az els pointer ltal mutatott tmbelemnek a tmbben hrtbb }
kell llnia rendezs utn, >0, ha elbb kell llnia (azaz csere }while(bal!=jobb && jobb->n>=bal->n);
szksges), s 0, ha a kett sorrendje mindegy (pl. ha egyenlek). lista_qsort(elso,jobb);
lista_qsort(bal,utolso);
Ezen a mdon tetszleges tpus elemeket tartalmaz tmbk }
rendezhetk. Pl. sztringekre mutat pointerek tmbje esetn az
strcmp fggvny visszatrsi rtke pont az, ami kell. A csere fggvny defincija a 24.3 fejezetben tallhat.
Struktratmb esetn pl.:
Gondolkozzunk egytt!
typedef struct _hallgato{
char nev[50];
char neptun[7];
double atlag;
}hallgato;
Oldja meg egyedl!
int hasonlit1(const void *a, const void *b){
hallgato *x=(hallgato*)a;
hallgato *y=(hallgato*)b; Hzi feladatnak (nagyon sok aprsgra oda kell figyelni a
return strcmp(x->nev,y->nev); megolds sorn): rjon fggvnyt, amely paramterknt kap
} egy szkzzel elvlasztott szavakat tartalmaz sztringet, s

93
ABC sorba rendezi a szavakat a sztringen bell! A szavak
hossza 1 s 25 karakter kztt brmennyi lehet. Maximum
31. Preprocesszor
hrom akkora segdtmbt hasznlhat, melyben egy-egy sz
elfr (nem biztos, hogy szksge lesz mindre), tovbbi segd- Mieltt egy C program a fordthoz kerlne, tmegy rajta az
tmbt nem hasznlhat! elfeldolgoz. Ez egy egyszer szvegszr s behelyettest
alkalmazs. Az a clja, hogy a fordtnak ne kelljen a C program
formai dolgaival foglalkoznia, csak a fordtssal trdhessen.
Eltvoltja a megjegyzseket a kdbl, a whitespace karaktereket
optimalizlja, s vgrehajtja a preprocesszor utastsokat (sor
eleji # jelzi ezeket, s vgket nem zrja ;, a sor vgig tartanak).
A legfontosabb preprocesszor utastsok a kvetkezk:

#define szimblum, konstans s makr defincira


szimblum:
#define SZIMBOLUM

definilja a SZIMBOLUM azonostt.


nmagban csak arra j, hogy ksbb meg lehessen lla-
ptani, hogy van ilyen szimblum.
A szimblumra ugyanazok a szablyok rvnyesek, mint
a tbbi C azonostra: az angol ABC kis- s nagybetibl,
szmokbl s alhzs jelekbl llhatnak, szmmal nem
kezddhetnek. Az a szoks, hogy kisbett nem hasznl-
nak, gy knnyen megklnbztethetk a tbbi azonost-
tl.
konstans:
#include <stdio.h>

#define KONSTANS 10
#define KONSTANS2 "Szveg"
#define EGYESIT for(i=0;i<KONSTANS;i++)tomb[i]=1.0;
#define KIIR
for(i=0;i<KONSTANS;i++)printf("%g\n",tomb[i]);

int main(void){
double tomb[KONSTANS];
int i;
for(i=0;i<KONSTANS;i++)tomb[i]=0.0;
KIIR
EGYESIT
KIIR
puts(KONSTANS2);
puts("KONSTANS2"); // nem helyettest
return 0;
}

Ahol az elfeldolgoz megtallja a konstanst, oda behe-


lyettesti a megadott, sor vgig tart szveget, ami akr
utasts is lehet. A kdban szerepl konstans sztringbe
nem helyettest.)
Ha ;-t tesznk a sor vgre, azt is behelyettesti a kdba.
Ha hibsan adjuk meg a definilt konstanst (vagy mak-
rt), akkor a fordt nem a konstans defincijnl jelzi a
hibt, hanem a behelyettests helyn. (Ha pl. #define
KONSTANS 10; szerepelne, a VC fordt ht hibazenetet
ad, pl.: syntax error : missing ']' before ';'. Nem knny
rjnni, mi is a baj.)
makr:
#include <stdio.h>

#define INT_KIIR(a) printf("%d\n",a)


#define MIN(a,b) ((a)<(b)?(a):(b))

int main(void){
int a=0,b=10;
INT_KIIR(6);
INT_KIIR(MIN(++a,++b));
// baj van: printf("%d\n",((++a)<(++b)?(++a):(++b)))
return 0;
}

Fggvnyre hasonlt.

94
Az elfeldolgoz szvegszer behelyettestst vgez, a
fordt a behelyettestett kdot kapja, ami gondokat
okozhat. Pl. a kdra rnzve azt hisszk, hogy a s b is Gondolkozzunk egytt!
eggyel n, s a behelyettests utn ltjuk, hogy a kettvel
ntt.

#undef Oldja meg egyedl!


#undef MIN

Szimblum, konstans, makr trlse. Akkor hasznos, ha pl.


lesz utna #ifdef vagy jra akarjuk definilni.

Feltteles fordts

#if kifejezs #if kifejezs



#else // opc #elif kifejezs

#endif #endif
#ifdef azonost #ifndef azonost

#else // opc #else // opc

#endif #endif

A kifejezs fordtsi idben kirtkelhet legyen (azaz kons-


tans). elif = else if

#error Fordtsi hibazenetet adhatunk.

#ifdef MIN
#error MIN redefinition.
#endif

Elre definilt preprocesszor konstansok

__DATE__: Az adott forrsfjl fordtsnak dtuma


Mmm dd yyyy formban.
__TIME__: Az adott forrsfjl fordtsnak id-
pontja hh:mm:ss formban.
__TIMESTAMP__: Az adott forrsfjl utols mdosts-
nak dtuma s idpontja Ddd Mmm
Date hh:mm:ss yyyy formban.
__FILE__: Az adott forrsfjl neve.
__LINE__: Az adott forrsfjl aktulis sornak
sorszma egsz konstansknt.

#include Az utna megadott nev fjlt beszerkeszti az adott


helyre.
A <> kztt megadott fjlt a fordt belltsainl belltott
fejlc mappkban keresi, az "" kztt megadott fjlt pedig a
fordtand program mappjba.
A fjlnv tvonalat is tartalmazhat, pl.: <sys/stat.h>,
"../../programok/headerek/lacigrafika.h". Nem csak fejlcfjl
szerkeszthet be, hanem brmi. #include-ot nem csak a fjl elej-
re tehetnk, hanem brmelyik sorba, a fordt oda fogja beszer-
keszteni.

#pragma Fordtspecifikus fordtsi belltsok megadst


teszi lehetv, ezek kztt teht nincs olyan, ami minden C ford-
tval megy.
Visual C-ben taln a legfontosabb a #pragma pack(1) bell-
ts: ezzel rhetjk el, hogy a struktrk/unionok adattagjai kztt
ne legyen hzag a memriban. Alapesetben a fordt 8 bjton-
knt helyezi el az adatokat a gyorsabb mveletvgzs rdekben.
1-re lltani akkor lehet rtelme, ha ilyen formtum binris fjlt
kell rni/olvasni, pl. ha bmp fjlt kezelnk.
A tovbbi #pragma lehetsgekrl a fordt HELP-jbl tj-
kozdhatunk.

95
32. Bitmezk, union
}

int main(void){
union uni x;
Kt, korbban nem rszletezett, kevsb fontos adattpus. int i;
for(i=0;i<100;i++)x.t[i]=0;
kiir(x);
32.1 Struktra bitmezi x.i=55; kiir(x);
x.d=88.0; kiir(x);
x.i=55; kiir(x);
Ha 1 bjtnl kisebb is elg egy vltoznk trolshoz, vagy x.i=500; kiir(x);
mondjuk 12 bit is elg, akkor hasznlhatjuk a struktra bitmezit. x.d=88.1; kiir(x);
return 0;
A mdszer akkor is hasznos, ha hardvert akarunk programozni. A }
bitmezkkel elrhet eredmnyek a bitszint opertorokkal is
megoldhatk, de a bitmezk hasznlata knyelmesebb. A program futsnak eredmnye Intel architektrj procesz-
szoron, 32 bites rendszerben:
#include <stdio.h>

struct bitmezos{ char: 0,0,0,0,0,0,0,0,


int a : 4; int=0
int b : 12;
double d; double=0
};

int main(void){
char: 55,0,0,0,0,0,0,0,
struct bitmezos b; int=55
b.a=10; double=2.717361052126856e-322
b.b=10;
b.d=b.a*b.b;
printf("%d, %d, %g\n",b.a,b.b,b.d); char: 0,0,0,0,0,0,86,64,
return 0; int=0
}
double=88
A bitmeznl hasznlt alaptpus csak int, signed int vagy char: 55,0,0,0,0,0,86,64,
unsigned int lehet.
int=55
Az a adattag 4 bites eljeles egsz szmot trol, azaz
double=88.000000000000782
-8..+7 kztti rtket. 10-et adva neki, tlcsorduls k-
vetkezik be, hibs rtk (-6) lesz benne. A b mr 12 bites,
gy gond nlkl trolja a 10-et. char: 244,1,0,0,0,0,86,64,
Ha a tpusa unsigned lenne, akkor mr a 10-et is jl trol- int=500
n, hiszen 4 biten 0..15-ig frnek a szmok. double=88.000000000007105
Mivel ezt a trolst a szmtgp bitenknti mveletek
felhasznlsval valstja meg, lassabb lesz a mkds, char: 102,102,102,102,102,6,86,64,
mint pl. norml int vagy char tpus hasznlata esetn len- int=1717986918
ne. double=88.099999999999994
A nagy helytakarkossgban ne feledjk, hogy a fordt-
program a gyorsabb mkds rdekben gyakran szha- Magyarzat:
trra (2, 4, 8, 16 bjtonknt, belltsfgg) illeszti a Az albb lertak csak 32 bites Windowsban, VisualC for-
struktrk tagvltozit. A fenti kdot Visual C-ben lefor- dtval vannak gy. Ms architektrn ms lehet az ered-
dtva, ha megnzzk, mennyi sizeof(b), 16-ot kapunk, mny, azaz a kd nem platformfggetlen!
mert a s b ugyanabban az int tpus vltozban van. Ezt A union tpus vltozban lv tagvltozk fizikailag
a vltozt egy 4 bjtos felhasznlatlan res hely kveti a ugyanazon a memriahelyen tallhatk, ami azt jelenti,
memriban, majd kvetkezik a d vltoz. vagyis ha a s hogy ha megvltoztatjuk az egyiket, az sszes tbbi is
b sima egsz lett volna, ugyanennyi helyet foglalna a megvltozik.
struktra. Ha d-t elhagyjuk, s csak a s b marad, akkor 4 Elszr kinullzzuk a karaktertmbt, ez egyttal a msik
bjt lesz a struktra mrete. Visual C-ben a szhatrt 1 kt vltoz kinullzst is jelenti, hiszen azok kisebbek
bjtra llthatjuk a #pragma pack(1) preprocesszor utas- 100 bjtnl.
tssal, bvebben lsd a Helpben. Ezutn az egsz szmba 55-t runk. Kirsnl az int va-
lban 55.
32.2 Union o A karaktertmb els bjtja szintn 55. Elsre taln
nem tnik fel, de ez nem nyilvnval. Azt vrnnk,
hogy a karaktertmb els 8 eleme 0,0,0,55,0,0,0,0 le-
Az union adattpus formailag megegyezik a struktrval, gyen. Az Intel architektrj processzorok azonban
mshogy mkdik azonban: az adatokat fordtott bjtsorrendben troljk.
#include <stdio.h>
A double rtk nem 55! Jl jegyezzk meg, hogy ezzel a
mdszerrel nem lehet tpuskonverzit vgrehajtani. A ka-
union uni{ pott rtk az a double szm, amelynek megegyezik a bit-
unsigned char t[100];
int i;
mintja a karaktertmbnl lthat bitmintval.
double d; A double rtket 88-ra lltjuk. A fordtott bjtsorrend
}; miatt az i rtke 0.
void kiir(union uni x){
Az i-be ismt 55-t runk. Mivel az i csak feleakkora he-
int i; lyet foglal a memribl, mint a d (32 bites a 64-gyel
printf("char: "); szemben), csak a d felt vltoztatja meg, d msik fele
for(i=0;i<8;i++)printf("%hhu,", x.t[i]);
printf("\nint=%d\ndouble=%.20g\n\n", x.i, x.d);

96
nem vltozik, s mivel abban a felben volt az rdemi
rsz, azt ltjuk, hogy alig rontottuk el a d-ben lv 88-at.
33. Vltoz paramterlistj fggv-
500-at rva ltjuk, hogy a karaktertmb i ltal lefoglalt r- nyek
szn mr 2 hely is klnbzik 0-tl. 500 knnyedn kiol-
vashat: 1256+244.
A C nyelvben tallkoztunk olyan fggvnyekkel, melyeknek
A 88.1 nem brzolhat pontosan kettes szmrendszer-
brmennyi paramtere lehetett (printf s scanf csaldok). Most
ben, gy a szm vge nem csupa 0.
megnzzk, hogyan lehet ilyet ltrehozni.
Vltoz argumentumszm fggvnyek ltrehozshoz az
A union adattpust ritkn hasznljuk.
stdarg.h fejlcllomny beszerkesztse szksges. Ebben vannak
definilva a makrk, valamint a va_list pointertpus. A vltoz
argumentumszm fggvnyeknek legalbb egy konkrt tpus
Gondolkozzunk egytt!
paramterrel kell rendelkeznie, ezt kveti az opcionlis paramte-
rek listja, melyet jell. Ezt mr nem kvethetik tovbbi konk-
rt paramterek, azaz a mindig a lista vgn ll.
Az argumentumlista kezelshez hrom makr hasznland:
Oldja meg egyedl! void va_start( va_list arg_ptr, prev_param ): a lista fel-
dolgozsakor ezzel kezdnk. A makr msodik param-
terknt kapja az els opcionlis argumentumot megelz
vltozt, s belltja az els paramterknt kapott pointert
az opcionlis argumentum kezelshez megfelelen. (Mi-
vel makrrl van sz, nem a pointer cmt kell tadni, ha-
nem magr a pointert.) Ha belenznk az stdarg.h-ba, eh-
hez hasonl megvalstst tallunk:
arg_ptr=&prev_param+1
type va_arg( va_list arg_ptr, type ): a makr visszaadja a
kvetkez opcionlis paramter rtkt. Ha belenznk az
stdarg.h-ba, ehhez hasonl megvalstst tallunk:
*(((type*)(arg_ptr=(type*)arg_ptr+1))-1)
void va_end( va_list arg_ptr ): ha befejeztk a lista fel-
dolgozst. Ha belenznk az stdarg.h-ba, ehhez hasonl
megvalstst tallunk: arg_ptr=NULL
A kvetkez pldaprogram kirja a paramterknt tvett rt-
keket a formtumsztringnek megfelelen. A formtumsztring
hrom karaktert tartalmazhat: g-t, d-t s s-t. A g double
tpust jell, a d int-et, az s pedig sztringet. Az argumentumo-
kat kln sorba rja, s kirja az argumentum sorszmt is.

#include <stdarg.h>
#include <stdio.h>

void unikiir(char t[],...){


va_list p;
int i;

va_start(p,t);
for(i=0; t[i]!=0; i++){
switch(t[i]){
case 'd':
printf("%d. %d\n",i+1,va_arg(p,int));
break;
case 'g':
printf("%d. %g\n",i+1,va_arg(p,double));
break;
case 's':
printf("%d. %s\n",i+1,va_arg(p,char*));
break;
}
}
va_end(p);
}

int main(){
unikiir("gdsd",3.14,-5,"Hello",3);
return 0;
}

Hibakezel fggvny A kvetkez fggvny a printf-hez


hasonlan hasznlhat, de kirja, hogy Error: a megjelentend
szveg el, tovbb a kirs utn kilp a programbl. A vfprintf-
hez hasonlan a tbbi printf fggvnynek is van ilyen tovbbdo-
bott vltozata.

97
34. Hasznos fggvnyek a C-ben
void error(const char *s,...){
va_list p;

va_start(p,s);
lvletlen szmok Az stdlib.h fejlc beszerkesztsvel rhet-
fprintf(stderr,"\n\nError: "); jk el a int rand( void ); prototpus fggvnyt, mely a
vfprintf(stderr,s,p);
fprintf(stderr,"\n\nPress ENTER to continue..."); 0RAND_MAX kztti lvletlen szmot ad vissza. RAND_MAX
rtke az ISO C szabvny szerint legalbb 32767.
va_end(p); Amennyiben 0n kztti egsz szmra van szksg vletlen
scanf("%*s");
exit(1);
szmknt, a rand()%n kifejezst alkalmazhatjuk.
} Ha lebegpontos vletlen szm szksges: double
d=(double)rand()/RAND_MAX mdon kaphatunk 0..1 kz es
rtket.
if(p==NULL)
error("Cannot open file (%s) in line %d of %s" Ha a rand() fggvnyt meghvva minden programindtskor
,filename,__LINE__,__FILE__); ugyanazt a szmsort kapjuk. Ezt elkerlhetjk a vletlen szm
genertor kezdrtknek tlltsval, melyet a

void srand( unsigned seed );

prototpus fggvny meghvsval tehetnk meg. Ahhoz,


Gondolkozzunk egytt! hogy a kezdrtk mindig ms lehessen, a fggvnynek a rend-
szeridt adjuk kezdrtkknt:

#include <stdio.h>
#include <stdlib.h>
Oldja meg egyedl! #include <time.h>

int main(){
int i;

srand((unsigned)time(NULL));
for(i=0; i<10; i++)printf("%d\n",rand());
}

Fjlok trlse, tnevezse Az stdio.h-ban tallhat fggv-


nyekkel lehetsges:
int remove(const char *path ): a path sztring a fjl nevt
tartalmazza, tvonalat is meg lehet adni. A visszatrsi
rtk 0, ha sikerlt.
int rename(const char *oldname, const char *newname ):
az oldname nev fjlt vagy mappt newnane nevre ne-
vezi t. A visszatrsi rtk 0, ha sikerlt. Fjl msik
mappba is helyezhet, ha a newname-ben megadott t-
vonal ms, mappa viszont nem helyezhet t.

Idkezels a C-ben A time_t time( time_t *timer ); fggvny


az 1970. janur 1. 00:00:00 ta eltelt idt adja vissza msodperc-
ben, a time_t tpus teht egy typedef-fel ltrehozott egsz tpus.
rtke nem definilt 2038. janur 18. 19:14:07 utn. Ugyanazt az
rtket adja visszatrsi rtkknt, amit paramtersoron. Param-
tersoron NULL is adhat.
A time ltal visszaadott idt tbb fggvnnyel is emszthet
alakv tehetjk.
gmtime(): struktrra mutat pointert ad vissza, melyben
kln van vlasztva v, hnap, nap, perc, msodperc, a
ht melyik napja, stb.
localtime(): ugyanolyan struktra cmt adja vissza, mint
a gmtime(), csak az idznnak megfelelen.
asctime(): sztringg konvertlja az elz kt fggvny
struktrjt
ctime(): sztringg konvertlja a time() ltal visszaadott
idpontot. A sztring formja pl.:
Wed Jan 02 02:03:55 1980\n\0
A processz indtsa ta felhasznlt idt krdezhetjk le a
clock_t clock( void ); fggvnnyel. A clock_t egy egsz tpus. A
fggvny msodpercnl sokkal pontosabban szmol. Programunk
sebessgt mrhetjk a kvetkez mdon:

clock_t start, stop;


double eltelt_ido;

start = clock();
... // itt van a mrend rsz

98
35. Programozsi rdekessgek
finish = clock();
eltelt_ido=(double)(stop-start)/CLOCKS_PER_SEC;
printf("%g sec\n",eltelt_ido);

A CLOCKS_PER_SEC konstans rtke Visual C-ben 1000. 35.1 Programozs tbb szlon
Ez nem jelenti azt, hogy a program valban kpes ezred msod-
perc pontossggal mrni, csak annyit, hogy a clock() ezredm- A C szabvny nem biztost lehetsget a tbbszl progra-
sodpercben adja vissza az idt. mok rsra, azonban elrhetek platformfggetlen fggvny-
A clock() fggvny a program tnyleges futsi idejt mri, knyvtrak erre a clra. A UNIX rendszerek rszt kpez
ami azt jelenti, hogy ha a szmtgpen tbb program generl POSIX Threads (pthreads) knyvtrral ismerkednk meg rvi-
nagy terhelst a CPU szmra, s pl. a programunk a CPU-t 50%- den, melynek 32 s 64 bites Windowsra rt vltozatai elrhetk
ig terheli, akkor 10 msodperces futsi idt a clock() 5 msod- pthreads-w32 nven (http://sourceware.org/pthreads-win32/). A
percnek fog jelezni. Ha programunk tbbszl, a clock() fgg- knyvtr hasznlathoz a letlttt kdot le kell fordtani, vagy
vny msknt viselkedik Windows s msknt Linux alatt. A hasznlhat az eleve lefordtott vltozat is.
Linux magonknt szmolja a terhelst, azaz ha egy ktmagos Windowsban a tbbszlnak kvnt programhoz hozz kell
gpen futtatjuk a programot, s a program mindkt magot 100%- szerkeszteni norml esetben a pthreadVC2.lib knyvtrat
ra terheli, akkor egy 10 msodperces futsi idt a clock() 20 (Properties => Linker => Input => Additional dependencies), a
msodpercnek fog mutatni, ezzel szemben Windowsban 10 m- pthreadVC2.dll pedig legyen a program mappjban vagy a
sodpercnek. windows/system32 mappban (esetleg ms olyan helyen, ahol a
program megtallja). A programhoz hozz kell adni a pthread.h
fejlcllomnyt. Hogy ez hasznlhat legyen, a Properties =>
C/C++ => General => Additional Include Directories sorban
adjuk meg a fejlcet tartalmaz mappt is (ez a header fjl ms
headereket is be akar szerkeszteni). Ezeken kvl a Properties =>
C/C++ => Code Generation => Runtime Library-nl Multi-
Gondolkozzunk egytt! threaded (Multi-threaded debug) knyvtrat lltsunk!
UNIX-ban nem kell semmit tenni, a pthread.h fejlc rendel-
kezsre ll.

Oldja meg egyedl! 1. Plda (minden plda forrs:


http://www.yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html)

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

void *print_message_function( void *ptr );

main()
{
pthread_t thread1, thread2;
char *message1 = "Thread 1";
char *message2 = "Thread 2";
int iret1, iret2;

/* Create independent threads


each of which will execute function */

iret1 = pthread_create( &thread1, NULL,


print_message_function, (void*) message1);
iret2 = pthread_create( &thread2, NULL,
print_message_function, (void*) message2);

/* Wait till threads are complete


before main continues. Unless we */
/* wait we run the risk of executing
an exit which will terminate */
/* the process and all threads before
the threads have completed. */

pthread_join( thread1, NULL);


pthread_join( thread2, NULL);

printf("Thread 1 returns: %d\n",iret1);


printf("Thread 2 returns: %d\n",iret2);
exit(0);
}

void *print_message_function( void *ptr )


{
char *message;
message = (char *) ptr;
printf("%s \n", message);
}

Ahol:

99
int pthread_create(pthread_t * thread, const pthread_attr_t * A mutexes vltozat a kvetkezkpp mkdik:
attr, void * (*start_routine)(void *), void *arg); Az egyik szl a pthread_mutex_lock() fggvnnyel
thread: a szl azonostja (olyan, mint a fjlpointer vagy mutex1 vltoz rtkt tlltja foglaltra, megnveli count
a lefoglalt memria cme: innentl ezzel lehet hivatkoznia rtkt, s visszalltja mutex1-et szabadra.
a szlra Ha kzben a msik szl szeretn megvltoztatni count-ot,
attr: attribtumok, klnbz tulajdonsgokat llthatunk eltte a pthread_mutex_lock() ellenrzi, hogy a mutex
be. Ha NULL, default. szabad-e. Ha foglalt, addig vr, amg fel nem szabadul, s
void * (*start_routine)(void *): ezt a fggvnyt futtatja utna zrja le.
kln szlon Vagyis a vltozhoz hozzfrst a pthread_mutex_lock()
arg: a fggvnynek tadott paramterek (ha tbb param- fggvny gtolja meg.
tert akarunk, hozzunk ltre struktrt, s annak a cmt
adjuk t) Join Nem szksges tovbbi magyarzat.
Amikor a fenti programban lefut a pthread_create fggvny,
akkor ltrejn egy j programszl, s elindul a megadott fgg- Felttel vltozk
vny, jelen esetben a print_message_function(). A pthread_create
visszatr, iret1-be bekerl a visszaadott rtk (0, ha nem volt #include <stdio.h>
#include <stdlib.h>
gond), s jn a msodik pthread_create fggvnyhvs a #include <pthread.h>
message2 paramterrel, de ezzel prhuzamosan, a httrben fut az
elzleg elindtott print_message_function() a message1-gyel! A pthread_mutex_t count_mutex =
PTHREAD_MUTEX_INITIALIZER;
msodik pthread_create elindtja a print_message_function()-t a pthread_mutex_t condition_mutex =
message2 paramterrel jabb szlknt, gy a programunk mr 3 PTHREAD_MUTEX_INITIALIZER;
szlon fut egyszerre (a kt print_message_function(), valamint a pthread_cond_t condition_cond =
PTHREAD_COND_INITIALIZER;
main fggvny).
A pthread_join fggvny addig vr, amg a paramterknt void *functionCount1(void*xxx);
adott programszl vget nem r, azaz a print_message_function() void *functionCount2(void*xxx);
int count = 0;
fggvnybl vissza nem trnk a kirs utn. Msodik paramtere #define COUNT_DONE 10
za a pointer, amely a fggvny ltal visszaadott pointert trolja. #define COUNT_HALT1 3
Mindkt szl befejezdst megvrjuk. #define COUNT_HALT2 6
Elkpzelhet, hogy a msodik print_message_function() ltal
main(){
kirt Thread 2 szveg jelenik meg elbb a kpernyn, hiszen a pthread_t thread1, thread2;
kt szl prhuzamosan fut, kzttk semmifle ersorrend nincs
rgztve. pthread_create(&thread1,NULL,&functionCount1,NULL);
pthread_create(&thread2,NULL,&functionCount2,NULL);
A kt szl befejezdse utn rjuk ki iret1 s iret2 rtkt. pthread_join( thread1, NULL);
A void pthread_exit(void *retval); fggvnnyel kilphetnk a pthread_join( thread2, NULL);
szlbl, pl. ha valami hiba trtnt. (Ha csak egy fggvny fut,
exit(0);
akkor abbl return-nel is kilphetnk, de ha abbl ms fggvnyt }
hvunk, s a hiba ebben a ms fggvnyben keletkezik, akkor
innen egyszerbb a pthread_exit() hasznlata. void *functionCount1(void*xxx){
for(;;){
pthread_mutex_lock( &condition_mutex );
Szlszinkronizls A Pthreads knyvtr hrom mdszert while( count >= COUNT_HALT1
biztost a szlak szinkronizlsra: && count <= COUNT_HALT2 ){
pthread_cond_wait( &condition_cond,
Mutexek (mutex=MUTual EXclusion lock=klcsns ki- &condition_mutex );
zrs). Blokkolhatjuk ms programszlak hozzfrst a }
vdett erforrsokhoz. pthread_mutex_unlock( &condition_mutex );
Join: vrakozs ms szlak befejezdsre pthread_mutex_lock( &count_mutex );
Felttel vltozk a pthread_cond_t tpussal megadva count++;
printf("Counter value functionCount1: %d\n",
count);
Mutex Egyszer plda mutex nlkl: pthread_mutex_unlock( &count_mutex );

int counter=0; if(count >= COUNT_DONE) return(NULL);


}
void functionC(){ }
counter++
} void *functionCount2(void*xxx){
for(;;){
Mutexszel: pthread_mutex_lock( &condition_mutex );
if( count < COUNT_HALT1
|| count > COUNT_HALT2 ){
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER; pthread_cond_signal( &condition_cond );
int counter=0; }
void functionC(){ pthread_mutex_unlock( &condition_mutex );
pthread_mutex_lock( &mutex1 );
counter++ pthread_mutex_lock( &count_mutex );
pthread_mutex_unlock( &mutex1 ); count++;
} printf("Counter value functionCount2: %d\n",
count);
A mutex nlkli esetben, ha a functionC fggvny tbb pl- pthread_mutex_unlock( &count_mutex );
dnyban fut, akkor megtrtnhet, hogy mindkt pldny egyszer- if(count >= COUNT_DONE) return(NULL);
re olvassa be a counter vltoz rtkt, majd mindkett megn- }
veli, s mindkett visszarja. Ez azt jelenti, hogy counter rtke }
csak eggyel n, pedig kt nvels is trtnt.

100
Mg count vltoz rtke 3 s 6 kztt van, functionCount1()
fggvny felfggesztett llapotba kerl. Ha count rtke ms,
functionCount1() s functionCount2() versenyez egymssal, s
hol ez, hol az lpteti s rja ki count rtkt.
A condition_cond vltozt mutexszel kell vdeni az ssze-
akads ellen. A pthread_cond_wait() fggvny felfggeszti a
sajt szlnak futst addig, amg egy msik szl signal-t nem
kld. Fel is szabadtja a felttel vltozt vd mutexet, gy nem
fagy le a msik szl a vrakozs miatt. Miutn functionCount2()
signal-t kldtt, pthread_cond_wait() ismt lefoglalja a felttel
vltozt vd mutexet, amit az felszabadul (addig vr), s ezutn
engedi csak tovbb a sajt szlt.
Ha tbb szl is vrakozik, akkor a pthread_cond_signal()
csak az egyiket szabadtja fl. Nem meghatrozott, hogy melyi-
ket. A pthread_cond_broadcast() felszabadtja az sszeset.

A tbbszlsg csapdi
Versenyhelyzetek: mutexszel s joinnal megoldhat
Szlbiztos kd: kerlni kell a globlis s statikus vlto-
zk hasznlatt. A fggvny eredmnynek a hv bizto-
stson helyet!
Mutex holtpont (deadlock): a mutexet szabadtsuk fel,
amint lehet
Felttel vltoz holtpont: if s while helyes alkalmazs-
val.

101
Trgymutat

! _

! opertor ........................................................................ 14, 51 __DATE__ .............................................................................. 94


!= opertor ...................................................................... 14, 50 __FILE__ ................................................................................ 94
__LINE__................................................................................ 94
__TIME__ .............................................................................. 94
# __TIMESTAMP__ ................................................................... 94

#define .................................................................................. 94
#elif ................................................................................... 94 |
#else ................................................................................... 94
#endif................................................................................. 94 | opertor.......................................................................... 39, 51
#if ........................................................................................ 94 || opertor ..................................................................... 15, 51
#ifdef................................................................................. 94
#ifndef .............................................................................. 94
#include ...................................................................... 21, 94 ~
#pragma ................................................................................ 94
#undef ................................................................................... 94 ~ opertor ........................................................................ 39, 51

% <

% opertor....................................................................... 14, 51 << opertor...................................................................... 39, 51

& =

& opertor........................................................................ 39, 51 = opertor ....................................................................... 13, 50


&& opertor .................................................................... 15, 51 == opertor ..................................................................... 14, 50

* >

* opertor.................................................................. 16, 51, 53 >> opertor...................................................................... 39, 51


-> ......................................................................................... 75

,
A,
, opertor ................................................ Lsd vessz opertor
adat ....................................................................................... 12
adatelem ................................................................................. 8
? adatszerkezet .......................................................................... 8
algoritmus ............................................................................... 8
?: opertor ....................................................................... 31, 52 llapotgrf ............................................................................. 79
llapottbla ........................................................................... 78
lvletlen szm ..................................................................... 98
^ asctime .................................................................................. 98
assembly ............................................................................... 45
^ opertor ......................................................................... 39, 51 asszociativits ........................................................................ 50
atof ........................................................................................ 63
atoi ........................................................................................ 63
atol ........................................................................................ 63
auto ....................................................................................... 68

102
azonost .............................................................................. 22
D

B De Morgan azonossgok ........................................................ 15


debugger ................................................................................ 17
decimlis ................................................................................ 13
back slash ............................................................................. 13
kirs .................................................................................. 38
BackusNaur Form ..................................................... Lsd BNF
default ................................................................................... 29
bjt .......................................................................................... 8
deklaratv programozsi nyelv .............................................. 12
bjt mrete ............................................................................. 8
dokumentls........................................................................ 10
balrtk ................................................................................. 50
double ............................................................................. 24, 38
bels formtum .................................................................... 43
konstans ............................................................................ 25
binris .............................................. Lsd kettes szmrendszer
binris fa ............................................................................... 83
binris keress ...................................................................... 88
E,
bit. ........................................................................................... 8
Biteltols ............................................................................... 39
EBNF ...................................................................................... 20
bitenknti
egsz
S ..............................................................Lsd & opertor
konstans ............................................................................ 25
KIZR VAGY............................................... Lsd ^ opertor
elgazs ................................................................................. 10
NEM ............................................................ Lsd ~ opertor
elemi utasts .................................................................... 8, 11
VAGY ........................................................... Lsd | opertor
lettartam ............................................................................. 68
bitenknti logikai opertorok .............................................. 39
eljrs ................................................................. Lsd fggvny
bitmez ............................................................................48, 95
elfeldolgoz ......................................................................... 20
BNF........................................................................................ 20
eljel nlkli egsz .................................................................. 8
break ................................................................................29, 31
eljeles egsz........................................................................... 8
brute-force mdszer ............................................................. 13
else......................................................................................... 28
bug ......................................................... Lsd szemantikai hiba
enum ..................................................................................... 47
busz ....................................................................................... 44
EOF......................................................................................... 42
EPIC ........................................................................................ 45
C rtkads............................................................................... 13
S
bitenknti .................................................... Lsd & opertor
C nyelv .................................................................................... 9
logikai ....................................................... Lsd && opertor
calloc ..................................................................................... 58
exit ......................................................................................... 42
case ....................................................................................... 29
extern .................................................................................... 68
case sensitive ........................................................................ 22
char ..................................................................................29, 38
ciklus ..................................................................................... 10
F
ell tesztel ...................................................................... 29
htul tesztel ................................................................... 29
fa... ......................................................................................... 83
vgtelen ........................................................................... 30
fclose ..................................................................................... 70
ciklusmag .............................................................................. 10
fejlcllomny........................................................................ 22
CISC ....................................................................................... 45
felsorolt tpus .......................................................... Lsd enum
clock ...................................................................................... 98
feltteles opertor ................................................................ 31
compiler ................................................................. Lsd fordt
fgets ....................................................................................... 43
const ..................................................................................... 63
FILE *...................................................................................... 70
const char* ........................................................................... 63
float ....................................................................................... 38
continue ................................................................................ 31
foglalt szavak ......................................................................... 22
CPU ....................................................................................... 45
folyamatbra ................................................................... 10, 65
ctime ..................................................................................... 98
fopen ..................................................................................... 70
for ................................................................................. 26, 29
Cs fordt .............................................................................. 17, 20
formtumsztring ............................................................. 13, 43
f hats .................................................................................. 50
csv ......................................................................................... 72
fprintf ............................................................................... 42, 71
fputc ................................................................................ 71, 72

103
fputs ...................................................................................... 71 isspace ................................................................................... 49
fread ...................................................................................... 70 isupper ................................................................................... 49
free ........................................................................................ 58 iterci ..................................................................... Lsd ciklus
fseek ...................................................................................... 70
function .............................................................. Lsd fggvny
funkci ................................................................ Lsd fggvny J
fggvny .................................................................... 11, 22, 48
definci ............................................................................ 22 jobbrtk ............................................................................... 50
deklarci ......................................................................... 22
fggvnyfej ....................................................................... 22
fggvnytrzs ................................................................... 22 K
prototpus ......................................................................... 22
fggvnyknyvtr ................................................................. 22 karakter
fggvnypointer .................................................................... 53 konstans ........................................................................... 25
fwrite ..................................................................................... 70 karakterisztika ....................................................................... 37
kettes komplemens szmbrzols................................ 37, 39
kettes szmrendszer ............................................................... 8
G kezdrtk ...................................................................... 14, 33
tmbnek ........................................................................... 35
gpi kd ....................................................................... 8, 20, 45 kirtkelsi pont ............................................................. 52, 73
getchar................................................................................... 42 kifejezs ................................................................................ 23
gets ........................................................................................ 42 utasts ............................................................................. 28
globlis vltoz ...................................................................... 67 kivtelkezels................................................. Lsd hibakezels
gmtime .................................................................................. 98 KIZR VAGY ................................................ Lsd VAGY, kizr
goto ....................................................................................... 32 bitenknti .................................................... Lsd ^ opertor
kdols .................................................................................... 9
konstans .......................................................................... 12, 25
Gy kulcsszavak.................................................. Lsd foglalt szavak
kls formtum .................................................................... 43
gykr elem........................................................................... 83

L
H
lthatsg ............................................................................. 68
Harvard architektra ............................................................. 44 lebegpontos
hasznlati utasts ................................................................. 10 konstans ........................................................................... 25
httrtr ................................................................................ 44 lebegpontos tpus ............................................................... 24
header fjl .................................................. Lsd fejlcllomny legkisebb kzs tbbszrs ................................................... 16
hexadeximlis legnagyobb kzs oszt ......................................................... 14
kirs.................................................................................. 38 lezr nulla............................................................................ 36
hibakezels ............................................................................ 11 lineris keress ..................................................................... 88
linker................................................................................ 17, 20
localtime ................................................................................ 98
I, logaritmikus keress ................................. Lsd binris keress
logikai
IDE ......................................................................................... 17 S .......................................................... Lsd && opertor
if .......................................................................................... 28 NEM ..............................................................Lsd ! opertor
igazsgtbla ........................................................................... 15 VAGY .......................................................... Lsd || opertor
imperatv programozsi nyelv ............................................... 12 loklis vltoz ........................................................................ 67
index ...................................................................................... 35 lokalits ................................................................................. 68
informci ............................................................................. 12 long ....................................................................................... 38
int........................................................................................ 38 long double............................................................................ 38
konstans ............................................................................ 25 long long................................................................................ 38
isalnum .................................................................................. 49 lvalue ....................................................................Lsd balrtk
isalpha ................................................................................... 49
islower ................................................................................... 49

104
M P

main fggvny ...................................................................... 22 paramter


makr .................................................................................... 94 aktulis .............................................................................. 32
malloc.................................................................................... 58 formlis ............................................................................. 32
mantissza .............................................................................. 37 paramtersor ........................................................................ 55
megjegyzs ........................................................................... 21 Pascal nyelv............................................................................ 12
mellkhats ........................................................................... 50 perifrik ................................................................................. 8
kirtkelse ...................................................................... 51 pointer ............................................................................. 48, 53
memria ............................................................................8, 44 ltrehozsa ....................................................................... 53
memriacm ......................................................................8, 53 NULL .................................................................................. 53
memriaszemt.................................................................... 14 tpus nlkli (void*)........................................................... 53
mikroprocesszor.................................................................... 45 tpusa ................................................................................ 53
mdost ............................................................................... 38 pontosvessz ......................................................................... 13
mutat .............................................................................48, 53 posztdekremens .................................................................... 51
posztinkremens ..................................................................... 51
precedencia ..................................................................... 24, 50
N predekremens........................................................................ 51
preinkremens ......................................................................... 51
NEGLS preprocesszor .............................................. Lsd elfeldolgoz
bitenknti .................................................... Lsd ~ opertor printf ................................................................................ 23, 43
ngyzetgyk ................................................................ Lsd sqrt processzor ............................................................................... 8
NEM program ................................................................................... 9
bitenknti .................................................... Lsd ~ opertor programozs............................................................................ 8
logikai ........................................................... Lsd ! opertor programozsi nyelv ................................................................. 8
nemterminlis szimblum ..................................................... 20 pszeudokd ........................................................................... 10
Neumann architektra .......................................................... 44 pthread_create ...................................................................... 99
Neumann elvek ..................................................................... 44 pthread_exit .......................................................................... 99
NULL ...................................................................................... 53 pthread_join .......................................................................... 99
pthreads ................................................................................ 99
putchar .................................................................................. 42
Ny puts ........................................................................................ 42

nyl opertor ......................................................................... 75


R
O, RAM ................................................................................... 8, 44
rand ....................................................................................... 98
object fjl .............................................................................. 20 realloc .................................................................................... 60
oktlis register .................................................................................. 68
kirs ................................................................................. 38 rekurzi ................................................................................. 81
Opercis rendszer ............................................................... 45 klcsns .......................................................................... 81
operandus ............................................................................. 50 nrekurzi ......................................................................... 81
opertor ................................................................................ 23 remove ................................................................................... 98
bitmvelet ........................................................................ 51 rename................................................................................... 98
feltteles .................................. 52, Lsd feltteles opertor return .............................................................................. 22, 31
lptet .............................................................................. 51 rewind ................................................................................... 70
logikai ............................................................................... 51 RISC ........................................................................................ 45
multiplikatv ..................................................................... 51 ROM ....................................................................................... 44
nyl .................................................................................... 75 rvidzr ........................................................................... 51, 73
vessz ............................................................................... 52 rvalue ................................................................. Lsd jobbrtk

, S
sszetett utasts ............................................................11, 28 scanf ............................................................................. 35, 43

105
sequence point ....................................... Lsd kirtkelsi pont time ....................................................................................... 98
shiftels ................................................................................. 39 tpus ...................................................................................... 22
short ...................................................................................... 38 tpusjelz ............................................................................... 38
signed .................................................................................... 38 tpuskonverzi
sizeof opertor ...................................................................... 59 explicit ............................................................ 25, 31, 38, 39
sorfolytonos .......................................................................... 36 implicit ........................................................................ 31, 39
specifikci .............................................................................. 9 tpuskonverzis opertor ................................................ 25, 50
sprintf .................................................................................... 61 tpusos nyelv ......................................................................... 13
sqrt ........................................................................................ 24 tolower .................................................................................. 49
srand ................................................................................... 98 toupper .................................................................................. 49
sscanf ..................................................................................... 61 tmb ................................................................................ 35, 47
stack ...................................................................................... 79 tbbdimenzis .................................................................. 36
static ...................................................................................... 68 trspont .............................................................................. 18
stdarg.h.................................................................................. 97 tlcsorduls ........................................................................... 37
stderr ............................................................................... 42, 73
stdin ....................................................................................... 73
stdio.h.................................................................................... 22 Ty
stdout..................................................................................... 73
strzsa ................................................................................... 75 typedef .............................................................................. 48
strcat...................................................................................... 62
strcmp.................................................................................... 62
strcpy ..................................................................................... 62 U,
strlen ..................................................................................... 62
strncpy ................................................................................... 62 union ............................................................................... 47, 95
strstr ...................................................................................... 62 unsigned ................................................................................ 38
struktra ................................................................................ 47
strukturlt programozs ....................................................... 10
switch..................................................................................... 29 V

va_arg ................................................................................... 97
Sz va_end ................................................................................... 97
va_start ................................................................................. 97
szabvnyos VAGY
bemenet ........................................................................... 34 bitenknti .................................................... Lsd | opertor
kimenet ............................................................................. 34 kizr ................................................................................ 15
szekvencia ............................................................................. 10 KIZR ......................................................... Lsd ^ opertor
szekvencilis ............................................................................ 8 logikai ........................................................ Lsd || opertor
szemantikai hiba ............................................................... 9, 18 vltoz ................................................................................... 12
szintaktikai hiba ...................................................................... 9 definci ...................................................................... 13, 23
szintaxis diagram................................................................... 20 inicializlatlan ................................................................... 14
sztring .................................................................................... 29 vltoz argumentumszm fggvnyek ................................ 97
konstans ............................................................................ 25 vletlen szm ........................................................................ 98
szubrutin ............................................................ Lsd fggvny verem .................................................................................... 79
vessz opertor..................................................................... 30
vezrlkarakterek ................................................................. 41
T vfprintf ................................................................................... 97
VLIW ...................................................................................... 45
trolsi egysg ...................................................................... 28 void............................................................................ 22, 33, 38
trolsi osztly ...................................................................... 68
terminlis szimblum ............................................................ 20
tervezs ................................................................................... 9 W
tesztels .................................................................................. 9
tevkenysgtbla .................................................................. 78 whitespace ............................................................................ 15

106
Tematika
1. A szmtgp felptse, programozs, algoritmus, adatszerkezet, a programozs menete, algoritmus megadsa pszeudokddal s
folyamatbrval, a teafz robot pldja, adat, vltoz, konstans, tpus, C nyelv, szmok kirsa 1-tl 10-ig (while), pratlan szmok
kirsa (if), LNKO, logikai S, VAGY, NEM.

2. A fordts menete, a szintaxis lersa (BNF, EBNF, szintaxis diagram), a C program rszei mi micsoda az LNKO pldjn keresz-
tl, double tpus s a msodfok egyenlet gykei, precedencia fogalma, konstansok, tlagszmt program, ++, += opertorok, tkrk-
pvel megegyez hromjegy szmok kirsa.

3. res utasts, sszetett utasts, trolsi egysg defincija/deklarcija, kifejezs utasts, if, else, switch, for, while, do-while, ell
s htul tesztel ciklusok, ugr utastsok, feltteles opertor, egyszer fggvnyek felptse, char kezelse, egsz mint logikai rtk.

4. Egy- s tbbdimenzis tmbk, egsz s vals tpusok fajti, szmbrzolsi krdsek, bitmveletek.

5. Bemenet s kimenet: printf, scanf rszletesen, getchar, putchar, ASCII, gets, puts. A szmtgpek felptse, mkdse, a Neumann
elvek, opercis rendszerek. sszetett s szrmaztatott adattpusok, enum, struktra, tpusdefinci. Opertorok ttekintse, balrtk-
jobbrtk, precedencia, asszociativits, mellkhats, rvidzr, kirtkelsi pont.

6. A szmtgp memrija, pointer fogalma, pointer aritmetika, cm s rtk szerinti paramtertads, dinamikus memriakezels,
dinamikus tmb. Sztringek.

7. A programozs menete ismt, struktogram, a C programok felptse bvebben: tbb modulbl ll programok, globlis vltozk,
trolsi osztly, lthatsg, rvnyessgi tartomny, loklis vltozk letciklusa. A main() vltozatai, parancssori paramterek. Fjlke-
zels: szveges s binris fjlok.

8. Lncolt listk felptse, a listakezels algoritmusai, fss listk.

9. Az llapotgp fogalma, llapottbla, llapotgrf, megvalsts C nyelven. A verem fogalma, fggvnyhvs verem segtsgvel.
Rekurzi fogalma, rekurzv algoritmusok: faktorilis, szm kirsa megadott szmrendszerben,

10. Binris s tbbg fk. A fabejrs algoritmusai. Fggvnypointer fogalma s hasznlata.

11. Lineris s binris keress. Kivlasztsos, bubork, beszr, gyorsrendezs, lista rendezse.

12. A preprocesszor: #include, #define s a makrk, #if s a feltteles fordts, #pragma. Bitmez s union. Vltoz paramterlistj
fggvnyek. Tovbbi hasznos szabvnyos fggvnyek: vletlenszm, idkezels, mappamveletek.

13. Egy komplex program bemutatsa, rdekes algoritmusok.

107

You might also like