kategória | ||||||||||
|
||||||||||
|
||
Programozás elmélet 3
1. A programkészítés lépései 3
1.1. A feladat megfogalmazása 3
1.2. A feladat modellezése 3
1.3. Az algoritmus meghatározása 4
1.4. A szükséges hardver és szoftver környezet megállapítása 4
1.5. Az algoritmus kódolása 4
1.6. A program tesztelése, hibakeresése, javítása 4
1.7. A hatékonyság növelése, optimalizálás 5
1.8. A dokumentációk elkészítése 5
1.8.1. Felhasználói dokumentáció 5
1.8.2. Fejlesztői dokumentáció 5
1.9. A működő program karbantartása, felügyelete 5
2. Az adatszerkezetek 5
2.1. Elemi adattípusok 5
2.2 Összetett adattípusok 6
3. Műveletek a számítógépen (programozási eszközök) 7
3.1. Értékadás 7
3.2. Adatbevitel és adatkiírás 7
3.3. Elágazások, feltételes programvégrehajtás 7
3.4. Ciklusszervezés 8
3.5. Függvények 8
3.6. Eljárások 8
4. Algoritmus leíró eszközök 8
4.1. Folyamatábra 8
4.2. Mondatszerű leírás 9
4.3. Struktrogram 10
5. Alapvető algoritmus típusok (programozási tételek) 10
5.1. Összegzés 10
5.2. Eldöntés 10
5.3. Kiválasztás 11
5.4. Keresés 11
5.5. Megszámlálás 11
5.6. Maximum- ill. minimum kiválasztás 12
5.7. Kiválogatás 12
5.8. Rendezés 12
5.9. Szétválogatás 13
5.10. Metszetképzés 13
5.11. Egyesítés 14
5.12. Összefuttatás 14
6. Programozási módszerek 15
A "majd lesz valahogy" elv 15
6.2. Moduláris programozás 15
6.3. Struktúrált programozás 15
6.4. Objektum - Orientált Programozás -> OOP 15
6.5. Eseményvezérelt programozás 15
6.6. Vizuális programozás 16
Programozás Pascal nyelven 16
1. Kialakulása 16
2. Pascal implementációk 16
3. Programkészítés TP6.0 segítségével 16
3.1. Parancssoros fordítóval - TPC.EXE 16
3.2. A TP6 saját fejlesztői környezetét használva (IDE) 17
4. A Pascal forrás program felépítése (szintaktikája) 18
5. Unitok és használatuk 20
6. Változók és használatuk 20
7. A Pascal nyelvben használható változók típusai 21
7.1. Elemi adattípusok 21
7.2. Összetett adattípusok 21
7.2.1 Szöveg típus 21
7.2.2. Tömb típus 21
7.2.3. Felsorolt típusok 22
7.2.4. Résztartomány típus 22
7.2.5. Halmaz típus 22
7.2.6. Rekord típus 23
7.2.7. File típus 23
7.2.8. Egyéb összetett adattípusok 23
8. Konstansok és használatuk 23
9. Új típusok definiálása és használatuk 24
10. Műveletek, kifejezések, relációk 24
10.1. Számokon végezhető műveletek 25
10.2. Logikai műveletek 25
10.3. String műveletek 25
10.4. Halmaz műveletek 25
10.4. Összehasonlító műveletek 25
11. Programozási eszközök, vezérlési szerkezetek 26
11.1. Értékadás 26
11.2. Adatbevitel és adatkiírás 26
Kiírás 26
Beolvasás 26
11.3. Feltételes programvégrehajtás 26
11.4. Esetszétválasztás 27
11.5. Ciklusszervezés 27
Adott számú ismétlés: 27
Elöltesztelő ciklus: 28
Hátultesztelő ciklus: 28
11.6. Eljárások 28
11.6.1. Globális és lokális változók 28
11.6.2. Paraméterek és kezelésük, cím szerinti és érték szerinti paraméter átadás 29
11.7. Függvények 29
12. Állománykezelés 30
12.1. Szöveges állománykezelés 30
12.2. Tipizált állománykezelés 31
12.3. Nem tipizált állománykezelés 31
13. Dinamikus memóriakezelés, mutatók és használatuk 32
13.1. Tipizált mutatók 32
13.2. Típus nélküli mutatók 33
Egyszerű esetben lehet úgy is programot írni, hogy egy-két mondatos feladat megfogalmazás után azonnal a számítógép elé ülünk, majd a feladatnak megfelelően begépeljük a szükséges utasításokat. Jobb esetben elindítjuk a programot, és ha hibát találunk, javítunk, majd valamilyen formában tároljuk.
Ez mindaddig megy is, amíg egyszerűbb feladatról van szó, és csak saját magunknak dolgozunk, de ha bonyolult, összetett feladatról van szó, akkor egy idő után megakadunk. Ha a program végre futni is fog és abban esetleg valamilyen változtatásra van szükség, akkor viszont vége, nincs tovább, újra kell írni.
Ebben a részben olyan ismereteket fogunk tanulni, amelyek segítenek az ilyen buktatók kikerülésén és hatékonyan segítik a számítógépes munkánkat.
A helyes programkészítés lépései:
a feladat megfogalmazása
a feladat modellezése
az algoritmus meghatározása
a szükséges hardver és szoftver környezet megállapítása
az algoritmus kódolása
a program tesztelése, hibakeresése, javítása
a hatékonyság növelése, optimalizálás
a dokumentációk elkészítése
a működő program karbantartása, felügyelete
A feladat megfogalmazása a megoldás első lépése, amelynek során egyértelműen rögzíteni kell (lehetőleg írásban) az elérendő célt a lehetséges pontossággal, a figyelembe vehető feltételekkel, különböző korlátok megadásával. Itt lehet elkövetni az első hibákat. Ha ugyanis a megfogalmazás nem világos, nem egyértelmű, akkor lehet, hogy a kész program nem egészen úgy és azt tudja, amit a feladat kitűzője gondolt.
Feladat: Írassuk ki azon tanulók nevét, akik 4-esnél jobb tanulmányi eredményt értek el!
Felmerülő kérdések:
Hol tároljuk a neveket és a tanulmányi eredményeket, a program elején kell beolvasni, vagy esetleg állományban, vagy valahol máshol tároljuk?
Maximum hány tanuló lehet?
Hova kell kiírni (képernyő, nyomtató) és hogyan írjuk ki, egymás mellé, egymás alá, egy oldalra egyet, vagy többet?
Rendezett-e a névsor a tanulmányi eredmény szerint, vagy sem?
Ezeket a kérdéseket mindenképpen tisztázni kell, hogy a programot el tudjuk készíteni.
Annak ellenére, hogy a számítógép felhasználásával megoldott feladatok nagy része nem matematikai problémaként fogalmazódik meg, az eredmény előállításához legtöbbször matematikai és logikai eljárások sorozatos alkalmazására van szükség. A megfogalmazott feladatokhoz ezért általában matematikai modellt kell keresni.
Ezek a modellek - mint az egyéb modellek - a valóság többé-kevésbé hű másai, esetünkben matematikai eszközökkel megvalósított másolatok.
Pl. a feladat: egy adott osztály tanulmányi eredményének meghatározása egy adott tantárgyból.
A tanár így látja a megoldást:
vesszük az első tanuló eredményét majd hozzáadjuk a 2. tanulóét majd így tovább az utolsó tanulóig
majd ezt az összeget osztjuk az osztály létszámával.
A matematikus:
tekintsük az eredményeket egy N-elemű számsorozatnak ekkor a tanulmányi eredmény:
Tehát a megoldás matematikai megfogalmazása, modellje egyetlen rövid képletbe sűrít 838d31i hető.
A modell alkotásának van egy olyan előnye is, hogy a különbözőnek látszó problémák ugyanazzal a módszerrel megoldhatók. Így előfordulhat, hogy már meglévő eljárásokat használhatunk fel, nem kell újra munkát befektetni.
Az algoritmus meghatározása, a megoldási folyamatnak az eredmény előállításáig vezető logikai felépítése igen fontos lépése a problémamegoldásnak.
Az algoritmusoknak feltétlenül rendelkezniük kell néhány alapvető tulajdonsággal. Ezek:
Általánosság
A megadott algoritmus nem csak a szóban forgó speciális feladat esetén vezessen a probléma megoldására, hanem a hasonló jellegű feladatok széles körére szolgáltasson helyes eredményt.
Teljesség
A választott algoritmus a feladatkör minden lehetséges megoldását szolgáltassa. Ehhez az szükséges, hogy a bemenő adatok minden szóba jöhető értékére (értelmezési tartomány) felkészült legyen az algoritmus. A teljesség és az általánosság követelménye egymásnak ellentmondó ezért célszerű a két tulajdonságnak a megoldás szempontjából optimális kielégítését kitűzni.
Végesség
Az eredmény véges számú lépésben elérhető legyen.
Egyértelműség
Azonos körülmények között (ugyanolyan bemenő adatokkal) az eljárást megismételve azonos eredményeket kapjunk.
Értelmezettség
Legyen pontosan körülhatárolt az a bemenő adathalmaz, amelyre az algoritmus megoldást szolgáltat.
Hardver környezet: meghatározza, hogy milyen típusú számítógép, minimálisan milyen részegységekből (pl. memória, háttértár kapacitás) épüljön fel, esetleg milyen speciális kiegészítőkre van szükség a program futtatásához.
Szoftver környezet: az adott hardveren milyen egyéb programok futtatását igényli. A legfontosabb, hogy milyen operációs rendszer (és milyen verziójú) szükséges a futtatáshoz.
Kódolás: az algoritmus alapján a kiválasztott programozási nyelv szimbólumainak felhasználásával a program elkészítése. A programozási nyelvet célszerűen az adott feladathoz illeszkedően ´illik´ kiválasztani. Ma már az a gyakoribb, hogy olyan programnyelven készül el a program, amelyet ismer a fejlesztő. Ez nem mindig a legoptimálisabb megoldáshoz vezet. Minden programozási nyelvnek megvannak a sajátosságai, amelyek bizonyos mértékig behatárolják, hogy hol és milyen feladatokat célszerű az adott nyelven megvalósítani.
Ez a fázis a programtermék elkészítése során talán a legtöbb figyelmet igényli. Ugyanis ha a programozó nem járja végig az összes lehetséges végrehajtási utat, amit a programfutás során el lehet képzelni, akkor az esetleges hiba csak a program használata során derül ki. Ez viszont adatvesztéshez, akár anyagi kárhoz is vezethet. Először meg kell vizsgálni, hogy a program az elvárt funkcióknak eleget tesz-e. Ez a tesztelés folyamata.
Ha ennek során hibajelzést kapunk, akkor azt meg kell keresnünk. Ez a hibakeresés.
Ha megtaláltuk a hibát, akkor azt javítanunk kell, ez a hibajavítás.
Ezután ismételten meg kell győződnünk a program működésének helyességéről, s mindaddig folytatni az előbbiekben leírtakat, míg tökéletesen nem fut a programunk.
A programozási tételek, algoritmusok csupán a program előkészítésének lehetőségét biztosítják, a program eredményessége mindig a programozótól függ. A hatékonyságot befolyásolja a végrehajtási idő, a program és adatainak helyfoglalása, valamint a bonyolultsága.
Kétféle dokumentáció létezik, egyik a felhasználó számára készül, míg a másik a programozónak.
1.8.1. Felhasználói dokumentáció
Ez a felhasználó számára készül. Önálló, a kész programmal együtt átadandó szöveg, mely megad minden a program használatához szükséges információt.
Tartalmazza:
a feladat megfogalmazását
a programnyelv meghatározását
a futtatáshoz szükséges géptípust, konfigurációt - hardver feltételek
a program installálását, betöltését, indítását
a program használatát, kezelését
az esetleges hibajelzéseket és annak javítási lehetőségeit
egy tipikus futtatás teljes leírását
a program fejlesztési lehetőségét, annak feltételeit
1.8.2. Fejlesztői dokumentáció
A programozóknak szól és a program fejlesztésével párhuzamosan készül. Részei:
a feladat megfogalmazása, pontosítása, általánosítása
az algoritmus részletes leírása
hardver és szoftver feltételek
változók meghatározása
az eljárások hierarchiáját (szerkezetét) megadó táblázat
az eljárások nevei és feladatai
a program fejlesztési lehetőségei, feltételei
a program teljes listája, valamint egy háttértáron őrzött példánya
A felhasználónak éreznie kell, hogy nem hagyták magára a mély vízben az új programmal az első számítógépén. Tudnia kell, hogy ha gondja, problémája van, mindig van valaki, aki segít. Ezt túlzásba sem szabad vinni, mindig az igényekhez kell alkalmazkodni.
Az adattípus megadása a típus értékkészletének, a rajta végzett műveleteknek, az értékek jelölésének és a tárban való ábrázolásának a rögzítését jelenti.
Az adattípusok kétfélek lehetnek: elemiek amelyeknek felhasználói szempontból nincs belső szerkezetük, valamint összetettek, amelyek elemiekből épülnek fel, ezek az adatszerkezetek.
Egész számok Legtöbbször két byte-on ábrázolják, kettes komplenens kódban. Így az értékkészlet a -32768 és 32767 közötti számok halmaza.
Valós számok A számítógépben kettes vagy tízes számrendszerben is ábrázolhatók a racionális számok. Megadásuk egy 0 és 1 közötti számmal és hatványkitevővel történik (számok normál alakja).
Logikai érték Igaz és hamis vagy TRUE és FALSE illetve 1 és 0.
Karakter Egy változóban tetszőleges karaktert tárolhatunk az ASCII kódtábla szerint.
Az összetett adattípusokban az egyes adatelemek valamilyen sorrendi, szerkezeti összefüggésben állnak egymással.
Tömb
A tömb egy olyan sorozat, amelynek elemszáma rögzített és bármely elemére egy indexszel (sorszámmal) hivatkozhatunk. Általában a tömb elemei azonos típusúak.
Szöveg
A szövegtípus hasonlít a tömbhöz. Elemei csak karakterek lehetnek, viszont az elemek száma (a szöveg hossza) változhat. A szövegekkel műveleteket is lehet végezni (pl. hozzáfűzés, részképzés).
A verem
Gyakran használt adatszerkezet, amelyet általában nekünk kell megvalósítani, ha szükségünk van rá. A verem adatok sorozatát tartalmazza, de csak speciális műveleteket engedünk meg vele kapcsolatban:
PUSH(x) - egy x értéket a verem tetejére (a sorozat végére) helyez.
POP(x) - a verem tetején (a sorozat végén) lévő értéket az x változóba teszi, majd a veremből eltávolítja
A verem szerkezete LIFO (Last In First Out) típusú, ami azt jelenti, hogy az elsőnek betett elemet dolgozhatjuk fel először.
A sor
A sor olyan sorozat, amelynek az egyik végére lehet tenni az új elemeket, a másik végéről pedig el lehet venni őket. Ez a FIFO (First In First Out) típusú szerkezet, mely azt jelenti, hogy az elsőnek betett elemet dolgozhatjuk fel először.
A lista
A lista olyan szerkezet, mely megmondja, hogy egy adott elemet logikailag melyik követ.
Egy adat mellé egy vagy több mutatóértéket helyezhetünk el, amely mutatók a logikailag következő vagy előző elemet határozzák meg.
|
Mindig van egy első elem ez a listafej és egy utolsó elem, amelyet valamilyen formában megkülönböztetünk a listában előforduló elemektől. Ez lehet a 0 vagy a NIL illetve a NULL is.
Ezen a példán jól látszik a lista előnye. A sorrend megváltoztatásához az elemeket nem kell mozgatni, csak a mutatókat kell átírni.
A halmaz
A halmaz olyan sorozat, ahol az elemeknek nincs definiálva a sorrendje, nincs értelme a következő elemet kérni. Használhatjuk viszont a halmazműveleteket: egyesítés, metszet, halmazkülönbség.
A gráf
A gráf olyan adatszerkezet, amely csúcsokból (adatelemek), valamint azokat összekötő élekből (kapcsolatok) áll.
Az ilyen típusú szerkezetek megvalósításához szintén a mutatókat használhatjuk.
Bináris fa
Egy speciális gráf, amelynél minden csúcs két éllel rendelkezik és van egy kitüntetett csúcsa a gyökér. Ezt a szerkezetet faszerkezetnek is nevezik.
A rekord
Lényege, hogy az összetett változónak (rekord) adunk egy közös nevet, s az egyes, rendszerint különböző típusú mezőinek szintén. Így lehetővé válik a rekord elemeinek önálló, külön kezelése és a részek együttes feldolgozása is.
pl. személynyilvántartás
teljes személy: adat
neve: adat.név
születési éve: adat.születés.idő.év
Alternatív szerkezet (változó szerkezet)
Az alternatív szerkezet abban különbözik a rekordtól, hogy az egyes részek összetétele függ a tartalomtól, vagyis a rekord felépítése a mezők tartalmától függ.
Adatállományok
Ezek az adatszerkezetek a háttértárakhoz kapcsolódnak, olyan rekordsorozatok, amelyek különbözőképpen szervezettek.
Szekvenciális (sorrendi) állomány:
A tárolt adatok csak a rögzítés sorrendjében nyerhetők vissza. Vagy csak olvasni, vagy csak írni lehet bele, illetve a végére új rekordot írni.
Direkt állomány:
Bármelyik rekordja bármikor elérhető, módosítható. Az egyes rekordokat általában sorszámmal tudjuk azonosítani. Az ilyen állományba írhatunk, olvashatunk, illetve az állomány végére új rekordokat vehetünk fel.
Indirekt állomány:
Az indirekt állományok azt a lehetőséget biztosítják, hogy a rekordokat nem sorszámmal, hanem jellemző adatukkal azonosíthatjuk, pontosabban a rekordokat valamelyik mezője (kulcsmező) alapján rendezetten kezelhetjük.
Ekkor az állományhoz tartozik egy táblázat, az indextábla, amely a kívánt adatot, valamint egy rekordra mutató értéket (rekordszám) tartalmaz.
A változóknak adhatunk új értéket.
A változók olyan tároló elemek, amelyeket névvel azonosíthatunk és a típusoktól függően különböző értékeket tárolhatnak. A programvégrehajtás során a változók értékei változhatnak.
pl.:
A_VÁLTOZÓ:=1 => A_VÁLTOZÓ legyen egyenlő 1-el.
Ezeknek az utasításoknak a segítségével a program és a külvilág közötti adatcserére nyílik lehetőségünk. A bevitel általában a billentyűzetről vagy háttértárolóról történik. A kivitel általában a monitor, a nyomtató vagy a háttértároló segítségével valósul meg.
Az egyes programrészek végrehajtása egy logikai feltételtől függ. Ha a logikai feltétel igaz, akkor az egyik utasítás vagy utasítássorozat kerül végrehajtásra, ha nem, akkor a másik utasítás vagy utasítássorozatok hajtódnak végre.
pl.:
Ha feltétel akkor utasítások1
különben utasítások2
Elágazás vége
Akkor alkalmazzuk, ha egyes utasításokat többször egymás után végre szeretnénk hajtatni. Több lehetőség is van:
Adott számú ismétlés
A ciklusmag utasításai a ciklusváltozó kezdő és végértékének, valamint a lépésköznek megfelelő számszor kerülnek végrehajtásra. Pl.:
Ciklus ciklusváltozó = kezdőérték-től végérték-ig lépésköz-ösével
:
: Ciklusmag
:
Ciklus vége
Elöltesztelő ciklus (mert a feltételvizsgálat a ciklus elején történik)
A ciklusmag utasításait addig kell végrehajtani, amig a feltétel igaz. Pl.:
Ciklus amíg feltétel
:
: Ciklusmag
:
Ciklus vége
Hátultesztelő ciklus (mert a feltételvizsgálat a ciklus végén történik)
Az előzőhöz hasonló, azzal a különbséggel, hogy a ciklusmag utasításait egyszer mindenképpen végre kell hajtani. Pl.:
Ciklus
:
: Ciklusmag
Amíg feltétel
Ciklus vége
A függvények fő sajátossága, hogy nevük egy értéket képvisel. Típusuk pontosan meghatározott. A függvényekre nevük és paramétereik leírásával hivatkozhatunk. Pl.:
SIN(x) függvény az x szám szinuszát jelenti.
Az eljárások annyiban különböznek a függvényektől, hogy nem értéket, hanem valamilyen tevékenységet képviselnek. Ezekre is nevükkel és paramétereikkel hivatkozhatunk.
Célja: a megoldás menetének géptől független, szemléletes, a logikai gondolatmenetet, a szerkezeti egységeket világosan tükröző leírása.
A folyamatábra a feladat megoldási lépéseinek sorrendjét utasítástípusonként különböző geometriai alakzatok felhasználásával szemléltető ábra.
Szimbólumok és jelentéseik:
|
- határszimbólumok, a program elejét és végét jelzik
- beolvasó és kiíró utasítások
- értékadó utasítás, művelet végrehajtás, aritmetikai kifejezés kiértékelése
- elágazás, a feladat végrehajtás a rombuszba írt feltétel alapján egyik vagy másik irányban folytatódik, a kér kimenet: Igaz (i), vagy Nem (n)
pl: Ciklusszervezés
|
A folyamatábrákban nyilakkal jelöljük a haladás irányát. Folyamatábra készítése, csak egyszerűbb algoritmusok esetén javasolt, mivel egy bonyolultabb szerkezeten nehéz követnünk a lépéseket.
Az algoritmus egymást követő lépéseit mondatokkal vagy mondatszerű szerkezetek egymásutánjával próbáljuk leírni. Két fajtája van.
Mondatok
Egyszerűbb esetben a mondatok sorozata írja le a feladatok megoldását. Ezeket sorszámmal látjuk el, hogy később hivatkozni tudjunk rajuk. Pl.:
Feladat: olvassunk be N db természetes számot, és határozzuk meg ezek összegét.
Algoritmus:
1. N beolvasása
2. Ha N<=0 vagy N nem egész szám, akkor 1
3. S:=0
4. Ciklus I=1-töl N-ig : A beolvasása : S:=S+A : Ciklus vége
5. S kiírása
Mondatszerű szerkezetek
Szemléletesebb az, amikor mondatok helyett csak ún. mondatszerű szerkezetek egymásutánjával írjuk le a feladat megoldását. Ha ezeket a mondatszerű szerkezeteket definiáljuk, rögzítjük, akkor tulajdonképpen egy algoritmus leíró nyelvet hozunk létre.
Egy példa algoritmus leíró nyelvre:
Értékadás: változó := kifejezés
Beolvasás: Be: változók felsorolása
Kiírás: Ki: kifejezések felsorolása
Elágazások: Lásd Műveletek számítógépen
Ciklusszervezés: Lásd Műveletek számítógépen
Eljárások: eljárásnév (paraméterek)
:
: az eljárás utasításai
:
Eljárás vége
Egyéb jelölések:
Egy sorba több utasítást is írhatunk, de közéjük ";"-t vagy ":"-t kell tenni.
Megjegyzések között.
Alkalmazzunk bekezdéseket az egyes szerkezetek megkülönböztetésére.
Pl.: Az előző feladat algoritmusa:
Program
Be: N
S:=0
Ciklus I=1-től N-ig
Be: A
S:= S+A
Ciklus vége
Ki: S
Program vége.
A struktogram elkészítése során az algoritmust egy téglalapba készítjük el, mely tartalmazza az utasítások szövegét. Majd ehhez továbbiak illeszthetők.
|
A téglalapokba az egymás utáni utasítások kerülnek bele.
|
Elágazás esetén a téglalapot három részre osztjuk. A felső részbe a feltétel kerül. A végrehajtás azon az oldalon folytatódik, amelyik állítás teljesül.
|
Ciklus esetén két téglalapot egymásba ágyazunk.
Általános feladat:
Adott egy N elemű számsorozat. Számoljuk ki az elemek összegét! A sorozatot egy N elemű A(N) tömbben tároljuk.
Algoritmus
Eljárás
S:=0
Ciklus I=1-től N-ig
S:=S+A(I)
Ciklus vége
Eljárás vége.
Konkrét feladat az alkalmazásra.
Átlagszámítás
Általános feladat
Adott egy N elemű sorozat és egy, a sorozat elemein értelmezett T tulajdonság. Feladat annak eldöntése, hogy van-e a sorozatban legalább egy T tulajdonsággal rendelkező elem.
Algoritmus
Eljárás
i:=1
ciklus amíg i<=N és A( i ) nem T tulajdonságú
i:=i+1
Ciklus vége.
VAN := i<=N
Eljárás vége.
Alkalmazás
Volt-e egy adott tantárgyból bukás egy adott osztályban? Számsorozat: jegyek; T tul.: 1-es jegy
Általános feladat
Adott egy N elemű sorozat, egy, a sorozat elemein értelmezett T tulajdonság, valamint tudjuk, hogy a sorozatban van legalább egy T tulajdonságú elem. A feladat ezen elem sorszámának meghatározása.
Algoritmus
Eljárás
I:=1
Ciklus amíg A(I) nem T tulajdonságú
I:=I+1
Ciklus vége
SORSZ:=I
Eljárás vége
Alkalmazás
Keressük meg, hogy NAGY PISTI hányadik a névsorban.
Általános feladat
Adott egy N elemű sorozat és egy, a sorozatban értelmezett T tulajdonság.
Feladat: eldönteni, hogy van-e T tulajdonságú elem a sorozatban, és ha van, akkor adjuk meg a sorszámát is.
Algoritmus
A keresési feladatokra több algoritmus is ismert lineáris, logaritmikus. Mi most csak a legegyszerűbbet ismerjük meg a lineárist.
Eljárás
I:=1
Ciklus amíg I< =N és A(I) nem T tulajdonságú
I := I+1
Ciklus vége
VAN := I< =N
Ha VAN, akkor SORSZ := I
Eljárás vége
Alkalmazás
Ismert egy osztály névsora . Adjunk meg egy NAGY vezetéknevűt!
Általános feladat
Adott egy N elemű sorozat és egy T tulajdonság. Számoljuk meg, hogy hány ilyen T tulajdonságú elem van a sorozatban!
Algoritmus
Eljárás
S := 0
Ciklus I=1-től N-ig
Ha A(I) T tulajdonságú, akkor S := S+1
Ciklus vége
Eljárás vége
Alkalmazás
Osztály névsora ismert. Adjuk meg a Nagy vezetéknevűek számát!
Általános feladat
Egy sorozat legnagyobb, ill. legkisebb elemének sorszámát kell megtalálni.
Algoritmus
Max. elem
INDEX := 1
Ciklus I=2-től N-ig
Ha A( INDEX)< A(I) akkor INDEX := I
Ciklus vége
MAX INDEX := INDEX
Eljárás vége
Alkalmazás
Ismert egy osztályban a 60m-es futás időeredménye . Adjuk meg a leggyorsabb tanuló nevét !
Általános feladat
Egy N elemű sorozat összes T tulajdonsággal rendelkező elemét kell meghatározni. A kiválogatott elemeket gyűjtsük a B( ) tömbbe!
Algoritmus
Eljárás
J := 0
Ciklus I=1-től N-ig
Ha A(I) T tulajdonságú, akkor J := J+1; B(J) := I
Ciklus vége
Eljárás vége
Alkalmazás
Ismert egy osztályban a 60n-es futás időeredményei . Adjuk meg azon tanulók nevét, akik egy X időnél jobb időt futottak !
Általános feladat
Adott egy rendezetlen sorozat. Feladat a sorozat adott tulajdonsága szerint növekvő vagy csökkenő sorrendben rendezett sorozat előállítása.
Algoritmus
Igen sokféle rendezési algoritmus van. Az, hogy melyiket választjuk, függ a módszer tárigényétől, a végrehajtási időtől, az eljárás során végrehajtott összehasonlítások, ill. mozgatások, cserék számától. A legegyszerűbb a közvetlen kiválasztásos rendezés.
Eljárás
Ciklus I=1-től N-ig
Ciklus J=1-től N-ig
Ha A(J)< A(I) akkor A := A(J); A(J) := A(I); A(I) := A
Ciklus vége
Ciklus vége
Eljárás vége
Alkalmazás
Egy osztály tanulóinak névsorba rendezése.
Általános feladat
Adott egy sorozat, valamint egy kijelölt elem (pl. X=A(1). Cseréljük fel úgy a sorozat elemeit, hogy az X-nél kisebbek X előtt legyenek, a nála nagyobbak pedig utána.
Algoritmus
Eljárás
X := A(1)
E := 1
U := N
ciklus amíg E<U
ciklus amíg E<U és A(U)>=X
U := U-1
ciklus vége
Ha E<U akkor
A(E) := A(U)
E := E+1
ciklus amíg E<U és A(E)<=X
E:=E+1
Ciklus vége
Ha E<U akkor
A(U) := A(E)
U := U-1
Elágazás vége
Elágazás vége
Ciklus vége
A(E):=X
Eljárás vége
Alkalmazás
Egy osztály tanulóiról tudjuk, hogy ki fiú és ki lány. Feladat olyan sorrend előállítása, ahol a lányok vannak elől, a fiúk pedig a végén.
Általános feladat
Adott egy N és egy M elemű halmaz az A( ) és a B( ) tömbökben. Készítsük el a két halmaz metszetét a C( ) tömbbe. Két halmaz metszetébe azok az elemek tartoznak, amelyek mindkettőben szerepelnek.
Algoritmus
Eljárás
CN:=D
ciklus I=1-től N-ig
J:=1
ciklus amíg J<=M és A(I)< >B(J)
J:=J+1
ciklus vége
Ha J<=M akkor
CN := CN+1
C(CN):=A(I)
Elágazás vége
ciklus vége
Eljárás vége
Alkalmazás
Adott egy osztály névsora és adott azoknak a tanulóknak a névsora, akik az iskolában vannak gyakorlati oktatáson. Feladat az adott osztályból azon tanulók nevének kiíratása, akik az iskolában vannak gyakorlaton.
Általános feladat
Adott egy N és egy M halmaz az A( ) és a B( ) tömbben. Készítsük el a két halmaz egyesítését (unióját) a C( ) tömbben! Az unióba azok az elemek tartoznak, amelyek legalább az egyikben szerepelnek!
Algoritmus
Eljárás
ciklus I=1-től N-ig
C(I):=A(I)
Ciklus vége
CN:=N
ciklus J:=1-től M-ig
I:=1
ciklus amíg I<=N és A(I)< >B(J)
I:=I+1
ciklus vége
Ha I>N akkor
CN:=CN+1
C(CN):=B(J)
Elágazás vége
ciklus vége
Eljárás vége
Alkalmazás
Adott két lista. Az egyikben szerepelnek azok a tanárok, akik az iskola dolgozói, vagyis innen kapják a fizetésüket. A másik listában szerepelnek a külső óraadók. Feladat mindazon tanárok nevének kilistázása, akik az iskolában bármit tanítanak.
Általános feladat
Adott két rendezett sorozat A(N) és B(M). Állítsunk elő belőlük egy sorozatot, hogy a rendezettség megmaradjon és az eredeti sorozatok minden eleme szerepeljen benne. (Az unio speciális esete)
Algoritmus
Eljárás
I := 1
J := 1
K := 0
A( N+1 ) := +végtelen
B( M+1) := +végtelen
Ciklus amíg I<N+1 vagy J< M+1
K:=K+1
Ha A( I )<B(J) akkor
C( k) := A(J)
I := I+1
Elágazás vége
Ha A(I) > B( J) akkor
C(k) := B(J)
J:=J+1
Elágazás vége
Ha A(I)=B(J) akkor
C(J) := A(J )
I := I+1
J := J+1
Elágazás vége
Ciklus vége
Eljárás vége
Alkalmazás
Az előző feladat névsorba rendezett listák esetén.
A feladat ismertetése után, mindenféle előzetes gondolkodás nélkül leülünk a gép elé és nyomkodjuk a billentyűt. Azután meg majd lesz valahogy.
Általában mindenki így kezdi. Ez a próbálkozások, kísérletezések időszaka. A lehetséges hibaüzenetek megismerésének időszaka. Egy összetettebb feladat esetén túlnőhet rajtunk, ismeretlenné válik a program. Egy komolyabb javítás felér egy öngyilkossági kísérlettel.
Lényege, hogy az adott feladat felbontható olyan részfeladatokra, amelyeket egymástól függetlenül is el lehet készíteni és le lehet tesztelni. Ilyenkor csak arra kell figyelni, hogy az egyes rutinok milyen változókon, paramétereken keresztül vannak kapcsolatban. Ezeket a változókat, paramétereket azután a munka megkezdése előtt pontosan meg kell határozni, rögzíteni kell. Általában nagyobb méretű programok esetén alkalmazzák, így egyszerre több programozó tud dolgozni ugyanazon a programrendszeren.
Lényege, hogy az adott feladatot először globálisan, teljes körűen kell definiálni. Vagyis egy modellt kell készíteni, ami a legjobban lefedi a feladat összes jellemzőjét. Definiálni kell a bemeneti (input) és kimeneti (output) adatokat, és azokat a műveleteket, melyeket a programnak a bemeneti adatokkal el kell végezni, hogy a megfelelő kimeneti adatokat kapjuk meg.
Ezek után a feladatokat lépésenként egyre jobban finomítani kell, míg el nem jutunk a program utasítások szintjére. Ez bonyolultabb feladat esetén soklépéses folyamat, de célszerű következetesen végigvinni (mivel így biztos, hogy nem fogunk összekeveredni a rutinok között). Jól definiált helyeken jól tesztelhető programhoz jutunk, és egyben a dokumentáció is majdnem készen van.
Az OOP az eddigi módszerekkel ellentétben a valóság hű megközelítésén alapszik. Az OOP-ben, úgy mint a valós világban is, a programozó tárgyakat (object - objektum) kezel. Minden tárgyat nemcsak alakja, elhelyezkedése jellemez, hanem az is, hogyan viselkedik bizonyos körülmények között. Az OOP-ben ezt a két jellemzőt statikus és dinamikus tulajdonságoknak nevezik.
Egy objektum deklarálásakor definiálni kell a szerkezetét és azokat a szubrutinokat is, melyek az objektum viselkedését írják le. Az OOP előnye, hogy ezeket a tulajdonságokat így együtt lehet kezelni valamint, hogy egy objektum örökölhet tulajdonságokat egy másik objektumtól.
Az eseményvezérelt programozás az egyik legújabb programozási technika. Filozófiája is teljesen eltér az eddigi programozási technikáktól. Az előző technikák esetében mindig a programozó döntötte el, hogy milyen sorrendben követik egymást az egyes feladatokhoz tartozó utasítások, eljárások. Az eseményvezérelt programozásnál a programozó sohasem tudja előre, hogy milyen feladatot kell elvégezni a következő pillanatban, csak azt tudja, hogy milyen események (event) történhetnek, és ezekhez az eseményekhez milyen feladatok tartoznak. Egy esemény lehet például egy billentyű lenyomása vagy az egér elmozdítása is.
A programok futási képernyőjét tervezzük meg tulajdonképpen úgy, hogy az eredmény azonnal látszik is. Ezek a nyelvek felhasználják az OOP és az eseményvezérelt programozás adta lehetőségeket. Megszabadítanak minket sok programozói munkától, mivel a futási képernyő előállítása automatikus. Pontosabban kész elemekből felépítjük a képernyőt, és az a programfutás során ugyanúgy jelenik meg, ahogyan definiáltuk. Az egyes elemekhez itt is események vannak hozzárendelve. Nekünk csak kiegészíteni kell a programot, hasonlóan az eseményvezérelt programozáshoz.
Mivel ezek a programnyelvek tulajdonképpen programrészeket állítanak elő automatikusan, szokták ezeket 4GL nyelveknek is nevezni. A 4GL a 4. generációs nyelv rövidítése. Egyes rendszerek tényleg képesek arra, hogy automatikusan forrásprogramot is előállítsanak.
A programozási módszerek közül a programozónak kell választania a követelményeknek és az esetleges fejlesztési igényeknek megfelelően. Mindig azt a módszert kell kiválasztani (esetleg többet is), amellyel a leghatékonyabban tudja elkészíteni az adott programot.
1968 Nicklaus Wirth kifejezetten oktatási célra fejlesztette ki
1970 az első fordítóprogram
1973 definiálták a szabványos (standard) Pascal nyelvet
az első változatok nagygépes rendszerekre készültek, de amikor megjelentek a személyi számítógépek, akkor kiderült, hogy ezekre is kiváló fordítóprogramokat lehet készíteni
nagyon sok implementációja (megvalósítása, verziója) létezik, melyek között lényeges eltérések is vannak, legelterjettebb a Turbo Pascal (Borland)
Több cég készített és ma is készít pascal fordító programokat. A Pascal nyelvet elsősorban DOS-os programok készítésére tervezték, de már léteznek olyan megvalósítások is, amelyekkel Windows 3.x, Windows 9x operációs rendszerek alatt futó programokat is készíthetünk.
PC-kre létező fordító programok:
Turbo Pascal és verziói (1.0, 2.0, ., 5.5, 6.0, 7.0)
Turbo Pascal for Windows (kifejezetten Windows-os programok készítésére)
Borland Pascal (DOS és Windows programok készítésére)
Free Pascal (DOS és Windows programok készítésére)
Delphi (kifejezetten Windows-os programok készítésére vizuális környezetben)
A továbbiakban a Turbo Pascal 6.0 verziója lesz a kiindulópontunk. A Pascal nyelvvel kapcsolatban leírtak azonban nemcsak erre a verzióra igazak, hanem minden Pascal implementációra is.
A TP6.0 segítségével kétféleképpen készíthetünk futtatható (.EXE vagy .COM) programot:
először valamilyen szövegszerkesztővel elkészítjük a program forrását, ezt egy. PAS kiterjesztésű fájlba mentjük (pl.: ELSO.PAS)
majd a
TPC.EXE segítségével elkészítjük a futtatható programot (.EXE-)
TPC ELSO.PAS
parancs hatására elkészül az ELSO.EXE futtatható program
EDIT ELSO.PAS |
TPC ELSO.PAS |
ELSO.EXE |
IDE - Integrated Development Environment (Integrált fejlesztői környezet
Az IDE indítása a TURBO begépelésével történhet. Ekkor elindul az IDE, egy menüvezérelt alkalmazás, amelynek segítségével hatékonyabban készíthetők el programjaink. Az IDE előnyei:
menüvezérelt rendszer
szövegszerkesztőként is használható
egyszerre több forrást is szerkeszthetünk
azonnali futtatás lehetősége (nem kell kilépni az IDE felületből)
azonnali fordítás lehetősége
lépésenkénti (soronkénti) programvégrehajtás lehetősége
a programban használt változók értékének folyamatos nyomkövetése a lépésenkénti végrehajtás során
beépített segítség (HELP) rendszer
A menüvezérelt rendszer azt jelenti, hogy az egyes lehetőségek menü pontokból választható ki. Van egy főmenü, ami az elindítás után rögtön látható (File Edit Search, stb). A főmenü egyes elemeit kiválasztva újabb menüpontok jelennek meg, amelyekből akár megint újabb menüpontok jelenhetnek meg. A menü kezelése történhet billentyűzettel illetve az egér segítségével is. Billentyűzetről az <ALT> + valamelyik másik billentyű lenyomásával juthatunk a főmenübe. Minden menüpont egyik betűje ki van emelve, a File menüpontnál az F. Ha az <ALT>+<F> kombinációt nyomjuk le, akkor a File menüt nyitottuk ki, ahogy a képen is látszik:
A menüpontok között pedig a kurzor (nyilas: ¯) billentyűkkel navigálhatunk. A menüpont kiválasztása az <ENTER> billentyűvel történik.
A beépített szövegszerkesztő a DOS EDIT programjához hasonló szolgáltatásokat nyújt, amelyeket csak akkor tudunk használni, ha megnyitottunk egy forrás fájlt (File / Open), vagy új forrást akarunk készíteni (File / New):
mozoghatunk a teljes szövegben (kurzor billentyűk)
sor elejére ugorhatunk (<HOME>)
sor végére ugorhatunk (<END>)
egy képernyőnyit ugorhatunk felfelé (<PAGEUP> / <PGUP>)
egy képernyőnyit ugorhatunk lefelé (<PAGEDOWN> / <PGDN>)
törölhetünk egy karaktert (<DEL> vagy <BackSpace> / < >)
törölhetünk egy teljes sort (<CTRL>+<Y>)
szerkesztési üzemmódot válthatunk , beszúró vagy felülíró mód (<INS>)
kijelölhetünk szövegrészeket, amelyekkel további műveletek végezhetők (<SHIFT> nyomva tartása mellett kurzor billentyűk illetve a <PAGEUP>, <PAGEDOWN>)
kijelölt szövegterület törlése (<SHIFT>+<DEL>)
kijelölt szövegterület másolása egy átmeneti tárolóterületre, ahonnan visszamásolható (<CTRL>+<INS>)
a tároló helyen lévő szöveg másolása a kurzor pozíciójába (<SHIFT>+<INS>)
kijelölt szövegterület jobbra mozgatása (<CTRL>+<K> és <CTRL>+<I>)
kijelölt szövegterület balra mozgatása (<CTRL>+<K> és <CTRL>+<U>)
A lehetőségek közül leginkább a segítség rendszert (HELP) emelném ki. Elindítása az F1 funkcióbillentyű lenyomásával történik. Itt információk találhatók az IDE kezelésével kapcsolatban, valamint a Pascal nyelv szintaktikájával és használatával kapcsolatban is. Ha valamilyen utasítás hirtelen nem jut eszünkbe, azt a Help-ben megtalálhatjuk teljes leírásával egyetemben, valamint példaprogramokat is a használatához. Nagyon hasznos tud lenni. Az eredeti HELP ugyan angol nyelvű, de elkészült a teljes magyarítása is.
Akkor is segíthet, ha ismerem ugyan az utasítást, de nem tudom hogyan kell használni. Ekkor be kell írni az utasítást, majd a kurzorral a beírt utasításra állni és lenyomni a <CTRL>+<F1> billentyű kombinációt. Ekkor az adott utasításhoz tartozó segítség jelenik meg.
Az elkészült program futtatása a <CTRL>+<F9> kombináció segítségével vagy menüből a Run / Run menüponttal történik. Kipróbálásához írjuk be első Pascal programunkat:
Begin
WriteLn('Hello');
End.
A program kiírja a képernyőre a Hello szöveget. Futtatás után nem láttunk semmi változást. Ahhoz, hogy a program eredményét lássuk, le kell nyomni az <ALT>+<F5> kombinációt. Ekkor jelenik meg a futtatási képernyő. Ha most még egy billentyűt lenyomunk, visszatérünk az IDE felületbe.
Ha .EXE állományt is szeretnénk látni a fordítás végén, akkor Compile menü Destination menüpontjában a Disk szöveget kell látnunk. Ez a menüpont érdekesen működik, ha kiválasztjuk, akkor mintegy kapcsolóként hol Memory lesz mellette, hol pedig Disk.
Ha csak .EXE állományt akarunk készíteni, akkor az <F9> billentyűt kell lenyomni, vagy a Compile / Make menüpontot kiválasztani.
Az IDE felületből kilépni az <ALT>+<X> billentyű kombinációval vagy a File / Exit menüponttal lehet.
Ez egy általános felépítés, nem kell minden eleméhez ragaszkodni (ahogy az első programunknál is láttuk):
Program program_nev;
Uses unitnev, .unitnev;
Const
konstansnev konstanertek;
.
konstansnev konstanertek;
Type
tipusnev tipusdefinico;
.
tipusnev tipusdefinico;
Var
valtozonev, .. valtozonev : típus;
.
valtozonev, .. valtozonev : típus;
Label labelnev, . labelnev;
Procedure eljarasnev(parameterek);
Function funkcionev(parameterek);
Begin
End.
A programfej kötelezően a Program kulcsszóval kezdődik, amelyet a program neve (azonosítója) követ. Jó, ha programnévként olyan nevet adunk, ami utal a program feladatára, és célszerű a programot ezen a néven is menteni (hajlékony vagy merev-) lemezre. Mentéskor a program automatikusan .PAS kiterjesztést kap, ezt külön nem is kell megadnunk. A fájlnév-adás kötöttségei egyébként ugyanazok, mint a DOS-ban (8 angol karakter stb.). A programfejben kell megnevezni a uses kulcsszó után azokat a rendszerhez tartozó egységeket (unit-okat), amit a programírás megkövetel. Az egységekről a későbbiekben még lesz szó, most csak annyit, hogy ezekben helyezkednek el - megfelelő csoportosításban - a Turbo Pascal parancsai, utasításai. Ilyen unit-okat természetesen a programozó is készíthet, de ez inkább csak a nagy méretű programok esetén indokolt.
A deklarációs részben azt adjuk meg, hogy milyen típusú változókkal fogunk dolgozni (type), az adott típusú változóknak milyen nevet adunk (var), milyen állandókat (konstansokat) szerepeltetünk a programban (const), valamint itt kell megadni a programban alkalmazott címkéket is (label). Mindezek a jellemzők globális jellegűek, ami azt jelenti, hogy érvényességi tartományuk az egész program. Ebből az is következik, hogy ugyanezeknek megvannak a lokális megfelelőik is, amelyek a programnak csak egy meghatározott részére érvényesek.
Az eljárás- és függvényblokk azokat az eljárásokat és függvényeket tartalmazza, amelyeket a programtervezés során hoztunk létre. Az eljárásokban azokat a feladatrészeket helyezzük el, amelyek logikailag, funkcionálisan egy egységet képeznek (a feladat részekre bontásáról már volt szó korábban!). Egyszerű esetben például az egyik eljárásban az adatbevitelt szerepeltethetjük, egy másikban az adatokkal való manipulálást, egy harmadikban pedig az eredmények kiíratását.
Az eljárás mindig a procedure kulcsszóval kezdődik, amit a neve követ, utána opcionálisan a paraméterek, a sort pedig pontosvesszővel zárjuk le. A végrehajtandó parancssorokat a begin (kezdés) után soroljuk fel, az eljárás végét pedig az end (vége) szóval jelöljük, utána pedig pontosvesszőt teszünk (a begin után soha nem teszünk pontosvesszőt!). Egyébként a parancssorokat is mindig a pontosvesszővel kell lezárni. Hiába írunk külön sorba valamit, ha nem teszünk közéjük pontosvesszőt, a fordító egy sornak fogja tekinteni az egészet. A függvény felépítése nagyjából hasonló az eljáráshoz, csak function kulcsszóval kezdődik, és mindig van paramétere.
A főprogram szintén a begin és az end kulcsszavak között helyezkedik el, de itt az end után pontot teszünk, ezzel jelezzük, hogy vége a programnak. A főprogram a programunk végrehajtó része. Itt hivatkozunk azokra az eljárásokra és függvényekre, amelyek az eljárás- és függvényblokkban helyezkednek el. Például megnevezzük az adatbevitelért felelős eljárást, majd a feldolgozó eljárást, végül pedig a kiírató eljárást.
A Pascal nyelvnek vannak bizonyos fenntartott szavai, amit a rendszer használ. A foglalt szavakat, vagy kulcsszavakat a programozónak nem szabad használni a programban változók, konstansok, eljárások, vagy bármi más elnevezésére. A foglalt szavakat foglalja össze a következő táblázat:
and |
asm |
array |
begin |
case |
const |
constructor |
destructor |
div |
do |
downto |
else |
end |
exports |
file |
for |
function |
goto |
if |
implementation |
in |
inherited |
inline |
interface |
label |
library |
mod |
nil |
not |
object |
of |
or |
packed |
procedure |
program |
record |
repeat |
set |
shl |
shr |
string |
then |
to |
type |
unit |
until |
uses |
var |
while |
with |
xor |
|
|
|
Az azonosítók a program bizonyos elemeinek elnevezésére szolgálnak. Azonosítókat maga a Pascal is tartalmaz, pl. az Integer, a ReadLn, vagy a Write. Vannak azonban olyan elemek, amiket nekünk kell elnevezni, pl. a programnak nevet kell adni, az egyes változókat, konstansokat, eljárásokat is el kell keresztelni. Az azonosító ASCII karakterekből állhat (kis- és nagybetűk, számjegyek). Vannak azonban bizonyos megszorítások:
kis- és nagybetűket (ékezet nélkül!) tetszés szerint használhatunk
számmal nem kezdődhet, de lehet benne
kötőjel nem, de aláhúzásjel ( _ ) lehet benne
szóköz, *, !, ? nem lehet
azonos változó- vagy konstansnév nem szerepelhet kétszer (eltérő típus esetén sem)
fenntartott szó nem lehet
hossza nem meghatározott (de csak az első 63 karakter számít).
Az elmondottak értelmében jó nevek lehetnek a következők:
Hki, Hallgatok, Folyo_Ev, Bbe1, Bbe2, ALMA
Ezek azonban rosszak:
2Bbe, Hallgatók, Folyó Év, 222, Egy*Egy, Gyere!
Ahhoz, hogy a fordító tudja, hogy pl. a Hallgatok egy változónk azonosítója, a deklarációs részben közölni kell vele. Saját változóink nevét a típusmegadás és a változók felsorolása helyén adhatjuk meg (a type és a var kulcsszavak után). Az azonos típusú változókat vesszővel elválasztva lehet felsorolni.
A Pascal program elválasztó szimbólumai a szóköz és a sorvég-jel. A szóköznek a programozás elemeinek felsorolásakor van jelentősége (a használatos szavak közé szóközt teszünk, ez természetes), a sorvég jel pedig általában pontosvessző (a program végén lévő end után pont). Ha egy programsor után nem teszünk pontosvesszőt, akkor a fordító a következő sort is az előző folytatásának fogja tekinteni.
A forrásnyelvi program sorokból áll. Minden sor maximálisan 126 karaktert tartalmazhat, de ezt nem célszerű kihasználni. A képernyőn egyébként is maximálisan csak 80 karakter fér el (sőt a szövegszerkesztő ablak kerete miatt még kevesebb). A program sorai pontosvesszővel vannak lezárva, de ez csak formai felépítés, az egyes sorok akár egymás mellett is lehetnek. Ez azt jelenti, hogy a pontosvessző csak az egyes utasítások szétválasztására szolgál, nem pedig a sorok lezárására.
A program adott helyein megjegyzéseket helyezhetünk el, ha indokolt. A megjegyzéseket kapcsos zárójelek közé tesszük, de használhatjuk a (* és *) párokat is. Megjegyzés lehet például:
(* Az n szerinti ciklus vege *) .
A unitok a Pascalban a moduláris programozás alapját képezik. Egy unitban definiálhatunk mindent, amit egy programban is definiálhatunk (konstans, típus, változó, eljárás, funkció, stb). Amikor az adott unitban definiált eljárást vagy konstanst akarom használni, akkor elég csak a unit nevével hivatkoznom a unitra, és minden abban a unitban definiált eljárást, változót, konstanst használhatok anélkül, hogy újra definiálnom kéne.
Vagyis a program elején a Uses kulcsszó után fel kell sorolni azoknak a unitoknak a nevét, amelyekben definiált eljárásokat vagy változókat használni akarok.
A Turbo Pascal több előre definiált unitot biztosít a programozáshoz. Ezek közül a legáltalánosabbak:
SYSTEM, az összes program és unit automatikusan használja, így sohasem kell megadni
CRT, képernyőkezeléssel kapcsolatos eljárásokat és változókat tartalmaz
GRAPH, grafikus eljárások és változók gyűjteménye
DOS, a DOS operációs rendszerrel kapcsolatos alacsony színtű eljárások gyűjteménye
Saját unitokat is készíthetünk, de ennek szintaktikája egy kicsit eltér a normál programok felépítésétől. Részletesebben lásd a HELP-et.
Egy változónak van neve, típusa és értéke. A deklarációs részben deklaráljuk a nevét és a típusát VAR kulcsszóval bevezetve. A névvel tudunk hivatkozni a programon belül a változóra, a típus pedig meghatározza, hogy milyen típusú értéket tárolhat a változó.
A változók nevüket onnan kapták, hogy a bennük tárolt érték változhat. A programon belül akárhányszor értéket lehet adni egy változónak. Az értékadás a következő formában történhet:
valtozonev := érték;
A változó neve nem tartalmazhat ékezetes vagy speciális karaktereket, csak betűket, számokat és aláhúzás jelet: "_".
A következő példa bemutatja a változók használatát:
Program Szampelda;
Var
Szam : Integer;
Begin
Szam := 12;
WriteLn(Szam);
End.
A program egyetlen Integer típusú változót használ, amelynek induláskor a 12 értéket adja. A WriteLn utasítás pedig kiírja a képernyőre a Szam nevű változóban tárolt értéket, vagyis jelen esetben a 12-t.
Egész számok:
Típusnév |
Méret |
Értelmezési tartomány |
Byte |
1 byte |
0 .. 255 |
ShortInt |
1 byte |
-128 .. 127 |
Word |
2 byte |
0 .. 65535 |
Integer |
2 byte |
-32768 .. 32767 |
LongInt |
4 byte |
|
Comp |
8 byte |
-9,22E-18 .. 9,22E+18 |
Valós számok:
Típusnév |
Méret |
Értelmezési tartomány |
Pontosság (tiz.jegy) |
Single |
4 byte |
1,401E-45 .. 3,402E+38 |
|
Real |
6 byte |
2,939E-39 .. 1,701E+38 |
|
Double |
8 byte |
4,841E-324 .. 1,797E+308 |
|
Extended |
10 byte |
3,363E-4932 .. 1,189E+4932 |
|
Logikai érték
Típusnév |
Méret |
Értelmezési tartomány |
Boolean |
1 byte |
True, False |
A logikai érték vagy igaz (True), vagy hamis (False) lehet.
Karakter
Típusnév |
Méret |
Értelmezési tartomány |
Char |
1 byte |
ASCII karakterkészlet (0 .. 255) |
Az értékadásnál a karaktert idézőjelek közé kell tenni:
Betu := 'A';
7.2.1 Szöveg típus
Típusnév |
Méret |
Értelmezési tartomány |
String |
Max 254 byte |
ASCII karakterkészlet (0 .. 255) |
Karakterek egymáshoz fűzött láncolata, amelynek hossza változhat, de maximum 254 lehet. A deklarációban a maximális hosszúságot rögzíthetjük:
Szoveg : String[10];
Ha nem rögzítjük a hosszt , akkor 254 karaktert tárolhatunk egy változóban:
Szoveg : String;
Értékadásnál szintén idézőjelek közé kell elhelyezni a karaktereket:
Szoveg := 'Ez itt a reklám helye!';
Mivel a String típus karakterekből épül fel, ezért külön karakterekre is hivatkozhatunk egy string-ből:
WritLn(Szoveg[5]);
A példában a String típusú Szoveg nevű szöveges változó 5. karakterét írja ki a képernyőre. Ez a hivatkozás értékadásnál is használható.
7.2.2. Tömb típus
A tömb azonos típusú elemek számozott sorozata.
Deklarálásuk:
tombvaltozoneve : Array [elsoelemsorszama .. utolsoelemsorszama] of tipus;
Felhasználásuknál csak a tömb egyes elemeire lehet hivatkozni:
tombvaltozoneve [elemsorszama] : = érték;
Konkrét példa a felhasználásra, amelyben a többdimenziós tömbökre is van példa:
Program TombPelda;
Var
Str_Tomb : Array [1..9] of String;
Byte_KetDim_Tomb : Array [1..5, 1..8] of Byte;
Begin
Str_Tomb[1] := 'Első elem';
Str_Tomb[2] := 'Második elem';
WriteLn(Str_Tomb[1]);
Byte_KetDim_Tomb[1,1] := 4;
Byte_KetDim_Tomb[1,2] := 5;
WriteLn(Byte_KetDim_Tomb[1,1] + Byte_KetDim_Tomb[1,2]);
End.
7.2.3. Felsorolt típusok
Az ilyen típust úgy adjuk meg, hogy valamennyi lehetséges értékét felsoroljuk. Az értékeket zárójelben, egymástól vesszővel kell felsorolnunk. Az egyes értékeknek egyedieknek kell lenniük, valamint nem lehet szöveges típus.
Deklarálásuk:
Madarak = (fecske, golya, sas, bagoly);
Lanyok = (Anna, Jolan, Eva, Adrienn);
Napok = (Hetfo, Kedd, Szerda, Csutortok, Pentek, Szombat, Vasarnap);
Felhasználásuk:
A változó értéke a felsorolt elemek közül csak egy lehet:
Madarak := fecske;
Lanyok := Eva;
Napok := Szerda;
Ez az érték nem szöveg, nem is szám, ezért közvetlenül kiíratni sem lehet a WriteLn utasítással. A pascal az egyes elemekhez tulajdonképpen sorszámokat (0, 1, 2, 3, ... ) rendel hozzá (nagyság szerint növekvő sorrendben - tehát lényeges a sorrend), és a változó csak a sorszámot tárolja. Ezért is nevezik ezt a típust is sorszámozott típusnak. Ezen kívül sorszámozott típusok még az egészek, a logikai, a char típus is, mivel ezek is véges számú rendezett elemek halmazai.
7.2.4. Résztartomány típus
Hasonló az előzőhöz, de itt egy intervallumot, pontosabban annak alsó és felső határát adjuk meg. Tulajdonképpen az intervallum típus egy már létező, sorszámozott típus intervalluma. Példák:
Betuk : 'A'..'Z';
MunkaNapok : Hetfo..Pentek;
Az első példa a char típus, a második példa pedig az előző pontban ismertetett Napok sorszámozott típus intervalluma. Az intervallum megadásánál megfigyelhetjük, hogy a Pascal az intervallumok jelölésére két pontot (..) használ.
7.2.5. Halmaz típus
A halmaz a matematikai halmaz pascal nyelvbeli megfelelője, némi megszorítással. A halmaz minden eleme azonos típusú kell legyen, valamint egy halmaz elemeinek száma nem haladhatja meg a 256-ot.
Definíciójuk:
Karakterek : Set of Char;
Kisbetuk : Set of 'a'..'z';
Nagybetuk : Set of 'A'..'Z';
Szamjegyek : Set of '0'..'9';
KetjegyuSzamok : Set of 10..99;
A definiált halmazokon értelmezhetők a halmazműveletek, valamint az értékadás is:
Karakterek := ['a'..'e'];
Karakterek := ['c', 'g', 'j', 'v'];
Karakterek := [];
A halmazműveletekről a 10. fejezetben lesz szó.
7.2.6. Rekord típus
A rekord tulajdonképpen egy adatmező, amely különböző típusú változókból, mezőkből állhat, de egy egységként kezelhető. A változókat a record és az end kulcsszavak között soroljuk fel.
Deklarálásuk:
Datum : record
Ev : 1900..2000;
Ho : 1..12;
Nap : 1..31;
end;
Hallgato : record
VezNev, KerNev : string[20];
SzulIdo : Datum;
TanKor : string[4];
TanAtlag : real;
end;
Lehetőség van arra is, hogy a rekord változói között egy másik rekordot alkalmazzunk. Példánkban így van beágyazva a Hallgato nevű rekord típusú változóba a Datum nevű.
Felhasználásuk:
A programban egy ilyen rekord típusú változóra a következőképpen hivatkozhatunk:
Hallgato.TanKor := '12F';
WriteLn(Hallgato.TanKor);
7.2.7. File típus
A file azonos típusú komponensekből álló adatszerkezet, amely nagy mennyiségű adat tárolását teszi lehetővé a háttértáron. A file komponensei lehetnek egyszerű és összetett típusok is.
Deklarálásuk:
AdatFile : File of Char;
TextFile : Text;
EzisFile : File;
A deklarálásnak megfelelően megkülönböztetünk:
tipizált fájlt, melynek elemtípusa pontosan definiált
szövegfájlt, melyet elsősorban szöveges állományok kezelésére használhatunk
nem tipizált fájlt, alacsonyszintű (gyorsabb) fájlkezelés megvalósításához
A fájlokkal kapcsolatos műveletekkel egy külön fejezet foglalkozik.
7.2.8. Egyéb összetett adattípusok
Az elméletből tanult további adatszerkezetek is (verem, sor, lista, gráf, bináris fa) megvalósíthatók pascal nyelvben, de ehhez a dinamikus memória kezeléssel, azon belül pedig a mutatók használatával kell tisztában lenni. Ezzel szintén egy külön fejezet foglalkozik.
A konstansok, mint nevük is mutatja, állandó értéket képviselnek. Definiálásukkor azonnal értéket is kapnak, amelyet a továbbiakban nem lehet módosítani a programon belül. Alapvetően háromféle konstans típusról beszélhetünk:
numerikus
szöveges
tipizált
A numerikus konstansok számokat tárolnak, a szövegesek pedig, szöveges adatokat, például:
AlsoHatar = 100;
FelsoHatar =200;
Hiba = 'Hiba történt a program végrehajtás során! A hiba: ';
A tipizált konstansok tulajdonképpen inicializált (értéket kapott) változók, amelyek lehetnek egyszerűek és összetettek a változóknak megfelelően. A tipizált konstansok értékeit ugyanúgy lehet módosítani, mint a változókét!
Deklarálásuk:
konstansnév : típusnév = érték;
Néhány példa, különböző típusú tipizált konstans megadásra:
Minimum : Integer = 0;
Maximum : Integer = 9999;
Factorial : Array [1..7] of Integer = (1, 2, 6, 24, 120, 720, 5040);
HexDigits : Set of Char = ['0'..'9', 'a'..'f', 'A'..'F'];
Origin : Point = (X: 0.0; Y: 0.0);
Ha az előre definiált típusok között nem találunk igényeinknek megfelelőt, mi is készíthetünk újabb típusokat, amelyeket azután változók, illetve konstansok deklaráláshoz is felhasználhatunk. A típusdefiníciónak két módja van:
az új típus már létező típusokból való felépítése vagy
a hozzárendelhető értékek felsorolása
Deklarálásuk a type kulcsszó után:
újtípusneve = típusdefiníció;
A konkrét példákon figyeljük meg a változódeklarálás és típusdeklarálás közötti különbséget:
Egesz = Integer;
Tomb = Array [1..100] of Byte;
Betu = Set of Char;
Ketjegyu = Set of 10..99;
Ido = record
Ev : 1000..2000;
Ho : (jan, febr, marc, apr, maj, jun, jul, aug, szept, okt, nov, dec);
Nap : 1..31;
Ora : 1..12;
Perc, Mp : 1..60;
End;
Evszak = (Tavasz, Nyar, Osz, Tel);
Szamjegy = '0'..'9';
Az előzőekben definiált típusok mindegyikét felhasználhatjuk változók és konstansok deklarálására:
Szam : Egesz;
A_Tomb, B_Tomb : Tomb;
Kisbetuk, Magybetuk : Betu;
SzulIdo, AktIdo : Ido;
Az így definiált változó azután ugyanúgy használható, mint az előző fejezetben definiált változók.
A változókkal műveleteket is végezhetünk, így kifejezéshez jutunk. Kifejezésnek nevezzük mindazt, aminek a programban kiszámítható értéke van. A kifejezésben a következők szerepelhetnek:
konstansok
műveletek, más néven operátorok (matematikai (pl. +), logikai (pl. <))
változók
függvények (a pascal beépített függvényei illetve a felhasználó által készített)
zárójelek (a műveletek sorrendjét módosíthatjuk segítségével)
kifejezések
Ha a program futása közben kifejezéssel találkozik, kiszámítja az értékét, és azt használja, ezt nevezik kifejezés kiértékelésnek. A kifejezések igen összetettek is lehetnek, így a kiértékelés során fontos szerepe van a precedenciának, a kiértékelési sorrendnek. A szorzás magasabb prioritású precedenciával rendelkezik, mint az összeadás, ezért kiértékeléskor először a szorzat kerül kiszámításra, és csak azután az összeg. Ezt a kiértékelési sorrendet befolyásolhatjuk a zárójelek segítségével.
A kifejezéseknek is van típusa. A típus meghatározza, hogy valami milyen értékeket vehet fel, és milyen műveletek végezhetők vele. A következőkben megvizsgáljuk, hogy az egyes típusokkal milyen műveletek végezhetők.
Az operandusok (amelyekkel műveletet kell végezni) és az eredmény is aritmetikai típusú. A használható operátorok:
Műv. |
Megnev. |
Példa |
Eredmény |
|
Összeadás |
Write(12+36); |
48 (egész) |
|
Kivonás |
Write(55-19); |
36 (egész) |
|
Szorzás |
Write(4*7); |
28 (valós) |
|
Osztás |
Write(75/2); |
37,5 (valós) |
div |
Egész osztás |
Write(75 div 2); |
37 (egész) |
mod |
Modulus |
Write(35 mod 4); |
3 (egész) |
and |
Aritmetikai és (bitenként) |
Write(50 and 19); |
18 (egész) |
or |
Aritmetikai vagy |
Write(21 or 25); |
29 (egész) |
xor |
Aritmetikai kizáró vagy |
Write(5 xor 9); |
12 (egész) |
shl |
Eltolás balra (bitenként) |
Write(9 shl 3); |
72 (egész) |
shr |
Eltolás jobbra (bitenként) |
Write(72 shr 3); |
9 (egész) |
not |
Bitek szerinti negáció |
Write(not 5); |
-6 (egész) |
Az operandusok (amelyekkel műveletet kell végezni) és az eredmény is logikai típusú. A használható operátorok:
Műv. |
Megnev. |
Példa |
Eredmény |
and |
Aritmetikai és (bitenként) |
Write(True and False); |
False |
Or |
Aritmetikai vagy |
Write(True or False); |
True |
xor |
Aritmetikai kizáró vagy |
Write(True or False); |
True |
not |
Bitek szerinti negáció |
Write(not True); |
False |
Szöveg típusú (String) és karakteres típusú (Char) változóra egyaránt értelmezhető, az eredmény mindig szöveg típusú:
Műv. |
Megnev. |
Példa |
Eredmény |
|
Összefűzés |
Write('Alfa' + 'Beta'); |
'AlfaBeta' |
Csak halmazokon értelmezhetőek:
Műv. |
Megnev. |
Példa |
Eredmény |
|
Unió |
A := [1,3,7] + [2,7]; |
|
|
Különbség |
A := [1,3,7] - [2,7]; |
|
|
Metszet |
A := [1,3,7] * [2,7]; |
|
In |
Tartalmazza-e |
A := [3,7] in [1, 2, 3, 7]; |
True |
>= |
Részalmaza-e |
A := [3,7] >= |
False |
<= |
Részalmaza-e |
A := [3,7] <= [1, 2, 3, 7]; |
True |
Gyakorlatilag az összes típusra alkalmazhatók (kivéve a halmaz), de megkötés, hogy mindkét operandusnak azonos típusúnak vagy legalább kompatíbilis típusúnak kell lennie.
Műv. |
Megnev. |
Példa |
Eredmény |
|
Egyenlő |
Write(5 = 3); |
False |
<> |
Nem egyenlő |
Write(5 <> 3 |
True |
> |
Nagyobb |
Write(5 > 3 |
True |
< |
Kisebb |
Write(5 < 3); |
False |
>= |
Nagyobb egyenlő |
Write(5 >= 3); |
True |
<= |
Kisebb egyenlő |
Write(5 <= 3); |
False |
Erről már volt szó, változóknak adhatunk értéket:
SzamValt := 12;
Alapesetben a képernyőre tudunk kiírni, illetve a billentyűzetről tudunk beolvasni valamit.
Eddig kétféle kiíró utasítással találkozhattunk, a WriteLn-el és a Write-al. A kettő között mindössze annyi a különbség, hogy a WriteLn a kiírt adatok után új sort kezd, így a következő kiíró utasítás eredménye már a következő sor elején kezdődik.
A ReadLn(i) utasítás szolgál arra, hogy az i változóba a billentyűzetről értéket olvassunk be. Arra azonban mindig figyelni kell, hogy a változó típusának megfelelő adatot írjunk be, különben hibaüzenetet kapunk.
Ha csak egy karaktert szeretnénk beolvasni a billentyűzetről, akkor használható még a ReadKey függvény is, mely a Crt unitban van definiálva.
A billentyűzet lenyomásának érzékelésére pedig a KeyPressed függvény használható, mely szintén a Crt unitban van definiálva.
A következő példaprogram beolvas két számot, majd az összegüket kiírja a képernyőre:
Program Osszeg;
Var
A, B : Integer;
Begin
Write('Írd be az első számot: ');
ReadLn(A);
Write('Írd be a második számot: ');
ReadLn(B);
WriteLn('A két szám összege: ', A + B);
End.
Az utasítás vagy utasítás blokk csak adott feltétel teljesülése illetve nem teljesülése esetén hajtódik végre.
Formái:
If feltétel Then utasítás;
If feltétel Then Begin
utasítás;
.
utasítás;
End;
If feltétel Then utasítás1 Else utasítás2;
If feltétel Then Begin
Utasítás1;
.
utasításn
Else
Utasítás1;
.
utasításn
End;
A feltétel valamilyen logikai kifejezés eredménye kell legyen. Ha ez IGAZ, akkor a Then utáni utasítás vagy utasítások (Begin End közé zárva) hajtódnak végre. Ha ez HAMIS, akkor az Else utáni utasítás vagy utasítások hajtódnak végre. Amennyiben nincs Else ág, akkor az If utáni utasítással folytatódik a végrehajtás. Figyeljük meg, hogy az Else előtt nincs pontosvessző!
A következő példa egy változó értékétől függően más-más szöveget ír ki a képernyőre:
If (Ivalt>10) Then WriteLn('Értéke nagyobb, mint 10') Else WriteLn('Értéke kisebb egyenlő, mint 10');
Az If Then szerkezet egymásba is ágyazható, ami azt jelenti, hogy az utasítás helyén egy újabb If utasítás található és ez tetszőleges mélységben folytatható. Ilyenkor arra kell vigyázni, hogy áttekinthető legyen a forrásprogram. Ebben az esetben célszerű minden utasítást utasítás blokkban elhelyezni (Begin End).
Segítségével egy változó vagy kifejezés különböző értékéhez különböző utasítások rendelhetők hozzá.
Formái:
Case változó Of
érték1: utasítás1;
érték2: utasítás2;
..
értékn: utasításn;
End;
Case változó Of
érték1: utasítás1;
érték2: utasítás2;
..
értékn: utasításn;
Else utasítás;
End;
Itt is, mint mindenhol az utasítások helyén utasítás blokk is állhat (Begin End közé zárva). Ha a változó aktuális értéke nem egyezik egyik felsorolt értékkel sem, akkor egyik utasítás sem kerül végrehajtásra. Ha van Else sor is, akkor az Else utáni utasítás hajtódik végre.
A következő példa szövegesen írja ki egy változó értéket:
Write('A változó értéke ');
Case Ivalt Of
1: WriteLn('egy');
2: WriteLn('kettő');
3: WriteLn('három');
4: WriteLn('négy');
5: WriteLn('öt');
6: WriteLn('hat');
7: WriteLn('hét');
8: WriteLn('nyolc');
9: WriteLn('kilenc');
10: WriteLn('tíz');
Else WriteLn('nagyobb, mint 10!');
End;
A ciklusszervezés során adott programrész ismételt végrehajtása a cél. Ezt a Pascal nyelvben is többféleképpen valósíthatjuk meg.
Adott számú ismétlés:
For változó := kezdőérték To végérték Do utasítás;
A változó értéke egyenként felveszi a kezdőérték és a végérték közötti értékeket, és minden értéknél végrehajtásra kerül az utasítás is. A változó értéke az utasításban is felhasználható. Az utasítás helyén utasítás blokk is állhat.
A következő példa 1-től 10-ig kiírja a számokat:
For I := 1 To 10 Do Writeln(I);
Elöltesztelő ciklus:
While feltétel Do utasítás;
Az utasítás vagy utasítások mindaddig végrehajtásra kerülnek, amíg a feltétel IGAZ. Ha a feltétel a végrehajtás kezdeténél HAMIS, akkor az utasítás vagy utasítások egyszer sem kerülnek végrehajtásra. Az előző példa elöltesztelő ciklussal:
I := 1;
While (I<=10) Do Begin
WriteLn(I);
I := I+1;
End;
Hátultesztelő ciklus:
Repeat
utasítás1;
utasítás2;
..
utasításn;
Until feltétel;
Az utasítások mindaddig végrehajtásra kerülnek, amíg a feltétel HAMIS. Ebben az esetben nem szükséges a Begin End használata, a Repeat Until szintén utasítás blokkot definiál. Az előző példa elöltesztelő ciklussal:
I := 1;
Repeat
WriteLn(I);
I := I+1;
Until (I>10);
Nagyobb feladatot célszerű lépésekre bontani. Továbbá, vannak olyan tevékenységek, melyeket a programban több helyen is el kell végezni. Az ilyen rész-tevékenységeket külön egységbe foglalhatjuk, ezek neve alprogram (subrutin) vagy eljárás (procedure). Az eljárásoknak azonosítójuk van, és a deklarációs részben adjuk meg őket a következőképpen:
Procedure eljárásnév(paraméterlista);
az eljárás saját deklarációs része
Begin
az eljárás utasításai
End;
Mint látható, a saját deklarációs rész miatt az eljárás valóban önálló programként viselkedhet. A saját deklarációs részben nem szerepelhet a Program és a Uses utasítás.
Az eljárásokat a nevükkel indíthatjuk el a főprogramból vagy más eljárásokból (természetesen csak akkor, ha az eljárás deklarációja megelőzte az eljárásra való hivatkozást). Ez az eljáráshívás. Így az eljárások pontosan úgy működnek, mint a Pascal saját utasításai. Ha úgy tetszik, a Pascal utasításkészletét bővítettük, amikor egy azonosítóhoz hozzárendeltünk egy tevékenységet.
Az eljárásokon belül definiálhatunk újabb eljárásokat is, de ezeket csak a fő eljáráson belül használhatjuk.
11.6.1. Globális és lokális változók
Az előbb láthattuk, hogy az eljárásoknak saját deklarációs részük is lehet. Így az is elképzelhető, hogy két különböző típusú változó azonos nevet kap, az egyiket a főprogramban, a másikat az eljárásban deklaráljuk. Ezt a problémát a Pascal nyelv a globális és lokális változók segítségével oldja meg.
A globális változók a főprogramban definiált változók. Ez azt jelenti, hogy a programban bárhol, bármelyik eljáráson belül hozzáférhetünk az értékéhez, illetve módosíthatjuk az értékét.
A lokális változók az eljárásokon belül definiált változók. Ezek a változók csak az eljáráson belül használhatók, a főprogram többi részében elérhetetlenek.
Abban az esetben, ha a főprogramban és az eljárásban is definiáltunk egy azonos nevű változót, akkor az eljáráson belül a lokális változót tudjuk használni, az eljáráson kívül pedig csak a globális változót. Az eljárás belsejében deklarált saját, avagy lokális változók kívülről, vagyis az eljárást hívó programból láthatatlanok: az eljárás hívásakor keletkeznek, és az alprogram lefutása után megszűnnek. Ha a főprogramnak van azonos nevű változója, azt a Pascal az eljárás működésének idejére elraktározza.
11.6.2. Paraméterek és kezelésük, cím szerinti és érték szerinti paraméter átadás
Az eljárások deklarálásakor egy paraméterlistát is megadhatunk. A paraméterlista a változódeklarációhoz hasonlóan a paraméterek azonosítóját és típusát tartalmazza. Példa egy karaktert adott helyre kiíró eljárásra:
Procedure KiirXY(x, y : Integer; c : Char);
Begin
GotoXY(x, y);
Write(c);
End;
A paraméterek az eljárásban lokális változókként viselkednek, azzal a különbséggel, hogy nem az eljáráson belül kapnak értéket, hanem az eljárás hívásakor, kívülről.
Var
I : Integer;
Begin
For I := 1 To 10 Do KiirXY(10, I, '*');
End.
Például amikor az I értéke 3, az eljárás hívásakor az egyes paraméterek értéke: x=10, y=3, c='*' lesz. Vagyis, eljáráshíváskor a hívó utasításban lévő értékeket veszik fel az eljárás paraméterei. Ez az érték szerinti paraméterátadás.
Előfordul, hogy az eljárásnak változókat szeretnénk átadni, és ezekkel kell valamilyen műveletet végezni, tehát a hívó program változóit kell változtatni. Ezt megoldhatjuk úgy is, hogy globális változókat használunk, melyeket tud kezelni az eljárás, de akkor a program áttekinthetetlenebb lesz, mert az eljárás önállósága megszűnik. Erre a célra használható a cím szerint paraméterátadás, más néven a változóparaméterek. Ekkor paraméterként nem értéket adunk át, hanem változót, és ezt a paraméterlistában Var szóval jelöljük:
Procedure Csere(Var a,b : Integer);
Var
m : Integer;
Begin
m := a;
a := b;
b := m;
End;
Var
p, q : Integer;
Begin
p := 8;
q := 4;
Csere(p, q);
WriteLn(p, q);
End.
Ez a program a 4,8 számokat írja ki. Ha a var szócskát nem írtuk volna a paraméterlista elejére, a főprogram változóival semmi nem történt volna, csak az eljárás lokális változóiban cseréltük volna fel az értékeket. A var szó hatására a következő történik: eljáráshíváskor létrejön az eljárás lokális a és b változója, de ezek a változók ugyanarra a memóriacímre mutatnak, mint a főprogram p és q változói. Tehát akármilyen műveleteket végzünk az a és b változókkal, ugyanaz fog történi a főprogram p és q változóival. Így a Csere eljárást nem is lehet számokkal meghívni, csak integer típusú változókkal.
Használhatunk változó- és közönséges paramétereket egyszerre is:
Procedure Valami(s : String; var c : Integer);
A deklarációnál s közönséges, c pedig változóparaméter. A Pascal több utasítása is használ változóparamétert, pl. az Initgraph.
A függvények pontosan úgy működnek, mint az eljárások, azzal a különbséggel, hogy visszatérési értéket is szolgáltatnak. A visszatérési értéket a függvény törzsében a következő utasítással állíthatjuk be:
függvénynév := érték;
A függvény deklarálásakor jelezni kell a visszatérési érték típusát, mely csak elemi típus lehet.
Function függvényneve(paraméterlista) : típus;
A függvény ezeken kívül ugyanúgy működik, mint egy eljárás. Nem elegáns azonban, ha a függvény a visszatérési érték kiszámításán kívül más tevékenységet is végez. Ilyen esetekben inkább használjunk eljárást, és a visszatérési értéket változóparaméterrel adjuk vissza a hívó programnak.
A Pascalban megfelelő beállítás esetén a függvényeket eljárásként is meghívhatjuk: ekkor csak a függvény mellékhatása jelentkezik. Például a Readkey függvényt utasításként használva a program egy billentyű lenyomásáig várakozik.
Példa a függvények deklarációjára és alkalmazásukra:
Function Kob(a : Real) : Real;
Begin
Kob := a * a * a;
End;
Begin
WriteLn(Kob(4));
End;
Gyakran szükség lehet arra, hogy a memóriában lévő adatokat lemezre írjuk, vagy lemezen lévő adatokat olvassunk be. A lemezen lévő adatok fájlokban helyezkednek el. Egy adatszerkezet működését a benne lévő adatok típusán kívül az is meghatározza, hogy miképpen tudunk bele adatot írni, vagy belőle adatot olvasni. Noha egy fájl minden esetben byte-ok sorozata, a fájlokat háromféle módon kezelhetjük:
szöveges fájlként
tipizált fájlként
nem tipizált fájlként
Az azonosságok a különböző fájlkezelési módszerek esetén:
az állományok kezeléséhez is szükség lesz egy változóra, amelyet ugyanúgy kell deklarálni, mint a változókat
a fájlok
használata előtt a változót hozzá kell rendelni egy fizikai fájlhoz, ezt a
hozzárendelést végzi az Assign eljárás, pl.:
Assign(F, 'C:\PRG\ADAT.DAT');
az F változóhoz az ADAT.DAT állományt rendeltük hozzá
mielőtt
olvasnánk vagy írnánk az állományba, meg kell nyitni
Reset(F) - megnyitjuk a fájl a további műveletekhez
ReWrite(F) - új fájlt hoz létre, illetve törli az előző ilyen nevű fájlt,
majd megnyitja
Append(F) - továbbírásra nyitjuk meg (csak szöveges fájlok esetén
alkalmazható)
olvasás a fájlból - Read eljárás
írás a fájlba - Write eljárás
minden megnyitott fájlhoz fájlmutató van hozzárendelve, mely a következő fájl elemre mutat, és automatikusan változik a Read, Write hatására, de mi is állíthajuk a Seek eljárás segítségével
lekérdezhető a fájlmutató aktuális értéke a FilePos függvénnyel
megtudhajuk, hogy a fájlmutató a fájl végén áll-e az Eof függvénnyel
a munka végeztével az állományokat le kell zárni a Close eljárással
A szöveges állományok kifejezetten szövegek tárolására használhatók. A szövegek betűkből állnak és értelmezve van a sor vége is. Gyakorlatilag a szövegfájl sorokból épül fel, a sor vége jel pedig az ENTER.
Szöveges fájlok esetén a Reset-el történő megnyitás csak olvasást tesz lehetővé. Nem alkalmazhatók a Seek, FilePos, FileSize, Truncate eljárások.
Deklarálásakor a Text típusnevet kell használni. Szövegfájlból olvasni célszerűen a ReadLn, írni pedig a WriteLn utasítással lehet úgy, hogy első paraméternek a fájlhoz hozzárendelt változót kell megadni.
A következő példaprogram megjeleníti az ALMA.TXT nevű szöveges fájl tartalmát a képernyőn:
Var
F : Text;
s : String;
Begin
Assign(F, 'ALMA.TXT');
Reset(F);
While not Eof(F) Do Begin
ReadLn(F, s);
WriteLn(s);
End;
End.
A tipizált állománykezelés lényege, hogy pontosan definiáljuk (tipizáljuk) az állományok felépítését. Már a változó definíciójával meghatározzuk, hogy milyen alapelemekből állnak. Pl.:
F : File Of Byte;
F : File Of Array [1..100] of Integer;
A következő példa egy tipizált állomány feltöltését mutatja be:
Type
AdatRecTipus = Record
Nev : String[20];
Szul : Integer;
End;
Var
F : File of AdatRecTipus;
r : AdatRecTipus;
Begin
Assign(F, 'NYILV.DAT');
Reset(F);
Repeat
Write('Név: ');
ReadLn(r.Nev);
If r.Nev <> '*' Then Begin
Write('Született: ');
ReadLn(r.Szul);
End;
Until r.Nev = '*';
Close(F);
End.
Ebben az esetben általában közömbös számunkra az állomány szerkezete, a hangsúly a gyors hozzáférésen van. Ebben az esetben az állományokat blokkonként olvassuk és írjuk. A kezelendő record méret a Reset utasítás segítségével állítható be.
Nem alkalmazhatók rájuk a Read és Write eljárások, helyettük a BlockRead és BlockWrite eljárásokat kell használnunk.
A következő példa egy egyszerű állománymásolást végez:
Program CopyFile;
Var
InFile, OutFile: File;
NumRead, NumWritten: Word;
buf: array[1..2048] of Char;
Begin
Assign(InFile, ParamStr(1));
Reset(InFile, 1);
Assign(OutFile, ParamStr(2));
Rewrite(OutFile, 1);
WriteLn('Másolok ', FileSize(InFile), ' bájtot...');
repeat
BlockRead(InFile, buf, SizeOf(buf), NumRead);
BlockWrite(OutFile, buf, NumRead, NumWritten);
until (NumRead = 0) or (NumWritten <> NumRead);
Close(InFile);
Close(OutFile);
End.
A Pascal hiányosságának tűnik az a megkötés, hogy a változókat előre deklarálni kell. Így a program elején deklarálhatunk egy tömböt, és a program futása közben derül ki, hogy a szükséges adat (pl. egy fájlból beolvasott hosszú számsorozat) nem fér bele. Ez mindig olyankor fordul elő, amikor nem ismerjük előre a feldolgozandó adat mennyiségét. Ezen segít a Pascal azon lehetősége, hogy a program futása közben is foglalhatunk le memóriát változóknak - ezek lesznek a dinamikus változók, szemben a program deklarációs részében előre megadott statikus változókkal.
Dinamikus változók használatánál a programozónak az eddiginél többet kell foglalkozni a memóriakezeléssel, melyet egyébként a Pascal automatikusan végez. A változó létrehozásakor le kell foglalni egy megfelelő méretű memóriaterületet, és gondoskodni kell annak felszabadításáról, ha a változóra már nincs szükség. Ehhez tudni kell, hogy a dinamikus változó hol helyezkedik el a memóriában, és mennyi helyet foglal le.
A mutató olyan változó, mely a memória adott helyére mutat. Két fajtáját különböztethetjük meg, a típusos mutatókat és típus nélküli mutatókét. A mutatók segítségével lehet kezelni a dinamikus változókat. A mutatók speciális értéke a NIL, ami azt jelzi, hogy a mutató éppen nem mutat sehová.
A tipizált mutatók lényege, hogy deklarációjuknál rögzítjük, hogy milyen típusú adatra fognak mutatni. A Pascal ezt megjegyzi, és a helyfoglalás az ilyen típusú adatok részére egyszerűbb.
Deklarálásuk:
változóneve : ^típusnev;
Vagyis a változók deklarálásától annyiban különbözik, hogy a típusnév előtt a hatvány jelnek (^) kell szerepelnie, pl.:
I_Mut : ^Integer;
Az így definiált I_Mut nevű változó azonban nem Integer értéket tartalmazhat, hanem csak egy memória címet vagy a NIL értéket. Megtehetjük azonban azt, hogy egy Integer típusú változó értékének címét adjuk meg értékül a mutatónak az Addr függvény segítségével. Ezután az Integer változó ugyanúgy kezelhető a mutatón keresztül is, mint a normál változó, de a ^ jelre ilyenkor is szükség van. Ezzel jelezzük, hogy a mutatott értékre van szükségünk és nem a mutató változó értékére:
Var
I_Valt : Integer;
I_Mut : Integer;
Begin
I_Valt := 12;
I_Mut := Addr(I_Valt);
WriteLn(I_Valt, ' ', I_Mut^);
I_Mut
WriteLn(I_Mut^);
End.
Ha önálló helyet szeretnénk a memóriában egy Integer típusú változónak, azt a következőképpen tehetjük meg a mutatók segítségével:
New(I_Mut);
Hatására a memóriában lefoglalásra kerül egy Integer változónak szükséges hely (feltéve, ha az I_Mut Integer típusú mutató), majd az I_Mut értéke a lefoglalt terület kezdőcíme lesz. Innentől az I_Mut^ formával úgy kezelhető, mint egy normál változó.
A különbség mindössze annyi, hogy program vagy eljárás vége előtt az előbb lefoglalt memóriaterületet fel is kell szabadítani a Dispose eljárással:
Dispose(I_Mut);
Nézzünk egy példát dinamikus változó létrehozására:
Var
P : ^Integer
Begin
New(p);
ReadLn(p^
WriteLn(p
Dispose(p);
End.
A példában p^ egyszerű változóként viselkedett, melyet a program futása közben hoztunk létre. A következő példa létrehoz 2, 150 elemű String-ből álló tömböt, így a pointerek használatával máris túlléptük a statikus memóriakezelés 64 Kbyte-os korlátját:
Type
Tomb = Array[1..150] Of String;
Var
p, q : Tomb;
i: Integer;
Begin
New(p);
New(q);
For i := 1 To 150 Do Begin
p[i] := 'Egyik szöveg';
q[i] := 'Másik szöveg';
End;
Dispose(p);
Dispose(q);
End.
Itt p^ és q^ olyan, mint két 150 elemű tömb. A p és q pointereket közvetlenül nem használjuk. A statikus memóriában csak a pointerek helyezkednek el, egy pointer pedig (mivel tartalma csak egy memóriacím) alig foglal memóriát.
Deklarálásuk:
változóneve : Pointer;
Mint neve is mutatja, az így definiált mutatóról nem tudhatjuk, hogy milyen típusú adatra mutat. Pontosabban bármilyen típusú adatra mutathat. Ebből következően a New és Dispose eljárás sem használható. Helyettük a GetMem és FreeMem eljárást használhatjuk. Mindkettőnek még azt is meg kell mondani, hogy mekkora memória területet foglaljon le, illetve szabadítson fel.
Minden mutató típusra igaz, hogy a memóriában a lefoglalásra felhasználható memóriaterület korlátozott. A szabad memóriaterületet a MemAvail és MaxAvail függvények segítségével ellenőrizhetjük. A MemAvail az összes szabad terület méretét adja vissza, míg a MaxAvail a legnagyobb szabad blokk nagyságát.
Találat: 3668