Turbo Pascal 3
Az alább ismertetésre kerül a TURBO PASCAL 3 lehetőségei,
igen kimerítő -minden részletre kiterjedő- módon, viszont a kezdők számára
egy kicsit nehéz olvasmányt jelent. Ha valakit érdekel a PASCAL, olvassa el
az ENTERPRESS Pascal sorozatát
is!
További Turbo Pascal példák itt találhatóak.
1. Bevezetés
A Pascal nyelv története 1968-ban kezdődik, ekkorra készült el Nicklaus Wirth professzor terve, amelyet az addigi legfejlettebb programozási nyelvek - többek között az ALGOL - felhasználásával, azoknak továbbfejlesztésével készített. 1970-ben készült el az első fordítóprogram a nyelvhez, az erről szóló publikáció 1971-ben jelent meg. 1973-ban látott napvilágot a javított (Revised Report) kiadása. Ekkor definiálták a Standard Pascal nyelvet, amely a nyelv különböző implementációjának alapja lett. Több egyetemen is kifejlesztették a nyelv változatait, ereje azonban akkor mutatkozott meg igazán, amikor a megjelentek a személyi számítógépek.
Kezdetben a Pascal nyelvet a strukturált programozás tanítására alkalmas
eszközként használták. Az olcsó és jó fordítóprogramok kidolgozása eredményeképpen
a nyelv rendkívül gyorsan elterjedt, és jelenleg a modern programozási nyelvek
egyik legfontosabb képviselője - különösen a rendszerprogramozás területén.
A szabványos Pascal nyelv legismertebb implementációja a vele 90%-ban kompatíbilis
Turbo Pascal nyelv, amelyet elsősorban mikroszámítógépes alkalmazásokra
adott ki a Borland cég, és amely piaci megjelenése után azonnal világsiker
lett. A Turbo Pascal első kiadása nem a Borland saját fejlesztése volt, hanem egy akkor még ismeretlen dán programozó, Anders Hejlsberg "PolyPascal" nevű termékén alapult. Hejlsberg ugyanakkor maga is elszegődött a Borland szolgálatába. A Turbo Pascal az elsőt követő két kiadása (2.x, 3.x) az eredeti kódbázis inkrementális továbbfejlesztését képezte.
A Borland cég által megvalósított implementáció legfontosabb előnyei közé
tartoznak: a fordítóprogram kis mérete, az igen gyors fordító algoritmus,
a fordítóprogram és az interaktív képernyős szövegszerkesztő összekapcsolása,
a forrásszintű hibajelzések, a nagy szubrutinkönyvtár, valamint azok a bővítések,
amelyek a szabványos nyelvhez képest nagymértékben megkönnyítik a rendszerprogramozást.
A Turbo Pascal interaktív programozási rendszer, amely a Turbo Pascal nyelv
fordítóprogramjából és a vele összekapcsolt képernyős szövegszerkesztőből
áll. A Turbo Pascal szövegszerkesztőjét a közismert WordStar szerkesztőprogramról
mintázták. A rendszer nemcsak azért interaktív, mert kényelmes szövegszerkesztést
tesz lehetővé, hanem azért is, mert a programban feltárt hibákat a forrásnyelvi
szövegben jelöli meg.
A szövegszerkesztés, fordítás és futtatás közötti üzemmódváltás természetes
és kevés manipulációt igényel. Emiatt a Turbo Pascal rendszerben a programok
"belövése" szinte kizárólag forrásszintű. A jelentős fordítási
sebesség miatt a forrásés a futtatható tárgyprogram közötti váltás szinte
azonnali, ez számottevően lerövidíti a javítási és újrafuttatási ciklust,
meggyorsítva a végleges programváltozat kifejlesztését.
A Turbo Pascal rendszer használatát egy egyszerű program mutatja be, amely
az adott sugarú gömb térfogatát számítja ki:
program Terfogat;
var Sugar,Terf:real;
begin
ClrScr;
GotoXY(10,11);
Write('sugar=');
Readln(Sugar);
Terf:=4/3*Pi*Sugar*Sugar*Sugar;
GotoXY(10,13);
Writeln('terfogat =',Terf);
repeat until KeyPressed
end.
A programban szerepel az előre definiált Pi konstansnév (a Pi szám
közelítése), valamint a Sugar (a gömb sugara) és a Terf (a gömb térfogata)
szimbolikus név. (A konstansnév olyan azonosító, amely egy konstans értéket
képvisel. E konstans olyan objektum, amely a program végrehajtása során
nem változik. Több szerző más fogalmakat használ, és a konstansneveket "állandók"-nak,
a változóneveket pedig "változók"-nak nevezi.) A ClrScr
eljárás végrehajtása képernyőtörlést eredményez, a GotoXY eljárás
pedig pl. a GotoXY(10,13) esetén a képernyő 10. oszlopát és 13. sorát jelenti.
A repeat until ciklus leállítja a program további futását mindaddig,
amíg a billentyűzetről nem viszünk be egy tetszőleges karaktert. Ez a karakter
megmarad a bemeneti pufferben, és a Turbo Pascal rendszer később értelmezheti.
A Turbo Pascal 3.xx verziókhoz több rendszerfile tartozik:
A program lefordításához és a futtatáshoz először el kell indítani - a TURBO név begépelésével - a Turbo Pascal rendszert. A 3.x verzióig a Turbo rendszer egységes kezelőfelülettel rendelkezik. A program indítása után a képernyőn a következő rendszerazonosító üzenet jelenik meg:
A megjelenő szövegben szereplő kérdés arra kíváncsi, akarjuk-e a hibaüzenetek szövegét a rendszerhez csatolni. Mivel a hibaüzenetek helyigénye csak 1,5 kbájt, s használatuk jelentősen megkönnyíti a hibakeresést, ajánlatos az Y (igen) válasz megadása. A választ követően a képernyőn megjelenik a rendszermenü, amelyben az egyes szavak kiválasztandó betűit nagyobb fényerő jelzi.
A kiemelt betűnek megfelelő billentyű leütésével interaktív módon adhatjuk ki a rendszerparancsokat.
Az L parancs
Az L billentyű megnyomása lehetővé teszi az alapértelmezés szerinti mágneslemezes
meghajtóegység megváltoztatását. Ha pl. a B meghajtót szeretnénk kijelölni,
akkor a feltett
New drive:
kérdésre be kell gépelnünk a B: karakterpárt, és a parancs megadását az
Enter billentyűvel kell befejeznünk.
A W parancs
A W billentyű megnyomása után megadhatjuk a forrásprogramot tartalmazó munkaállomány
nevét. A megadott név egy létező vagy egy új, létrehozandó állomány neve.
A feltett
Work file name:
kérdésre be kell gépelnünk az állomány nevét meghatározó szöveget, amelyet
az Enter billentyűvel zárunk le.
A CP/M-80 és a PC DOS operációs rendszerben az állománynév két tagból állhat.
Az első tag legfeljebb 8 karakter hosszúságú, a második tag - melyet kiterjesztésnek
nevezünk - max. 3 karakter hosszúságú lehet. A név két tagját a . (pont)
karakter választja szét. Ha az előző kérdésre csak az állománynév első tagját
adjuk meg, akkor az alapértelmezés szerint a név automatikusan kiegészül
egy ponttal és a PAS kiterjesztéssel. Ha le akarjuk tiltani az automatikus
kiterjesztés-hozzáadást, elegendő begépelni az állománynév első tagját és
a pontot.
Megjegyzés: ha egy új munkaállományt jelölünk ki - mielőtt az eddigit kivittük
volna a mágneslemezre -, akkor a rendszer előbb megkérdezi, hogy az eddigi
forrásszöveget szándékozzuk-e megőrizni. A lehetséges válasz e kérdésre
(szokásos módon) Y (igen) vagy N (nem).
Az M parancs
Az M billentyű megnyomása után megadhatjuk a lefordítandó forrásprogramot
tartalmazó állomány nevét. Ha ezt a nevet nem határozzuk meg, akkor a lefordítandó
forrásszöveget az aktuális munkaállomány tartalmazza.
A lefordítandó forrásprogramot tartalmazó állomány (a továbbiakban főállomány)
nevére vonatkozó szabályok megegyeznek a munkaállomány nevére vonatkozó
előírásokkal. A főállomány használata akkor kényelmes, ha a forrásprogram
tartalmaz olyan direktívákat, amelyek - az előfordulási helyükön - beiktatnak
más állományokban szereplő programrészeket. Ha ekkor valamely "beiktatott"
programrészben a fordító hibát jelez, az adott programrészt tartalmazó állomány
automatikusan munkaállománnyá válik, amely azonnal szerkeszthető, javítható.
A javítások befejezése után egyszerűen újraindíthatjuk a főállományban szereplő
forrásprogram fordítását.
Az E parancs
Az E billentyű leütésével behívjuk a képernyős szövegszerkesztőt, ezután
elkezdhetjük a munkaállományban levő szöveg szerkesztését. Ha még nem határoztuk
meg a munkaállomány nevét, akkor először a W parancsnál ismertetett módon
a rendszer megkérdezi az állománynevet, s csak ezután kezdődhet el a szerkesztés.
A C parancs
A C billentyű leütésével elkezdhetjük a főállományban levő forrásszöveg
fordítását. Ha eddig nem határoztuk meg a főállomány nevét, akkor a munkaállományban
szereplő szöveget fordítja le a rendszer. Ha megadtuk ugyan a főállomány
nevét, de a munkaállományt szerkesztettük, akkor a rendszer előbb elmenti
a munkaállományt a háttértárolóra, s csak ezután kezdi el a fordítást.
A fordítás eredményeképpen keletkező tárgyprogram az operatív tárba vagy
.COM, ill. .CHN kiterjesztésű mágneslemezes állományba kerül. A fordítás
jellemzői az O paranccsal (fordítási opciók) állíthatók be. Az alapértelmezés
szerint a tárgyprogram az operatív tárban kap helyet. Ideiglenesen bármelyik
billentyűvel megszakíthatjuk a fordítást. A feltett
Abort compilation (Y/N)?
kérdésre válaszolva, a fordítás véglegesen megszakad (Y), ill. folytatódik
(N).
Az R parancs
Az R billentyűvel elindítjuk az operatív tárban levő, lefordított program
végrehajtását. Ha az O paranccsal előzetesen beállítottuk a COM-fájl opciót,
akkor a rendszer a mágneslemezről előbb betölti a programot. Ha az R parancs
előtt nem használtuk a C parancsot, akkor a program fordítása automatikusan
megelőzi futtatását.
Az S parancs
Az S billentyű megnyomása után a rendszer mágneslemezre menti az eddig szerkesztett
forrásszöveget. A munkaállomány előző, eredeti példányának névkiterjesztése
.BAK-ra változik.
Az X parancs (csak a CP/M-80 alatt)
Az X billentyűvel tetszőleges bináris programot futtathatunk le. A feltett
Program:
kérdésre a végrehajtandó - gépi kódú - programot tartalmazó, .COM kiterjesztésű
mágneslemezes állomány nevét kell megadnunk.
A D parancs
A D billentyű leütésével egy tetszőleges mágneslemezes alkönyvtár tartalomjegyzéke
jeleníthető meg a képernyőn. A feltett
Dir mask:
kérdésre megadhatjuk a konkrét állománynevet vagy egy állománycsoport nevét,
pl. B: *.JB? (a" tetszőleges karaktersorozatot, a ? pedig tetszőleges
karaktert jelent). Ha a kérdésre nem adjuk meg a meghajtó vagy az alkönyvtár
nevét, akkor a főmenü szerinti alapértelmezés a mérvadó.
A Q parancs
A Q billentyű megnyomásával befejeződik a Turbo Pascal rendszer futása,
a vezérlés visszakerül az operációs rendszerhez. Ha a Q parancs megadása
előtt szerkesztettük a munkaállományt, akkor a rendszer előbb megkérdezi,
hogy elmentjük-e mágneslemezre a szerkesztett szöveget.
Az O parancs
Az O billentyűvel fordítási opciókat adhatunk meg:
Ha bármely művelet hatására megváltozik a képernyő és nem látszik a menü, nyomjunk le tetszőleges olyan billentyűt, amely nem szerepel a főmenüben. Ennek hatásár a rendszer újra megjeleníti a menüt.
A fenti leírásból látható, hogy a Turbo Pascal rendszer parancsainak
és alparancsainak használata nem túlságosan bonyolult. Egyszerű a forrásprogram
írása és javítása is (az E paranccsal vagy automatikusan, a fordítási hibák
fellépésekor).
A Turbo Pascal rendszer szövegszerkesztője nagymértékben hasonlít az ismert
WordStar programhoz. A függelékben megtalálható a szövegszerkesztő
teljes leírása; itt csak a forrásszövegek alapvető feldolgozására alkalmas,
minimális parancskészletet mutatjuk be.
Megjegyzés: ha nem követünk el hibákat, akkor közvetlenül a szövegszerkesztő
behívása után (E parancs) begépelhetjük a program szövegét karaktersorok formájában,
amelyeket az ENTER billentyűvel zárunk le. A szöveg begépelése után a 'CTRL+KD'
paranccsal befejezzük a szerkesztést, és visszatérünk a főmenühöz.
A Turbo Pascal rendszer szövegszerkesztőjének többi parancsához hasonlóan -
szükség van még a CTRL billentyűre, amelyet lenyomva kell tartanunk a vezérlő-billentyű
leütésekor. A képernyőn megjelenített szövegrészen belül fontos szerepe van
a kurzor feletti karakternek. A szövegmanipulációk mindig e karakterre (vagy
az őt tartalmazó szóra, ill. sorra) vonatkoznak. A kurzor mozgatása egy pozícióval
balra, jobbra, felfelé vagy lefelé a beépített borkormány fel, le, jobbra vagy balra döntésével
lehetséges.
Karaktertörlésre az ERASE billentyű használható, amely törli a kurzortól
balra eső karaktert. Új karakterek beszúrásához (akár szavakon belül, akár szavak
közt) nincs szükség semmilyen különleges műveletre; a begépelt karakterek a
kurzor fölötti karakter elé szúródnak be, ugyanakkor a sor többi karaktere egy
pozícióval jobbra tolódik. Egész sorok törlésére a CTL-Y parancs, szavak törlésére
a CTRL T parancs, új sorok beszúrására a CTRL-N parancs alkalmas. A szövegszerkesztő
számos más parancsát és lehetőségét a függelék írja le. E
fejezet tartalmát összegezve elmondhatjuk, hogy a fejezet elején bemutatott
1. program futtatható változatának előállítása a következő műveletek elvégzését
igényli:
E tevékenységek befejezése után a Q paranccsal visszatérhetünk
az operációs rendszerhez.
Ha a tárgyprogramot szeretnénk megőrizni egy mágneslemezes állományban (.COM
kiterjesztéssel), akkor a fordítás előtt adjuk ki az 0 parancsot, utána pedig
a C és a Q alparancsokat. A fordítás és az operációs rendszerhez való visszatérés
után a példaprogram már a Turbo Pascal rendszer felügyelete nélkül, önállóan
is futtatható.
2. Lexikális elemek, elválasztók, megjegyzesek
A Turbo Pascal programozási nyelv részletes leírását lexikális (szótári) elemeinek
felsorolásával kezdjük. A többi programozási nyelvhez hasonlóan ezek a következők:
kulcsszavak, azonosítók, konstansok és határolók: A szóközök, tabulátorjelek,
sorvégjelek és megjegyzések (kommentárok) nem lexikális elemek; e karakterek
és a megjegyzések tetszőleges sorozata (a továbbiakban elválasztó szintaktikai
elem) a fordító szempontjából - egy szóköznek tekinthető. Az elválasztó elem
használata csak akkor nélkülözhetetlen, ha a forrásprogramban szomszédos azonosítók
vagy kulcsszavak szerepelnek.
Az osztályozásnak megfelelően egy Turbo Pascal nyelvű program lexikális és elválasztó
elemekből tevődik össze. A program lexikális elemzésekor különíthetjük el az
egyes elemeket. Az elemzés természetes sorrendben megy végbe, vagyis balról
jobbra, ill. felülről lefelé. A fordító az adott karaktersorozatot akkor tekinti
lexikális elemnek, ha nem tartalmaz elválasztót.
A lexikális elemek és megjegyzések a következő alapszimbólumokból épülnek fel:
A :=, <=, >=, <>, (*, *) szimbólumok esetén fontos a karakterek megadási sorrendje. A nyelv nem engedi a karakterpárok felcserélését (pl.: =<). Hibajelzést kapunk akkor is, ha ezekben a szimbólumokban a karakterek közé szóközt teszünk.
A nagy- és kisbetűket az azonosítókban és a kulcsszavakban
azonosnak tekinti a nyelvi definíció. Emiatt pl. a filename és a FileName azonosító
nem különbözik egymástól.
A forrásnyelvi program sorokból áll. Minden sor maximálisan 126 karaktert tartalmazhat - az ezen túliakat a fordító nem tudja feldolgozni. Ajánlatos a 126 karakter helyett 80-as határt betartani, mert az ennél hosszabb sorok értelemszerűen nem láthatóak egyben a képernyőn, és általában a nyomtatók is sort váltanak a 80. karakter után.
2.1. Kulcsszavak
A felsorolt, kötött jelentésű, összefüggő betűsorozatok a kulcsszavak:
absolute | external | nil | shl |
and | file | not | shr |
array | for | of | string |
begin | forward | or | then |
case | function | overlay | to |
const | goto | packed | type |
div | if | procedure | until |
do | in | program | var |
downto | inline | record | while |
else | label | repeat | with |
end | mod | set | xor |
A szabványos Pascal packed kulcsszava a Turbo Pascal-ban hatástalan.
Példa
A Turbo Pascal nyelven megírt legrövidebb program a következő:
Begin
end.
A program két kulcsszóból és egy határolóból áll. A program lefuttatása semmilyen következménnyel sem jár.
2.2. Azonosítók
A Pascal programban az általunk létrehozott elemeknek (változóknak, konstansoknak, típusoknak, eljárásoknak, függvényeknek, rekordmezőknek) egyedi nevet kell adni, hogy hivatkozni tudjunk rájuk. A betűvel kezdődő, betűkből és / vagy számjegyekből álló karaktersorozatot (feltéve,
hogy nem azonos egyetlen kulcsszóval sem) azonosítónak nevezzük. A "betű"
alatt az angol ábécé tetszőleges kis- vagy nagybetűje, ill. az aláhúzásjel értendő.
Az azonosító karaktereinek száma nem lépheti túl a 127-et, minden karakter szignifikáns.
Számos azonosító előre definiált; ezek konstansokat, függvényeket és eljárásokat
képviselnek. E csoportba a következő azonosítók tartoznak:
Abs | Dispose | Length | Real |
Addr | Eof | Ln | Release |
ArcTan | Eoln | Lo | Rename |
Assign | Erase | LowVideo | Reset |
Aux | Execute | Lst | Rewrite |
Bdos | Exit | Mark | Round |
Bios | Exp | MaxAvail | Seek |
BiosHL | False | MaxInt | Sin |
BlockRead | FilePos | Mem | SizeOf |
BlockWrite | FileSize | MemAvail | SeekEof |
Boolean | FillChar | Move | SeekEoln |
Buflen | Flush | NormVideo | Sqr |
Chain | Frac | Odd | Sqrt |
Char | FreeMem | Ord | Str |
Chr | GetMem | Output | Succ |
Close | GotoXY | OvrDrive | Swap |
ClrEol | Halt | ParamCount | Text |
ClrScr | HeapPtr | ParamStr | Trm |
Con | Hi | Pi | True |
Concat | Input | Port | Trunc |
Copy | Insert | Pos | UpCase |
Cos | InsLine | Pred | Usr |
CrtExit | Int | Ptr | Val |
CrtInit | Integer | Random | Write |
DelLine | IOresult | Randomize | Writeln |
Delay | Kbd | Read | |
Delete | Keypressed | Readln |
Ha a listán szereplő azonosítók valamelyikét deklaráljuk, akkor ezzel a deklaráció érvényességi körén belül "eltakarjuk" az adott azonosító eredeti jelentését.
Példa
Az azonosító jelentésének "eltakarása":
program jb;
const false=true;
begin
Writeln(false)
end.
A programfuttatás eredményeképpen a TRUE felirat jelenik meg a képernyőn. Ha a programból kitörölnénk az első pontosvessző és a begin közötti szövegrészt, akkor futási eredményként a FALSE felirat jelenne meg.
2.3. Konstansok
A konstansok aritmetikai, karakter, karakterlánc és logikai konstansok lehetnek.
Az aritmetikai konstansok tovább csoportosíthatók egész és valós típusú konstansokra.
Az aritmetikai konstansokat a továbbiaknak számoknak fogjuk nevezni.
2.3.1. Egész típusú konstansok
Az egész típusú konstans decimális számjegyek sorozata, melyet a + vagy a
- jel előzhet meg. Az egész típusú konstans számértékének a [-32768, 32767]
zárt intervallumba kell tartoznia. Azon egész típusú konstanst, amelynek számértéke
a [0,255] zárt intervallumba tartozik, byte típusú konstansnak nevezzük.
A Turbo Pascal nyelvben az egész és a byte típusú konstansok hexadecimális
(tizenhatos számrendszerbeli) számokkal is megadhatók. Ez esetben a konstans
a $ jelből és az azt követő hexadecimális számjegyek sorozatából áll. A $
jel előtt szerepelhet a + vagy a - jel.
Példa
Néhány - helyes és hibás - egész típusú konstans:
Egész típusú konstansok: 23, -23, 002, $ABC, -$2B
Olyan karaktersorozatok, amelyek nem képviselnek egész típusú konstansokat:
2B6 (a B betű nem decimális számjegy);
$3G a G betű nem hexadecimális számjegy);
2.6 (a . karakter nem számjegy.)
2.3.2. Valós típusú konstansok
A valós típusú konstans egymás utáni összetevői a következők: előjel egészrész, tizedespont,
törtrész, hatványjel (kis vagy nagy E betű), kitevő. Az egészrész, a törtrész és a kitevő
decimális számjegyek sorozata; az egészrészt és a kitevőt megelőzheti a +
vagy a - jel. Ha elhagyjuk az előjelet, akkor a szám pozitív lesz. A törtrész (a tizedesponttal együtt) és a kitevő (az E betűvel
együtt) elhagyható, de az egész részt mindíg meg kell adni. Megengedhető továbbá, hogy a konstans törtrésze üres legyen.
Példa
Néhány - helyes és hibás - valós típusú konstans:
Valós típusú konstansok: -2.3, 2.5e2, 4.E-3, $ABC, 2E3
Olyan karaktersorozatok, amelyek nem képviselnek valós típusú konstansokat:
3e2.0 (a kitevőben nem lehet tizedespont);
.25 (hiányzik az egészrész);
2.3D2
(hibás kitevő).
2.3.3. Karakter, illetve karakterlánc típusú konstansok
A karakterlánc típusú konstansok karaktersorozatokat képviselnek. Ha a karakterlánc
egyetlenegy karakterből áll, akkor karaktertípust képvisel. Általános esetben
egy karakterlánc típusú konstans a következőkből állhat: két aposztróf közötti
karaktersorozatból, vezérlő karakterekből, valamint decimálisan vagy hexadecimálisan
ábrázolt karakterekből. A két aposztróf között levő karaktersorozatban tetszőleges
látható karakterek (a szóközt is beleértve) fordulhatnak elő; az ' (aposztróf)
karaktert pedig egy aposztróf-pár képviseli. A vezérlő karaktereket egy karakterpár
ábrázolja, ahol az első karakter egy ^, a második pedig egy látható karakter.
Az így ábrázolt vezérlő karakter kódja azonos azzal a kóddal, amely a CTRL
billentyű és az adott látható karakter billentyűjének együttes lenyomásával
keletkezik. A decimálisan ábrázolt karakterek a # karakterből és az utána
következő decimális karakterkódból állnak, a hexadecimálisan ábrázolt karakterek
pedig a # karakterből, a $ karakterből és az utána következő hexadecimális
karakterkódból.
Példa
Néhány - helyes és hibás - karakterlánc típusú konstans:
2.3.4. Logikai konstansok
A logikai konstansokat a true és a false karaktersorozat képviseli.
Közülük az első a logikai "igaz" értéket, a második pedig a logikai
"hamis" értéket jelenti.
2.4. Megjegyzések
A megjegyzés nyitó kapcsos zárójellel kezdődő és záró kapcsos zárójellel végződő
karaktersorozat. A nyitó és záró kapcsos zárójelek helyett használhatók a
(* és *) összetett szimbólumok is. A { és } karakterekkel határolt megjegyzések
beágyazhatók a (* és *) szimbólumokkal határolt megjegyzésekbe; hasonlóképpen
a (* és *) szimbólumokkal határolt megjegyzések beágyazhatók a { és } karakterekkel
határolt megjegyzésekbe.
Ha a megjegyzést megnyitó karakter vagy szimbólum után közvetlenül a $ karakter
következik, akkor ezt a megjegyzést a fordítóprogram direktívának tekinti.
A direktíva nem szerepelhet beágyazott megjegyzésben.
3. Standard skalártípusok
Számítógépes programok többsége a futása során megadott adatokat valamilyen módon feldolgozza és megjeleníti az eredményeket. A program által kezelt adatok sokfélék lehetnek (számok, szövegek, stb.). A programban az adatokat változókban tároljuk. Az adattípus határozza meg, hogy egy változó milyen értéket vehet fel és milyen műveletek végezhetők rajta. A változók számára a fordítóprogram egy vagy több bájtot foglal le a memóriában. Ez a tárterület tartalmazza a változó aktuális értékét, ami a program futása során meg is változhat. Minden változóhoz tartozik egy adattípus (röviden tipus), amely előírja a változó számára lefoglalandó memóriaterület nagyságát és a változóban tárolt adat értelmezését. A típus azt is meghatározza, hegy egy változó milyen értéket vehet fel.
A típus fogalma egy adathalmazhoz kapcsolódik. Ilyen értelemben egy változó
bizonyos típusú, ha e típust leíró halmaz elemeit értékéül kaphatja. A Turbo
Pascal nyelv megköveteli a program összes változójának nyílt típusmeghatározását. A változó adattípusa előírja a változó számára lefoglalandó memóriaterület méretét és a változóban tárolt adat értelmezését. Így a típus meghatározza, hogy a változó milyen értékeket vehet fel.
A változó nevét és a kiválasztott típust a változó deklarációjában kapcsolhatjuk
össze. A változótípusok az alább látható elemi és összetett típusokra oszthatók
fel. Elemi típus a skalár- és a mutatótípus; az összetett típusokhoz a karakterlánc-,
a tömb-, a rekord-, a halmaz- és a file-típus tartozik. A skalártípusok között
megkülönböztethetünk standard skalártípusokat, mégpedig integer (egész-),
byte, char (karakter-), boolean (logikai) és real (valós) típusokat. Az első
négyet rendezett típusnak is nevezzük. Jellemző tulajdonságuk, hogy mindegyikük
egy megszámlálható halmazhoz kapcsolódik.
A logikai (boolean), egész (integer, byte), karakter (char) és felsorolás típusokat (és ezek résztartományait) sorszámozott típusnak is nevezzük.
A standard skalártípusok előre definiáltak. "Rejtett" definíciójuk
érvényességi tartománya az egész programra kiterjed, kivéve azokat a részeket,
amelyekben nyílt eltakaró deklarációk vannak.
Az integer típus
Az integer típusú adat az egész számok részhalmazának az eleme. E számok értékei
a [-32768,32767] zárt intervallumhoz tartoznak. Az integer típusú adatok mindegyike
2 bájt tárhelyet foglal le. Az integer típusú adatokon végzett aritmetikai
műveletekben nincs túlcsordulásellenőrzés. Emiatt az eredmény helyességének
az a feltétele, hogy a művelet argumentumai és az összes közbenső eredmény
az előbb meghatározott intervallumhoz tartozék.
A Turbo Pascal a legnagyobb integer típusú számot (32767) a MaxInt konstansban tárolja.
A byte típus
A byte típusú adat egész számok részhalmazának az eleme, értékei a [0,255]
zárt intervallumhoz tartoznak. Ahol a programban egy byte típusú adatra hivatkozunk,
majdnem mindenhol hivatkozhatunk egy integer típusú adatra (és fordítva).
Fontos kivétel e szabály alól a paraméterek és argumentumok társítása az eljárásokban
és a függvényekben; ekkor az adattípusok teljes megfeleltetése a követelmény.
A byte típusú adatok mindegyike 1 bájt tárhelyet foglal le.
A char típus
A char típusú adat az ASCII kódkészlet eleme. A char típusú adatok mindegyike
1 bájt tárhelyet fogfal le és egyetlen karakter tárolására alkalmas.
A boolean típus
A boolean típusú adat a kételemű logikai adathalmaz eleme. Ezeket az adatokat
a false és a true szabványos azonosítókkal jelölhetjük. A boolean típusú adatok
mindegyike 1 bájt tárhelyet foglal le.
A real típus
A real típusú adat valós számhalmaz eleme. E halmazhoz tartozik a 0 szám,
ill. azok a pozitív és negatív számok, melyek abszolút értékei a [10^-38,
10^83] intervallumhoz tartoznak.
A Turbo Pascal-ban a nem szabványos String típus is előre definiált, melyet karaktersorozatok tárolására használhatjuk.
A string-ben tárolt karakterek száma változhat, ezért a Turbo pascal egy külön byte-ot rendel (0-s indexszel), ahol tárolja a karakterek aktuális darabszámát. Mivel egy byte-ba írható maximális érték 255, a string típusú változó 255-nél több karaktert nem tárolhat. A változó definícióban szögletes zárójelben meg kell adnunk a string maximális hosszát.
var name:string[30];
A string típusú változóban tárolt szöveget egy darabban és karakterenként is feldolgozhatjuk. A karakteres elérés esetén a string-indexben,a string azonosítója mellett szögletes zárójelben) kell megadni a vizsgálandó karakter sorszámát:
name:='Bielaczky';
name[5]:='e';
Writeln(name[1]);
4. Programszerkezet
A Turbo Pascal nyelvben megírt program programfejlécből, blokkból és . (pont)
karakterből áll. A fejlécben a program neve és egy kerek zárójelekkel határolt
azonosítólista van, amely leírja a program és környezete közötti adatátvitel
módját. A blokk egy deklarációs és egy végrehajtó részből áll. A fejléc és
a deklarációs rész el is hagyható.
4.1. Programfejléc
Ha a program fejléccel kezdődik, akkor szerepel benne legalább a program neve.
A programnév után megadható - kerek zárójelekkel határolva - a program paraméterlistája.
Ez a lista felsorolja azon adatállományok azonosítóit, melyekkel a program
kapcsolatot tart környezetével. A fordítóprogram nem értelmezi a lista tartalmát,
ezért figyelmen kívül hagyja (a határoló zárójelekkel együtt). Szintaxis:
Program programnév(állománynévlista)
A Turbo Pascal-ban nem kötelező a programfej, el is maradhat.
Példák:
program Volume
program Lister(Output);
program Copier(Input,Output);
4.2. Blokk
A blokk egy deklarációs és egy végrehajtó részből áll. A deklarációs részben
vannak a típusdefiníciók, a konstansnév-definíciók, az alprogramok (eljárások
és függvények) definíciói és deklarációi, valamint a címkék és a változók
deklarációi. Mindezek a definíciók és deklarációk tetszőleges sorrendben következhetnek;
az egyes definíciók és deklarációk csoportjai keveredhetnek egymással. Ezt
úgy kell érteni, hogy pl. a típusdefiníciók után írhatjuk a változók deklarációit,
utánuk újból a típusdefiníciókat és a változódeklarációkat stb. A végrehajtó
rész - a programtörzs - egy csoportosító utasításból (begin ... end) áll, amely a program utasításalt tartalmazza. Az end szót ebben az esetben egy - a program végét jelző - pont is követi.
Szintaxis:
blokk:
deklarációs_ rész végrehajtó_rész
deklarációs_rész:
a_deklarációk_és_a_ definíciók_felsorolása
végrehajtó, rész:
csoportosító_utasítás
deklarációk_és_definíciók:
címkedeklarációk
konstansnév-definíciók
típusdefiníciók
változódeklarációk
alprogram_definíciók_és_-deklarációk
inicializálások
4.2.1. Címkedeklarációk
A program minden utasítását címkével láthatjuk el, amely vezérlésátadást tesz
lehetővé a goto utasítás használatakor. A címke egy azonosítóból vagy
egy számjegysorozatból áll. A közvetlenül a címke után következő : karakter
a címkét elválasztja egy másik címkétől vagy utasítástól. Mielőtt címkét használnánk
a programban, deklarálnunk kell a nevét. A címkedeklarációk a label
kulcsszóból és az utána következő - a címkenevekkel azonos - karaktersorozatok
listájából állnak, végül a ; következik.Szintaxis:
label címkelista;
Példák:
label 10,abort,quit;
label 9999;
4.2.2. Konstansnév-definíciók
A program áttekinthetősége szempontjából gyakran hasznos, ha a konstansokat
az őket képviselő, megfelelően megválasztott azonosítókkal helyettesítjük.
Ilyen esetekben az azonosító azonos a vele összekapcsolt konstanssal. A Turbo
Pascal nyelvben az azonosítókat és a konstansokat a konstansnév-definíciók
értelmezésekor kapcsolhatjuk össze. A konstansnév-definíció a const
kulcsszóból és az utána következő hozzárendelések sorozatából áll. A hozzárendelés
az azonosítóból, az = karakterből, a konstanskifejezésből és a ; karakterből
áll. A konstanskifejezés lehet szám, karakterlánc, konstansnév vagy - (mínusz)
karakterrel megelőzött konstansnév. Az előre definiált konstansnevek a következők:
Pi - real típusú, a 3.1415926536 konstanst képviseli;
Maxlnt - integer típusú, a 32767 konstanst képviseli.
Szintaxis:
konstansnév-definíciók
const hozzárendelések_sorozata
hozzárendelés:
azonosító = szám;
azonosító = karakterlánc;
azonosító = konstansnév;
azonosító = mínuszjel konstansnév
Példa:
const e=2.718282;
A konstansnevek olyan azonosítóval (névvel) ellátott értékek, amelyek nem változnak meg a program futása során. Következésképpen a konstansnevek nem szerepelhetnek értékadó utasítás bal oldalán! A definiált konstansnevek számára a fordító nem foglal helyet a memóriában, ezeket a fordító csak a fordítás során használja. A konstansnevekre a deklarációs részben és a programban egyaránt hivatkozhatunk.
Típusos konstansok
A Turbo Pascal - kibővítve a szabványos Pascal nyelvet - lehetővé teszi olyan (csak nevükben) konstansok használatát, amelyek memóriában tárolódnak és melyek tartalma megváltoztatható. Ezek az ún. típusos konstansok valójában a Pascal nyelv kezdőértékkel ellátott változói. A típusos konstansok másik fontos tulajdonsága, hogy a program indításakor létrejönnek, és a program lefutásáig léteznek.
A típusos konstansok szintén a deklarációs rész const szekciójában helyezkednek el. A típusos konstans definíciójában a konstans kezdőértékét is meg kell adni:
const konstansnév:típus=kezőérték
Például:
const name:string[20]='Micimacko';
A típusos konstans definíciója tulajdonképpen egy olyan változódeklaráció melyet az egyenlőségjel után a kezdőérték követ.
A típusos konstansokat a programban csak ott használhatjuk, ahol egyébként változó is szerepelhet. (Ellentétben a normál konstansnevekkel, nem hivatkozhatunk rájuk a deklarációs részen belül.)
A típusos konstanst a fájltípuson (file) kívül tetszőleges típussal készíthetünk.
4.2.3. Típusdefiníciók
A program változóinak deklarálásakor meghatározzuk a változók típusait. A
változó típusa lehet előre definiált vagy standard típus (pl. boolean vagy
real, de külön is meghatározható egy típusdefinícióban, amely általános esetben
a type kulcsszóból és a típusdefiníciók sorozatából áll. A típusdefiníciók
mindegyike a definiált típus azonosítójából, az = karakterből, a típusleírásból
és a ; karakterből áll.
Szintaxis:
típusdefiníciók:
type típusdefiníciók_sorozata
típusdefiníció:
definiált_típus = típusleírás;
definiált_típus:
azonosító
típusleírás:
a_standard_típus_leírása
a_definiált_típus_ leírása
a_ standard_típus_leírása:
standardtípus-azonosító
a_definiált_típus_leírása:
felsorolásitípus-leírás
intervallumtípus-leírás
karakterlánctípus-leírás
tömbtípus-leírás
rekordtípus-leírás
halmaztípus-leírás
a file-típus_leírása
mutatótípus-leírás
Példák
type
Number=integer;
Color=(Red,Green,Blue,Orange);
RGB=Red..Blue;
Name=string[20];
Matrix=array(1..5,1..5) of real;
Person=record
FirstName:string[6];
LastName:Name;
Salary:real;
end;
Digits=set of 0..9;
DataFile=file of Person;
Ref=Matrix;
4.2.4 Változódeklarációk
A program - egyszerű és összetett - változóját használat előtt deklarálni
kell. A változódeklarációk a var kulcsszóból és a deklarációk azt követő
felsorolásából állnak. A deklarációfelsorolós az azonosítók listájából, a
: karakterből, a típus meghatározásból és a ; karakterből tevődik össze. A
deklaráció értelmezése a megadott típusú változó(k) létrehozását eredményezi.
Szintaxis:
változódeklarációk:
var deklarációk_sorozata
deklaráció:
azonosítók_listája : típusmeghatározás
Példák:
Var Length,Area,Volume:real;
Count:integer;
Buffer:array[0..255] of byte;
Rejected:boolean;
Egy változó láthatósági tartománya (hatásköre) az a blokk, amelyikben a változót deklaráltuk. Ha ez a blokk más blokkokat is tartalmaz, melyekben ugyanilyen azonosítóval deklarált változók szerepelnek, akkor a deklaráció érvényességi tartománya kisebb, mint a láthatósági tartománya, és nem vonatkozik azokra a belső blokkokra, ahol az eltakaró deklarációk előfordultak. A változó láthatósági tartománya nem a blokk elején, hanem azonosítójának deklarálási helyén kezdődik.
4.2.5. Alprogram-deklarációk
Az alprogramok eljárásokra és függvényekre oszthatók. Az alprogram deklarációja
azokat a tevékenységeket határozza meg, amelyek az alprogram hívása során
végrehajtódnak. A függvénydeklaráció meghatározza a hívás helyén átadott eredmény
típusát is. Az alprogram törzsét tartalmazó deklarációkat definícióknak nevezzük;
azokat a deklarációkat, amelyekben a fejléc után a forward kulcsszó
következik, előzetes deklarációknak hívjuk.
Az előzetes deklarációt csak akkor kell használni, ha a deklarációkat nem
lehet úgy elrendezni, hogy az alprogramokat deklarációjuk hatáskörében hívjuk. (Mint ismeretes a Pascal nyelvben minden azonosítót a felhasználása előtt deklarálni (definiálni) kell. Abban az esetben azonban, ha két egymást kölcsönösen hívó alprogramot készítünk az első alprogram a később definiált alprogram hívását tartalmazza. A probléma a második alprogram előzetes deklarációjával oldható meg.) Az előzetes deklaráció csupán az alprogram fejlécét tartalmazza, amelyet a forward Pascal direktíva és egy pontosvessző követ. Az előzetesen deklarált alprogramra ugyanúgy hivatkozhatunk más alprogramokból, mint a már definiáltra. Az előzetesen deklarált alprogram "teste", vagyis az alprogram teljes definíciója a deklarációs részben belül bárhol megadható.
Példa (Eljárások kereszthívása:)
program jb;
...
procedure second; forward;
procedure first;
begin
...
second;
end;
procedure second;
begin
...
first;
end;
begin
...
end.
Mivel a first eljárás deklarációjában benne van a second eljárás hívása, a second eljárás deklarációjában pedig a first eljárásé, a second eljárást előzetesen deklarálni kell:
procedure second;forward;
A definiáló deklarációval ellentétben az előzetes deklaráció csupán "bejelenti" az alprogram azonosítóját (és paramétereit, ha vannak).
5. Kifejezések
Azokat a karaktersorozatokat, amelyek az adat kiszámításához (ill. meghatározásához)
végrehajtandó tevékenységeket határozzák meg, kifejezéseknek nevezzük. E tevékenységek
végrehajtását a kifejezés kiértékelésének hívjuk. Mivel a kifejezés kiértékelésének
az eredménye egy adat, magát a kifejezést az adatot képviselő karaktersorozatnak
tekinthetjük. E fejezetben tárgyaljuk azon kifejezések kiértékelési szabályait,
amelyek összetevői integer, real, char és boolean típusú adatokat képviselnek.
A definiált típusú adatokra hivatkozó kifejezésekkel a megfelelő típusok leírásánál
foglalkozunk majd.
5.1. Operátorok
Operátoroknak nevezzük a különféle műveleti jeleket, amelyek összekapcsolják a kifejezésekben szereplő operandusokat (változókat, konstansokat és függvényhívásokat). A Pascal nyelvben bizonyos operátorokhoz többféle művelet is társul. Azt, hogy egy operátor az adott műveletben mit jelöl, az operandusok száma és típusa határozza meg. A műveleteket az operandusok típusa alapján az alábbi csoportokba sorolhatjuk:
Az operátorok egy- vagy kétargumentumosak lehetnek, de elsőbbségük (precedenciájuk) szerint is osztályozhatók. Csökkenő precedencia szerint a következőképpen osztályozhatjuk őket:
Ha egy alkifejezésben két, azonos elsőbbségű operátor van,
akkor a megfelelő műveletek balról jobbra hajtódnak végre. Legelőször a kerek
zárójelekkel körülvett alkifejezések értékelődnek ki. Ilyen értelemben a kerek
zárójelek egyargumentumú, legnagyobb precedenciájú operátornak tekinthetők.
Mivel - más nyelvekkel szemben - a relációs jelek is operátorok, a kifejezés kiértékelésének sorrendje eltér pl. a BASIC-ben megszokottól. Például az
a<2 or a>10
a Pascalban
a<(2 or a)>10
formában értékelődik ki. Ezért az ettől eltérő szükséges műveleti sorrendet zárójelekkel kell jelölni. Az elöbbi művelet helyes felírása:
(a<2) or (a>10)
Ha a szorzás, ill. az összeadás jellegű műveletek argumentumai integer vagy real típusú adatokat képviselő kifejezések, akkor a művelet eredménye csak akkor integer típusú, ha mindkét argumentum integer típusú és a művelet nem osztás. Egyébként a művelet eredménye real típusú.
Példa
A 2+3/4 kifejezés által képviselt adat kiértékelése:
5.2. Előjelváltó operátor
Az egyargumentumú - (mínusz) művelet végrehajtása ellenkezőjére változtatja
meg az adat előjelét. Ha az adat értéke 0, akkor a művelet eredménye szintén
0 értékű adat. A - (mínusz) művelet argumentumai csak real és integer típusú
adatok lehetnek.
Példa:
Kifejezés Eredmény -(-4) 4 -3/2 -1.5
5.3. Negációs operátor
Az egyargumentumú not művelet végrehajtása kizárólag a boolean és az integer
típusú adatokra vonatkozik. Az első esetben egy false értékű adat true eredményt
ad és fordítva; a második esetben az adatreprezentáció minden bitje ellenkező
értékűre változik.
Példák:
Kifejezés Eredmény not false true not true false not 0 -1 not $FFFF 0 not -2 1 not -32768 32767
5.4. Szorzás jellegű operátorok
A kétargumentumú *(szorzás) és / (osztás) operátor a real és az integer (beleértve annak byte részhalmazát is) típusú
adatokra vonatkozik, a kétargumentumú and operátor a boolean és az integer típusú
adatokra, a többi, szorzás jellegű operátor pedig kizárólag az integer típusú
adatokra. E követelményeket és az eredmény típusát az alábbi táblázat foglalja
össze. A * és a / műveletek végrehajtását nem szükséges magyarázni. Jegyezzük
meg, hogy az osztás eredménye mindig real típusú adat.
Operátor |
1. argumentum
|
2. argumentum
|
Eredmény
|
* |
real
|
real
|
real
|
real
|
integer
|
real
|
|
integer
|
real
|
real
|
|
integer
|
integer
|
integer
|
|
/ |
real
|
real
|
real
|
real
|
integer
|
real
|
|
integer
|
real
|
real
|
|
integer
|
integer
|
real
|
|
div |
integer
|
integer
|
integer
|
mod |
integer
|
integer
|
integer
|
and |
integer
|
integer
|
integer
|
boolean
|
boolean
|
boolean
|
|
shl |
integer
|
integer
|
integer
|
shr |
integer
|
integer
|
integer
|
Példák:
Kifejezés Eredmény 25*40 1000 25*40.0 1000.0 0.25*40 10.0 24/3 8.0 24.0/3.0 8.0
Az osztás eredménye mindig real típusú, függetlenül attól, hogy a kifejezés értékének törtrésze nulla-e vagy sem. Így osztás eredményét nem tudjuk közvetlenül integer típusú változóba tölteni. A megoldás a kerekítést végző Round konverziós függvény használata lehet:
a:=Round(i/2);
(ahol a integer típusú változó). Azonban többnyire felesleges kiszámolni egy osztás törtrészét, csak azért, hogy rögtön eldobjuk (kivéve, amikor fontos a pontosabb kerekítés), ezért célszerűbb és gyorsabb megoldás a div operátort - mely az egész számok osztásakor keletkező hányadost adja - használni ilyen esetben:
a:= i div 2;
A div művelet eredménye integer típusú adat, melynek értéke egyenlő a két argumentum osztási eredményének egészrészével. A mod művelet (az egész számok osztásakor keletkező maradékot szolgáltatja) definíciója a következő:
a mod b=a-((a div b)*b)
Tetszőleges a és b (b<>0) egészre igaz az alábbi összefüggés:
a=(a div b)*b+a mod b
Példák:
Kifejezés Eredmény 25 div 7 3 -25 div 7 -3 25 mod 7 4 -25 mod 7 -4
Az and művelet eredménye két boolean típusú adaton az argumentumok logikai szorzata:
a. argumentum |
b. argumentum |
a and b |
false |
false |
false |
true |
false |
false |
false |
true |
false |
true |
true |
true |
Az and művelet eredménye két integer típusú adaton olyan integer típusú adat, amelynek bitjei az argumentumok megfelelő bitpárjának logikai szorzatával egyenlők. Egy bitpár logikai szorzata csak akkor 1, ha mindkét bit 1, különben 0.
Példák:
Kifejezés Eredmény false and true false 2 and 2 2 12 and 22 4 -5 and 0 0
A kétargumentumú shl és shr művelet kizárólag az integer típusú adatokra vonatkozik. A műveletek eredménye is integer típusú. Az eredmény bitképe úgy keletkezik, hogy az első argumentum bitjeit annyi pozícióval balra (shl) vagy jobbra (shr) toljuk el, amennyi a második argumentum értéke. Az eltolás logikai jellegű, vagyis az előjelbit nem sokszorozódik, ugyanakkor az üresedő bitpozíciók 0 értékű bitekkel töltődnek fel.
Példák:
Kifejezés Eredmény 2 shl 1 4 2 shl 3 16 3 shr 1 1 -3 shr 1 32766
5.5. Összeadás jellegű operátorok
A kétargumentumú + és - operátor a real és az integer (beleértve annak byte részhalmazát is) típusú adatokra vonatkozik,
a többi, összeadás jellegű operátor pedig az azonos típusú argumentum-párokra.
E követelményeket és az eredmény típusát az alábbi. Táblázat foglalja össze.
Operátor |
1. argumentum |
2. argumentum |
Eredmény |
+ |
real
|
real
|
real
|
real
|
integer
|
real
|
|
integer
|
real
|
real
|
|
integer
|
integer
|
integer
|
|
- |
real
|
real
|
real
|
real
|
integer
|
real
|
|
integer
|
real
|
real
|
|
integer
|
integer
|
integer
|
|
or |
integer
|
integer
|
integer
|
boolean
|
boolean
|
boolean
|
|
xor |
integer
|
integer
|
integer
|
boolean
|
boolean
|
boolean
|
Példák:
Kifejezés Eredmény 20+40 60 20.0+40 60.0 60.0-40.0 20.0
A + és a - műveletek végrehajtását nem szükséges magyarázni. Jegyezzük meg, hogy a művelet eredménye csak akkor integer típusú, ha mindkét argumentum integer típusú. Egyébként a művelet eredménye real típusú.
Az or művelet eredménye két boolean típusú adaton az argumentumok logikai összege:
a. argumentum |
b. argumentum |
a or b |
false |
false |
false |
true |
false |
true |
false |
true |
true |
true |
true |
true |
Az or művelet eredménye két integer típusú adaton olyan integer típusú adat, amelynek bitjei az argumentumok megfelelő bitpárjainak logikai összegével egyenlők Egy bitpár logikai összege csak akkor 0, ha mindkét bit 0, különben 1.
Példák:
Kifejezés Eredmény false or true true 2 or 3 3 12 or 22 30 $8000 or 1 -32767
A xor művelet eredménye két boolean típusú adaton az argumentumok logika "kizáró VAGY" kapcsolata:
a. argumentum |
b. argumentum |
a xor b |
false |
false |
false |
true |
false |
true |
false |
true |
true |
true |
true |
false |
A xor művelet eredménye két integer típusú adaton olyan integer típusú adat, amelynek bitjei az argumentumok megfelelő bitpárjainak modulo 2 összegével egyenlők. Egy bitpár modulo 2 összege csak akkor 0, ha mindkét bit azonos különben 1.
Példa:
Kifejezés Eredmény true xor true false $8000 xor 2 32766 12 xor 22 26 -1 xor -1 0
5.6. Relációk
A relációk operátorai tetszőleges integer, real, char és boolean típusú adatokra
vonatkozhatnak. A műveletek eredménye mindig egy boolean típusú adat, melynek
értéke false vagy true. Ha a reláció egyik argumentuma boolean vagy char típusú,
akkor a másik argumentumnak ezzel azonos típusúnak kell lennie. Aritmetikai
argumentumok esetén nem követelmény a típusazonosság. Ez lehetővé teszi pl.
a real és a integer típusú adatok összehasonlítását.
A relációk operátorai a következők: = (egyenlő), <> (nem egyenlő), <
(kisebb), > (nagyobb), <= (kisebb vagy egyenlő), >= (nagyobb vagy
egyenlő).
Példák
Kifejezés Eredmény 20=20 true 30.0>20 true 'J'<'B' false false<true true
5.7. Függvényhívások
A függvényhívás a függvény azonosítójából és az azt követő, kerek zárójelekkel
körülvett hívási argumentumok listájából áll. A paraméter nélküli függvény
hívása csak a függvény azonosítójából áll.
Példák:
Eof(Input)
KeyPressed
5.8. Típuskonverzió
A Pascal erősen típusos nyelv. Ez a megállapítás azt jelenti, hogy a nyelv mentes a automatikus típusátalakításoktól. Ha egy kifejezésben, különböző, nem kompatibilis kifejezések fordulnak elő (pl. egy értékadó utasítással integer típusú változóba real típusú értéket akarunk tölteni), típuskeveredési hibával (Type mismatch) megszakad a fordítás. Ebben az esetben két lehetőséget választhatunk:
Az első megoldás, hogy a szabványos függvények segítségével végezzük el az átalakítást:
A második megoldást az teszi lehetővé, hogy a Turbo Pascal nyelvben bővítették az ord függvény koncepcióját (ez a függvény egy tetszőleges, rendezett típusú adatot integer típusú adattá konvertál). Bevezették ui. az egyparaméteres operátorok családját (nevük megegyezik a rendezett típusokéval), ezért adatkonverzióra nyíik lehetőség tetszőleges, rendezett típusok között.
A konverziós operátor opr(arg) alakú, ahol az opr egy rendezett típus azonosítója, az arg pedig bármilyen rendezett típusú kifejezés. A konverzió eredménye egy olyan opr típusú adat, amelyre igaz az ord(a) = ord(opr(a)) reláció.
Példák:
Az előre definiált, rendezett típusok és a Color nyílt típusdefiníció
Type Color=(Heart,Diamond,Spade,Club);
érvényességi tartományán belül érvényesek a következő összefüggések:
Kifejezés Eredmény integer(Club) 3 Color(2) Spade char(65) 'A' integer('A') 65 boolean(Heart) false byte(true) 1
Példák:
Writeln(integer('a');
Writeln(byte('b'));
Writeln(char(65));
Writeln(Boolean(12));
6. Utasítások
Az utasítás azon tevékenységek leírása, amelyeket végre kell hajtani az algoritmus
megvalósításakor. A Turbo Pascal nyelvben két utasításfajta van: egyszerű
és strukturált. Egyszerű utasítás az értékadás, az eljáráshívás, az ugró utasítás
és az üres utasítás; strukturált utasítás pedig a csoportosító utasítás, a
feltételes utasítás, a kiválasztó utasítás és három iterációs utasítás. A
programban szereplő minden szomszédos utasításpárt a ; karakter választja
el.
6.1. Értékadó utasítás
Az értékadó utasítás a változónévből, az értékadó szimbólumból és a kifejezésből
áll. Egy függvénydefiníción belül szerepelnie kell legalább egy értékadó utasításnak,
amelyikben a változót azonosító karaktersorozat a függvény azonosítója.
Az értékadó utasítás végrehajtása során kiértékelődik a kifejezés képviselte
adat, és ennek értékét megkapja az értékadó szimbólum bal oldalán álló azonosítóval
meghatározott változó. A függvénydefiníción belüli értékadás a függvény értékét
adja meg (vagyis azt az adatot, amely hozzáférhetővé válik a függvényhívás
helyén).
Az értékadáskor a kifejezés típusának a változó típusával azonosnak kell lennie.
Ez a típusazonosság akkor is fennáll, ha a változó real, a kifejezés pedig
integer típusú. Egyetlen értékadó utasítással csak egy változónak adhatunk értéket. Ha például az a, b, c és d változók mindegyikének nullát akarunk adni értékül, akkor azt csak négy értékadó utasítással tehetjük meg (persze a négy értékadó utasítás egyetlen sorban is elhelyezhető).
Megjegyzés: a tömb, a rekord és a halmaz típusú adataggregátumban megengedett
az értékadás, a file típusú változóban nem.
Szintaxis:
változónév:=kifejezés
függvényazonosító:=kifejezés
Példák:
i:=i+2
x1:=(-b+sqrt(b*b-4*a*c))/(2*a)
arr[2,3]:=m=n
fun:=false
Mielőtt bármilyen kifejezésben használnánk a programunk elején deklarált változókat, azokat kezdőértékkel kell ellátni, más szóval inicializálni kell. Bár a változó létrejöttekor kap valamilyen értéket, ez azonban mindig véletlenszerű és nem nulla. A változó inicializálás nélküli értéke attól függ, hogy éppen mi volt a változó számára kijelölt memóriaterületen.
Aritmetikai értékadás
Az aritmetikai értékadás során a bal oldalon szereplő változó numerikus értéket vesz fel. Az értékadó utasítások használata során gyakran előforduló hiba a típuskeveredés, amikor a bal és a jobb oldal típusa nem értékadás-kompatibilis. A másik, szintén gyakori hiba, hogy a bal oldalon szereplő változónak nagyobb értéket adunk, mint a típusának megfelelő maximális érték. Valamely változók típusának a megválasztásakor mindig át kell gondolni, hogy a változó milyen értékeket vehet fel. Ugyancsak meg kell vizsgálni, hogy a műveletek következtében a program futása során hogyan alakulnak az értékhatárok.
Például, ha a v integer típusú változó (2 bájton tárolt előjeles egész, melynek értéktartománya -32768..32767), akkor az alábbi értékadások programhibához vezetnek:
v:=23456;
v.=2*v;
Ez a hiba nehezen kideríthető, mivel a v változó hibás értéke a program további részeiben vagy csak az eredményekben jelenik meg hibaként.
Különös figyelemmel kell eljárnunk a változó típusának megválasztása során. Ha előre tudjuk, hogy a változó a típusánál nagyobb (kisebb) értékeket is felvehet, akkor a tágabb értékkészlettel rendelkező real típust kell használnunk.
A következő példában látszólag minden rendben van, hisz a változók típusa és az eredmény típusa elegendő az értékeik tárolására:
var a,b:integer;
r:real;
begin
a:=30000; b:=25000;
r:=a+b;
end.
Az eredmény azonban mégis hibás lesz: 55000 helyett -10536-ot kapunk! A hibát jobb oldalon álló kifejezés kiértékelése okozza. Kétoperandusú művelet elvégzéséhez a számítógép az operandusok típusának megfelelő típusú munkaterületet használ. A bal oldalon szereplő változóba csak a művelet elvégzése után kerül az eredmény. Így a példában hiába szerepel real típusú változó a bal oldalon, a kifejezés kiértékelése során integer típust használ a rendszer.
A problémát (ha sikerült megtalálnunk!) kétféleképpen oldhatjuk meg. Vagy mindhárom változót real típusúra deklaráljuk, vagy az a értékét először betöltjük az r változóba.
var a,b:integer;
r:real;
begin
a:=30000; b:=25000;
r:=a; r=r+b;
end.
6.2. Eljáráshívás
Az eljáráshívás az eljárás azonosítójából és az azt követő, kerek zárójelekkel
körülvett hívási argumentumok listájából áll, a paraméter nélküli eljárás
hívása pedig csak az eljárás azonosítójából. Az eljárás hívásakor végrehajtódnak
az eljárás definíciójában meghatározott tevékenységek. Előtte azonban lezajlik
a hívott eljárás argumentumainak meghatározása és a hívásban szereplő kifejezések
kiértékelése.
Szintaxis:
eljárásnév (argumentumlista)
eljárásnév
Példák:
Rewrite(OutFile)
Move(source,target)
Exit
6.3. Ugró utasítás
Az ugró utasítás (vezérlésátadás) a goto kulcsszóból és az azt követő
címkenévből áll. Az ugró utasítás végrehajtása eredményeképpen a program a
címkével ellátott utasítással (és az utána következő utasítássorozattal) folytatódik
(feltétel nélküli vezérlésátadás). Ennek feltétele, hogy egy bizonyos címkenevet tartalmazó ugró utasítás e címkedeklaráció
hatáskörén belül legyen. Nem megengedett, hogy az ugró utasítás végrehajtása
a vezérlést egy strukturált utasítás vagy egy alprogram belsejébe, ill. az
alprogramon kívülre adja át.
Szintaxis:
goto címkenév
Példák:
goto 345
goto finish
6.4. Üres utasítás
Az üres utasítás a nyelv egyetlen olyan szerkezete, amely nem igényli a nyelvi
szimbólumok használatát. Akkor alkalmazzuk, amikor a programon belül szükség
van egy utasításra, de semmilyen tevékenységet nem akarunk végeztetni vele.
Az üres utasítás végrehajtásának nincs következménye.
Példák (Az üres utasítás helyét egy felkiáltójelet tartalmazó megjegyzés jelöli):
begin {!} end
while false do {!};
repeat {!} until true
begin {!} ; {!} end
case true of false: {!} ; true {!} end
6.5. Csoportosító utasítás
A csoportosító utasítás (röviden csoportos utasítás) a begin kulcsszóból,
az utasítások sorozatából és az end kulcsszóból áll. A csoportosító
utasítást ott használjuk, ahol a nyelv szintaxisa csak egy utasítást enged
meg, itt viszont utasítássorozatra van szükség. A csoportosító utasítás végrehajtásakor
végrehajtódik a benne foglalt utasítássorozat.
Szintaxis
Begin
utasítások sorozata
end
Példák:
begin
i:=2;j:=3
endbegin
Writeln(OutFile);
Close(OutFile)
end
Meghegyzés: az end-et megelőző utasítást nem kell pontosvesszővel zárni, de a fordító nem jelez hibát, ha kitesszük.
6.6. Feltételes utasítás
A feltételes utasítás az if kulcsszóból, az azt követő logikai kifejezésből,
a then kulcsszóból és egy utasításból áll (egyágú szelekció). Az utasítás után az else
kulcsszó és egy újabb utasítás is következhet (kétágú szelekció). A feltételes utasítás végrehajtása
a logikai kifejezés kiértékelésével kezdődik; ha az eredmény true, akkor a
then kulcsszó utáni utasítás hajtódik végre. Ha az eredmény false és az utasítás
nem tartalmazza az else kulcsszót, akkor az utasítás végrehajtását befejezettnek
tekintjük; ellenkező esetben az else kulcsszó utáni utasítás hajtódik végre. Az
if ... then ... else ... egyetlen strukturált utasítás, melynek része mindhárom
kulcsszó, mégpedig ebben a sorrendben. A szintaktika a then illetve az else utasítás
után egy-egy utasítást vár (ez lehet összetett utasítás is). A pontosvessző lezárja
az if utasítást, így az else elé nem szabad pontosvesszőt tenni, mert szintaktikai
hibát eredményezne (else-zel egyetlen utasítás sem kezdődik).
Ha a feltételes utasításban szereplő utasítás is feltételes, akkor csak az
else kulcsszó előtt állhat (feltéve, hogy ez az utasítás is tartalmazza az
else kulcsszót).
Szintaxis:
if logikai_ kifejezés then utasítás
if logikai_ kifejezés then utasítás
else utasítás
Példák:
if a=b then a:=5 else b:=5
if a=b then begin
a:=6;
b:=6
endif a=b then
if a=5 then
b:=2
else
a:=3
else
a:=13
6.7. Kiválasztó utasítás
A kiválasztó utasítás segítségével könnyen megoldhatjuk a programunk egy értéktől függő többirányú elágaztatását. A kiválasztó utasítás a case kulcsszóból, az azt követő kiválasztó
(szelektor-) kifejezésből, az of kulcsszóból, a kiválasztási címkékkel
ellátott utasítások sorozatából és az end kulcsszóból áll.
A kiválasztási címkék listája konstansokból épül fel; a listát egy : karakter
választja el az utasítástól. A szelektor és az egyes eseteket azonosító konstansok csak sorszámozott típusúak lehetnek. A listában szereplő mindegyik konstans típusának
azonosnak kell lennie a kiválasztó kifejezés típusával. Ha a konstanslistán
belül rendezett típusú, egymás utáni elemek sorozata jelenik meg, akkor a
sorozat az
első.. utolsó
szerkezettel helyettesíthető, mely meghatározza a sorozat első és utolsó elemét.
Ha több értékhez ugyanaz az utasítás tartozik, akkor az esetkonstansokat vesszővel elválasztva is megadhatjuk:
első, második, ...
A kiválasztó utasítás utolsó ágában (az end kulcsszó előtt) szerepelhet az
else kulcsszó is (kettőspont nélkül).
A kiválasztó utasítás végrehajtása a kiválasztó kifejezés kiértékelésével
kezdődik; utána az az utasítás (ez lehet összetett utasítás is) hajtódik végre, amelyiknek a kiválasztási címkéje
egyenlő a kiválasztó kifejezés értékével. Ha nincs ilyen utasítás, akkor az
else kulcsszó utáni utasítások hajtódnak végre; ha hiányzik az else ág, akkor
egy üres utasítás hajtódik végre.
Szintaxis:
kiválasztó_utasítás:
case kiválasztó_kifejezés of
kiválasztó_utasítások_sorozata end
Példák:
case a=b of
false: i:=5;
true: j:=2;
endcase Year of
1945..1955: Writeln('hard work');
1956..1969: Writeln('hopes');
1970..1979: Writeln('prosperity');
1980..1981: Writeln('euphoria');
else Writeln('no comment')
endcase st of
'A','a': c:=65;
'B','b': c:=66;
end
6.8. Iterációs utasítások
Az iterációs utasításokkal programozott ciklusok szervezhetők. Három fajtájuk
van: a for, a while és a repeat. Ha előre (a ciklusba való belépés előtt) ismerjük az ismétlések számát, akkor a for utasítás használata javasolt. Amennyiben a ciklust valamilyen feltétel vezérli (vagyis az ismétlések száma attól függ, hogy mikor válik a feltétel igazzá vagy hamissá), akkor a while vagy a repeat utasításokat használjuk. A ciklusokat a belépési (illetve a kilépési) feltétel ellenőrzésének helye alapján is csoportosíthatjuk.
A for utasítás
A for utasítás a for kulcsszóból, az azt követő ciklusváltozó azonosítójából,
az értékadás-szimbólumból, a ciklusváltozó kezdeti értékét meghatározó kifejezésből,
a to vagy a downto kulcsszóból, a ciklusváltozó végértékét meghatározó
kifejezésből, a do kulcsszóból és egy tetszőleges utasításból áll. A ciklusváltozónak
és mindkét kifejezésnek rendezett típusúnak kell lennie.
Szintaxis:
for változónév:= kifejezés(a) to kifejezés(b) do utasítás
for változónév:= kifejezés(a) downto kifejezés(b) do utasítás
A for utasítás végrehajtásakor a ciklusban szereplő utasítások a ciklusváltozó
összes olyan értékére végrehajtódnak, melyek a "kifejezés(a)" és
a "kifejezés(b)" által határolt zárt intervallumhoz tartoznak.
Ha a for utasításban a to kulcsszó szerepel, akkor a ciklusváltozó
növekvő sorrendben vesz fel értékeket (a legkisebbtől a legnagyobbig). Ha
a downto kulcsszó jelenik meg, akkor a ciklusváltozó csökkenő sorrendben
vesz fel értékeket (a legnagyobbtól a legkisebbig). Ha az első esetben igaz
a
Kifejezés(a)>kifejezés(b)
reláció, vagy a második esetben igaz a
kifejezés(a)<kifejezés(b)
reláció, akkor a for utasítással meghatározott ciklus egyáltalán nem hajtódik
végre. Ilyen esetben a for utasítás végrehajtása csupán a két kifejezés kiértékelését
jelenti. Egyéb esetben a ciklus legalább egyszer végrehajtódik; befejezés
után a ciklusváltozó értéke egyenlő a "kifejezést" értékével.
Megjegyzés: az említett kifejezések csak egyszer értékelődnek ki (a ciklusba
való belépéskor). A ciklusváltozónak nyíltan nem lehet értéket adni.
Példák:
for i:= 2 to 8 do Writeln(i)
for j:=8 downto 2 do Writeln(j)
for toggle:=false to true do
for letter:='i' to 'n' do
arr[toggle,letter]:= 2Program Szorzotabla;
var i,j:integer;
begin
for i:=1 to 10 do begin
for j:=1 to 10 do
Write(i*j:4);
Writeln
end
end.
Ha a ciklusszervezés során nem ismerjük előre a szükséges ismétlések számát, akkor a feltételes ciklusutasítások egyikét kell használnunk. Ilyenből kétfélét ismert a Turbo Pascal:
A while utasítás
A while utasítás a while kulcsszóból, az azt követő boolean típusú
változóból, a do kulcsszóból és egy tetszőleges utasításból áll. Egynél több utasítás while ciklusban történő végrehajtásához összetett utasítást kell használnunk.
Szintaxis
while kifejezés do utasítás
A while utasítás a következő algoritmus szerint hajtódik végre:
A while szerkezet elöltesztelő ciklusutasítás. Abban az esetben, ha a feltétel értéke már a ciklusba belépéskor hamis, a ciklusmag egyszer sem hajtódik végre. Ha a belépési feltétel igaz értéke hibás ciklusszervezés miatt sosem változik hamisra, végtelen ciklust kapunk.
Példa:
while i<>0 do begin
i:=i-1;
Writeln(i)
end
A repeat utasítás
A repeat utasítás a repeat kulcsszóból, az azt követő tetszőleges utasítások
sorozatából, az until kulcsszóból és egy boolean típusú kifejezésből
áll. A repeat until ciklusban összetett utasítás nélkül is több utasítás helyezhető el. A ciklusmag határait a repeat-until utasításpáros egyértelműen meghatározza.
Szintaxis:
repeat utasítások until kifejezés
A repeat utasítás a következő algoritmus szerint hajtódik végre:
Példák:
Repeat
Writeln(i);
i:=i-1
until i=0repeat until KeyPressed
repeat
read(kbd,k);
until (k>='1') and (k<='5') or (k=chr(27));
A repeat szerkezet hátultesztelő ciklusutasítás. Ezért a ciklusmag legalább egyszer mindenképpen végrehajtódik. Ha a belépési feltétel igaz értéke hibás ciklusszervezés miatt sosem változik hamisra, végtelen ciklust kapunk.
7. Felsorolási és intervallumtípusok
A Turbo Pascal elemi adattípusai a skalártípusok, ezen belül pedig a rendezett
típusok. A rendezett típusok mindegyikének fontos tulajdonsága, hogy az őt definiáló
halmaz megszámlálható.
Megjegyzés: a real típus - annak ellenére, hogy skalártípus - nem rendezett
típus. Ez az oka annak, hogy a case utasítás szelektorkifejezése és címkéi,
valamint a vezérlőkifejezések, íll. a for utasításban szereplő kifejezések nem
lehetnek real típusúak.
7.1. Felsorolási típusok
A rendezett típusok közül az egyik legfontosabb a felsorolási típus. A felsorolási
típusok mindegyike kis elemszámú halmazhoz kapcsolódik, amelynek elemein nem
hajtunk végre aritmetikai műveleteket. E halmazok egyes elemeit egyedi azonosítókkal
jelöljük, rendezettségük a felsorolási típus leírásában szereplő azonosítók
sorrendjén alapul. A felsorolási típus leírása az adott típus elemazonosítóinak
listájából és az azt körülvevő kerek zárójelekből áll. Az azonosítók mindegyike
egyben az adott típus konstansa is. Lényeges a lista azonosítóinak felsorolási
sorrendje.
Szintaxis:
felsorolástípus_leírás:
(az_azonosítók_listája)
Példák:
Type
Day=(Mon,Tue,Wed,Thu,Fri,Sat,Sun);
Color=(Heart,Diamond,Spade,Club);
RGB=(Red,Green,Blue);
A felsorolási típus érvényességi tartományán belül nem megengedett egy másik felsorolási típus használata, amely az első típusban szereplő szimbólumok (konstansok) bármelyikére hivatkozik. Ez a korlátozás nem vonatkozik az előre definiált boolean felsorolási típusra; tehát megengedett pl. a (false, true) típusleírás.
Példa:
type
Day=(Mon,Tue,Wed,Thu,Fri,Sat,Sun);
WeekEnd=(Sat,Sun);
Mivel a felsorolási típusok megszámlálható halmazokhoz kapcsolódnak, az ilyen halmaz minden eleméhez egy nem negatív egész szám rendelhető hozzá. Ez a szám meghatározza a felsorolási típus azonosító-listáján az elem helyét. Ilyen értelemben a
type
Direction=(North,South,East,West)
definícióban a North azonosítóhoz a 0-t, a South-hoz az 1-et, az East-hez a
2-t, ill. a West-hez a 3-at rendelhetjük hozzá. A hozzárendelt számok értékeit
az előre definiált ord függvény adja meg. E függvény argumentuma a felsorolási
típusú adatot képviselő kifejezés, értéke pedig az az inieger típusú nem negatív
szám, amely megadja az argumentum 0-tól számított pozícióját (sorszámát) az
adatot tartalmazó, rendezett halmazon belül.
A felsorolási típusú adatokon értelmezett két további függvény a pred és a succ. A ered függvény argumentuma egy tetszőleges, rendezett típusú
kifejezés, amely a rendezett halmaz egyik elemét képviseli. A függvény értéke
a halmaz azon eleme, amely közvetlenül megelőzi az argumentum képviselte elemet.
A pred függvény argumentuma nem képviselheti a halmaz első elemét, mivel
ezt az elemet nem előzi meg más elem.
A pred függvényhez hasonló a succ függvény. A függvény argumentuma egy
tetszőleges, rendezett típusú kifejezés, amely a rendezett halmaz egyik elemét
képviseli. A függvény értéke a halmaz azon eleme, amely közvetlenül követi az
argumentum képviselte elemet. A succ függvény argumentuma nem képviselheti a
halmaz utolsó elemét, mivel ezt az elemet nem követi más elem.
Az ord, a pred és a succ függvény argumentuma lehet integer, ill. byte típusú
adatokat képviselő kifejezés. Ilyen esetben, ha a függvény használata szabályos,
érvényesek a következő összefüggések:
ord(n)=n
pred(n)=n-1
succ(n)=n+1
Példák:
Az előre definiált boolean típus és a nyíltan definiált Color típus
type Color = (Heart,Diamond,Spade,Club);
érvényességi tartományán belül érvényesek a következő állítások:
Kifejezés Eredmény ord(false) 0 pred(true) false ord(Club) 3 succ(Diamond) Spade
7.2. Intervallumtípusok
Az intervallumtípus a rendezett típusok másik fajtája. Minden ilyen típus egy
tetszőleges rendezett halmaz olyan részhalmaza, amelynek elemeit az ord függvény
egy 1-es különbségű számtani sorozatra képezi le. Az intervallumtípus leírása
az intervallum alsó határát jelölő konstansból, a .. szimbólumból (pont párból)
és a felső határt jelölő konstansból áll. Az itt felsorolt konstansok által
meghatározott intervallum nem lehet üres halmaz.
Szintaxis:
intervallumtípus-leírás:
alsó_határ..felső_határ
határ:
konstans
konstansnév
Példák:
type
Quadrant=0..90;
Upper=A'..'Z';
Logical=false..true;
Colour=(Red,Blue,Green,Yellow,Orange);
Hue=Blue..Yellow;
Megjegyzés: az előre definiált byte adattípus - bizonyos korlátozásokkal - az integer alaptípusból származtatott intervallumtípus, vagyis érvényes rá a következő "rejtett" definíció:
Type
byte=0..255;
Az intervallum típusú adatokra is alkalmazható az ord, a pred és a succ függvény. E függvények értékképzése az alaptípuson belül megy végbe.
Példák:
A Hue típusdefiníció
type Colour=(Red,Blue,Green,Yellow,Orange);
Hue=Blue..Yellow;
érvényességi tartományán belül érvényesek a következő összefüggések:
Kifejezés Eredmény ord(Blue) 1 succ(Yellow) Orange pred(Yellow) Green
Hangsúlyoznunk kell, hogy a felsorolási intervallumtípusok használata megnöveli a programok áttekinthetőségét és megkönnyíti "belövésüket", mert lehetővé teszi az adatok értéktartományának automatikus vizsgálatát. Ezekkel az adattípusokkal operatívtár-helyeket is megtakarítunk, ugyanis ha az alaptípus halmazelemeinek száma nem haladja meg a 255-öt, akkor a Turbo Pascal az adat tárolására csak egy bájtot használ fel. Hasonlóan takarékos az adatábrázolás, ha integer az alaptípus, és a két tartományhatár a [0,255] zárt intervallumba tartozik.
7.3. Értéktartomány-ellenőrzés
A Turbo Pascal nyelv fordítóprogramja lehetővé teszi, hogy a lefordított forrásprogram
végrehajtása közben megtörténjék a skalár típusú adatok értéktartomány-ellenőrzése.
Mivel ezek az ellenőrzések lelassítják a program futását, az alapértelmezés
szerint ki vannak kapcsolva, de a {$R+} direktívával bekapcsolhatók. A forrásprogram
azon részeiben, ahol ezek az ellenőrzések feleslegesek, a {$R-} direktívával
kikapcsolhatók. Az értéktartomány-ellenőrzés csak a fordítóprogramnak szóló
direktívák között álló értékadó utasítás idejére marad bekapcsolva.
Példa az értéktartomány-ellenőrzésének be- és kikapcsolására:
Program Check;
type Figure=(Square,Circle,Diamond,Triangle);
var Shape: Figure;
begin
Shape:=Circle;
Shape:=Figure(4);
{$R+}
Shape:=succ(triangle);
{$R-}
Shape:=pred(Square)
end.
8. Karakterlánc-típusok
A karakterlánc változó hosszúságú karakteres típust jelent, azaz értékül egy karaktersorozatot vehet fel, amelynek maximális hossza rögzített. A tárolt karaktersorozat hossza 0-zól a felső értékig terjedhet, amelyet előre definiálni kell.
A karakterlánc-típusok mindegyike összetett típus. Egy karakterlánc-típus definiálásakor
meghatározzuk az e típushoz tartozó változó maximális karakterszámát. Minden
karakterlánc-típushoz karaktersorozatok halmaza kapcsolódik. A halmaz elemei
az üres karakterlánc és mindazok a karaktersorozatok, amelyek hosszúsága nem
lépi túl a (definícióban meghatározott) maximális karakterszámot. A Turbo Pascal minden karakterlánchoz egy külön bájtot rendel (0-s indexszel), ahol megőrzi a tárolt karakterek aktuális darabszámát. (A karakterek számával a szövegfüzér hosszát jellemezzük.) Mivel egy bájtba írható maximális érték 255, egy karakterlánc-változó 255-nél több karaktert nem tartalmazhat.
A karakterlánc-típus leírása a string kulcsszóból és az azt követő, szögletes
zárójelekbe foglalt maximális karakterszámból áll. E szám kifejezhető egy integer
típusú konstanssal vagy egy ilyen konstanssal egyenértékű konstansnévvel.
Szintaxis:
string [méret]
Példák:
type
Cities=string[20];
Names=string[12];
A karakterlánc típusú adatok az adott típus maximális karakterszámánál eggyel több bájtot foglalnak le a tárban. Ez a plusz bájt tartalmazza a karakterlánc pillanatnyi hosszát. Ebből következik, hogy egy karakterlánc 255 karakternél hosszabb nem lehet.
8.1. Karakterláncok összefűzése
Két karakterlánc a konkatenáció-operátorral egy lánccá fűzhető össze. Az operátor
jele a + karakter, amely tetszőleges típusú karakterlánc-párokat fűzhet össze.
A művelet eredménye olyan karakterlánc, amely az első karakterlánc összes karakteréből
és az utána következő második lánc összes karakteréből áll. Követelmény, hogy
az összefűzés eredményeképpen keletkező karakterlánc ne legyen hosszabb 255
karakternél.
Példák:
Kifejezés Eredmény 'jan'+'ewa' 'janewa' '5'+'.'+'4' '5.4' 'j'+''+'b' 'jb'
8.2. Relációk
Két karakterlánc a relációs operátorokkal hasonlítható össze. A relációs operátorok
a következők: = (egyenlő), <> (nem egyenlő), > (nagyobb),< (kisebb),
>= (nagyobb vagy egyenlő), <= (kisebb vagy egyenlő). A relációs operátorok
elsőbbsége kisebb az összefűző operátor elsőbbségénél. Ez teszi lehetővé olyan
kifejezések szerkesztését, mint pl. jan'= j'+ 'an'- zárójelek használata nélkül.
Két karakterlánc akkor egyenlő, ha azonos a hosszúságuk és azonos karakterekből
állnak. Ha nem egyenlőek, akkor a karakterlánc-összehasonlítás helyett az első
egymásnak megfelelő, de eltérő karaktereket hasonlítjuk össze. Ha nincs ilyen
karakterpár, mert az egyik karakterlánc a másiknak a kezdőrésze, akkor az a
karakterlánc kisebb, amelyik rövidebb.
Példák:
Kifejezés Eredmény 'A'>'B' false 'jan'>'Jan' true ''<char(0) true ''='' true 'Jan'<='Jane' true '2599'<'270' true
8.3. Értékadás
Egy karakterlánc típusú változó az értékadó utasítással kaphat értéket. Az értékadó
szimbólum jobb oldalán tetszőleges; karakterlánc típusú kifejezés áll, a szimbólum
bal oldalán pedig egy karakterlánc típusú változó neve. Ha a kifejezés által
képviselt karakterlánc hosszabb, mint a változóban ábrázolható lánc, akkor az
értékadás balról jobbra megy végbe, a többletkarakterek elhagyásával.
type
Name=string[7]
var
FirstName,LastName:Name;
...
FirstName:='Jan';
LastName:=:'Bielecki'
8.4. Karakterlánc-függvények
és -eljárások
A karakterláncokon végezhető műveleteket bővítik a karakterlánc-függvények és
-eljárások. Használatuk nagyban megkönnyíti a karakterlánc típusú adatok kezelését.
A Length függvény
Hívása: Length(Str)
A Str egy karaktersorozatot képviselő karakterlánc típusú kifejezés. A Length
függvény eredménye e karaktersorozat hosszát (karaktereinek számát) jelentő,
integer típusú adat.
Példa:
Length('jb') = 2
A Str eljárás
Hívása: Str(Val,Var)
Az első paraméterben megadott (byte, integer vagy real típusú) számot karakterlánccá alakítja. A Val aritmetikai kifejezés, a Var pedig egy karakterlánc típusú változó neve.
Az Str eljárás végrehajtásakor a Var változó új értéket kap, mégpedig a Val
kifejezés által képviselt adat számértékét, karakterlánc formájában. Ha a Val
kifejezés integer típusú, akkor a keletkező karaktersorozat olyan egész számot
ábrázol, amely a legkevesebb számjegyet tartalmazza.
Ha közvetlenül a Val kifejezés után :m alakú módosító tag is van, ahol az m
integer típusú kifejezés, akkor a Val képviselte adat átalakításából kapott
karakterlánc m hosszúságú lesz. A keletkező számjegysorozat jobbra igazítottan
jelenik meg a karakterláncban. Ha a számérték nem ábrázolható m számú karakterben,
akkor az m értéke automatikusan annyival nő, amennyi a szám ábrázolásához kell.
Példák (Feltételezzük, hogy a StrVar típusa string[4].)
Hívás | Karakterlánc | StrVar |
Str(45,StrVar) | 45 | '45' |
Str(-250,StrVar) | -250 | '-250' |
Str(45:3,StrVar) | b45 | '45' |
Str(45:5,StrVar) | bbb45 | ' 4' |
Str(-2:5,StrVar) | bbb-2 | ' -' |
Ha a Val kifejezés real típusú, akkor a mintasorozat a következő
alakú:
bsd.ddddddddddEsdd
ahol b egy szóköz (space karakter), s a mantissza vagy az exponens (kitevő)
előjele és d a számjegy. A mantissza előjelét egy szóköz vagy egy - (mínusz)
karakter, az exponens előjelét pedig egy + vagy - (mínusz) karakter ábrázolja.
Ha közvetlenül a Val kifejezés után :m alakú módosító tag is van, ahol az m
integer típusú kifejezés, akkor a Val képviselte adat átalakításából kapott
karakterlánc m hosszúságú lesz. A keletkező számjegysorozat jobbra igazítottan
jelenik meg a karakterláncban. Ha a számérték nem ábrázolható m számú karakterben,
akkor a bemutatott mintasorozatból elmaradnak a vezető szóközök; ha ez nem elegendő,
akkor csökken a mantissza számjegyeinek száma (legfeljebb két számjegyig). Ekkor
az eredmény kerekítve jelenik meg.
Példák (Feltételezzük, hogy az Exp értéke 45.678E1, a StrVar típusa pedig string[10].)
Hívás | Karakterlánc | StrVar |
Str(Exp:9,StrVar) | 4.568E+02 | '4.568E+02' |
Str(Exp:8,StrVar) | 4.57E+02 | '4.57E+02' |
Str(Exp:7,StrVar) | 4.6E+02 | '4.6E+02' |
Str(Exp:6,StrVar) | 4.6E+02 | '4.6E+02' |
Str(Exp:10,StrVar) | 4.5678E+02 | '4.5678E+02' |
Str(Exp:11,StrVar) | 4.56780E+02 | '4.56780E+0' |
Ha közvetlenül a Val kifejezés után :m:n alakú módosító tag is van, ahol m és n integer típusú kifejezés, akkor a keletkező karakterlánc - jobbra igazítva - m hosszúságú lesz, és az m értékétől függetlenül egy n hosszúságú törtrésszel rendelkező, fixpontos, kerekített számkonstansként jelenik meg. Ha a számérték nem ábrázolható m számú karakterben, akkor az m értéke automatikusan annyival nő, amennyi a szám ábrázolásához kell.
A Val eljárás
Hívása: Val(Str,Var,Rep)
Az első paraméterben megadott szövegfüzért integer vagy real típusú számmá alakítja. Az Str karakterlánc típusú kifejezés, a Var integer vagy real típusú változó,
a Rep pedig integer típusú változó. A Val eljárás végrehajtásakor a Var változó
új értéket kap, mégpedig a Str kifejezés által képviselt, karakterlánc típusú
adat számértékét. Ez az adat nem kezdődhet és nem végződhet szóközökkel. Ha
a Var változó integer típusú, akkor a konvertálandó számnak is integer típusúnak
kell lennie. Ha a konverzió elvégezhető, akkor a Rep változó 0 értéket kap,
különben az új értéke olyan pozitív szám, amely sorszáma annak a karakternek
(a konvertálandó karakterláncban), amelyik leállította a konverziót. Ekkor a
Var változó nem kap új értéket.
Példák (Feltételezzük, hogy az IntVar és az IntRep integer típusú változó.)
Hívás | IntVar | IntRep |
Val(23,IntVar,IntRep) | 23 | 0 |
Val('23.0',IntVar,IntRep) | változatlan | 3 |
Val(-200,IntVar,IntRep) | változatlan | 5 |
Ha a futó programban számot kérünk be, de string típusú adatot ad meg a felhasználó, a program hibaüzenettel leáll. A Val eljárással megvalósítható a bolondbiztos adatbevitel, ha előbb string típusú adatot olvasunk be:
repeat
Write('Input an integer: ');Readln(inp);
Val(inp,nr,k);
until k=0;
A Copy függvény
Hívása: Copy(Str,Pos,Num)
Visszaadja az első paraméterből kimásolt részsztringet. A Str karakterlánc típusú kifejezés, a Pos és a Num pedig integer típusú változó.
A Copy függvény eredménye olyan karakterlánc típusú adat, amely az Str karakterlánc
Pos pozíciójától kezdve Num számú karakterből áll. Ha Pos > Length(Str),
akkor a függvény eredménye egy üres karakterlánc. Ha (Pos+Num) > Length(Str),
akkor az eredmény úgy alakul, mintha a Num értéke csak Length(Str)-Pos+1 lenne.
Pos értéke nem lehet 1-nél kisebb és 255-nél nagyobb.
Példák:
Kifejezés Eredmény Copy('Pascal',3,4) 'scal' Copy('Pascal',5,3) 'al' Copy('Pascal',7,2) '' Copy('Pascal'2,1) 'a'
A Concat függvény
Hívása: Concat (St2, . .
., Stk)
A paraméterként megadott sztringekből összefűzött karakterláncot adja vissza. A St,St2,...,Stk karakterlánc típusú kifejezés. A Concat függvény eredménye
a St,+St2+...+Stk karakterlánc típusú adat. A függvény argumentumainak teljes
hossza nem lépheti túl a 255-öt.
Példák:
Kifejezés Eredmény Concat('j','a','n') 'jan' Concat('j','','b') 'jb' Concat('jan',' ','b') 'jan b'
A Pos függvény
Hívása: Pos (Src, Trg)
Visszaadja az első paraméterben megadott részsztring kezdőpozícióját a második paraméterben megadott sztingben. Az Src és a Trg karakterlánc típusú kifejezés. A Pos függvény eredménye egy
integer típusú adat, amely a Trg karakterláncban azt a karakterpozíciót határozza
meg, amelytől kezdve az Src tartalmával azonos karakterek következnek. Ha az
Src karakterlánc nem fordul elő a Trg-ben, akkor a függvény eredménye 0.
Példák:
Kifejezés Eredmény Pos('23','123123') 2 Pos('21','123123') 0 Pos('c','abcabc') 3 Pos(",'Pascal') 0
Az Insert eljárás
Hívása: Insert (Src, Trg,
Pos)
Az első paraméterben megadott sztringet beékeli a második paraméterében megadott sztringbe a harmadik paraméterben definiált pozíciótól kezdve. Az Src karakterlánc típusú kifejezés, a Trg karakterlánc típusú változó, a Pos
pedig egy integer típusú kifejezés. Az Insert eljárás beszúrja a Trg képviselte
karaktersorozatba - a Pos pozíciójú karakter elé - az Src karakterlánc tartalmát.
Ha Pos > Length( Trg), akkor feltételezzük, hogy Pos:= Length(Trg)+1. Pos
értéke nem lehet 1-nél kisebb és 255-nél nagyobb. Ha a karakterek beszúrása
a Trg változó maximális méretének túllépését okozná, akkor a jobb oldali többletkarakterek
elvesznek.
Példák
(Feltételezzük, hogy a Trg változó típusa string[5], értéke pedig - az Insert
eljárás mindenkori hívása előtt - jb'.)
Kifejezés Eredmény Insert('an',Trg,2) 'janb' Insert('jb',Trg,4) 'jbjb' Insert('Janek',Trg,1) 'Janek'
A Delete eljárás
Hívása: Delete (Str,Pos,Num)
Az első paraméterben magadott szövegfüzérből karaktereket töröl. A Str karakterlánc típusú változó, a Pos és a Num pedig integer típusú változó.
A Delete eljárás a Pos pozíciójú karaktertől kezdve Num számú karaktert töröl
a Str képviselte karaktersorozatból. Ha Pos > Length(Str), akkor nem történik
semmi. Ha Pos+Num-1 > Length (Str), akkor az eredmény úgy alakul, mintha
a Num értéke Length(Str)-Pos+1 lenne. Pos értéke nem lehet 1-nél kisebb és 255-nél
nagyobb.
Példák
(Feltételezzük, hogy a Trg változó típusa string[5], értéke pedig - az Insert
eljárás mindenkori hívása előtt - 'janek'.)
Kifejezés Eredmény Delete(Trg,4,2) 'jan' Delete(Trg,6,1) 'janek' Delete(Trg,5,3) 'jane'
8.5. Karakterlánc- és karaktertípusok
Valamennyi karakterlánctípus megfelel a rendezett char típusnak. Ez azt jelenti,
hogy a program mindazon helyein, ahol megengedett a karakterlánc típusú kifejezés
használata, használható a char típusú adat, és fordítva. Csak az a követelmény,
hogy amikor egy char típusú változónak értéket adunk, az értékadó szimbólum
jobb oldalán álló karakterlánc típusú adat 1 karakter hosszúságú legyen. A karakterlánc
típusú változó egyes karaktereihez nemcsak az előre definiált Copy függvénnyel
férhetünk hozzá, hanem - sokkal egyszerűbben - indexeléssel is. Az indexelés
definíciójának elfogadhatjuk a következő azonosságot:
St[i]=Copy(St,i,1)
Ez az azonosság csak akkor igaz, ha teljesül az 1 <= i < Length(St) feltétel.
Ezen az intervallumon kívül megengedett az operatív tár szomszédos bájtjainak
elérése, különösen az ord(St[0]) kifejezés esetén, amely megadja az St által
képviselt karakterlánc hosszúságát.
Megjegyzés: a {$R+} direktíva használata csak kismértékben teszi lehetővé a
helytelen indexeléssel kapcsolatos hibák kiderítését. Ez abból ered, hogy a
direktíva bekapcsolja ugyan a - deklarációból ismert - maximális index túllépésének
vizsgálatát, de nem vezeti be a pillanatnyi mérettúllépés ellenőrzését.
Példa:
Var
Name:string[5];
...
Name:='Jan';
{$R+}
Name[0]:=chr[5];
Name[4]:='e';
Name[5]:='k';
9. Tömbtípusok
A tömbtípusok mindegyike összetett típus. A tömb meghatározott számú, azonos
típusú komponensből (elemből) áll. A komponensek akár elemi, akár összetett
típusúak lehetnek. A tömbelemek indexeléssel érhetők el. Az index szögletes
zárójelekkel körülvett, tetszőleges skalárkifejezés, melynek megengedett értéktartományát
a tömbtípus leírása határozza meg.
A tömbtípus leírása az array kulcsszóból, az azt követő, szögeletes zárójelekbe
foglalt indexleírásból, az of kulcsszóból és a komponensek típusleírásából
áll.
Szintaxis:
array [indextípus] of elemtípus
indextípus:
rendezett-típus-leírás
elemtípus:
típusleírás
Az indextípus csak sorszámozott típus lehet, minden értékére létezik egy jól meghatározott tömbelem. Az elemek számát a tömbben az indextípus számossága határozza meg. Az elemek bármelyike közvetlenül elérhető az indexre való hivatkozással.
Példák:
var tc:array[1..15] of char;
tb:array['A'..'Z'] of byte;
tn:[-5..5] of integer;
Egy összetettebb példa:
Type
Color=(Red,Green,Blue);
TruthTable=array[boolean] of boolean;
Height=0..200;
Var
Square:array[Color] of Height;
Matrix:array[2..8] of array[2..8] of integer;
Table:TruthTable;
Korlátozás, hogy a tömbök definiálásakor sem változót, sem kifejezést nem használhatunk a határértékek jelölésére (csak konstanst), azaz a tömbök méretét előre meg kell határozni. Ennek magyarázata, hogy a fordító minden változónak, így a tömböknek is, előre - még a futás előtt - lefoglalja a helyét a tárban. (Ezért van szükség az előzetes változó-deklarációra is.) Minden tömb a memória egy-egy folytonos területén helyezkedik el. Az egydimenziós tömb esetén az elemek egyszerűen az indexek növekvő sorrendjében követik egymást.
A tömbelemeket a programokban tömbelem-nevek képviselik. A
tömbelem neve a tömbnévből és az azt követő, szögletes zárójelekkel körülvett
indexkifejezésből áll. Az indexkifejezés tetszőleges rendezett típusú kifejezés,
típusa a tömbtípus leírásában szereplő "indextípus"-sal egyezik meg.
A ($R+} direktíva használata olyan kódgenerálást eredményez, mely lehetővé teszi
az indexkifejezések helyességének vizsgálatát. A vizsgálat során a rendszer
ellenőrzi, hogy az indexkifejezés értéke a tömbtípus leírásában szereplő indextípus
értéktartományán belül van-e. Ha a fordító $R+ (bekapcsolt) direktíva mellett végzi a program fordítását, akkor a kódba ellenőrzést épít be, és indexelés előtt a program végzi el a vizsgálatot: beleesik-e az index az indextartományba. Ez az ellenőrzés ugyan némileg megnöveli a program kódját és a futási idejét, de elkerülhetők az alattomos hibák! Ha a vizsgálatot mi végezzük el, akkor elkerülhetjük a programleállást. Ha a program kiállta a tesztelési próbákat, akkor az indexhatár-ellenőrzést kikapcsolhatjuk - így a program végső változatát nem lassítják a felesleges ellenőrző kódok.
Példa:
Type
Color=(Red,Green,Blue);
var
Matrix:array[Color] of boolean;
9.1. Többdimenziós tömbök
A tömb egy olyan összetett adatstruktúra, melyben azonos típusú elemeket tárolunk. Eddig ezeket az elemeket egyetlen index különböző értékeihez rendeltük hozzá (egydimenziós tömb). Nem mindig kényelmes azonban az összes elemet folyamatosan indexelni. Sok esetben az adathalmaz elemeit nem sorosan látjuk, hanem pl. egy táblázat elemeit kétszintű (oszlop, sor) indexeléssel határolhatjuk be. Ilyenkor kétdimenziós dömböt deklarálunk:
tm:array[1..10] of array[1..15] of integer;
Ugyanez egyszerűbben:
tm:array[1..10,1..15] of integer;
Mivel egy tömbelem tömb is lehet, könnyű létrehozni két- és többdimenziós tömböket. A szintaxisnak megfelelően, egy kétdimenziós tömböt leíró típus definíciója a következő alakú:
Type TwoDim=array[2..5] of array [boolean] of real;
Ezt a definíciót egyszerűsítve is felírhatjuk:
Type TwoDim=array[2..5,boolean] of real;
vagyis az indextípusok leírása szögletes zárójellel körülvett listát alkothat. Hasonló egyszerűsítéssel élhetünk a tömbelem-nevek esetén; pl. a
Var Matrix:TwoDim;
deklaráció érvényességi körén belül helyesek és egyenértékűek a következő nevek
(amelyek a Mátrix tömb elemei): Matrix[3][true] és Matrix[3,true].
A tömb tárolása a memóriában sorfolytonosan történik. Először az 1. sor kerül tárolásra, melyet a második sor követ, stb..
Példa:
type
Pupils=string[20];
Class=array[1..30] of Pupils;
var
School:array[1..20] of Class;
Turbo Pascal-ban nincs korlátozva hány dimenziós tömböt hozhatunk létre, egyetlen határ a memória mérete.
9.2. Karaktertömbök
A karaktertömb olyan egydimenziós tömb, amelynek indexe integer típusú, elemei
pedig standard char típusúak. A karaktertömbök olyan karakterlánc típusú változónak
tekinthetők, amelyek állandó hosszúságú karaktersorozatokat képviselnek. Ennek
az értelmezésnek köszönhetően a karaktertömbök és az elemek neve a karakterlánc
típusú kifejezésekben mindazon helyeken előfordulhat, ahol egyébként karakterlánc
típusú változók állnak. Ez különösen a relációkra érvényes.
Példa:
Type
Number=2..5;
StrTyp=string[5];
ArrTyp=array[Number] of char;
var
StrVar:StrTyp;
ArrVar:ArrTyp;
i:byte;
begin
for i:=2 to 5 do
ArrVar[i]:=chr(63+i);
StrVar:='98765';
StrVar:=Copy(StrVar,2,2)+ArrVar+'/'+ArrVar[4];
end;
9.3. Értékadások
Összhangban azzal a szabállyal, miszerint tetszőleges típusú változó egyetlen
utasítással megkaphatja az azonos típusú adat értékét, egyetlen utasítással
egy teljes tömb értékét is átadhatjuk a tömbváltozónak. Megengedett egy karakterkonstans
értékének átadása is, de csak akkor, ha a konstans karaktereinek száma egyenlő
a tömb méretével. A tömböknek más karakter típusú kifejezés értéke nem adható
át. A karakterlánc típusú változók viszont értéket kaphatnak karakterlánc típusú
kifejezésektől és karaktertömböktől egyaránt.
Példa:
Type
Line=string(60);
Page=array[1..30] of Line;
Chapter=array[1..50] of Page;
Word=array[1..5] of char;
Var
Book1,Book2:array[1..6] of Chapter;
Arr:Word;
Brr:array[1..5] of char;
Str:string[5];
9.4. Előre definiált tömbök
A Turbo Pascal nyelvben a 8 bites mikroszámítógépek számára előre definiáltak
két tömböt, amelyek byte típusú elemekből állnak. E tömbök segítségével hozzáférhetünk
az operatív tárhoz és a bemeneti, ill. kimeneti portokhoz.
A Mem tömb
A Mem tömbbel hozzáférhetünk az operatív tár bájtjaihoz. A tömbhivatkozásban
szereplő index integer típusú kifejezés, amely meghatározza a bájt tárcímét.
Példa:
ByteVar:=Mem[200]
Mem[300]:=$FF
A Port tömb
A Port tömbbel hozzáférhetünk a bemeneti, ill. kimeneti portokhoz. A tömbhivatkozásban
szereplő index integer típusú kifejezés, amely meghatározza a port címét. A
Port tömb elemei nem lehetnek alprogram-paraméterek; de előfordulhatnak kifejezésekben
és az értékadó szimbólum bal oldalán. A kifejezésben a megadott portról származó
adatokat jelentik, az értékadó szimbólum bal oldalán pedig azt eredményezik,
hogy az adat a megadott portra íródik.
Példa:
Port[34]:=$5F
PortStatus:=Port[35]
10. Rekordtípusok
A rekord a legrugalmasabb Pascal adatszerkezet, mivel benne tetszőleges számú, különböző tulajdonságú (típusú) rész szerepelhez. Rugalmasságát tovább növeli az a lehetőség, hogy egy megadott feltételtől függően más és más mezői lehetnek. A rekordtípusok mindegyike összetett típus. A rekord meghatározott számú, nem
feltétlenül azonos típusú komponensből áll. A komponensek akár elemi, akár összetett
típusúak lehetnek. A rekordelemek, melyeket mezőknek is nevezünk, szelekcióval
(kiválasztással) érhetők el. Kiválasztáskor megadjuk a rekord nevét, a . (pont)
karaktert és a rekordmező azonosítóját.
A rekordtípus leírása a record kulcsszóból, a rekordmezők listájából
és az end kulcsszóból áll. A lista minden eleme egy-egy meződeklaráció.
A meződeklarációkat pontosvessző választja el egymástól; a lista utolsó eleme
lehet a változó rekordrész. A rekordtípus rugalmasságát növeli az a lehetőség, hogy a megadott feltételtől függően más és más mezői lehetnek. A változó rekordrész a case kulcsszóból,
az azt követő vezérlőmező-deklarációból (vagy vezérlőtípus-leírásból), az of
kulcsszóból és a változatlistából áll. A változatlista minden eleme a kiválasztási
címkék listájából (melyet kettőspont követ), valamint a kerek zárójelekkel körülvett
változatmezők listájából áll. A változatlista egyes elemeit pontosvessző választja
el egymástól.
Szintexis:
rekodtípus_leírás:
record rekordmező-lista end
rekordmező-lista:
meződeklaráció
változó_rekordrész
meződeklaráció:
mezőnévlista : típusleírás
mezőnév:
azonosító
változó_rekordrész:
case vezérlőmező-deklaráció of változatlista
case vezérlőtípus-leírás of változatlista
vezérlőmező-deklaráció:
vezérlőmező-név : vezérlőtípus-leírás
vezérlőmező-név:
azonosító
vezérlőtípus-leírás:
rendezett-típus-azonosító
változatlista:
kiválasztásicímke-lista: (változatmezők_listája)
kiválasztási_címke:
konstans
konstansnév
Példák:
type
Days=1..31;
Date=record
Day:Days;
Month:1..12;
Year:1900..1999
end;
Person=record
Name:string[20];
BirthPlace:string[30];
case Sex:(male,female,alien) of
male,female:(BirthDate:Date);
alien:(BirthDate:real;
BodyData:record
H:integer;
W:real
end)
end;
var
MyBirthDay:Date;
EarthMan,Galaxian:Person;
A rekord elemeire (mezőire) úgy hivatkozhatunk, hogy a rekordváltozó neve után ponttal elválasztva írjuk a mező azonosítóját. Pl.:
Date.Years:=1973;
Date.Month:=12;
Date.Days:=24;
Több rekordtípusban is szerepelhet egyazon mezőnév, de egy rekordon belül a mezőnévnek egyedinek kell lennie.
10.1. A with utasítás
A rekordkomponensekre hivatkozás nemcsak a mezőnév megadását igényli, hanem
a rekord névét is. Mivel ez bizonyos esetekben számottevően meghosszabbítja a
program szövegét, kényelmes a with összekötő utasítás, amely mintegy "kitakarja"
a rekordtípus-definíció belsejét.
Általános esetben a with utasítás a with kulcsszóból, az azt követő rekordnévlistából,
a do kulcsszóból és egy tetszőleges utasításból áll. Az utasításon belül a listában
szereplő rekord mezőinek kiválasztása a mezőnévvel helyettesíthető. A mezők ekkor automatikusan a with utasításban megadott rekordváltozóhoz tartoznak. Definíciószerűen
elfogadjuk, hogy a
with a,b,..., z do i
alakú utasítás egyenértékű a
with a do
with b do
...
with z do i
utasítással.
Példa:
Var
Alfa:record
Beta:record
Gamma:char;
Delta:real
end;
Gamma:integer
end;
Beta:array[boolean] of record
Chi,Tau : real
end;
10.2. Változatok (unionok)
Gyakran kényelmes és természetes, ha ugyanaz a tárterület hol ilyen, hol olyan adatcsoportot tud tárolni. A Turbo Pascal lehetőséget ad a változó rekordok deklarálására. Ilyenkor a rekord első része egy állandó (fix) rész, melyet különböző változatok leírása követ. A rekord fizikai hosszát (a foglalt memóriahelyet) a leghosszabb változat határozza meg. A programból bármikor bármelyik változatra hivatkozhatunk, a helyes adattárolásra és hivatkozásra a programozónak kell figyelnie. Ha a rekordban változatok vannak, akkor a Turbo Pascalban elfogadott belső ábrázolás
szerint minden változat első mezője ugyanazon a memóriacímen kezdődik. Mivel
a vezérlőmező deklarációja típusleírássá egyszerűsíthető, a rekordleírást könnyű
átalakítani olyan szerkezet leírásává, amelyet a C nyelvben unionnak hívnak.
Tudnunk, kell azonban, hogy a rekordokon végzett műveletektől eltérően az unionokon
végrehajtott műveletek megkövetelik a komponensek ábrázolásának - vagy legalább
tárolásának és méretének - ismeretét. A rekord fizikai hosszát (a foglalt memóriahelyet) a leghosszabb változat határozza meg. A programból bármikor bármelyik változatra hivatkozhatunk, a helyes adattárolásra és hivatkozásra a programozónak kell figyelnie.
A változó rekord szintaktikája:
Type TRekord = Record
Mezőlista
Case Változó: Típus of
Érték1: (Mezőlista1);
Érték2: (Mezőlista2);
...
end;
A Mezőlista és Változó együttesen határozzák meg a rekord állandó részét, melyet a rekord változó része követ. Mezőlista1, Mezőlista2, stb. mezői egymásra vannak definiálva. Az egyes mezőlisták mezőire ugyan bármikor lehet hivatkozni, de fontos, hogy az aktuális hivatkozás megfeleljen a konkrét adatnak. A Változó ennek segítését célozza: e szelektormező értékétől függ, hogy melyik mezőlista van érvényben.
Például:
Type TFajta = (Tegla,Kor);
TIdom = Record
Terulet: Real;
Case Fajta: TFajta of
Tegla: (Alap,Magassag: real);
Kor: (Sugar: real);
end;
var K: TIdom;
...
K.Fajta:= Kor;
K.Sugar:=3.9;
K.Terulet:=Sqr(K.Sugar)*Pi;
Területe minden idomnak van, de míg a téglának alapja és magassága, addig a körnek sugara. A rekord hosszúságát a változó rész hosszabbik ága, jelen esetben a tégla határozza meg. A teljes hosszúság: Terület+Fajta+Alap+Magasság = 19 (6+1+6+6) byte.
Előfordulhat, hogy az adattartalomtól függetlenül szeretnénk többféleképen hivatkozni az adatokra. Ekkor nem adunk meg szelektormezőt, csak egy típust. Példaként olvassunk be egy számot és írjuk ki a Szám div 256 és a Szám mod 256 értékeit. Ismeretes, hogy a tárolt integer-nek előbb az alsó, majd a felső byte-ja kerül tárolásra:
type TRekord=record
case boolean of
false:(egesz:integer);
true:(also,felso:byte);
end;
var r:trekord;
begin
readln(r.egesz);
writeln(r.felso:3,r.also:3);
end.
Példa:
Var
Word:record
case boolean of
false: (LowByte,HighByte:byte);
true: (FullWord:integer)
end
10.3. Rekordértékadás
A tömbváltozókhoz hasonlóan megengedett, hogy egy rekord típusú változó az egész
rekord értékét megkapja egy utasítással. Egyetlen követelmény, hogy a rekordváltozó
típusa azonos legyen az értékadó rekord típusával.
Példa:
Type
Name=record
LastName:string[32];
Names:array[(fst,snd,trd)] of string[8]
end;
var
JohnName,EwaName:Name;
...
EwaName:=JohnName;
11. Halmaztípusok
A halmaz bizonyos tulajdonságú elemek összessége. A Pascal nyelv speciális lehetőségei közé tartozik a halmazok nyelvi szinten történő támogatása. A halmaztípusok mindegyike összetett típus. A halmazváltozó olyan változó, amely
egy hatványhalmaz részhalmazától kaphat értéket. A hatványhalmaz alaphalmaza
rendezett típusú elemek tetszőleges halmaza. A halmazváltozó elemeinek mindegyike
ilyen elem.
Két halmaz típusú adat akkor és csak akkor egyenlő, ha azonos elemekből áll.
Ha az egyik halmazváltozó minden eleme egyben eleme a másik halmazváltozónak,
akkor azt mondjuk, hogy az első változó részváltozója a másiknak.
Halmazok esetében több fogalomról beszélhetünk, ezekről az alábbiakban néhány alapvető fogalmat leírunk, természetesen a teljesség igénye nélkül, mivel a halmazok elmélete egy külön tudományág.
A halmaztípus leírása a set kulcsszóból, az azt követő of kulcsszóból és az alaptípus leírásából áll. Az alaptípusként felfogható rendezett típus nem tartalmazhat 256 elemnél többet, és az elemek mindegyikére alkalmazott ord függvény értékének a [0,255] zárt intervallumhoz kell tartoznia.
A halmaz deklarásakor meg kell adni az alaphalmazt, vagyis az alaptípust.
Szintaxis:
halmaztípus-leírás:
set of alaptípus
alaptípus:
rendezett_típus
Példák:
type
DaysOfWeek=set of (Mon,Tue,Wed,Thu,Fri,Sat,Sun);
Chars=set of char;
SmallLetters=set of 'a'..'z';
DayNumbers=set of 1..31;
11.1. Halmazkonstansok
Egy halmazkonstans szögletes zárójelekkel körülvett, azonos (rendezett) típusú
konstansok listájából áll. A lista lehet üres, tartalmazhat ismétlődő elemeket,
ill. min..max alakú szerkezeteket, ahol a min és a max azonos típusú konstans.
Ekkor a min..max egyenértékű a min-től a max-ig terjedő összes konstanssal,
a határértékeket is beleértve. Ha min nagyobb mint max, akkor üres részhalmazról van
szó.
Megjegyzés: a halmazkonstans értéke nem függ az őt alkotó alap típusú konstansok
sorrendjétől; többszörös fellépésük nem befolyásolja a halmazkonstans értékét.
Példa:
11.2. Kifejezések
A halmazkifejezések a következő alkotóelemekből tevődnek össze: halmazváltozókra,
-konstansokra, -szerkezetekre való hivatkozások, valamint az unió, a különbség
és a metszet operátorai.
A halmazszerkezetek a halmazkonstansokhoz hasonló alakúak, azzal a különbséggel,
hogy a listájukon szereplő elemek nemcsak az alaptípus konstansai, hanem ilyen
típusú tetszőleges kifejezések is lehetnek. A halmazműveleteket két csoportra osztjuk. Az első csoport az ún . Boole-algebra műveleteit tartalmazza: A halmazunió-operátor jelölésére
a + karaktert, a különbségoperátor jelölésére a - (mínusz) karaktert, a metszetoperátor
jelölésére pedig a * karaktert használjuk.
A halmazok uniója olyan halmaz, amely mindkét összetevő összes elemét tartalmazza (az eredményhalmazban a közös elemek csak egyszer szerepelnek!).
A halmazok különbsége olyan halmaz, amely a kisebbítendő halmaz azon elemeiből
áll, melyek nem elemei a kivonandónak. A halmazok metszete olyan halmaz, amely
mindkét tényező közös elemeiből áll.
A halmazműveleteken kívül a következő relációkban
fordulhatnak elő halmaz típusú adatok:
a=b | igaz, ha a és b azonos elemek halmazai; |
a<>b | igaz, ha a és b különböző elemek halmazai; |
a<=b | igaz, ha a üres halmaz, vagy az a minden eleme egyben b eleme is; |
a>=b | igaz, ha b üres halmaz, vagy a b minden eleme egyben a eleme is; |
e in a | igaz, ha az e alap típusú elem az a halmaz eleme. |
Műveletek precedenciája:
Halmazt nem tudunk a WRITE utasítással kiírni. A halmaz kiírása úgy történik, hogy az alaphalmaz összes eleméről levizsgáljuk, benne van-e a megadott halmazban. Ha igen, akkor kiírjuk. Mivel az alaphalmaz minden esetben sorszámozott típus, a kiíratást egy növekményes ciklussal elvégezhetjük. A ciklus természetéből adódik a kiírt elemek rendezettsége.
Példák:
Var h1,h2: set of byte;
...
h1:=[1,2,6];
h2.=[1,4..7];
A fenti értékadások után a h1 és h2 halmazokon végzett műveletek eredményei:
h1+h2 = [1,2,4..7]
h1*h2 = [1,6]
h1-h2 = [2]
A SetVar változódeklaráció érvényességi körén belül (feltételezve, hogy a változó jelenlegi értéke a [Red,Green] konstans által képviselt halinaz típusú adat):
Type
Colors=(Red,Green,Blue);
Paint=set of Colors;
Var
SetVar:Paint;
...
SetVar:=[Red,Green];
igazak a következők kifejezések:
SetVar=[Red..Blue]-[Blue]
SetVar<>[]
SetVar<=[Red..succ(Green)]
SetVar>=[BLue..Green]
SetVar*[Red]=[Red]
Green in SetVar
11.3. Halmazértékadás
Az értékadás bal oldalán egy halmazváltozó áll, jobb oldalon pedig egy halmaz típusú kifejezés. A kifejezés operandusai halmazkonstansok, illetve halmazváltozók, operátorai pedig halmazműveletek.
Példák:
Var
h:set of byte
b.byte;
...
b:=3;
h.=[b+2];
h:=[1,10..24]+h;
h:=[0..25]-h;
h:=h-[b,b+2,b*2,20..23];
h=[5]
h=[1,5,10..24]
h=[0,2,3,4,6..9,25]
h=[0,2,4,7..9]
A tömbváltozókhoz és a rekordokhoz hasonlóan megengedett, hogy egy halmaz típusú változó egy utasítással az egész halmaz értékét megkapja, de a halmazváltozó típusának azonosnak kell lennie az értékadó halmaz típusával.
Példa:
Var
SetVar:array[2..5, boolean] of set of 20..30;
SetVar[3,false]:=[5*5...pred(29)];
12. File-típusok
A fájltípusok mindegyike összetett típus. A fájl komponensekből áll, melyek
azonos típusúak. A fájl komponenseit elemeknek nevezzük. A tömbtípusoktól eltérően
egy fájl elemeinek számát nem határozzuk meg a fájldeklarációban, hanem a program
futásának eredményétől tesszük függővé (elsősorban attól, hogy a fájlt milyen
adatállományhoz rendeljük hozzá).
Hangsúlyozni kell, hogy a fájlnak nevezett objektum csupán elvont logikai modellje
annak a fizikai adatállománynak, amely leggyakrabban a programon kívül létezik.
A fizikai adatállományok - itt röviden állományok - helyet foglalhatnak a számítógép
háttértárában vagy operatív memóriájában, de azonosíthatók a külső berendezések
segítségével be- és kivihető adatfolyamokkal is.
A programozás szempontjából nagy egyszerűsítést jelent, hogy különböző állományok
ugyanazzal a fájllal dolgozhatók fel, ha hozzárendeltük őket egymáshoz. Így
a programozónak nem kell ismernie a konkrét operációs rendszer tulajdonságait,
sem a háttértárak adatszervezési és -tárolási megoldásait. Ezért a fájl szintű
programozás többnyire a fájl megnyitását, a fájl elemein végrehajtandó műveleteket
és a fájl lezárását jelenti.
Állományok használatára a Turbo Pascal alapvetően három lehetőséget kínál:
Típusos állomány:
Direkt szervezésű állomány. A kiírás, illetve beolvasás egysége a komponens. A komponensek egyforma típusúak, mely típus az állományra jellemző. A komponens hosszát a típus határozza meg. A komponensek sorszámozva vannak 0-tól. Akármelyik sorszámú elemre közvetlenül pozícionálhatunk, azt beolvashatjuk, illetve kiírhatjuk. A komponens helyét a rendszer a sorszám és a komponens hosszúsága alapján meg tudja határozni. A típusos állományt szekvenciálisán is feldolgozhatjuk a komponensek fizikai sorrendjében, vagyis a sorszámok szerint.
Elemtípus nélküli állomány:
Direkt szervezésű állomány. Abban különbözik a típusos állománytól, hogy itt a komponensek hosszúsága tetszőlegesen megadható, azt nem a típus határozza meg. Általában akkor használjuk, amikor csak az számít, hogy hány byte-ot írunk ki, illetve olvasunk be egyszerre - az adatok típusa érdektelen.
A Turbo Pascal legalapvetőbb állománytípusa a típusos állomány. A típusos fájlok olyan adathalmazok, amelyek azonos típusú adatelemekből épülnek fel. Az adatelemek azonos mérete lehetővé teszi, hogy az adatokat szekvenciálisan és közvetlen (direkt) módon egyaránt elérjük. Az elemek típusát (alaptípust) az állomány deklarálásánál meg kell adni: A fájltípus leírása a file kulcsszóból, az azt követő of kulcsszóból
és az elemtípus leírásából áll. A fájlelemek tetszőleges elemi típusúak, ill.
összetett típusúak lehetnek (kivéve a fájltípust).
Az elemek típusa meghatározza annak hosszát, ha például az elemek típusa integer, az állomány 2 byte-os, real típus esetén 6 byte-os egységekből áll. Az adatelemek azonos mérete lehetővé teszi, hogy az adatokat szekvenciálisan és közvetlen (direkt) módon is elérjük.
Szintaxis:
file-típus-leírás:
file of elemtípus:
elemtípus
típusleírás
Példák:
Type
Measurements=file of real;
Persons=file of Record
Name : string[20];
Sex:(male,female);
Age:18..65
end;
Var
Experiment:Measurements;
Population:Persons;
Complexes:file of record
Re,Im:real
end;
Arrays:file of array[2..6,4..8,boolean] of byte;
12.1. Alprogramok
A fájlokon végezhető műveletek kizárólag függvényekkel és eljárásokkal valósíthatók
meg. E műveletek végrehajtását meg kell előznie a fájl és az adatállomány egymáshoz
rendelésének, ha a művelet a fájl elemeire vonatkozik, akkor előzőleg a fájlt
meg kell nyitni. A fájlt és az adatállományt az Assign eljárás rendeli
egymáshoz; a fájlt a Reset és a Rewrite eljárás nyitja meg. A
Reset eljárás használata nem jelenti azt, hogy a fájlt csak olvasásra nyitjuk
meg; a Rewrite eljárás sem csak írásra nyitja meg a fájlt. A program befejezése
előtt minden fájlt le kell zárni: erre való a Close eljárás. A programfutás
befejezése nem jelenti a nyitott fájlok lezárását!
Közvetlenül a megnyitás után a fájl kezdeti pozícióban (az elején) áll. A fájlpozíciót
a Seek eljárással változtathatjuk. A fájl aktuális mérete a FileSize
függvénnyel, pozíciója pedig a FilePos függvénnyel határozható meg. Ha
a fájl közbenső pozícióban van (azaz a kezdeti és a végpozíció között), akkor
minden Write eljáráshívás a legközelebbi fájlelemet írja felül. Ez a
felülírás nincs hatással a fájl többi elemére, ezért az adott típusú elemekből
álló fájlok szekvenciális szervezésű adatállományokat képviselhetnek.
Az Assign eljárás
Hívása: Assign (FileVar,StrExp)
A FileVar egy fájlváltozó neve, a StrExp pedig egy karakterlánc típusú kifejezés.
A FileVar névvel azonosított fájl nem lehet nyitva. Az Assign eljárás végrehajtása
hozzárendeli a FileVar névvel azonosított fájlt a StrExp kifejezéssel meghatározott
adatállományhoz. StrExp egy állományspecifikáció, tehát a név a név és kiterjesztés előtt tartalmazhatja a lemezegység azonosítóját és az útvonalat is. Ez utóbbiak hiányában az állomány az aktuális lemezegység aktuális könyvtárára értendő.
Az adatállományokkal kapcsolatos műveleteknél mindig a logikai névre kell hivatkozni, de a művelet az összekapcsolás miatt mindig a megadott fizikai állományra vonatkozik.
Példa:
var Results:file of real;
...
Assign(Results,A:TEST,DAT');
A Reset eljárás
Hívása: Reset(FileVar)
A FileVar egy fájlváltozó neve. Az eljárás hívása előtt a FileVar névvel azonosított
fájlt egy létező adatállományhoz kell hozzárendelni. A Reset eljárás megnyitja
a FileVar névvel azonosított fájlt. A megnyitás kezdeti pozícióba (az első elem
elé) állítja a fájlt.
Példa:
Var InpFile:file of record
Name:string[30];
Income:real
end;
...
Assign(InpFile,'INCOME.DOC');
Reset(InpFile);
A Rewrite eljárás
Hívása: Rewrite (FileVar)
A FileVar egy fájlváltozó neve. Az eljárás hívása előtt a FileVar által képviselt
fájlt egy adatállományhoz kell hozzárendelni. A Rewrite eljárás megnyitja a
FileVar által képviselt fájlt. A megnyitás kezdeti pozícióba (az első elem elé)
állítja a fájlt. Ha a Rewrite hívása előtt a fájlhoz hozzárendelt állomány nem
létezett, akkor az eljárás végrehajtásakor létrejön. Ha pedig volt már ilyen
állomány, akkor törlődik és újra létrejön. Mindkét esetben egy üres adatállomány
keletkezik.
Példa:
Var OutFile:file of array[1..20] of byte;
...
Assign(OutFile,'B:TESTS.OUT');
Rewrite(OutFile);
A Read eljárás
Hívása: Read(FileVar,VarList)
A FileVar egy fájlváltozó neve, a VarList pedig egy változónév vagy változónév-lista.
A FileVar névvel azonosított fájlnak nyitottnak kell lennie. A VarL.ist változó(k)
csak a fájltípussal azonos típusú(ak) lehet(nek). A változónév-listát tartalmazó
Read eljárás egyenértékű a változóneveket tartalmazó Read eljárások sorozatával.
Egy változónévvel hívott Read eljárás beolvas egy elemet a fájlból, és ennek
értékét a megadott nevű változónak adja át.
Példa:
Type ElmType=record
Re,Im:real
end;
var InpFile:file of ElmType;
ArrVar:array[boolean,2..4] of ElmType;
...
Assign(InpFile,'COMPLEX.DAT');
Reset(InpFile);
Read(InpFile,Arr,Var[true,3]);
A Write eljárás
Hívása: Write (FileVar,VarList)
A FileVar egy fájlváltozó neve, a VarList pedig egy változónév vagy változóné-vlista.
A FileVar névvel azonosított fájlnak nyitottnak kell lennie. A VarList változó(ak)
csak a fájltípussal azonos típusú(ak) lehet(nek). A változónév-listát tartalmazó
Write eljárás egyenértékű a változóneveket tartalmazó Write eljárások sorozatával.
Egy változónévvel hívott Write eljárás a megadott nevű változó értékét beírja
a FileVar változóval azonosított fájlba.
Példa:
Type ElmType=record
Re,Im:real
end;
var OutFile:file of ElmType;
ArrVar:array[boolean] of ElmType;
...
Assign(OutFile,'COMPLEX.RES');
Rewrite(OutFile);
Write(OutFile,ArrVar[false]ArrVar[true]);
A Seek eljárás
Hívása: Seek(FileVar,PostExp)
A FileVar egy fájlváltozó neve, a PosExp pedig egy integer típusú kifejezés.
A FileVar névvel azonosított fájlnak nyitottnak kell lennie. A PosExp kifejezés
értékének a [0,FileSize(FileVar)] zárt intervallumon belül kell lennie. (A FileSize
függvény értelmezését l. később, ugyanebben a szakaszban.) A Seek eljárás a
PosExp kifejezés értékének megfelelő sorszámú elem elé állítja a fájlt: Ha a
kifejezés értéke 0, akkor a Seek eljárás a fájlt a kezdeti pozícióba állítja,
ha ez az érték FileSize(FileVar), akkor pedig a végpozícióba. Egy típusos állományt úgy tudunk bővíteni (ahhoz elemeket hozzáírni), hogy az utolsó elem utáni helyre pozícionálunk, és onnan folytatjuk a szekvenciális írást.
Példa:
Type Name=string[5];
var FileVar:file of Name;
ElmVarl,ElmVar2:Name;
Len,Pos:integer;
Begin
Assign(FileVar,'FAMILY');
Reset(FileVar);
Len:=FileSize(FileVar)-1;
for Pos:=0 to Len shr 1 do begin
Seek(FileVar,Pos);
Read(FileVar,ElmVar1);
Seek(FileVar,Len-Pos);
Read(FileVar,ElmVar2);
Seek(FileVar,Pos);
Write(File,ElmVar2);
Seek(FileVar,Len-Pos);
Write(FileVar,ElmVar1)
end;
Close(FileVar)
end.
A Close eljárás
Hívása: Close (FileVar)
A FileVar egy fájlváltozó neve. A FileVar névvel azonosított fájlnak nem kötelező
nyitva lennie. A Close eljárás lezárja a FileVar névvel azonosított fájlt. Ha
az eljárás hívása előtt a fájl nem volt nyitva, akkor állapota nem változik.
Megjegyzés: a programfutás befejezése nem jelenti a Close eljárás(ok) automatikus
hívását!
Példa:
Var NewFile:file of boolean;
begin
Assign(NewFile,'EMPTY');
Rewrite(NewFile);
Close(NewFile)
end.
Az Erase eljárás
Hívása: Erase (FileVar)
A FileVar egy fájlváltozó neve. Ajánlott, hogy a FileVar névvel azonosított
fájt ne legyen nyitva. Az Erase eljárás törli azt az állományt, amelyet hozzárendeltünk
a FileVar névvel azonosított fájlhoz.
Példa:
Var KillFile:file of byte;
begin
Assign(KillFile,'SECRET.DOC');
Erase(KillFile)
end.
A Rename eljárás
Hívása: Rename (FileVar,
StrEpx)
A FileVar egy fájlváltozó neve, a StrExp pedig egy karakterlánc típusú kifejezés.
A FileVar névvel azonosított fájl nem lehet nyitva. A Rename eljárás átnevezi
azt az állományt, amelyet hozzárendeltünk a FileVar névvel azonosított fájlhoz.
Az állomány nevét a StrExp karakterlánc-kifejezés határozza meg. Az új név nem
tartalmazhatja a lemezmeghajtó kijelölését, és ilyen nevű állomány nem létezhet.
Példa:
Var RenFile:file of byte
begin
Assign(RenFile,'SECRET.DOC');
Rename(RenFile,'SECRET.BAK')
end.
Az Eof függvény
Hívása: Eof(FileVar)
A FileVar egy fájlváltozó neve. A FileVar névvel azonosított fájlnak nyitottnak
kell lennie. Az Eof függvény értéke true, ha a FileVar névvel azonosított fájl
végpozícióban van, egyébként false.
A FileSize függvény
Hívása: FileSize (FileVar)
A FileVar egy fájlváltozó neve. A FileVar névvel azonosított fájlnak nyitottnak
kell lennie. A FileSize függvény értéke integer típusú adat, amely a FileVar
változóval azonosított fájl pozícióját adja meg. A kezdeti fájlpozíció sorszáma
0, a végpozícióé pedig FileSize (FileVar).
12.2. Szövegfájlok
A többi fájltípustól eltérően a szövegfájlok nem azonos típusú elemekből, hanem
karakterekből összetett sorokból állnak. A szövegfájl minden sora CR/LF (carriage
return / line feed, "kocsi vissza" / soremelés) karakterpárral zárul.
A fájl utolsó sorát egy Ctrl-Z karakter követi. Ez a karakter a fájl lezárásakor kerül az írásra vagy bővítésre megnyitott fájlba. Mivel a fájl sorai különböző
hosszúságúak lehetnek, feldolgozni csak szekvenciálisan tudjuk; a fájl csak
olvasásra (Reset), ill. írásra (Rewrite) nyitható meg. A szövegfájl-típust az
előre definiált text azonosítóval írhatjuk le.
Példa:
Type TextType=text;
var OutFile:TextType;
InpFile:text;
A Turbo Pascal nyelvben külső berendezéseken - konzolon, terminálon, nyomtatón és modemen - keresztül szövegfájlokkal lehet adatokat átvinni. Ezek a szövegfájlok tehát az e berendezéseken át elérhető fizikai állományok modelljei. A külső berendezéseket három betűből és egy kettőspontból álló szimbolikus névvel (logikai eszköznévvel) jelöljük.
CON: konzol
A konzol beviteli, ill. kiviteli berendezés, amelynek beviteli eleme a billentyűzet,
kiviteli eleme pedig a képernyő. A konzolról bevitt adat pufferelt, azaz teljes
sorok formájában olvashatjuk be. Mivel minden sor CR ("kocsi vissza")
karakterrel végződik, bevihetünk a konzolról egy karaktersorozatot, s mielőtt
lezárnánk CR karakterrel, átszerkeszthetjük. A következő karakterekkel szerkeszthetünk:
Megjegyzés: a konzol beviteli pufferének méretét az előre definiált BufLen változó határozza meg. E változó max. és alapértelmezés szerinti (default) értéke 127. Ha a BufLen változónak értéket adunk, akkor az csak a legközelebbi beviteli utasításig lesz érvényben; a bevitel után a BufLen újból a 127-es értéket veszi fel.
TRM: terminál
A terminál beviteli, ill. kiviteli berendezés, amelynek beviteli eleme a billentyűzet,
kiviteli eleme pedig a képernyő. A konzoltól eltérően az adatbevitel nem pufferelt,
ami azt jelenti, hogy minden bevitt karaktert azonnal feldolgoz, és ki is ír
a képernyőre. A vezérlőkarakterek közül ez csak a CR karakterre vonatkozik,
amely CR/LF karakterpórként íródik ki.
KBD: billentyűzet
A billentyűzet beviteli berendezés. A bevitt karakterek a konzol beviteli eleméből
származnak, nem pufferoltak, és nem íródnak ki a képernyőre.
LST: nyomtató
A nyomtató kiviteli berendezés. A kivitt karaktereket a rendszer nem pufferoja,
ami azonban megoldható a nyomtatóban. A szövegfájlt az Assign eljárással rendelhetjük
hozzá egy logikai eszközhöz. Hívásakor meg kell adni a fájlváltozó nevét, és
a logikai eszköz nevét meghatározó karakterlánc-kifejezést. A fájl-adatállomány
jellegű hozzárendeléstől eltérően a szövegfájl hozzárendelése egy logikai eszközhöz
automatikusan meg is nyitja a szövegfájlt. Ekkor felesleges a Reset és a Rewrite
eljárás használata; végrehajtásuk - a Close eljáráshoz hasonlóan - nem jár semmilyen
következménnyel. Hibás azonban pl. az Erase vagy a Rename eljárás használata,
mivel ezek csak a mágneslemezes háttértárban található állományokon értelmezhetők.
Példa:
Var Console:text;
...
Assign(Console,'CON:');
A logikai eszközhöz hozzárendelt szövegfájlok esetén - az egyszerűsítésre
törekedve - a Turbo Pascal nyelvben több előre definiált fájlváltozót vezettek
be, amelyek szövegfájlokat azonosítanak.
Szövegfájlok és logikái eszközök egymáshoz rendelése:
Fájlváltozó | Logikai Eszköz |
Input | CON: vagy TRM: |
Output | CON: vagy TRM: |
Con | CON: |
Trm | TRM: |
Kbd | KBD: |
Lst | LST: |
Mint a táblázatból kiderül, a konkrét logikai eszközök hozzákapcsolódnak
az előre definiált fájlváltozók nevéhez. E szabály alól kivétel az Input és
az Output fájlváltozó: mindegyikük akár a CON:, akár a TRM: logikai eszközhöz
hozzárendelt fájlt azonosíthatja.
A CON: és a TRM: közötti választást a fordítóprogram {$B+} és {$B-}
direktívái befolyásolják. Alapértelmezés szerint a {$B+} van érvényben; ekkor
az Input és Output fájlváltozóval azonosított fájlok a CON: logikai eszközhöz
kapcsolódnak. A {$B-} direktíva viszont a TRM: eszközt választja a CON: helyett.
A felsorolt fájlváltozókkal (Input, Output, Con, Trm, Kbd és Lst) azonosított
szövegfájlok mindig nyitottak, és a rajtuk végezhető műveletek a konkrét logikai
eszközökre vonatkoznak (CON:, TRM:, KBD: és LST:).
Példa:
Begin
Writeln(Con,'-Hello world-')
end.
12.3. Szövegfájlokon értelmezett műveletek
A szövegfájlok adatállományokhoz vagy logikai eszközökhöz rendelhetők hozzá.
Az első esetben a fájlban tárolt adatok feldolgozását meg kell előznie az Assign
és a Reset vagy a Rewrite eljárás hívásának. A feldolgozás végét a Close eljárás
jelenti. A második esetben (vagyis fájl és eszköz társításakor) használhatjuk
az előre definiált fájlváltozót. Ekkor nem megengedett az ilyen változóra vonatkozó
Assign, Reset, Rewrite és Close eljárás hívása. Jó megoldás az is, hogy az eszközt
egy szimbolikus nevet viselő adatállománynak tekintjük, és az Assign eljárással
társítjuk a szövegfájllal (utána már kezelhetjük).
Szöveges állományból a következő típusú adatokat lehet beolvasni, illetve oda kiírni:
Az Assign eljárás
Hívása: Assign (TextVar,StrExp)
A TextVar egy text típusú fájlváltozó neve, a StrExp pedig karakterlánc típusú
kifejezés. A TextVar névvel azonosított fájl nem lehet nyitva. A TextVar nem
lehet egy előre definiált fájlváltozó. Az Assign eljárás végrehajtása hozzárendeli
a TextVar névvel azonosított fájlt a StrExp kifejezéssel meghatározott adatállományhoz
vagy logikai eszközhöz.
Példa:
var Device:text;
...
Assign(Device,'CON:');
A Reset eljárás
Hívása: Reset (TextVar)
A TextVar egy text típusú fájlváltozó neve. Az eljárás hívása előtt a TextVar
névvel azonosított fájlt egy létező adatállományhoz vagy logikai eszközhöz hozzá
kell rendelni. A Reset eljárás megnyitja a TextVar névvel azonosított fájlt.
Ha ez a fájl egy logikai eszközhöz kapcsolódik, akkor már megnyitottnak tekinthető,
és a Reset eljárás hívása nem jár következménnyel.
Példa:
var InpFile:text;
...
Assign(InpFile,'OLDBOOK');
Reset(InpFile);
A Rewrite eljárás
Hívása: Rewrite (TextVar)
A TextVar egy text típusú fájlváltozó neve. Az eljárás hívása előtt a TextVar
által képviselt fájlt egy adatállományhoz vagy egy logikai eszközhöz kell hozzárendelni.
A Rewrite eljárás megnyitja a TextVar által képviselt fájlt. Ha ez a fájl egy
logikai eszközhöz kapcsolódik, akkor már megnyitottnak tekinthető, és a Rewrite
eljárás hívása nem jár következménnyel. Ha a Rewrite hívása előtt a fájlhoz
hozzárendelt állomány nem létezett, akkor az eljárás végrehajtásakor létrejön.
Ha pedig volt már ilyen állomány, akkor törlődik és újra létrejön. Mindkét esetben
egy üres adatállomány keletkezik.
Példa:
var OutFile:text;
...
Assign(OutFile,'NEWBOOK');
Rewrite(OutFile);
A Read eljárás
Hívása: Read (TextVar,VarList)
A TextVar egy text típusú fájlváltozó neve, a VarList pedig egy változónév,
ill. char, síring, integer vagy real típusú változónevek listája. Ha a TextVar
értéke Input, akkor a hívás Read(VarList) alakra egyszerűsíthető. Ha a hívás
explicit vagy "rejtett" Input paramétert tartalmaz, és a {$B+} direktíva
van érvényben, akkor a TextVar nevet a fordítóprogram Con névnek tekinti; ha
a {$B-} érvényes, akkor pedig Trm névnek. A TextVar névvel azonosított fájlnak
mindig nyitottnak kell lennie. A Read eljárás a TextVar változóval azonosított
fájlból karakterláncot olvas be, melyet - megállapodás szerinti - adat(ok)nak
értelmez; értékét a VarList-ben szereplő változó(k)nak adja át.
Megjegyzés: ha a bevitel a CON: logikai eszközről megy végbe, akkor a Read mindenkori
hívása egy új sor beolvasását jelenti, még akkor is, ha a konzol pufferében
maradt(ak) még be nem olvasott karakter(ek). Ekkor a pufferben található karakterek
csak a CR karakteres sorlezárás után értelmezhetők; az esetleg korábban bevitt
Ctrl-Z karakter figyelmen kívül marad. Ez a karakter egyébként mindig a puffer
végére kerül, de csak a CR bevitele után.
A TextVar változóval azonosított fájl karaktereinek értelmezése függ a VarList-beli
változó(k) típusától:
A char típusú változók
A rendszer beolvas egy karaktert, és átadja a változónak.
A string típusú változók
A rendszer beolvassa a lehetséges leghosszabb karakterláncot, és átadja
a változónak. A bevitt karakterek száma nem lépheti túl a karakterlánc-változó
max. hosszát, és nem lehet több az aktuális sor karakterszámánál.
Az integer, ill. a real típusú változók
A rendszer beolvas egy egész, ill. valós számot ábrázoló karakterláncot,
amely után a következő karakterek valamelyike következik: szóköz, tabulátor,
CR vagy Ctrl-Z. A beolvasandó számot megelőző szóközök, tabulátorok, Cr
és LF karakterek figyelmen kívül maradnak. A soron következő VarList beli
változó a maradó karakterekkel ábrázolt következő egész, ill. valós számot
kapja értékül stb. Ha a beolvasott karakterlánc a leírástól eltérő alakú,
akkor beviteli vagy kiviteli hiba keletkezik.
Példa:
Var IntVar:integer;
Fixvar:real;
TextVar:text;
Ter1,Ter2:char;
Str:string[8];
begin
Assign(TextVar,'ONELINE.DAT');
Reset(TextVar);
Read(TextVar,IntVar,Terl,FixVar,Ter2,Str);
end.
Ha a Read eljárás végrehajtásakor a fájl végpozícióba kerül,
és a VarList változói közül maradt még olyan, amely nem kapott értéket, akkor
minden char típusú változó Ctrt-Z karaktert kap értékként, a string típusú változó
üres karakterláncot, az integer és a real típusú változók pedig nem kapnak új
értéket.
Ha a fájlt a konzolhoz rendeljük hozzá, akkor minden beolvasott sor végén Ctrl-Z
karakter lesz. Ennek az a hatása, mintha a fájl minden sor végén végpozícióba
kerülne.
Példa:
Var IntVar:integer;
StrVar:string[3];
ChrVar:char;
begin
IntVar:=-2;
StrVar:='jan';
ChrVar:='b';
Read(IntVar,StrVar,ChrVar);
...
end.
A Readln eljárás
Hívása:
Readln (TextVar)
Readln (TextVar, VarList)
A TextVar egy text típusú fájlváltozó neve, a VarList pedig egy változónév,
ill. char, string, integer vagy real típusú változónevek listája. Ha a TextVar
értéke Input, akkor a hívás egyszerűsíthető: az első esetben Readln, a másodikban
Readln(VarList) alakra. A Readln(TextVar) típusú hívás karaktereket olvas a
fájlból, CR/LF-ig (bezárólag); a beolvasott karakterláncot figyelmen kívül hagyja.
Ha a fájl egy logikai eszközhöz kapcsolódik, akkor csak CR-ig (bezárólag) olvassa
be a karaktereket, és a beolvasott karakterláncot figyelmen kívül hagyja. Ha
a TextVar konzolt jelent, akkor a képernyőre CR/LF-et ír ki. A
Readln (TextVar,VarList)
hívás egyenértékű a
Read (TextVar,VarList); Readln(TextVar)
alakkal, ezért nem igényel további magyarázatot.
Példa:
var Count:integer;
Source:text;
Line:string[128];
begin
Assign(Source,'VOLUME.DAT');
Reset(Source);
Count:=0;
while not Eof(Source) do begin
Readln(Source,Line);
Count:= Count+l
end;
Writeln(Count)
end.
A Write eljárás
Hívása: Write (TextVar,ExpList)
A TextVar egy text típusú fájlváltozó neve, az ExpList pedig char, string, integer,
real vagy boolean típusú változó neve (vagy ilyen nevek listája). Közvetlenül
a felsorolt kifejezések után következhet a :m alakú minősítő tag; real típusú
kifejezés után megengedett még a :m:n alakú minősítő is, ahol az m és az a integer
típusú kifejezés. Ha a TextVar értéke Output, akkor a hívás Write(ExpList) alakra
egyszerűsíthető. Ha a hívás explicit vagy "rejtett" Output paramétert
tartalmaz, akkor a TextVar nevet a fordítóprogram Con (vagy a megfelelő programkörnyezetben
ezzel egyenértékű Trm) névnek tekinti. A TextVar névvel azonosított fájlnak
mindig nyitottnak kell lennie. A Write eljárás a TextVar változóval azonosított
fájlba karakterláncot ír be, amely az ExpList-ben szereplő kifejezések értékét
képviselő adatokat ábrázolja.
Az említett karakterlánc alakjának értelmezése az ExpList-beli változók) típusától
és az m, a minősítők értékétől függ:
A char típusú kifejezések
A rendszer kiviszi a kifejezés által képviselt karaktert. Ha van m minősítő,
és m>1, akkor a karaktert m-1 szóköz előzi meg.
A string típusú kifejezések
A rendszer kiviszi a kifejezés által képviselt karakterláncot. Ha van m
minősítő, és m nagyobb a karakterlánc I hosszánál, akkor a karakterláncot
m-I szóköz előzi meg.
Az integer típusú kifejezések
A rendszer kiviszi a kifejezés értékét ábrázoló legrövidebb karakterláncot.
Ha van m minősítő, és m nagyobb a karakterlánc I hosszánál, akkor a karakterláncot
m-l szóköz előzi meg.
A real típusú kifejezések
A rendszer kiviszi a kifejezés valós értékét ábrázoló bsd.ddddddddddEsdd
alakú karakterláncot, amelyben a b szóközt jelent; az első s a szám előjelét
ábrázolja, mégpedig szóközként (nem negatív érték esetén) vagy - (mínusz)
karakterként (negatív érték esetén). Minden d egy decimális számjegyet jelent;
a második s pedig egy + vagy - (mínusz) karaktert. Ha van m minősítő, és
m > 18, akkor a karakterláncot m-18 szóköz előzi meg. Ha m=18, akkor
a 4. pont elején megadott minta szerint keletkezik a karakterlánc. Ha m<18,
akkor pontosan m karaktert visz ki a rendszer, mégpedig úgy, hogy először
a kezdő szóközöket, utána pedig a mantissza utolsó számjegyeit hagyja el,
kerekítve. Ha az m értéke 2-nél kevesebb számjegyet hagyna a mantisszából,
akkor a rendszer csak a harmadik és az utána következő számjegyeket vágja
le, kerekítve. Ha a minősítő tag :m:n alakú, akkor a rendszer olyan valós
számformátumot képez, amely exponens nélküli, a darab tizedesjegyű, jobbra
igazított, m hosszúságú karakterlánc. Ha a szám nem ábrázolható ilyen formában,
akkor az m értéke automatikusan annyival nő, hogy a számot ábrázolni lehessen.
Ha n=0, akkor a rendszer a számot tizedespont és tizedesrész nélkül viszi
ki; a [0,24] zárt intervallumon kívülre eső a értékek esetén a : m:n minősítőt
a rendszer - az előzőekben leírt - : m tagként értelmezi.
A boolean típusú kifejezések
A rendszer kiviszi a kifejezés értékét képviselő TRUE vagy FALSE karakterláncot.
Ha van m minősítő, és m nagyobb a képzett karakterlánc I hosszánál, akkor
a karakterláncot m-I szóköz előzi meg.
Példák (A b szimbólum szóközt jelent.)
Kifejezés | Kivitt karakterlánc |
'j' | j |
'j':2 | bj |
'jan' | jan |
'jan':4 | bjan |
-44 | -44 |
44:5 | bb44 |
23.5 | bb2.3500000000E+01 |
23.456789:0 | 2.3457E+01 |
23.456789:6 | 2.3E+01 |
23.456789:6:2 | b23.46 |
-23.456789:6:0 | bbb-23 |
23.456789:6:-2 | 2.3E+01 |
A Writeln eljárás
Hívása:
Writeln (TextVar)
Writeln (TextVar,ExpList)
A TextVar egy text típusú fájlváltozó neve, az ExpList pedig char, string, integer,
real vagy boolean típusú változó neve (vagy ilyen nevek listája). Közvetlenül
a felsorolt kifejezések után következhet a :m alakú minősítő tag; egy real típusú
kifejezés után megengedett még a :m :n alakú minősítő is, ahol az m és az n
integer típusú kifejezés. Ha a TextVar értéke Output, akkor a hívás egyszerűsíthető:
az első esetben Writeln, a másodikban Writeln(ExpList) alakra.
A Writeln(TextVar) típusú hívás a TextVar változóval azonosított fájlba CR/LF
karakterpárt visz ki. A
Writeln(TextVar, ExpList)
hívás egyenértékű a
Write(TextVar,ExpList); Writeln(TextVar)
alakkal, ezért nem igényel további magyarázatot.
Példa:
Begin
Writeln(false);
Writeln;
Writeln(true)
end.
A Close eljárás
Hívása: Close (TextVar)
A TextVar egy text típusú fájlváltozó neve. A TextVar nem (ehet előre definiált
fájlváltozó. A Close eljárás lezárja a TextVar névvel azonosított fájlt.
Példa:
Var Output:text;
begin
Assign(Output,'JB.DOC');
Rewrite(Output);
Writeln(Output,'jasio');
Close(Output)
end.
Az Eof függvény
Hívása: Eof (TextVar)
A TextVaregy text típusú fájlváltozó neve. Ha a TextVar értéke Input, akkor
a hívás Eof alakúra egyszerűsíthető. Az Eof függvény adatállományhoz és logikai
eszközhöz hozzárendelt fájlra is alkalmazható. A függvény mindkét esetben boolean
típusú, és false vagy true értéket vehet fel.
Ha a fájl egy állományhoz kapcsolódik, és a Ctrl-Z karakter előtt vagy a végpozícióban
állt, akkor az Eof függvény értéke true, egyébként false.
Ha a fájl egy logikai eszközhöz kapcsolódik, és az utolsó értelmezett karakter
Ctrl-Z volt, akkor az Eof függvény értéke true, egyébként false.
Az Eoln függvény
Hívása: Eoln (TextVar)
A TextVar egy text típusú fájlváltozó neve. Ha a TextVar értéke Input, akkor
a hívás Eoln alakúra egyszerűsíthető. Az Eoln függvény adatállományhoz és logikai
eszközhöz hozzárendelt fájlra is alkalmazható. A függvény mindkét esetben boolean
típusú, és false vagy true értéket vehet fel.
Ha a fájl egy állományhoz kapcsolódik, és a CR karakter előtt áll, vagy az Eol
függvény értéke szintén true lenne, akkor az Eoln függvény értéke true, egyébként
false.
Ha a fájl egy logikai eszközhöz kapcsolódik és az utolsó értelmezett karakter
CR volt, vagy az Eof függvény értéke szintén true lenne, akkor az Eoln függvény
értéke true, egyébként false.
Példa:
var ChrVar:char;
TxtVar:text;
begin
Assign(TxtVar,'STRANGE.DOC');
Reset(TxtVar);
while not Eof(TxtVar) do begin
Writeln(Eoln(TxtVar));
Read(TxtVar,ChrVar)
end
end.
A SeekEof függvény
Hívása: SeekEof (TextVar)
A TextVar egy text típusú fájlváltozó neve. Ha a TextVar értéke Input, akkor
a hívás SeekEof alakúra egyszerűsíthető. A SeekEof függvény működése hasonlít
az Eof függvényre: a legközelebbi szóközök, tabulátorok, CR és LF karakterek
elhagyása után az eredmény az Eof függvényével azonos.
A SeekEoln függvény
Hívása: SeekEoln (TextVar)
A TextVar egy text típusú fájlváltozó neve. Ha a TextVar értéke Input, akkor
a hívás SeekEoln alakúra egyszerűsíthető. A SeekEoln függvény működése hasonlít
az Eoln függvényre: a legközelebbi szóközök és tabulátorok elhagyása után
az eredmény az Eoln függvényével azonos.
Példa:
var TxtVar:text;
Tally:integer;
ChrVar:char;
begin
Tally:=0;
Assign(TxtVar,'TEXT.DOC');
Reset(TxtVar);
while not SeekEof(TxtVar) do begin
while not SeekEoln(TxtVar) do begin
Tally:=Tally+1;
Read(TxtVar,ChrVar)
end
end;
Writeln(Tally)
end.
Az alábbi program a megadott nevű szöveges állományt listázza ki a képernyőre oldalanként:
Program Textfile;
var FilVar:text;
Line:string[80];
FileName:string[14];
i:byte;
begin
ClrScr;
Write('Enter name of file to list: ');Readln(FileName);
Assign(FilVar,FileName);
Reset(FilVar);
i:=1;
while not Eof(FilVar) do begin
Readln(FilVar,Line);
Writeln(line);
i:=i+1;
if i=23 then begin
repeat until KeyPressed;
i:=1
end
end;
LowVideo;Write('{ End of file }');NormVideo;
repeat until KeyPressed
end.
Karakterlánc beolvasásánál feltétlenül a Readln eljárást használjuk, mert a Read(FileVar,Line) beolvassa ugyan a teljes sort, de a sorvégejelen megáll. Ezért a következő Read eljárás üres karakterláncot fog beolvasni.
A szöveges állományba egy egész sort egyszerre a Writeln(FileVar,Line) eljárással írhatunk, ahol Line egy String típusú változó vagy kifejezés.
12.4. Elemtípus nélküli fájlok
A számítógépen tárolt adatok többsége nem tagolható szövegsorokra, és a bennük tárolt adatelemek mérete nem azonos. Az ilyen állományokat sem szöveges, sem pedig típusos fájlként nem kezelhetjük. A Turbo Pascal-ban a típus nélküli fájlok használata nagy segítséget jelent ismeretlen, illetve nem szabályos szerkezetű állományok feldolgozásában.
Az elemtípus nélküli fájlok lehetőséget adnak a nem pufferolt beviteli, ill.
kiviteli műveletek végrehajtására, közvetlenül a program változói és a külső
mágneslemezes háttértár között. Az elemek - megállapodás szerint - olyan objektumok,
amelyek 128 bájtnyi memóriát foglalnak le. Az elemtípus nélküli fájl tetszőleges
mágneslemezes adatállományt képviselhet; ezért pl. az Erase vagy a Rename
jellegű műveletek is végrehajthatók. Az elemtípus nélküli fájl leírása a file
kulcsszóból áll.
Példa:
var
DiskFile:file;
FileName:string[40];
begin
Write('FileName:-');
Readln(FileName);
Assign(DiskFile,FileName);
Erase(DiskFile)
end.
Az elemtípus nélküli fájlokon végrehajtható beviteli, ill. kiviteli műveleteket a BlockRead és a BlockWrite eljárás valósítja meg; ezek helyettesítik a megfelelő elemtípusos eljárásokat. Más műveletek (Assign, Reset, Rewrite, Close, Seek és Eof) értelmezése azonos az elemtípusos fájlokéval.
A BlockRead eljárás
Hívása:
BlockRead (FileVar,Buffer,Count,Reply)
BlockRead (FileVar,Buffer,Count)
A FileVar egy elemtípus nélküli fájlváltozó neve, a Buffer tetszőleges változónév,
a Count integer típusú kifejezés, a Reply pedig integer típusú változó neve.
A BIockRead eljárás a FileVar változóval azonosított fájlból Count számú, 128
bájt méretű objektumot olvas be, a Buffer változó által lefoglalt memóriaterületre.
Ha a hívás tartalmazza a Reply paramétert, akkor a Reply változó új értéke a
ténylegesen beolvasott objektumok számát adja meg. Ha ez a szám Count nál kisebb,
akkor a fájl a végpozícióban van.
A BlockWrite eljárás
Hívása:
BlockWrite (FileVar,Buffer,Count,Reply)
BlockWrite (FileVar,Butfer,Count)
A FileVar egy elemtípus nélküli fájlváltozó neve, a Buffer tetszőleges változónév,
a Count integer típusú kifejezés, a Reply pedig egy integer típusú változó neve.
A BIockWrite eljárás a FileVar változóval azonosított fájlba Count számú, 128
bájt méretű objektumot ír be, a Buffer változó által lefoglalt memóriaterületről.
Ha a hívás tartalmazza a Reply paramétert, akkor a Reply változó új értéke a
ténylegesen kivitt objektumok számát adja meg. Ha ez a szám Count-nál kisebb,
akkor a kivitel sikertelen volt.
Példa:
Program Copy;
var
Src,Trg:file;
Buffer:array [0..255, boolean] of byte;
Source,Target:string[40];
Reply:integer;
begin
Write('Source :-');Readln(Source);
Write('Target :-');Readln(Target);
Assign(Src,Source);
Assign(Trg,Target);
Reset(Src);
Rewrite(Trg);
repeat
BlockRead(Src,Buffer,4,Reply);
BlockWrite(Trg,Buffer,Reply)
until Reply<4;
Close(Src);
Close(Trg)
end.
12.5. Beviteli és kiviteli
műveletek ellenőrzése
A beviteli és kiviteli műveletek ellenőrzése a program fordításakor kérhető.
Az alapértelmezés szerinti {$I+} direktíva érvényességi körén belül a
rendszer minden beviteli és kiviteli műveletet ellenőriz. Hiba esetén a program
leáll, és hibaüzenet íródik ki a konzolra. A {$I-} direktíva hatáskörében
a hibaállapot nem állítja le a program futását, csak felfüggeszti a további
beviteli, ill. kiviteli műveleteket. Ez az állapot a beépített IOresult
függvény hívásáig áll fenn. A függvény integer típusú értéke megadja a hiba
jellegét. Ha ez az érték 0, akkor az eddigi beviteli, ill. kiviteli műveletek
hibátlanul végződtek; ha a függvény 0-tól különböző értékkel tér vissza, akkor
ez az érték - a Függelékben felsoroltak szerint - a hiba kódját
jelenti.
Példa:
Program Delete;
var
FileVar:file;
FileName:string[40];
Flag:Bodean;
Begin
Write('FileName:-');
Readln(FileName);
Assign(FileVar,FileName);
{$I-} Erase(FileVar);{$I+}
if not (IOresult=0) then
Writelnt('File'+FileName+' did not exist')
end.
12.6. A fájlkezelés általános lépései
A számítógépeken az operációs rendszer feladatai közé tartozik a fájlrendszer támogatása és a fájlok elérésének biztosítása. Az állományok tartalmának eléréséhez a programozási nyelvtől és az operációs rendszer fajtájától függetlenül mindig ugyanazokat a főbb lépéseket kell végrehajtani:
Természetesen a Turbo Pascal nyelvben is megtalálhatjuk a fenti lépések elvégzését támogató alprogramokat. Ahhoz azonban, hogy a Pascal programtól használni tudjunk egy fájlt, szükség van egy előkészítő (nulladik) lépésre is.
Mielőtt hozzákezdenénk a fájlkezelés lépéseinek ismertetéséhez, tisztázzunk néhány gyakran használt fájlokkal kapcsolatos fogalmat. A fájlokat a bennük tárolt adatok elérése alapján is csoportosíthatjuk. Azokat a fájlokat, amelyet adatelemeit csak sorban egymás után érhetjük el, soros (szekvenciális) állományoknak nevezzük. Turbo Pascal-ban soros fájlként a szöveges állományokat használjuk. A másik csoportot a közvetlen elérésű állományok alkotják. Ezekben a pozicionálás műveletét használva közvetlenül kiválaszthatjuk a feldolgozni kívánt adatelemeket. A Turbo Pascal-ban a típusos és a típus nélkül fájlok tartalmához soros és közvetlen eléréssel egyaránt hozzáférhetünk.
Nulladik lépés: előkészületek
A Pascal programból a lemezen tárolt állományokat és az eszközöket a fájlműveletek során ún. fájlváltozóval azonosítjuk. A fájlváltozót a fájl típusától függően az alábbi három mód egykével deklarálhatjuk:
változónév: text; szöveges fájl változónév: file of típus; típusos fájl változónév: file; típus nélküli fájl
A megfelelő típusú fájl változó létrehozása után, az assign eljárás segítségével össze kell rendelnünk a fájl változót egy létező vagy egy új állomány nevével:
assign(fájlváltozó, fájlnév);
A fájlnév egy 'NNNNNNNN.KKK' formában megadott sztring, ahol az első legfeljebb 8 karakteres rész az állomány igazi neve, és a pont után megadott maximum 3 karakter pedig a kiterjesztés. A fájl neve előtt fájlhoz vezető útvonalat (a fájl elérési útvonalát) is megadhatjuk, amely a meghajtó nevéből és az állományt tartalmazó összes alkönyvtár nevének '\' jellel tagolt listájából áll. Az érési utat mindig meg kell adni, ha az állomány nem az aktuális könyvtárban helyezkedik el.
Első lépés: fájlnyitás
A felhasználni kívánt állományt meg kell nyitni ahhoz, hogy a fájlműveletekkel hozzáférjünk a tartalmához. A Turbo Pascal-ban két eljárással is megnyithatjuk a fájljainkat:
reset(fájlváltozó);
rewrite(fájlváltozó);
A két eljárás működésének lényege az alábbiak szerint foglalható össze:
A fájlnyitó eljárások az adatok áramlásának irányát is meghatározzák. A szöveges állományok a reset eljárással való megnyitás után csak olvashatók, míg a rewrite után csak írhatók lesznek. Nem így van ez a típusos és a típus nélküli fájlok esetén. Alaphelyzetben bármelyik eljárással is nyitunk meg egy ilyen típusú állományt, az egyszerre írható és olvasható is lesz.
Ha a fájl nyitásakor valamilyen hiba lép fel (például hibás fájlnevet adunk meg), akkor a programunk hibaüzenettel leáll. A Turbo Pascal rendszer lehetővé teszi, hogy a be- és kiviteli (I/O) műveletek végzése során fellépő hibákat programon belül dolgozzuk fel. Ha a kritikus programrészletet {$I-} és az {$I+} direktívák közé helyezzük, akkor az ioresult függvény visszaadott értékéből következtethetünk a hiba okára. (A nulla visszatérési érték azt jelzi, hogy nem történt hiba, míg minden más érték valamilyen hibát azonosít.) A függvény használatával biztonságossá tehetjük a fájlnyitást. Az ioresult függvény értékéből mindig csak a legutolsó I/O művelet lefolyására következhetünk. A függvény hívása törli a belső állapotjelző értékét, így ha többször szeretnénk a hibakódot lekérdezni, akkor egy egész típusú változóban kell eltárolnunk a függvény első hívásakor visszaadott értéket.
Második lépés: fájlműveletek
A fájlműveletek alatt a megnyitott állományokon elvégezhető műveleteket értjük. Ebben a tekintetben az egyes fájltípusok között még a nyitásnál is jelentősebb az eltérés. A következő táblázatban felsoroltuk a műveleteket megvalósító eljárásokat és függvényeket. Ugyancsak megadtuk a műveletek rövid leírását, és azt, hogy milyen típusú fájlok esetén alkalmazhatók.
művelet | leírás | szöveges file |
típusos file |
típus nélküli file |
BlockRead | blokk olvasása | + |
||
BlockWrite | blokk írása | + |
||
Eof | fájlvége lekérdezése | + |
+ |
+ |
Eoln | sorvége lekérdezése | + |
||
FilePos | fájlpozíció lekérdezése | + |
+ |
|
FileSize | fájlméret lekérdezése | + |
+ |
|
IOresult | hibakód lekérdezése | + |
+ |
+ |
Read | adatok olvasása | + |
+ |
|
Readln | adatsor olvasása | + |
||
Seek | pozicionálás | + |
+ |
|
SeekEof | fájlvége lekérdezés | + |
||
Write | adatok írása | + |
+ |
|
Writeln | adatsor írása | + |
Harmadik lépés: a fájl lezárása
Munkánk végeztével a fájlt a close eljárás hívásával kell lezárni:
Close(fájlváltozó);
Ez a lépés különösen fontos, ha az adatállomány tartalmát módosítjuk. A close eljárás frissíti az adatállományt, így az utoljára (pufferolt) végrehajtott fájlműveletek eredménye is megjelenik a lemezen tárolt állományban. A Pascal programból kilépve minden még nyitott állományt automatikusan, a fájltartalom frissítése nélkül zár le a rendszer. Ez az írásra megnyitott fájlok esetében adatvesztéssel járhat!
Az állomány lezárása után is megmarad a kapcsolat a fájlnév és a fájlváltozó között, így ha a programunkban újra meg kell nyitni az előzőleg lezárt állományt, akkor nincs szükség újabb assign hívásra.
13. Mutatótípusok
Az eddig használt egyszerű és strukturált típusú változók közös tulajdonsága, hogy rájuk a deklarálás során megadott névvel hivatkozunk. Az így definiált változók mérete a program fordításakor dől el, és a program futása során a módosítható. A Pascal nyelvben ezeket a változókat statikus helyfoglalású változóknak nevezzük.
A hatékony memória-felhasználás érdekében szükség van arra, hogy bizonyos memóriaterülettel a programozó szabadon gazdálkodjon. A Pascal nyelv rendelkezik olyan eszközökkel, amelyek segítségével a programozó maga foglalhat memóriaterületet a változói számára. A lefoglalt területet fel is szabadíthatja, ha már nincs szüksége a változóra. A felszabadított terület egy következő memóriafoglalás során újra felhasználható. A memóriafoglalás és felszabadítás műveleteivel a memória dinamikus felhasználását valósítjuk meg. A dinamikus helyfoglalású változók számára rendelkezésre álló területet a Turbo Pascal-ban halomterületnek (heapnek) nevezzük.
Mindenekelőtt nézzük, mi is a heap? A heap-nek a pointeres változók használatában van nagy Jelentősége. A heap egy verem típusú adatszerkezet. A verem olyan adatszerkezetet Jelent, amelybe adatok érkeznek és távoznak. Az egyszerűbb verem szekvenciális szerkezetű. A később érkező adat 'feljebb' kerül, tehát az adatok szemléletesen egymás fölött helyezkednek el. Az utoljára betett adatot vehetjük ki először, tehát a kivétel a betétellel fordított sorrendben történik, akár egy valódi verem esetén. Erre utal ennek az adatszerkezetnek az angol neve, a LIFO (last in first out), azaz: az utolsó először távozik. Említsük meg a másik fontos adatszerkezetet, a sor típust. Ezt itt nem alkalmazzuk, csupán a veremmel való párhuzamba állítás miatt említjük meg. A sor adatszerkezet angol neve: FIFO, a 'first in first out' szavak kezdőbetűiből, azaz: az első először távozik. A betétei és a kivétel ez esetben az adatokon azonos sorrendben történik.
A bonyolultabb verem típusú adatszerkezetek megengedik a direkt hozzáférést is. Ez azt Jelenti, hogy nemcsak az utoljára betett adatot lehet kivenni, hanem bármelyiket 'alulról' is. Ebben az esetben ott egy 'lyuk' marad a memóriában. Így a következő input alkalmával nem feltétlenül a verem tetejére tesszük az adatokat, hanem az Így keletkező lyukak valamelyikébe. Ezt a memóriával való takarékosság jegyében érdemes alkalmazni. Ha több lyuk van, akkor többféle stratégiát is alkalmazhatunk annak eldöntésére, hogy melyik lyukat 'tömjük' be, pl. a legkisebbet, amelybe még belefér (hogy a későbbi, esetleg nagyobb adattömeg számára növeljük a helybiztosítás valószínűségét). Ezeket a stratégiákat most nem részletezzük, mivel azok külön fejezetet képeznek az adatbázis-kezelésben, célunk csupán a pointerekhez kapcsolódó adatszerkezetekbe és rendszertevékenységekbe betekintést nyerni. A rendszer ugyanis a programozó számára láthatatlanul végzi ezeket a tevékenységeket, belső mutatói segítségével.
A pointeres változókat a Turbo rendszer egy ilyen, direkt elérésű verem-struktúrában tárolja. Ezt heap-nek, azaz halomnak nevezzük. A heap-et a rendszer minden program futásának kezdetén a szabad memóriaterület kezdetére helyezi, s hozzárendel egy belső mutatót, amelyet a futás kezdetekor a heap elejére állít. Ennek neve: HeapPtr. A 'New' eljárás (ld. később) ezt a mutatót állítja a változó méretének megfelelően feljebb, oly módon, hogy ez a mutató mindig a szabad memóriaterület elejére állítódik, így a heap következő szabad helyére mutat. A következő eljárások szintén kapcsolódnak a heap-hez, sőt, működésük bemutatásához elengedhetetlen annak ismerete.
A másik verem típusú adatszerkezet a stack, amelyben a rendszer a lokális változókat, a számítások részeredményeit tárolja, valamint rajta keresztül történik a paraméterátadás a függvények és az eljárások hívásakor. A stack a program indításakor a stack terület végéről indul, üresen, azaz a stack-pointer értéke a stack vége. Innen növekszik a stack visszafelé.
Mindez azt Jelenti, hogy a heap és a stack - két verem típusú struktúra - a szabad memória két végéről indulva, egymással szemben híznak. Amíg össze nem érnek, addig nincs baj - ezt pl. a New eljárás minden meghívásakor ellenőrzi -, amennyiben viszont a két verem összeér, a program futási hibával leáll. Ezt az ütközés-figyelést kikapcsolhatjuk a K direktíva passzív állapotba állításával: {$K-}, de ezt nem ajánljuk, mivel a két verem ekkor egymásra fut, ami igen nagy problémákat okozhat.
Ellentétben az eddig megismert változókkal, a mutató típus segítségével a tulajdonságaiban lényegesen eltérő változókat hozhatunk létre. A dinamikus változó feloldja az eddigi kötöttségeket, a deklaráció - a típus, méret és kezdőcím attribútumok - megadása a futás közben történik és ezek az attribútumok futás közben változhatnak is. Innen a 'dinamikus' elnevezés. Ezek a változók tehát a deklarációs részben nem is Jelennek meg, ezért kell egy közbülső típus, amelynek szerepe az, hogy a futási részben mindezt megtehessük. Ezt nevezzük mutató típusnak. A mutató tartalma a memória egy címe, amely kijelöli a dinamikus változó kezdőcímét. A mutató is többféle típusú lehet, aszerint, hogy milyen változóra hivatkozunk vele. Ez azt Jelenti, hogy egy adott típusú változó kezdőcímét jelöli ki. A mutató deklarációjakor azt definiáljuk, hogy milyen típusú változóra mutasson.
A mutatótípusok mindegyike elemi típus. A mutató típusú adat értéke a mutató
(pointer). A mutatótípus leírása a ^ karakterből és az azt követő típusnévből
áll. E típusnevet nem kötelező előbb definiálni; ez az egyetlen kivétel azon
szabály alól, miszerint csak az előzőleg definiált objektumokra hivatkozhatunk. A mutatók deklarásának általános formája:
var változónév:^típusnév;
ahol a típusnév tetszőleges szabványos vagy felhasználó által definiált típus neve. A Pascal nyelvben a mutatók lényeges tulajdonsága, hogy típussal rendelkeznek. A típus kijelöli, hogy a dinamikus helyfoglalás során mekkora területet kell a mutatóhoz hozzárendelni.
Szintaxis:
mutatótípus-leírás:
^típusnév
típusnév:
azonosító
Példa:
Type
EmployeePtrs=^EmployeeData;
EmployeeData=record
Name:string[30];
Salary:real
end;
var
EmployeeRef:EmployeePtr;
IntRef:^integer;
A mutatótípusokon és -változókon kívül van egy "üres" mutató is a Turbo Pascal-ban, melyet a nil kulcsszó képvisel. E mutató típusa egyenértékű bármilyen más mutatótípussal. A mutató típusú változók neveit és az üres mutatót az = és a <> (nem egyenlő) relációkban használhatjuk. Az értékadó utasításban kötelező a bal és a jobb oldal típusazonossága. Ez csak akkor teljesül, ha az értékadó szimbólum két oldalán álló nevek azonos típusú változókat képviselnek.
Példa:
Type
Days=(Mon,Tue,Wed,Thu,Fri,Sat;Sun);
Week=Mon..Sun;
Var
Day1:^Days;
Day2,Day3:^Week;
A mutató típusú változók felhasználhatók pl. az operatív tár dinamikus szervezésében (helyfoglalásban). Ehhez nyújtanak segítséget a tárfoglaló és -felszabadító eljárások.
A New eljárás
Hívása: New (PtrVar)
A PtrVar egy mutató típusú változó neve. A New eljárás végrehajtása következtében
olyan típusú változó jön létre, mint amilyenre a PtrVar mutat. A művelet elvégzése
után a PtrVar éppen a létrehozott változóra fog mutatni. Az új változó a halom-nak
(heap) nevezett tárterületen foglal helyet, és ugyanúgy kezelhető, mint tetszőleges
más - azonos típusú - változó.
Példa:
Type Matrix=array[boolean] of array[boolean] of real;
var MatrixPtr:^Matrix;
begin
New(MatrixPtr);
MatrixPtr^[true][true]:=23.5;
end.
A Dispose eljárás
Hívása: Dispose (PtrVar)
A PtrVar egy mutató típusú változó neve. A Dispose eljárás végrehajtása következtében
megszűnik az a változó, amelyre a PtrVar mutat. A megszüntetendő változót előzőleg
a New eljárással kell létrehozni. A változó által eddig lefoglalt tárterület
visszakerül a halomba, és más változók létrehozására újra felhasználható.
A Mark eljárás
Hívása: Mark (PtrVar)
A PtrVar egy tetszőleges típusra mutató változó neve. A Mark eljárás végrehajtása
következtében a PtrVar változó új értéke a halom pillanatnyi teteje lesz.
A Release eljárás
Hívása: Release (PtrVar)
A PtrVar egy tetszőleges típusra mutató változó neve, amely a Mark eljárással
kapott értéket. A Release eljárás végrehajtása következtében megszűnik az a
változó, amelyre a PtrVar mutat, és a halmon utána következő összes változó
is.
A New-Dispose és a Mark-Release eljárás két különböző halom-szervezési módszert
ad a programozónak; egy programban lehetőleg csak az egyiket használjuk! A két
módszer közötti lényeges különbséget a következő ábra mutatja, ahol a Ptr változó
a var3-ra mutat.
Halom
|
a Dispose után
|
a Release után
|
var1
|
var1
|
var1
|
var2
|
var2
|
var2
|
var3
|
||
var4
|
var4
|
|
var5
|
var5
|
A GetMem eljárás
Hívása: GetMem (PtrVar,IntExp)
A PtrVar egy mutató típusú változó neve, az IntExp pedig integer típusú kifejezés.
A GetMem eljárás lefoglalja a halmon az IntExp értékkel meghatározott (bájtban
értendő) tárterületet; a PtrVar mutató a lefoglalt területre fog mutatni.
A FreeMem eljárás
Hívása: FreeMem (PtrVar,IntExp)
A PtrVar egy mutató típusú változó neve, az IntExp pedig integer típusú kifejezés.
A FreeMem eljárás visszaadja a halomnak a PtrVar mutatóval megcímzett IntExp
méretű (bájtban értendő) tárterületet. A FreeMem eljárással visszaadott tárterületnek
pontosan akkorának kell lennie, mint a GetMem eljárással lefoglaltnak.
A MaxAvail függvény
Hívása: MaxAvail
A MaxAvail függvény értéke egy integer típusú adat, amely megadja a halmon hozzáférhető
legnagyobb összefüggő tárterület méretét (a 8 bites mikroszámítógépekét bájtban,
az IBM PC méretét pedig paragrafusban, ahol 1 paragrafus = 16 bájt). Ha az eredmény
negatív, akkor a valódi méretet úgy kapjuk meg, hogy az eredményhez a 65 536
valós számot adjuk hozzá.
A MemAvail függvény
Hívása: MemAvail
A MemAvail függvény értéke egy integer típusú adat, amely megadja a heap-ben hozzáférhető legnagyobb összefüggő tárterület méretét (a 8 bites mikroszámítógépekét bájtban, az IBM PC méretét pedig paragrafusban, ahol 1 paragrafus = 16 bájt). Ha az eredmény negatív, akkor a valódi méretet úgy kapjuk meg, hogy az eredményhez a 65 536 valós számot adjuk hozzá.
Tömb a halomterületen
A dinamikus helyfoglalás előnye természetesen akkor tűnik ki igazán, ha nem néhány bájtos, hanem több kilobájtos dinamikus változót, például tömböt, rekordot használunk. Erre mutat példát a következő program, melyben egy 20,5 kbyte méretű tömböt használunk. A tombt típusú tömböt a tptr mutató segítségével helyezzük el a halomterületen. A tömböt ebben az esetben a tptr^hivatkozással érjük el, a tömb elemeire pedig a tptr[i] kifejezéssel hivatkozhatunk.
Program Tomb;
const n=3500; { elemek szama }
type tombt=array[1..n] of real;
tombptr=^tombt;
var tptr:tombptr;
i:integer;
begin
randomize;
New(tptr); { helyfoglalas a tomb szamara }
for i:=1 to n do
tptr^[i]:=i*pi; { a tomb feltoltese }
for i:=1 to 20 do begin
i:=Random(n)+1;
Writeln(i:10,tptr^[i]:16:5,tptr^[i]/i:10:5);
end;
Dispose(tptr)
end.
14. Kezdeti értékadás
A Turbo Pascal nyelv lehetővé teszi, hogy a változóknak kezdeti értéket adhassunk.
Ha a program végrehajtásakor ezek a változók megőrzik kezdeti értéküket, akkor
konstansoknak tekinthetők. Ha viszont a program futtatásakor más, a kezdeti
értéküktől eltérő értéket is kapnak, akkor a program ismételt futtatásakor (ha
az az operatív tárban marad) ezek a változók az előző futás befejezése utáni
értékkel indulnak. Mivel egy ilyen program futtatásának ismételhetősége elvész,
csak a konstans jellegű változók használata ajánlott. Éppen ezért azon változódeklarációk,
amelyekben kezdeti értéket adunk, a programban a const kulcsszó (és nem
a var kulcsszó) után szerepelnek.
Példa:
Program Increment;
const
Number:integer=1;
begin
Writeln('Number=',Number);
Number:=Number+1
end.
A kezdeti értékadással bővített változódeklaráció tehát a következő:
változónév, kettőspont, típusleírás, egyenlőségjel, kezdeti érték, pontosvessző.
A kezdeti érték alakja a változó típusától függ. Elemi változókban konstans,
tömbváltozókban kerek zárójelekkel körülvett kezdeti értékek listája, rekordváltozókban
pedig - szintén kerek zárójelekkel körülvett - kezdeti értékek felsorolása.
Kétdimenziós tömb is deklarálható konstansként. Ez esetben a tömb elemeinek értékét sorindexenként zárójelben kell felsorolnunk:
Const:Number:array[1..5,1..3] of byte=
((5,3,1),(4,9,8),(3,3,3),(1,4,6),(2,2,5));
Példák:
Const
LineLength:byte=132;
Radius:real=13.64;
FullName:string[12]='Jan Bielecki';
CtrlM:char=^M;
Separator:set of char=[' /',';','.'];
SexIsMale:boolean=true;
ShortName:string[3]='Izabela';
WholeReal:real=44;
Ha a kezdeti értékkel inicializált változó egy tömb, akkor kezdeti értéke kerek zárójelekkel körülvett lista, amely felsorolja a tömb összes elemének kezdeti értékét. Ha a kezdeti értékkel inicializált változó egy rekord, akkor kezdeti értéke kerek zárójelekkel körülvett lista, amely felsorolja a rekord összes (vagy néhány) elemének kezdeti értékét. A kezdeti értékadások felsorolási sorrendjének azonosnak kell lennie a rekordkomponensek deklarációbeli sorrendjével. A lista elemeit pontosvesszők választják el; egy listaelem a rekordmező nevéből, a kettőspontból és a rekordmező kezdeti értékéből áll.
Példák:
Type
Color=(Red,Black,Fair);
Person=record
FirstName:string[3];
LastName:string [12];
Hair:Color;
Age:byte
end;
Sex=(male,female);
const
Vector:array[1..3] of Sex=(male,male,female);
Matrix:array[Color,2..3] of byte=((0,0),(1,1),(2,5));
ThreeD:array[boolean,boolean,boolean] of Color=
(((Red,Red),(Red,Fair)),((Black,Black),(Red,Black)));
JanB:Person=
(FirstName:'Jan';
LastName:'Bielecki';
Hair:Black;
Age:44);
Family:array[1..3] of Person=
(FirstName:'Jan';
LastName:'Bielecki';
Hair:Black;
Age:44),
(Firstname:'Ewa';
LastName:'Bielecka';
Hair:Black;
Age:38),
(FirstName:'Iza';
LastName:'Bielecka';
Hair:Black;
Age:3));
A változó rekordrészt tartalmazó rekordokban a kezdeti értékadásnak csak akkor van értelme, ha azokra a változó rekordrészmezőkre vonatkoznak, amelyek az adott változathoz tartoznak. Ezt a követelményt a fordítóprogram nem ellenőrzi.
15. Függvények és eljárások
A függvények és az eljárások olyan objektumok, amelyek a programmal megvalósított
algoritmus jól definiált részeit írják le. Emiatt a továbbiakban alprogramoknak
nevezzük őket.
Egyéb strukturált utasításoktól (pl. a kiválasztó utasítástól) eltérően az alprogram
végrehajtása igényli az alprogram hívását, azaz - a helyzetnek megfelelően az
eljáráshívó utasításnak vagy a függvény hívásának az alkalmazását. Az eljáráshívó
utasítás a program mindazon helyein szerepelhet, ahol tetszőleges utasítás állhat;
ezzel szemben a függvény hívása csak egy kifejezésben megengedett.
A változókhoz hasonlóan az alprogramokat is deklarálni kell. Az alprogramok
deklarációi a blokk deklarációs részében vannak. Az alprogram deklarációja a
fejlécből és az alprogram törzsét jelentő blokkból áll. Az eljárás fejléce a
következő: a procedure kulcsszó, az eljárásparaméterek felsorolása (kerek
zárójelekkel körülvéve) és a pontosvessző. A függvény fejléce a következő: a
function kulcsszó, a függvényparaméterek felsorolása (kerek zárójelekkel
körülvéve), a kettőspont, a függvény eredményének típusmeghatározása és a pontosvessző.
Ha az alprogramnak nincs paramétere, akkor a paraméter-felsorolás a körülvevő
zárójelekkel együtt elhagyható.
A függvény végrehajtásakor olyan értékadó utasításnak is lennie kell, amelyben
az értékadó szimbólum bal oldalán a függvény azonosítója, jobb oldalán pedig
a függvény eredményének típusával azonos típusú kifejezés áll. Ebben az értékadásban
a kifejezés értéke a függvény eredménye. A függvény végrehajtása nem korlátozódik
az eredmény átadására; a hívás argumentumainak megváltoztatását is jelentheti.
Az alprogram paramétereinek felsorolása pontosvesszővel elválasztott elemekből
áll. A felsorolás mindegyik eleme a paraméterazonosítók listája, amelyet kettőspont
és a listában szereplő paraméterek típusazonosítója követ.
Az alprogram hívásának pillanatában megtörténik az alprogram paramétereinek
és a hívás argumentumainak egymáshoz rendelése. Az argumentumok számának egyenlőnek
kell lennie a paraméterek számával; a paraméterek és az argumentumok egymáshoz
rendelése az alprogram fejlécében és hívásában meghatározott sorrendű.
A paramétert és az argumentumot kétféleképpen lehet egymáshoz rendelni: érték
vagy név szerint. Az érték szerinti hivatkozásban a paraméter az alprogram egyik
belső változójának tekinthető, amely az alprogram végrehajtásának pillanatában
(az adott hívásra értelmezve) megkapja az argumentum híváskori értékét. A név
szerinti hivatkozásban a paraméter magát az argumentumot képviseli. Ennek az
az eredménye, hogy a paraméteren értelmezett műveletek úgy hajtódnak végre,
mintha az argumentumra vonatkoznának. A név szerinti hivatkozást a paraméterazonosítók
listája előtt álló var kulcsszóval jelölhetjük ki.
A név szerinti hivatkozás különleges esetében az argumentum egy alprogram neve.
A Pascal nyelv szabványával ellentétben a Turbo Pascal nyelvből hiányzik az
ilyen hivatkozás lehetősége.
Paraméter nélküli eljárások
A paraméter nélküli eljárások általában mindig ugyanazt a műveletet végzik. Például az előre definiált ClrScr képernyőtörlést végez. Ha egy paraméter nélküli eljárás működését mégis kívülről kívánjuk vezérelni, akkor globális változókat használhatunk az alprogrammal való kommunikációra. Általánosságban elmondható, hogy a paraméter nélküli eljárások és globális változók együttes használata rossz programozási technikát takar.
Az értékparaméterek
Az eljárás fejlévében szereplő paramétereket formális paramétereknek nevezzük. Ezek határozzák meghatározzák, hogy az eljárás hívásakor hány és milyen típusú adatot kell megadnunk. Az eljárás törzsében a formális paraméterekre mint helyi (lokális) változókra hivatkozhatunk.
A paraméterek deklarációját a változódeklarációhoz hasonlóan kell elvégezni: a paraméternevet kettősponttal elválasztva követi a paraméter típusa:
Procedure PascalT(row:byte)
var c,i,k:integer;
begin
ClrScr;
for i:=0 to row do begin
GotoXY(37-i*3,i+1);
c:=1;
for k:=0 to i do begin
Write(c:6);
c:=(c*(i-k div k+1))
end;
Writeln
end;
end;
Ha több paramétert használunk, akkor az egyes paraméter-leírások közé pontosvesszőt kell tennünk:
Procedure Out(x:integer; y:integer; value:real);
Az azonos típusú paramétereket együtt is deklarálhatjuk:
Procedure Out(x,y:integer; value:real);
A szabványos Pascal nyelvvel ellentétben a Turbo pascal nem engedi, hogy típusleírást (mint például array[1..100] of char vagy string[100]) helyezzünk el a paraméterlistán. Az ilyen típusokhoz először típusnevet kell rendelnünk (type), amit aztán már minden korlátozás nélkül felhasználhatunk.
type tmat=array[1..10,1..10] of integer;
procedure kiir(m:tmat; n:integer);
var i,j:integer;
begin
for i:=1 to n do begin
for j:=1 to n do
write(m[i,j]:6);
writeln;
end;
end;
Az értékparaméter csak egyirányú kommunikációt tesz lehetővé a hívó program és az eljárás között. Eljáráshíváskor minden egyes aktuális (hívási) paraméter értéke a paraméterlista azonos helyén álló formális paraméterbe másolódik. Az eljáráson belül az átadott értékeket a formális paraméteren keresztül érhetjük el. A fordítóprogram az eljárás hívásakor ellenőrzi, hogy az aktuális és a formális paraméterek száma és típusa egyezik-e. Ha a paraméterek száma különböző, vagy ha két típus nem értékadás-kompatibilis (ami enyhébb a típusazonosság feltételénél), akkor hibajelzést kapunk.
Az értékparaméter összetett típusú is lehet. Ekkor a paraméterdeklarációban használt típusnévvel deklaráljuk a hívási paraméterlistában megadott változókat is.
A változó-paraméterek
A programozás során gyakran találkozunk olyan feladattal, amikor egy eljárás a paraméterein fejti ki hatását (például csökkenti, növeli vagy felcseréli azokat). Ekkor a bemenő (egyirányú) paraméterek használatával nem érjük el célunkat, hiszen az ilyen paramétereken elvégzett műveletek hatása csak az eljáráson belül érzékelhető. Megoldást az ún. változó-paraméterek bevezetése jelenti. A változó-paraméter kétirányú adatcserét biztosít a hívó program és a hívott eljárás között.
Az eljárás formális paraméterlistáján bármelyik értékparamétert változó-paraméterré alakíthatjuk, ha a neve elé a var foglalt szót tesszük.
Procedure Swp(var x,y:integer);
var tmp:integer;
begin
tmp:=x;x:=y;y:=tmp
end;
A lokális deklarációk
Minden eljárás rendelkezhet egy ún. saját (lokális) deklarációs résszel, ahol az eljárásban felhasználni kívánt címkéket, konstansokat, típusokat, változókat és esetleges további alprogramokat deklarálhatjuk. A lokális deklarációs rész az eljárás fejléce és a törzse között helyezkedik el. A lokálisan deklarált azonosítók az eljáráson kívülről nem érhetők el.
A lokális változók a paraméterekhez hasonlóan csak az eljárás hívásakor jönnek létre, és megszűnnek létezni, ha az eljárás visszatér a hívó programhoz. A legtöbb programozási nyelv az ilyen jellegű objektumait egy speciálisan kezelt adatterületen, a veremben (stack) tárolja. Ezzel szemben a főprogram szintjén létrehozott változók a program adatszegmensében helyezkednek el, és statikus élettartamúak. A statikus élettartamú változó a program indításakor jönnek létre, és csak a programból való kilépéskor semmisülnek meg.
A szabványos Pascal nyelvtől eltérően a Turbo Pascal-ban olyan lokális változót is létrehozhatunk, amely az eljáráshívások között is megőrzi értékét. Az ilyen tulajdonságú változókat típusos konstansként kell megadnunk a lokális deklarációs részben. Az alábbi eljárás minden híváskor 2 újabb hatványát írja ki:
Program Kettohat;
var ch:char;Procedure n2;
const e:integer=0;
h:real=1;
begin
writeln(2,'^',e:2,' =',h:10:0);
h:=h*2;e:=e+1
end;begin
for ch:='A' to 'U' do n2
end.
A példában e és a h változók a megadott értéket (0 és 1) egyetlenegyszer, a program indításakor veszik fel.
Példák:
(1, Egyparaméteres eljárás, érték szerinti hivatkozással:)
Program FiveMessages;
var Tally:byte;
Procedure SlowDown(Count:integer);
begin
for Count:=Count downto 1 do
end;begin
for Tally:=1 to 5 do begin
Writeln('Wake up!');
SlowDown(400)
end
end.
Példa:
(2. Kétparaméteres eljárás, név szerinti hivatkozással:)
Program ConvertAndSwap;
var theFloat:real;
theFixed:integer;Procedure Swap(var Float:real;var Fixed:integer);
var Temp:real;
begin
Temp:=Float;
Float:=Fixed;
Fixed:=trunc(Temp + 0.5)
end;begin
theFloat:=12.8;
theFixed:=10;
Writeln(theFloat,theFixed:3);
Swap(theFloat,theFixed);
Writeln(theFloat,theFixed:3)
end.
Példa:
(3. A legrövidebb, egy paraméter nélküli eljárás deklarációját
és hívását tartalmazó program:)
Procedure P;
begin
end;
begin
P
end.
Példa:
(4. Háromparaméteres függvény:)
Program MultiplyDivide;
var Product:integer;
Function Divide(SourceOne,SourceTwo:byte;
var Target:integer):real;
begin
Target:=SourceOne*SourceTwo;
Divide:=SourceOne/SourceTwo
end;
begin
Writeln(Divide(12,4,Product),Product:3)
end.
Példa:
(5. Az alprogramokat képviselő paramétereket tartalmazó alprogram:)
Program VeryComplicated;
Procedure Ext(procedure Par; Flag:boolean);
var Fix:byte;
Procedure Int;
begin
Fix:=Fix+1;
end;
begin {Ext}
Fix:=0;
if Flag then Ext(Int,false)
else Par;
Writeln(Fix)
end;
begin {VeryComplicated}
Ext(Ext,true)
end.
Példa:
Program MoveArray;
var
SourceArray:array[1..3,1..4] of integer;
TargetArray:array[1..2,1..6] of integer;
...
Procedure MoveBytes(var Source,Target; Count:integer);
var Index:integer;
type
ByteField=array[1..MaxInt] of byte;
var
Src:ByteField absolute Source;
Trg:ByteField absolute Target;
begin
for Index:=1 to Count do
Trg[Index]:=Src[Index]
end;
...
begin
...
MoveBytes(SourceArray,TargetArray,24);
...
end.
A háromszög területének kiszámítása csak az oldalak hosszúságának ismeretében Hérón-képlettel:
Function Haromsz_ter(a,b,c:real):real;
var s:real;
begin
s:=(a+b+c)/2;
Haromsz_ter:=Sqrt(s*(s-a)*(s-b)*(s-c));
end;
A függvényt például az alábbi módon lehet meghívni:
Writeln('Terulet = ',Haromsz_ter(6,8,7):6:2)
Az a program, amelyben meghatározott típusú paraméterhez eltérő
típusú argumentumot rendelünk, nyilvánvalóan hibás. Kivétel a real típusú paraméter,
mert ehhez integer típusú argumentum is hozzárendelhető.
Kizárólag a karakterlánc típusú paraméterek és argumentumok esetén mellőzhető
a típusazonosság követelménye. A {$V-} direktíva hatáskörén belül minden
karakterlánc típusú paraméter azonos a hozzárendelt karakterlánc típusú argumentummal.
Ezáltal tetszőleges típusú karakterláncok feldolgozására nyílik lehetőség.
A függvények és az eljárások összehasonlítása
A Pascal nyelvben alprogramokat eljárásként (procedure) és függvényként (function) egyaránt készíthetünk. A kétféle alprogram között nincs lényegi különbség, az alkalmazásuk módja határozza meg, hogy melyiket választjuk. A függvények sok mindenben (például a paraméterezés, a lokális deklarációk használata stb.) hasonlítanak az eljárásokra, azonban három lényeges dologban különböznek is tőlük:
15.1. Rekurzió
A többi Algol-szerű nyelvhez hasonlóan a Turbo Pascal nyelvben
megírt alprogramok rekurziós változatban is megfogalmazhatók, ez sokszor egyszerűsíti
az algoritmust. Egy függvényt vagy eljárás rekurzívnak nevezünk, ha az meghívja saját magát (közvetlen vagy közvetett rekurzióval). Fontos tudni, hogy 8-bites gépeken a fordító alapértelmezés szerint abszolút kódot generál, a lefordított progam így kisebb lesz, a programfutás pedig gyorsabb, rekurzív hívás viszont nem használható ebben a módban. Ha tehát rekurzív algoritmust használó programot akarunk írni, a program elején ki kell adnunk a
{$A-}
direktívát.
Egy eljárás vagy függvény hívásakor a veremre kerülnek a rutin lokális változói, paraméterei, valamint a visszatérési cím. Mindezek helye akkor szabadul fel, ha a vezérlés a rutin befejezésére kerül, vagyis a rutin befejezte a feladatát. Ezért a rekurzív program sokkal jobban igénybe veszi a vermet.
Példa:
Function Fibonacci(Index:byte):integer;
begin
if Index<3 then
Fibonacci:=1
else
Fibonacci:=Fibonacci(Index-1)+Fibonacci(Index-2)
end
A függvény kiszámítja a Fibonacci-sor elemeit. E sorban az első két elem értéke 1, az összes utána következő elemé pedig egyenlő az őt közvetlenül megelőző két elem összegével.
Ha a rekurziós algoritmus két olyan eljárást használ, amelyben
az első hívja a másodikat és a második is hívja az elsőt, lehetetlen úgy átrendezni
a deklarációkat, hogy minden hívás a már deklarált objektumra vonatkozzék. Ekkor
szükség van az ún. előzetes deklarációra, amely az alprogram fejlécéből, a pontosvesszőből
és a forward kulcsszóból áll.
Az előzetes deklaráció után a megfelelő helyen szerepelnie kell az alprogram
tulajdonképpeni deklarációjának. Ennek fejléce már nem tartalmazza a zárójelekkel
körülvett paraméterfelsorolást, függvény esetén pedig a kettőspontot és a típusmeghatározást
sem.
Példa:
Function FunOne(var Source:byte; Target:byte):char; forward;
Function FunTwo(Count:byte):real;
begin
...
Write(FunOne(Count,2 *Count));
...
end;
Function FunOne;
begin
...
Write(FunTwo(Source+Target));
...
end;
Hatványozás
A Turbo Pascal előre definiált függvényei között nincs hatványozás (csak négyzetre emelés). Írjunk eljárást, amely kiszámítja az A valós szám X. hatványát.
Ha X>=0, akkor A^X = A*A^(X-1), vagyis A^X kiszámításának problémája visszavezethető A^(X-1) kiszámítására. Ha ugyanis A^(X-1) ismert, akkor már csak A-val kell szorozni azt. A^(X-1) kiszámítását A^(X-2)-re vezethetjük vissza és így tovább. Mivel X=0-ra ismerjük a megoldást (definíció szerint 1), ezért a rekurzió véges számú lépés után befejeződik.
Definíció szerint A^-X = 1-A^X. Ha X<0, akkor -X>=0, ezért ilyen esetben a függvényt a -N paraméterrel hívjuk meg, és az eredmény reciprokát vesszük.
function Pow(a:real;x:integer):real;
begin
if x=0 then pow:=1
else if x>0 then
pow:=a*Pow(a,x-1)
else
pow:=1/Pow(a,-x)
end;
16. Standard alprogramok
A standard alprogram megnevezés azokra a beépített alprogramokra vonatkozik,
amelyek nyílt deklarálásuk nélkül használhatók. Számos ilyen alprogramot leírtunk
már az előzőekben; ide tartoznak azok az alprogramok, amelyek karakterláncokon
végeznek műveleteket (pl. a dinamikus társzervező alprogramok, valamint a beviteli,
ill. kiviteli műveleteket megvalósító alprogramok). Pascalban az alapvető I/O műveleteket is eljárások végzik.
E terjedelmes csoport kiegészítői a képernyős és a különleges eljárások, az
aritmetikai, a skalár és a konverziós függvények, valamint más segédfüggvények.
16.1. Képernyős eljárások
A képernyős eljárások azokban az implementációkban használhatók, amelyekben
installálták őket.
A ClrEol eljárás
Hívása: ClrEol
A CIrEoI eljárásnak nincs paramétere. Az eljárás szóközökkel felülírja a kurzor alatti és a tőle jobbra álló karaktereket a sor végéig. A kurzor pozíciója nem változik.A ClrScr eljárás
Hívása: ClrScr
A ClrScr eljárásnak nincs paramétere. Az eljárás "törli" a képernyőt, azaz szóközökkel tölti fel. A kurzor a képernyő bal felső sarkába kerül. Az installációtól függ, hogy a - később leírt - LowVideo és NormVideo eljárással beállított jellemzők változnak-e.A Crtlnit eljárás
Hívása: Crtlnit
A Crtlnit eljárásnak nincs paramétere. Az eljárás a Turbo Pascal rendszer installálásakor meghatározott inicializáló karaktersorozatot küld a képernyőre.A CrtExit eljárás
Hívása: CrtExit
A CrtExit eljárásnak nincs paramétere. Az eljárás a Turbo Pascal rendszer installálásakor meghatározott lezáró karaktersorozatot küld a képernyőre.A DelLine eljárás
Hívása: DelLine
A DelLine eljárásnak nincs paramétere. Az eljárás törli azt a sort, ahol a kurzor áll. Az alatta levő sorok eggyel feljebb kerülnek, így a képernyő legalsó sora üres lesz. A kurzor pozíciója nem változik.Az InsLine eljárás
Hívása: InsLine
Az InsLine eljárásnak nincs paramétere. Az eljárás hatására az a sor, ahol a kurzor áll (és az alatta levő sorok) eggyel lejjebb kerül. Így a képernyőn üres lesz a sor, ahol a kurzor áll, a legalsó sor pedig törlődik. A kurzor pozíciója nem változik.A GotoXY eljárás
Hívása: GotoXY(xPos,yPos)
Az xPos és az yPos integer típusú kifejezés. Az eljárás az (xPos,yPos) koordinátájú karakterpozícióba állítja a kurzort. A képernyő bal felső sarkának koordinátája (1,1); a vízszintes pozíciók balról jobbra, a függőlegesek pedig felülről lefelé növekednek. Ha az xPos vagy az yPos kifejezés értéke nagyobb a sor- vagy oszlopméretnél, akkor a rendszer azt a moduloméret szerint veszi figyelembe.A LowVideo eljárás
Hívása: LowVideo
A LowVideo eljárásnak nincs paramétere. Az eljárás hatására a legközelebbi NormVideo eljárás hívásáig a képernyőre kivitt karakterek más színben jelennek meg.A NormVideo eljárás
Hívása: NormVideo
A NormVideo étjárásnak nincs paramétere. Az eljárás a szokásosra (vö. a LowVideo eljárással) állítja vissza a karaktermegjelenítését.A Read és ReadLn eljárás
Hívása: ReadLn(változó)
Mindkét eljárás adatok bevitelére szolgál. (Mindkét eljárás file-típusokon is értelmezhető művelet, itt csak a képernyőről való beolvasást tárgyaljuk.) A Read és ReadLn eljárások segítségével adatokat olvashatunk be terminálról a memóriába. Ez azt jelenti, hogy amikor a program vezérlése ehhez az utasításhoz ér, akkor a billentyűzeten leütött karakterek az aktuális kurzorpozíciótól megjelennek a képernyőn, s azokat az ENTER leütéséig szerkeszthetjük. Ha a szerkesztés befejeződött (ezt az ENTER leütése jelenti), akkor azt a paraméterként megadott változóba (változó-azonosítóba) kerül. A Read eljárás paramétereként csak változó adható, vagyis a zárójelben csak változó azonosítója lehet.
A karakter begépelése után a karakter megjelenik, s a kurzor eggyel tovább lép. Ha az sor végén állt, akkor sort vált, és a gépelés a következő sorban folytatódik. A bevitt karaktereket szerkeszthetjük: az ERASE billentyűvel a legutoljára beütött karaktert törölhetjük, az ESC billentyű leütésével az összes most beírt karaktert törölhetjük. A Read és ReadLn eljárások után mindig soremelés következik a képernyőn, vagyis a kurzor a következő sor elejére áll. A begépelt adat természetesen ott marad.
Ha a Read által értelmezett adat nem adható értékül a változónak, akkor futási hiba következik be. A 9.5-öt nem tudja fogadni például egy Integer változó, vagy real típusú változóba string típusú adatot próbálunk bevinni. Ezért célszerű minden paramétert string típusú változóba bekérni, majd a megfelelő típusba konvertálni. A paraméter nélküli ReadLn eljárás nem csinál mást mint vár egy bevitelt, majd üríti a puffert. Felesleges tehát ekkor mást beütnünk, min az ENTER-t.
A Readln eljárás az ENTER billentyű lenyomása után az adatbeviteli puffer teljes tartalmát beolvassa és feldolgozza a paraméterként megadott változók típusának megfelelően. Ha a puffer több adatot tartalmaz a szükségesnél, akkor a fel nem dolgozott karakterek elvesznek. Amennyiben a pufferben nem volt elegendő adat a változók számára, akkor az eljárás az adatbevitel végét jelentő karaktereket - hasonlóan a szóközhöz - tagoló jelként értelmezi és várakozik a további adatbevitelre. Így egy Rreadln hívás után biztosak lehetünk abban, hogy a következő adatbeviteli utasítás csak az újonnan begépelt adatokat dolgozza fel.
Ezzel szemben a Read eljárás az ENTER billentyű lenyomása után csak annyi adatot dolgoz fel az adatbeviteli pufferből, amennyi a híváskor megadott változók számára szükséges. Ha a puffer több adatot tartalmaz, akkor a következő adatbeviteli utasítás megkapja a fel nem dolgozott részt.A Write és WriteLn eljárás
Hívása:
Write(kifejezés1,kifejezés2,...)
WriteLn(kifejezés1,kifejezés2,...)
Megjelenítés a képernyőn: A képernyőre a Write utasítással írhatunk. A Write és WnteLn utasítások közt mindössze annyi a különbség, hogy a WriteLn (Write Line) a kiírás végén sort emel, vagyis a kurzor a következő sor elejére kerül. A Write utasítás a felsorolt paramétereket egymás után, sorfolytonosan megjeleníti a képernyőn az aktuális kurzorpozíciótól kezdve. A Write-nak több paramétere is lehet. A Write utasítás használata több paraméterrel egyenértékű azzal, hogy ha az összes paraméterre egymás után alkalmazzuk azt. A Write paraméter nélküli használata értelmetlen. A paraméter nélküli WriteLn eljárással sort emelhetünk.
Numerikus kifejezés esetében, ha nem adunk meg mást, a rendszer eldönti, hogy hány karakterhelyen történjen a kiírás. Egész szám esetén a szám karakterlánc megfelelőjének a hossza a mérvadó. Valós szám esetén - ha nem rendelkezünk másképpen, - a lebegőpontos forma kerül kiírásra.
Minden paraméter után - legyen az szám vagy szöveg - megadhatjuk, hogy milyen hosszon kívánjuk a kiírást. Ha megadunk hosszt, és az nagyobb, mint a kiírandó karakterszám, jobbra ütköztetés történik. Ha a megadott hosszba nem fér ki a kiírandó karakterlánc, akkor a hossz felülbírálódik, vagyis több karakter kerül kiírásra, mint az általunk megadott szám.
Real típusú számok esetén egy második hossz is megadható, a tizedesjegyek száma. Egész szám esetén a kiírt tizedesjegy rész természetesen 0 lesz. Valós számoknál ekkor már nem a lebegőpontos forma kerül kiírásra, hanem a egész rész, tizedespont és a tizedesjegyek. Ha a tizedesjegyek számát is megadjuk, akkor az első hossz ekkor is a kiírandó karakterek teljes számát jelenti, tehát beleértve az előjelet, a tizedespontot és a tizedesjegyeket is. Ha a megadott tizedesjegyek száma kisebb, mint a kiírandó számé, akkor a kiírás kerekítve csonkul, ha pedig nagyobb, akkor jobbról nullákkal egészül ki. Az egész rész sem egész, sem valós számok esetén nem csonkul, legfeljebb hosszabban kerül kiírásra. Pl.:WriteLn(Sin(Pi/3):6:4)
Writeln('':5,'darabszam: ',db:4)Ha a képernyő utolsó sor utolsó pozíciójába írunk, vagy a WriteLn eljárással az utolsó sorba írunk, akkor képernyőgörgetés (scrollozás) történik, vagyis a képernyő összes sora egyel feljebb kerül, kiszorítva az eddigi legfelső sort, és egy üres alsó sor keletkezik, melybe a kurzor a sorváltás miatt kerül.
A logikai konstansok, változók és kifejezések értékének kilistázásakor kétféle eredményt kaphatunk a képernyőn: a TRUE vagy FALSE szót. Az ilyen eredmények kiíratásakor is megadhatunk mezőszélességet, ekkor a TRUE vagy FALSE szavak jobbra igazítva jelennek meg.
Példaprogram a henger térfogatának kiszámítására:
Program Terfog;
Var sugar,magassag,terfogat:real;
key:char;
Begin
repeat
Sugar:=0;Magassag:=0;
Clrscr;
LowVideo;
Gotoxy(27,8);Write('Henger terfogatszamitasa');
NormVideo;
Gotoxy(28,11);Write('Sugar : cm');
Gotoxy(28,13);Write('Magassag : cm');
Gotoxy(28,15);Write('------------------------');
Gotoxy(28,16);Write('Terfogat = m3');
Lowvideo;
Gotoxy(39,11);Readln(Sugar);
Gotoxy(39,11);Write(Sugar:10:2);
Gotoxy(39,13);Readln(Magassag);
Gotoxy(39,13);Write(Magassag:10:2);
Terfogat:=(Sqr(sugar)*Pi*magassag)/1e6;
Gotoxy(39,16);Write(Terfogat:10:2);
NormVideo;
Gotoxy(48,22);Write('ENTER / ESC');
repeat
read(kbd,key)
until (key=#13) or (key=#27)
until key=chr(27);
end.
A Delay eljárás
Hívása: Delay(Time)
A Time integer típusú kifejezés. Az eljárás a program végrehajtását kb. Time ms időtartamra felfüggeszti. Ha a Time kifejezés értéke negatív, akkor 0-nak tekinti a rendszer.A FillChar eljárás
Hívása: FillChar(Var,Cnt,Val)
A Var egy tetszőleges típusú változó neve, a Cnt integer típusú kifejezés, a Val pedig char vagy byte típusú kifejezés. Az eljárás a Var változó által lefoglalt tárterület elejétől Cnt számú bájtot feltölt a Val által képviselt bájtos adat értékével.Az Exit eljárás
Hívása: Exit
Az Exit eljárásnak nincs paramétere. Az eljárás hatására a vezérlés a blokk - amelyben a hívás szerepel - end kulcsszava elé adódik át. Ezzel befejeződik a blokk végrehajtása, ha pedig a programblokkban szerepelt az Exit hívása, akkor ez a program végét jelenti.A Halt eljárás
Hívása: Halt
A Halt eljárásnak nincs paramétere. Az eljárás hatására befejeződik a program futása.A Move eljárás
Hívása: Move(Src,Trg,Cnt)
Az Src és a Trg tetszőleges típusú változók neve, a Cnt pedig integer típusú kifejezés. Az eljárás az Src változó által lefoglalt terület elejéről Cnt számú bájtot másol át a Trg változó által lefoglalt terület elejére. Az eljárás akkor is helyesen másol, ha e területek részben vagy egészben fedik egymást.A Randomize eljárás
Hívása: Randomize
A Randomize eljárásnak nincs paramétere. Az eljárás véletlen értékű adattal inicializálja az álvéletlenszám-generátort.
Az Abs függvény
Hívása: Abs(Num)
A Num real vagy integer típusú kifejezés. Az Abs függvény értéke a Num képviselte adat abszolút értéke, típusa azonos az argumentum típusával.
Abs (-2) = 2
Abs(Pi) = 3.1415926536Az ArcTan függvény
Hívása: ArcTan(Num)
A Num real vagy integer típusú kifejezés. Az Arctan függvény értéke a Num képviselte adat arkusz tangense, típusa real.
ArcTan(0) = 0.0
ArcTan(1.0) = 0.7853981634A Cos függvény
Hívása: Cos(Num)
A Num real vagy integer típusú kifejezés. A Cos függvény értéke a Num képviselte adat koszinusza, típusa real.
Cos(0) -1.0
Cos(Pi) =-1.0Az Exp függvény
Hívása: Exp(Num)
A Num real vagy integer típusú kifejezés. Az Exp függvény típusa real, értéke az e^num hatványozás eredménye, ahol e a természetes logaritmus alapja: e = 2.7182818285.
Exp(0) -1.0
Exp(-1.0) = 0.36787944117A Frac függvény
Hívása: Frac(Num)
A Num real vagy integer típusú kifejezés. A Frac függvény értéke a Num képviselte adat törtrésze, típusa real.
Frac(3) = 0.0.
Frac(pi) = 0.1415926536Az Int függvény
Hívása: Int(Num)
A Num real vagy integer típusú kifejezés. Az Int függvény értéke a Num képviselte adat egészrésze, típusa real.
Int(2) = 2.0
Int(-Pi) = -3.0Az Ln függvény
Hívása: Ln (Num)
A Num real vagy integer típusú kifejezés. Az Ln függvény értéke a Num képviselte adat természetes alapú logaritmusa, típusa real.
Ln(1)=0.0
Ln(3.0) = 1.0986122887A Sin függvény
Hívása: Sin(Num)
A Num real vagy integer típusú kifejezés. A Sin függvény értéke a Num képviselte adat szinusza, típusa real.
Sin(0) = 0.0
Sin(Pi/2) =1.0Az Sqr függvény
Hívása: Sqr (Num)
A Num real vagy integer típusú kifejezés. Az Sqr függvény értéke a Num képviselte adat négyzete, típusa azonos az argumentum típusával.
Sqr(2) = 4
Sqr(2.0) = 4.0Az Sqrt függvény
Hívása: Sqrt (Num)
A Num real vagy integer típusú nemnegatív kifejezés. Az Sqrt függvény értéke a Num képviselte adat négyzetgyöke, típusa real.
Sqrt(4) = 2.0
Sqrt(4.0) = 2.0
A Turbo Pascal a szögfügvényeket radiánban számolja. A radián-fok konverzió könnyen elvégezhető.
Az x radián szög értékét fokban így határozhatjuk meg:
Function Deg(x:real):real;
begin
Deg:=x*180/Pi;
end;
Az x fok értéke radiánban, azaz x*PI/180:
Function Rad(x:real):real;
begin
Rad:=x*Pi/180;
end;
Néhány, a Turbo Pascal 3-ban nem definiált szögfüggvény kiszámítása:
A Tangens függvény
Function Tan(alfa:real):real;
begin
Tan:=Sin(alfa)/Cos(alfa)
end;A Kotangens függvény
Function Cot(alfa:real):real;
begin
Cot:=Cos(alfa)/Sin(alfa)
end;A Szekáns függvény
Function Sec(alfa:real):real;
begin
Sec:=1/Cos(alfa)
end;A Koszekáns függvény
Function Csc(alfa:real):real;
begin
Csc:=1/Sin(alfa)
end;A Hiperbolikus szinusz függvény
Function Sinh(alfa:real):real;
begin
Sinh:=(Exp(alfa)-Exp(-alfa))/2
end;A Hiperbolikus koszinusz függvény
Function Cosh(alfa:real):real;
begin
Cosh:=(Exp(alfa)+Exp(-alfa))/2
end;A Hiperbolikus szekáns függvény
Function Sech(alfa:real):real;
begin
Sech:=2/(Exp(alfa)+Exp(-alfa))
end;
Az Odd függvény
Hívása: Odd (Num)
A Num integer típusú kifejezés. Az Odd függvény "a Num kifejezés értéke páratlan szám" mondat logikai értékét adja meg, típusa boolean.
Odd(3) = true
Odd(4) = falseA Pred függvény
Hívása: Pred (Num)
A Num tetszőleges, rendezett típusú kifejezés. A Pred függvény értéke a rendezett típus azon eleme, amely közvetlenül az argumentum képviselte elem előtt áll, típusa azonos az argumentum típusával.
Pred('B') ='A'
Pred(-20) = -21A Succ függvény
Hívása: Succ (Num)
A Num tetszőleges, rendezett típusú kifejezés. A Succ függvény értéke a rendezett típus azon eleme, amely közvetlenül az argumentum képviselte elem után áll, típusa azonos az argumentum típusával.
Succ(false) = true
Succ(0) = 1
A Chr függvény
Hívása: Chr (Num)
A Num integer típusú kifejezés. A Chr függvény típusa char, értéke a Num kódú karakter.Chr(65) = 'A'
A beépített botkormány az alábbi kódokat adja:
joy jobbra
joy balra
joy fel
joy le= Chr(28);
= Chr(29);
= Chr(30);
= Chr(31)SHIFT + joy jobbra
SHIFT + joy balra
SHIFT + joy fel
SHIFT + joy le= Chr(189);
= Chr(185);
= Chr(177);
= Chr(181)CTRL + joy jobbra
CTRL + joy balra
CTRL + joy fel
CTRL + joy le= Chr(190);
= Chr(186);
= Chr(178);
= Chr(182);Az Ord függvény
Hívása: Ord (Num)
A Num tetszőleges, rendezett típusú kifejezés. Az Ord függvény típusa integer, értéke megadja a Num képviselte adat sorszámát a rendezett típuson belül.
Ord(true) = 1
Ord(-2) = -2Az alábi program kiírja a lenyomott billentyűt és annak kódját. A programot az ESC megnyomásával szakíthatjuk meg:
var key:char;
begin
repeat
Read(kbd,key);
Writeln(key,' = ',ord(key));
until key=chr(27)
end.A Round függvény
Hívása: Round (Num)
A Num real típusú kifejezés. A Round függvény típusa integer, értéke a Num képviselte adathoz legközelebb álló szám.
Round(5.5) = 6
Round(-1.5) = -2A Trunc függvény
Hívása: Trunc (Num)
A Num real típusú kifejezés. A Trunc függvény típusa integer, értéke a Num képviselte adat egészrésze.
Trunc(3.14) = 3
Trunc(-2.9) = -2
A Hi függvény
Hívása: Hi (Num)
A Num integer típusú kifejezés. A Hi függvény típusa integer, értéke a Num képviselte adat magasabb helyi értékű bájtja.
Hi(256) = 1
Hi(-1) = 255A KeyPressed függvény
Hívása: KeyPressed
A KeyPressed függvénynek nincs paramétere. A függvény boolean típusú, értéke "a konzol-pufferban van még be nem olvasott karakter" mondat logikai értékét adja meg. (Azaz, ha van a billentyűzet pufferben várakozó kód, akkor az értéke true.) A puffer tartalma változatlan marad, a függvény onnan nem vesz ki karaktert.A Lo függvény
Hívása: Lo (Num)
A Num integer típusú kifejezés. A Lo függvény típusa integer, értéke a Num képviselte adat alacsonyabb helyi értékű bájtja.
Lo(256) = 0
Lo(-1) = 255A ParamCount függvény
Hívása: ParamCount
(Csak a 3.x verziókban.) A ParamCount függvénynek nincs paramétere. A függvény integer típusú, értéke megadja a program hívásakor átadott paraméterek számát. Feltételezzük, hogy a paramétereket szóközök vagy tabulátorok választják el egymástól.A ParamStr függvény
Hívása: ParamStr (Num)
(Csak a 3.x verziókban.) A Num integer típusú kifejezés. A ParamStr függvény karaktertánc típusú adat, amely a program hívásakor átadott Num sorszámú paramétert jelenti. Feltételezzük, hogy az első paraméter sorszáma 1.A Random függvény
Hívása:
Random
Random (Num)
A Num integer típusú kifejezés. A Random függvény értéke paraméter nélküli változatban real típusú véletlen szám, amelynek értéke 0.0 vagy annál nagyobb, de 1.0-nél kisebb. Ha a Random függvénynek van paramétere, akkor az eredmény integer típusú véletlen szám, értéke 0.0 vagy annál nagyobb, de Num-nál kisebb.A SizeOf függvény
Hívása: SizeOf (Nam)
A Nam változónév vagy típusnév. A SizeOf függvény integer típusú, értéke megadja a Nam változónak kiosztott vagy a Nam típusú adat ábrázolásához szükséges bájtok számát.
SizeOf(Boolean) = 1
SizeOf(integer) = 2A Swap függvény
Hívása: Swap (Num)
A Num integer típusú kifejezés. A Swap függvény integer típusú, értékének magasabb helyi értékű bájtja Lo(Num), alacsonyabb helyi értékű bájtja pedig Hi(Num).
Swap(256) = 1
Swap(1) = 256Az UpCase függvény
Hívása: UpCase (Chr)
A Chr char típusú kifejezés. Az UpCase függvény char típusú, értéke - ha a Chr betű - nagybetű, különben Char.
UpCase('a') = 'A'
UpCase('.') = '.'
17. Állományok beillesztése
A fordítóprogram fontosabb direktívái közé tartozik az állományt beillesztő
direktíva (include). Alakja a következő:
{$I Name}
ahol Name az állomány neve. E direktívát új sorba kell írni. Végrehajtásakor
a fordítóprogram helyettesíti a Name nevű állomány tartalmával. Beilleszthetjük
vele a programba az előzőleg megírt deklarációs, ill. alprogram-könyvtárakat,
forrásnyelvi programrészeket, a beillesztett állományban azonban nem szerepelhet
egy újabb beillesztési direktíva.
Figyelembe kell még venni, hogy ha a Name állománynév nem tartalmaz hárombetűs
kiterjesztést, akkor a direktívát lezáró kapcsos zárójel és a Name között legalább
egy szóköz álljon, mert különben a fordítóprogram az állománynév részének tekinti
majd a zárójelet.
Példa:
Legyen a FACTOR.DOC állomány tartalma a következő:
Function Factorial(Num:byte):integer;
begin
if Num<2 then Factorial:=1
else Factorial:=Num*Factorial(Num-1)
end;
A program:
Program Demo;
{$I Factor.doc}
begin
Writeln(Factorial(5))
end.
E program fordítása olyan eredménnyel jár, mintha a következő programot fordítottuk volna le:
Program Demo;
Function Factorial(Num:byte):integer;
begin
if Num<2 then Factorial:=1
else Factorial:=Num*Factorial(Num-1)
end;
begin
Writeln(Factorial(5))
end.
Vagyis amikor a fordító az I direktívához ér, a megadott file tartalmát fordítja, majd azt befejezve, visszatér az eredeti programhoz, és annak soron következő utasításán folytatja a fordítást. A file-ot tehát csak logikailag szúrja be, veszi figyelembe a fordító, annak szövege fizikailag nem jelenik meg a programban, de a lefordított program kódja szempontjából a beszúrt rész egyenértékű azzal, mintha az is a forrásnyelvi szövegben lenne.
Fontos körülmény, hogy ha egy programon dolgozunk és a fordító a beszúrt file-ban talál hibát, akkor a programot elmenti és kurrens file-nak a beszúrt file-t tölti be, megjelölve azon a hiba helyét. Nem vész el tehát ez esetben sem az aktív file-on a legutóbbi módosítás sem. A fordító direktívák - a B és C kivételével - csak arra a file-ra vonatkoznak, amelyben előfordulnak.
A beszúrt file-ok alkalmazhatók a Turbo Pascal egy korlátjának áthidalására. A Turbo rendszer CP/M operációs rendszer alá futó változata egyszerre maximum kb. 24 Kbyte nagyságú forrásnyelvi programokkal tud dolgozni, ennyi szabad memória marad ugyanis a forrásnyelvi program tárolására. Ha ennél nagyobb forrásnyelvű file-ot akarunk lefordítani, akkor szét kell tördelnünk a több, 24 K-nál kisebb részre, majd össze kell fűzni őket logikailag a beszúrásos technikával. Az így keletkező programot már le tudja fordítani a compiler. A beszúrásos technikával készült forrásprogramok nagyságának forrásnyelvi szinten nincs felső korlátja. Csak az szab korlátot, hogy a lefordított - .COM kiterjesztésű - file nagysága nem haladhatja meg a 64 Kbyte-ot.
18. Alprogramok átlapolása
A Turbo Pascal és a CP/M rendszer lényeges korlátozása, hogy a tárgyprogram és adatai
valamint maga a futtató környezet nem lehetnek nagyobbak 64 kbájtnál. E korlátozás megkerülhető a 3.x verzióban az átlapolt alprogramok
(overlay módszer) alkalmazásával. A tárgyprogram számára kiosztott tárterület két részre bontható: tárrezidens
részre (amelyet a program állandó része fogfal le) és átlapolási (overlay) területre
(ahova az egyes átlapolt programrészek - alprogram-csoportok töltődnek be). Az átlapolási területen különböző időpontokban más-más modulok kódja helyezkedik el. A lemezen tárolt overlay-modulok a program igényeinek megfelelően töltődnek be a memóriába.
Eljárások és függvények is átlapolhatók; az átlapolt alprogramok azonban nem
hívhatók rekurzív módon, és nem szerepelhetnek előzetes deklarációkban sem.
Ez nem jelent akadályt, hiszen deklarálható egy nem átlapolt alprogram is, amely
a másik - eredetileg rekurzív módon hívandó - alprogramot hívja.
Hibakereséskor viszont számíthatunk bizonyos nehézségekre, ezért csak a kipróbált,
"belőtt" alprogramokat alakítsuk át átlapolttá.
Minden átlapolt alprogram-csoport több alprogramból áll; a csoporthoz egy átlapolási
terület tartozik. A program végrehajtásakor az átlapolási területen a csoport
egyetlen tagja tartózkodhat. E terület mérete akkora, hogy a csoport minden
alprogramja belefér. Ez azt is jelenti, hogy egy átlapolt csoport használatakor
a megtakarított tárterület a csoportméret és a csoporton belüli legnagyobb alprogram
méretének különbségével egyenlő.
Az operatív tár megtakarításának ára:
Az átlapolt alprogramcsoportok létrehozási szabálya igen egyszerű:
egy vagy több egymás utáni alprogram-deklaráció elé az overlay kulcsszót
kell írni. Az így kijelölt alprogramok csoportot alkotnak, melyet a rendszer
mágneslemezes állományban tárol. Az állomány neve a főprogram nevével azonos
(I. a rendszermenü M parancsát), kiterjesztése háromjegyű. Az első csoport kiterjesztése
.000, a másodiké .001 stb. Ha az átlapolt alprogramok között rezidens alprogramok
is szerepelnek, akkor az átlapoltak különálló csoportokba kerülnek. Az átlapolt
csoportok létrehozási szabálya nem zár ki újbóli átlapolást (az átlapolt alprogramon
belül).
Példa:
program OverlayProgram;
overlay procedure One;
begin
...
end;
overlay procedure Two;
begin
...
end;
procedure Middle;
begin
...
end;
overlay procedure Three;
begin
...
end;
overlay procedure Four;
begin
...
end;
begin
...
end.
Az OverlayProgram példaprogram lefordításából keletkezett tárgykód szerkezete:
19. Néhány kiválasztott implementációs bővítés
A Turbo Pascal rendszer - mint beépített képernyős szövegszerkesztővel rendelkező
programozási nyelv - különböző operációs rendszerek környezetében installálható.
Mindegyikben biztosítja az adott rendszerre és fordítóprogramra jellemző járulékos
szolgáltatásokat:
E bővítéseket a CP/M operációs rendszerben érvényes alakban mutatjuk be.
19.1. Nyílt helyfoglalás
programváltozók számára
A változódeklaráció absolute kulcsszavával helyet foglalhatunk a változó számára
egy másik változóhoz hozzárendelt címen vagy egy előírt című tárhelyen. Az ilyen
deklaráció a deklarált változó nevéből, a kettőspontból, az absolute
kulcsszóból, a tárhely-meghatározásból és a pontosvesszőből áll. A tárhely meghatározása
egy előzőleg deklarált név vagy egy abszolút cím (a 8 bites mikroszámítógépen
egy integer típusú konstans, az IBM PC esetén pedig kettősponttal elválasztott
szegmens- és eltolás-érték).
Példa (8 bites mikroszámítógépen:)
var CharStr:string[6];
StrLen:byte absolute CharStr;
Buffer:array[0..15] of byte absolute $2000;
Function Fun(var IntVar:integer):byte;
var LSB:byte absolute IntVar;
begin
if LSB=Lo(IntVar) then ...
...
end;
19.2. Különleges rendszerfüggvények és eljárások
Az Addr függvény
Hívása: Addr (Nam)
A Nam egy változó vagy egy alprogram neve. Az Addr függvény értéke integer típusú adat, a Nam változó (vagy alprogram) kijelölt tárcímét adja meg.
Addr(Mem[2])Az OvrDrive eljárás
Hívása: OvrDrive (Drv)
A Drv integer típusú kifejezés. Az OvrDrive eljárás hatására az átlapolt programrészek a Drv által meghatározott mágneslemezes egységről töltődnek be (0 = alapértelmezés szerinti egység, 1 = A, 2 = B stb.).
OvrDrive(2)
19.3. Rendszerrutinok hívása
(8 bites mikroszámítógép)
A rendszerrutinok falprogramok) a Bdos és Bios eljárással, valamint a Bdos,
BdosHL, Bios és BiosHL függvénnyel közvetlenül hívhatók.
A Bdos eljárás
Hívása:
Bdos (Fun,Par)
Bdos (Fun)
A Fun és az (elhagyható) Par integer típusín kifejezés. A Bdos eljárás végrehajtásakor a processzor C regiszterébe betöltődik a Fun képviselte adat alacsonyabb helyi értékű bájtja, ezután a program a 0005-ös címen folytatódik (vagyis a Fun sorszámú BDOS rendszerfunkciót hajtja végre). Ha a hívás kétparaméteres, akkor az említett ugrás előtt a Par képviselte adat a DE regiszterbe kerül.A Bdos függvény
Hívása:
Bdos (Fun,Par)
Bdos (Fun)
A Fun és az (elhagyható) Par integer típusú kifejezés. A Bdos függvényhívás hatása azonos a Bdos eljáráséval; a függvény értéke byte típusú adat, amelyet a BDOS az A regiszterben ad át.A BdosHL függvény
Hívása:
BdosHL (Fun,Par)
BdosHL (Fun)
A Fun és az (elhagyható) Par integer típusú kifejezés. A BdosHL függvényhívás hatása azonos a Bdos függvényével; a függvény értéke integer típusú adat, amelyet a BDOS a HL regiszterben ad át.A Bios eljárás
Hívása:
Bios (Fun,Par)
Bios (Fun)
A Fun és az (elhagyható) Par integer típusú kifejezés. A Bios eljárás a Fun sorszámú BIOS alrendszer-funkciót hajtja végre. Ha a hívásban szerepel a Par paraméter, akkor előtte a Par képviselte adat a processzor BC regiszterébe kerül.A Bios függvény
Hívása:
Bios (Fun,Par)
Bios (Fun)
A Fun és az (elhagyható) Par integer típusú kifejezés. A Bios függvényhívás hatása azonos a Bios eljáráséval; a függvény értéke byte típusú adat, amelyet a BIOS az A regiszterben ad át.A BiosHL függvény
Hívása:
BiosHL (Fun,Par)
BiosHL (Fun)
A Fun és az (elhagyható) Par integer típusú kifejezés. A BiosHL függvényhívás hatása azonos a Bios függvényével; a függvény értéke integer típusú adat, amelyet a BDOS a HL regiszterben ad át.
19.4. Gépi szintű programozás
Néha szükség van egy gépi kódú alprogram beillesztésére a Turbo Pascal nyelvben
megírt programba (vagy legalább egy gépi szintű "betét"-re). E célra
az external és az inline kulcsszót használhatjuk. Ha egy alprogram törzsét képező
blokk helyett az
external integer_típusú_ konstans
szerkezet fordul elő, akkor ez azt jelenti, hogy a gépi kódú alprogram e konstanssal meghatározott tárcímen található. Fontos, hogy az alprogram végrehajtásának eredményeként az SP regiszter tartalma (a veremméret) ne változzék!
Példa:
Function Factorial(Arg:byte):integer;
external $6000;
Az external szerkezet csupán a gépi kódú alprogram helyét mutatja meg, az inline utasítással azonban gépi kódot is generálhatunk. Az inline utasítás az inline kulcsszóból és az azt követő, kerek zárójelekkel körülvett kódelem-sorozatból áll. A kód elemeit perjelek választják el egymástól; minden kódelem + vagy - (mínusz) jellel elválasztott adatelemekből áll. Az adatelem lehet integer típusú konstans, változó vagy egy alprogram azonosítója és a *-gal jelölt programszámláló (PC) pillanatnyi értéke.
Példa:
inline(20/$40/Fun-2/ *+3)
Minden elem 1 bájtot vagy 1 szót (2 bájtot) hoz létre. Az előállított
adat az adatelemeken végrehajtott műveletek eredménye. A változó vagy az alprogram
azonosítója e változó (vagy alprogram) címét képviseli, a programszámláló szimbóluma
pedig azt a címet, ahova a generált kód kerül.
Ha egy kódelem kizárólag konstansokból és szeparátorokból áll, értéke pedig
0..255 között van, akkor a fordítóprogram 1 bájtot generál. Ha az érték ennél
nagyobb, ill, a kódelem változónevet vagy alprogramnevet, esetleg programszámláló-hivatkozást
tartalmaz, akkor a fordítóprogram 1 szót generál. E szóban az alacsonyabb helyi
értékű bájt megelőzi a magasabb helyi értékűt.
Ez a szabály felülbírálható a kódelem elé helyezett < vagy > jellel. Az
első esetben a szó alacsonyabb helyi értékű bájtja generálódik, a másodikban
pedig 2 bájt még akkor is, ha a második (magasabb helyi értékű) bájt tartalma
0.
Példa:
inline(>$12/<$3456)
Egy összetettebb példa (A Turbo Pascal Reference Manual, Version 3.0 alapján):
type anystr=string[255];
Procedure UpperStr(var Str:anystr);
begin
inline($2A/Str/$46/$04/$05/$CA/*+20/$23/
$7E/$FE/$61/$DA/*-9/$FE/$7B/$D2/
*-14/$D6/$20/$77/$C3/*-20)
end;
L1:
L2:LD HL,(Str)
LD B,(HL)
INC B
DEC B
JP Z,L2
INC HL
LD A,(HL)
CP 'a'
JP C,L1
CP 'z'+1
JP NC,L1
SUN 20H
LD (HL),A
JP L1
A gépi kódú rutinok készítését segíti a Turbo Pascal Assembler bővítés.
19.5. Külső programok indítása
A fordítóprogram által készített, lefordított (.COM kiterjesztésű) file-ok felépítésében közös, hogy az első 8 kbyte-juk tartalmazza a standard eljárásokat tartalmazó Turbo könyvtárat. A .COM file tehát két részből épül fel: az említett könyvtárból és magából a lefordított kódból. Egy rövidebb program esetében a file méretének nagyobb hányadát is kiteszi a Turbo könyvtár.
A fordító képes olyan kódot is generálni, amely nem tartalmazza a könyvtárat, csak a kódot. Az ilyen file .CHN kiterjesztést kap. Hogy melyik lehetőséget választjuk, azt a 'compiler options' menüből választhatjuk ki. A létrehozott .CHN kiterjesztésű file önmagában azonban nem futtatható, azt csak egy másik, .COM kiterjesztéssel fordított programból hívhatjuk meg.
A Turbo Pascal nyelvben írt programokban két segédeljárást használhatunk, ezek külső programok indítását (programok láncolását) teszik lehetővé. E két eljárás az
Execute(FileVar) és a Chain(FileVar),
ahol FileVar egy fájlváltozó neve. E változó azonosítja a betöltendő (külső) programot tartalmazó állományt. Az Execute eljárás .COM kiterjesztésű programot indít, a Chain pedig .CHN kiterjesztésűt.
Ha a meghívott program nincs a lemezen, akkor I/O hibát kapunk, kivéve, ha az 'I' direktívát előtte passzívvá tettük. Ez esetben a hibát a hívó programban kell lekezelni, az IoResult függvény segítségével. Ezt az első input-output műveletig kell megtenni, mivel I/O műveletet mindaddig nem tudunk végrehajtani I/O hiba után, míg az említett függvényt meg nem hívjuk. Ezután a hiba fajtáját a forrásprogramban le tudjuk kezelni.
A Chain-nel meghívott program tulajdonsága, hogy a hívó programot kitörli a tárból. Ezért az eljárás újbóli alkalmazásával lehet visszahívni.
A Turbo Pascal egyik tulajdonsága, hogy a deklarált változókat nem Inicializálja, ezért egy alprogram behívása után a tárban a főprogram által használt tárterület abban az állapotban marad, ahogy azt a főprogram hagyta. Ezt használhatjuk ki, oly módon, hogy a fő-és az alprogramban közös deklarációkat alkalmazunk. Azokat a változókat, amelyeket mindkét program használni kíván, mindkét programban elsőként és azonos sorrendben kell deklarálni, mert az Így lefoglalt tárterület a programok közös adatmezejének fogható fel, mivel ezek változatlan formában átadódnak a hívott programnak. Célszerű a közös deklarációkat egy include file-ba tenni, s azt minden - azt felhasználó - programban behívni. E szabály betartásával a hívó és a hívott programban szereplő (globális) változóhivatkozások ugyanazokra az adatokra vonatkoznak. Másik módja a közös adatmezők létrehozásának az abszolút című változók alkalmazása. Ezzel a lehetőséggel átgondoltan kell élni, mert a különböző programokban azonos helyre való rádefiniálás komoly problémákat okozhat.
A .CHN típusú programok előnye még, hogy a .COM file-oknál gyorsabban töltődnek be a memóriába. Lényeges, hogy a főprogramnak - illetve az először hívott programnak - .COM típusúnak kell lennie, míg az összes többi lehet .CHN típusú.
Példa:
Két program, amelyből az első átad a másodiknak egy karakterlánc típusú és egy
számadatot.
program First;
var LastName:string[8];
Age:byte;
NameFile:file;
begin
Write('Jan ');
LastName:='Bielecki';
Age:=44;
Assign(NameFile,'Second.chn');
Chain(NameFile)
end.Program Second;
var Surname:string[8];
Age:byte;
begin
Writeln(SurName,' is',Age:3,' now')
end.
19.6. Paraméterátadás
A Pascal program és alprogramjai közötti paraméterátadásról már volt szó. A 3.0-ás verziótól kezdve a teljes lefordított programot is lehetőség van paraméterezni, amikor az operációs rendszerből meghívjuk. Ehhez a ParamCount és a ParamStr standard függvényeket kell alkalmaznunk.
A ParamCount függvénynek nincs bemenő paramétere, visszatérési értéke pedig a paraméterek számát adja meg. A ParamStr függvény bemenő paramétere egy egész szám, értéke pedig a bemenő paraméterrel, mint sorszámmal kiválasztott paraméter értéke, azaz például ParamStr(3) értéke a programnak megadott 3. paraméter string formában (akkor is, ha a megadott paraméter pl. egész szám).
program param;
var k:integer;
begin
for k:=1 to ParamCount do
Writeln(k:1,'. parameter: ',ParamStr(k))
end.
A fenti lefordított példaprogramot IS-DOS-ból a
param par1 par2 par3
paranccsal elindítva láthatjuk, hogy a paramétereket az elválasztó szóközöktől "megtisztítva" kapjuk meg. Ha nem írunk programindításkor paramétert, a paraméter-számláló (ParamCount) értéke 0 lesz.
20. Az adatok ábrázolása (8 bites mikroszámítógépeken)
20.1. Rendezett típusú adatok
A rendezett típusú adatok az operatív tár 1 vagy 2 bájtját foglalják le.
Egybájtos ábrázolásúak a char típusú adatok, valamint azok a felsorolási típusú
adatok, amelyek 256 elemnél kisebb elemszámú halmazhoz kapcsolódnak, ill. azok
a min..max intervallum típusú adatok, amelyekben az ord(min) és az ord(max)
a 0..255 intervallumhoz tartozik. A boolean és a byte típusú adatok is 1 bájt
tárhelyet foglalnak le.
Kétbájtos ábrázolásúak az integer típusú adatok, az 1 bájtban nem ábrázolható
intervallum típusú adatok, valamint a 256 elemnél nagyobb elemszámú felsorolási
típusú adatok. A 2 bájtot elfoglaló adatokban az alacsonyabb helyi értékű bájt
mindig megelőzi a magasabb helyi értékűt.
Példa:
type Color=(Red,Green,Blue,Yellow,Orange);
Hue=Green..Yellow;
Selector=(enum,card,bool);
union=record case Selector of
enum:(Rng:Hue);
card:(Int:integer);
bool:(Log:boolean);
end;
const HueVar:union=(Rng:Green);
begin
with HueVar do
Write(Int,Log:5)
end.
20.2. Valós típusú adatok
A real típusú adatok az operatív tár 6 bájtját foglalják le. Ezek az adatok
egybájtos kitevőből és ötbájtos mantisszából tevődnek össze; a legkisebb címen
a szám kitevője van, ezt a mantissza bájtjai követik (a legalacsonyabb helyi
értékű bájttól a legmagasabbig). A kitevő értéke $80-nal eltolt; a mantissza
normalizált alakú, és a legmagasabb helyi értékű bitje nélkül tárolódik. Ez
az ún. implicit bit megadja a mantissza előjelét. Egy real típusú, 0.0 értékű
adat kitevője csupa 0-s bitből áll.
Példa:
type union=record case boolean of
false:(Float:real);
true: (Arr:array[0..5] of byte)
end;
const RealVar:union=(Arr:($83,0,0,0,0,$80));
begin
with RealVar do
Write(Float)
end.
20.3. Karakterlánc típusú adatok
A string[n] típusú adatok ábrázolása n+1 bájtot igényel. A karakterlánc típusú
adat első bájtja megadja ezen adat karaktereinek számát (a karakterlánc hosszát).
Példa:
const StrVar:string[5]='Janek';
procedure CutOff(var Par);
var len:byte absolute Par;
begin
Len:=Len-2
end;
begin
Writeln(StrVar);
CutOff(StrVar);
Write(StrVar)
end.
20.4. Halmaz tipusú adatok
A min legkisebb és a max legnagyobb elemű rendezett típuson alapuló halmaz típusú
adatok a memória
ord(max) div 8 - ord(min) div 8 + 1
bájtját foglalják le. A halmaz típusú adatok úgy ábrázolhatók, mintha a rendezett
alaptípus 256 elemből állna. Így egy változónak 32 bájtra lenne szüksége (elem
1 bitet foglal le, így 256 elem 256/9=32 bájtot., amelyek közül azonban az esetek
többségében csak keveset használunk (hiszen a halmaz típusú változó általában
256-nál kevesebb elemből áll), ezért a 32 bájtból a rendszer elhagyja azokat
a "szélső" bájtokat, amelyek értéke sosem változik.
A set of 10..16 típusú adat ábrázolásához pl. nem 32 bájtra van szükség (az
x-szel az adat "aktív" pozícióit jelöltük).
00000000 ... 00000000 000000x xxxxxx00 00000000,
hanem csak 2 bájt a helyigénye:
0000000x xxxxxx00
(a legalacsonyabb helyi értékű bájttól a legmagasabbig).
Példa:
type union=record
case boolean of
false:(Ref:^byte);
true: (Int:integer)
end;
const PtrVar:union=(Int:0);
begin
Write(PtrVar.Ref=nil)
end.
20.5. Mutató típusú adatok
A mutató típusú adatok 2 bájtot foglalnak le. Ábrázolásuk azonos az integer
típusú adatokéval, tartalmuk viszont más: memóriacímet jelentenek. A nil
mutató által képviselt adat csupa 0-s bitből áll.
20.6. Tömb típusú adatok
A tömbök elemei soronként helyezkednek el az operatív tárban.
Példa:
type union=record
case boolean of
false:(Arr:array[boolean,boolean] of byte);
true: (Vec:array[1..4] of byte)
end;
const ArrVar: union=(Arr:((11,12),(21,22)));
var index: 1..4;
begin
with ArrVar do
for Index:=1 to 4 do
Write(Vec[Index]:3)
end.
20.7. Rekordtípusok
A rekordmezők deklarációjuk sorrendjében helyezkednek el a memóriában. Ha a
rekord nem tartalmaz változórészt (variánst), akkor mérete azonos a mezőméretek
összegével, különben a fix rész és a legnagyobb helyigényű változat méretének
összege adja meg a rekord ábrázolásához szükséges tárhelyet. Akár tartalmaznak
változórészt, akár nem - a rekordok fix méretűek. Ez a tény lényeges a beviteli,
ill. kiviteli műveletek szempontjából.
Példa:
var RecVar:record
case Selector:integer of
6:(Arr:array (1..3,1..2] of byte);
8:(aSet:set of A'..'z')
end;
begin
with RecVar do
Write(SizeOf(RecVar),SizeOf(Arr):2,SizeOf(aSet):2)
end.
A Függelék: Kapcsolat az operációs rendszerrel
A Turbo Pascal külső rutingyűjteménnyel érheti el az Enterprise operációs rendszerének funkcióit. Erre szolgál az OS.TPU. Használatához közvetlenül a változódeklarációs rész után kell beilleszteni programunkba a következő utasítással:
{$I os.tpu}
A unitban néhány változó deklarálva van; a programban más ilyen nevű változókat nem használhatunk. Ezek rendre: ra,rb,rc,rd,re,rf,rh,rl,raf,rbc,rde,rhl BYTE ill. INTEGER típusú változók, amelyeken keresztül Z80 azonos jelölésű regisztereinek adhatunk át értékeket ill. itt kapjuk az eljáráshívás eredményétől függő értékeket vissza; és egy command nevű STRING ctype típussal.
A használható eljárások:
Az Exos eljárás
Hívása: Exos(funct)
A funct számú Exos funkcióhívás. Hívás előtt a kívánt regisztereknek megfelelő változók értékeit be kell állítani, és az eljárás ezekben a változókban adja vissza az EXOS által szolgáltatott értékeket. Például egy csatornát a következőképpen lehet lezárni:ra:=(a csatorna szama); exos(3);
Az Isdos eljárás
Hívása: Isdos(funct)
A func számú IS-DOS funkció hívása. Hasonlóan működik, mint az előző eljárás. Pl. a dátum lekérdezése a következőképpen lehetséges:Isdos($2A);
Ezek után rhl-ben az év, rd-ben a hónap, re-ben a nap sorszáma található, ra-ban pedig, hogy a hét melyik napja.
A Dos_com eljárás
Hívása: dos_com
DOS parancs végrehajtása. Hívása előtt a command változóba be kell tölteni a végrehajtani kívánt parancsfűzért. Például:command:='dir *.txt'; dos_com;
Ennek hatására megkapjuk a kívánt directory-t. Hibás parancs eseten a hibaüzenet íródik ki.
Az Stlin eljárás
Hívása: stlin(szöveg)
Írás a státuszsorba. Például azstlin('Fomenu');
utasításra megjelenik a státuszsorban a 'Fomenu' felirat. FIGYELEM! Mivel a státuszsor bal es jobb szélét a rendszer megszakításból írja ill. törli (CAPS, HOLD, stb. feliratok), ezért csak 22-23 karaktert tudunk kiírni.
A SetVar eljárás
Hívása: SetVar(változó,érték)
A 'változó' számú EXOS-változóba beírja a megadott értéket.A Toggle eljárás
Hívása: Toggle(változó)
A meagdott számú változó értékét átbillenti.A GetTime eljárás
Hívása: GetTime(óra,perc,másodperc)
A három integer típusú változóba betölti a rendszeridőt 24 órás alakban.A GetDate eljárás
Hívása: GetDate(év,hónap,nap)
A három integer típusú változóba betölti az aktuális rendszerdátumot. Az évet négy számjegyen adja.A SetTime eljárás
Hívása: SetTime(óra,perc,másodperc)
A rendszeridő beállítása. Minden változó integer típusú. Az órát 24 órás alakban kell megadni.A SetDate eljárás
Hívása: SetDate(év,hónap,nap)
A rendszerdátum beállítása. Minden változó integer típusú, az évet négy számjeggyel kell megadni.
A használható függvények:
A Bcd függvény
Hívása: Bcd(nr)
A byte típusú BCD számot decimális alakba konvertálja.A ToBcd függvény
Hívása: ToBCD(nr)
A byte típusú decimális számot BCD alakba konvertálja.Az Ask függvény
Hívása: Ask(n)
Az n számú rendszerváltozó állapotát adja vissza. N és az eredmény byte típusú érték.A Get függvény
Hívása: GET(ch)
A ch számú megnyitott csatornáról beolvas egy karaktert és visszaadja annak kódját integer típusú értékként. Ch byte típusú kifejezés. Ha nincs a csatornában karakter, akkor -1-et ad vissza. A GET grafikus képernyőn is működik, de itt nem a szín kódját adja vissza, hanem a grafikus laphoz tartozó szín-sorszámot. (Az ISDOS a 254-es csatornát rendeli a billentyűzethez.)A Joy függvény
Hívása: Joy(nr)
Az nr számú botkormány állapotát olvassa le. A visszaadott érték a botkormány helyzetétől függ:
1 - jobbra dől;
2 - balra dől;
4 - lefelé;
8 - felfelé;
16 - a tűzgomb benyomva.
Ha a botkormány átlósan áll vagy a tűzgomb is be van nyomva, akkor függvény az egyes értékek összegét adja. A beépített botkormány száma 0, ezenkívül az 1 (EXT1) és a 2 (EXT2) használható. A beépített botkormánynál a szóközbillentyű a tűzgomb. Pl.:repeat
j:=Joy(2);
Gotoxy(10,10);Write(j:2);
until j=16A ReadKey függvény
A függvény karaktert olvas a billentyűzetről. Ha a billentyűpuffer üres (nincs lenyomott billentyű), a függvény várakozik egy billentyű lenyomásáig. Az eljárásnak nincs paramétere, a visszaadott paraméter char típusú.
B Függelék: Grafika Enterprise-on
A Turbo Pascal kulcsszavak és eljárások nem tartalmaznak grafikus képernyőt kezelő eljárásokat. Ennek az az oka, hogy a grafikus képernyő kezelése hardware és operációs rendszer-függő, így a különböző CP/M-kompatibilis gépekre nem lehet egységes grafikus eljárásgyűjteményt készíteni. Enterprise-ra több ilyen rutingyűjtemény létezik, most az egyszerűen használható és kis méretű GRAFCS.TPU include-file-ban lévő eljárásokat ismertetjük.
Általános szabály, hogy azon programokat, melyekben használunk ilyen rutinokat csak úgy tudjuk futtatni, ha futtatható állományba fordítjuk ezeket! A program elején természetesen csatolni kell a fordítandó programhoz a rutingyűjteményt, esetünkben ezt a
{$I grafcs.tpu}
sorral tehetjük meg. A rutingyűjtemény a következő eljárásokat tartalmazza:
A GRAF_ON eljárás
Hívása: GRAF_ON(ch,vidmode,vidcolor,xsize,ysize)
Megnyitja ch csatornán a vidmode videó módú, vidcolor színüzemmódú, xsize és ysize méretű videólapot.A GRAF_OFF eljárás
Hívása: GRAF_OFF(ch)
Lezára a korábban megnyitott ch csatornaszámú videólapot. A program befejezése előtt zárjuk le a megnyitott videólapokat!A DISPLAY eljárás
Hívása: DISPLAY(ch,at,from,to)
Megjeleníti a már megnyitott ch csatornaszámú videólapot a képernyő at sorától kezdve. A videólap a from-adik sorától to számú sort jelenít meg.A PRINT eljárás
Hívása: PRINT(ch,str)
A ch csatornára kiírja str szövegfüzért a kurzor pillanatnyi pozíciójától kezdve. Írhatunk akár grafikus, akár szöveges videólapra is. Ha szöveges lapra írunk, számolnunk kell azzal, hogy nem használhatjuk az EDITOR eszközkezelő szolgáltatásait! (Nincs sor végi szóátvitel, és a sorok végén nekünk kell gondoskodni a kocsivissza, soremelés karakterek kiírásáról. A WRITE, WRITELN, READ, READLN eljárások természetesen nem működnek ezeken a videólapokon.).
Példa:Print(102,'Enterprise 128'+chr(10)+chr(13))
A GOXY eljárás
Hívása: GOXY(ch,x,y)
A ch csatornaszámú videólapon a szövegkurzort az x. sor y. oszlopába állítja. A grafikus sugármutató pozíciója változatlan marad. x és y integer típusú érték.A CLEAR eljárás
Hívása: CLEAR(ch)
Törli a ch csatornaszámú videólap tartalmát.A PLOT eljárás
Hívása: PLOT(ch,x,y)
A ch csatornaszámú grafikus videólap x,y pozíciójába mozgatja a rajzolósugarat. Ha a rajzolósugarat bekapcsolt állapotban hagyjuk, vonalat húzunk az előző rajzolósugár pozícióból. x és y integer típusú érték.A PLOTREL eljárás
Hívása: PLOTREL(ch,x,y)
A ch csatornaszámú grafikus videólapon az aktuális pozícióból az x és y távolságba mozgatja a rajzolósugarat. Azaz x és y relatív koordináták, így negatív értéket is felvehetnek. Ha a rajzolósugarat bekapcsolt állapotban hagyjuk, vonalat húzunk az előző rajzolósugár pozícióból. x és y integer típusú érték.A BEAM eljárás
Hívása: BEAM(ch,sw)
A rajzolósugarat kapcsolja ki-be ch csatornaszámú videólapon. Ha sw=0 a rajzolósugarat kikapcsoljuk, a sw nagyobb mint nulla, bekapcsoljuk. sw integer típusú érték.A MOVETO eljárás
Hívása: MOVETO(ch,x,y)
A rajzolósugarat az x,y pozícióba mozgatja, anélkül, hogy vonalat húzna. x és y integer típusú érték.A MOVEREL eljárás
Hívása: MOVEREL(ch,x,y)
Az aktuális rajzolósugár-pozíció áthelyezése relatív koordinátákkal megadott pontba: A ch csatornaszámú grafikus videólapon az aktuális pozícióból az x és y távolságba mozgatja a rajzolósugarat, anélkül, hogy vonalat húzna. x és y integer típusú érték.A DRAW eljárás
Hívása: DRAW(ch,x1,y1,x2,y2)
Vonalat húz x1,y1 és x2,y2 koordinátájú pontok között, a ch csatornaszámú videólapon. x1, y1 és x2,y2 integer típusú értékek.A BOX eljárás
Hívása: BOX(ch,x1,y1,x2,y2)
Négyszöget rajzol a ch csatornaszámú videólapon. A négyszög két átellenes sarka az x1,y1 és x2,y2 koordinátájú pont. x1, y1 és x2,y2 integer típusú értékek.Az ELLIPSE eljárás
Hívása: ELLIPSE(ch,x,y)
Ellipszist rajzol a ch csatornaszámú videólapon, melynek középpontja az aktuális rajzolósugár-pozíció. x az ellipszis vízszintes sugara, y a függőleges sugara, Ha x és y egyenlő, kört kapunk. Ha nem akarjuk, hogy az ellipszis közepén levő pont is megjelenjen a képernyőn, akkor a középpont kijelölése előtt kapcsoljuk ki a rajzolósugarat. x és y integer típusú érték.A PALETTE eljárás
Hívása: PALETTE(ch,c0,c1,c2,c3,c4,c5,c6,c7)
A ch csatornaszámú videólapra beállítja a színpalettát. 2 és 4 színes üzemmódban és meg kell adni c0-c7 értékeket is, melyek integer típusúak.Az INK eljárás
Hívása: INK(ch,color)
A tinta színét állítja be a ch csatornaszámú videólapon a színpaletta color sorszámú színére. A color integer típusú érték.A PAPER eljárás
Hívása: PAPER(ch,color)
A papír színét állítja be a ch csatornaszámú videólapon a színpaletta color sorszámú színére. A color integer típusú érték.A LINESTYLE eljárás
Hívása: LINESTYLE(ch,mode)
Szaggatott vonalak rajzolását teszi lehetővé a mode paraméter (1-14) értékélől függően a ch csatornaszámú videólapon. A mode integer típusú érték.A LINEMODE eljárás
Hívása: LINEMODE(ch,mode)
A régi és az új képernyősorok színeinek egymásra hatását adja meg a ch csatornaszámú videólapon. A mode integer típusú érték. Nullás módban (alapértelmezés) az új sorok színei felülírják a régieket, a többi módban viszont a kettő kombinációja alakul ki a következők szerint:
mód 1 - vagy (OR)
mód 2 - és (AND)
mód 3 - kizáró vagy (XOR).A FILL eljárás
Hívása: FILL(ch)
Zárt alakzat kitöltése az aktuális tintaszínnel, a ch csatornaszámú videólap aktuális sugárpozíciójából kiindulva.
A ch (csatornaszám) minden esetben byte típusú. A rutinok nem végeznek hibaellenőrzést. Ha pl. az újonnan megnyitandó videólapnak már nincs elég memória, vagy nem megnyitott csatornára hivatkozunk, a program nem áll le, hibajelzést nem kapunk, de a művelet sikertelen maradt. Erre teszteléskor legyünk figyelemmel!
Példaprogramok a Felhasználói Kézikönyv bemutató programjai alapján:
Program Ellipse;
{$I grafcs.tpu}
var sugar:integer;
begin
Randomize;
Graf_ON(101,1,1,40,20);
Display(101,1,1,20);
Plot(101,640,360);
repeat
for sugar:=16 downto 1 do begin
Ink(101,random(3)+1);
Ellipse(101,sugar*16,sugar*16);Fill(101)
end;
until KeyPressed;
Graf_OFF(101)
end.Program Csatorna;
{$I grafcs.tpu}
const x:integer=640;y:integer=360;
var a,a1,c,c1:integer;
r:byte;
Procedure Tuzlabda(szin,x1,y1:integer);
var jel:byte;
sugar:integer;
begin
Linemode(101,3);
Ink(101,szin);Beam(101,1);
for jel:=1 to 2 do
for sugar:=1 to 21 do begin
Plot(101,x1,y1);Ellipse(101,sugar*30,sugar*30)
end;
Linemode(101,0)
end;
begin
Graf_ON(101,1,3,40,20);
Display(101,1,1,20);
for r:=1 to 255 do begin
Ink(101,r);
a:=x-r-220;a1:=y-r-50;
c:=x+r+220;c1:=y+r+50;
Box(101,a,a1,c,c1)
end;
MoveTo(101,x,y);
repeat
Tuzlabda(random(254)+1,x,y);
until KeyPressed;
Graf_OFF(101)
end.
A TURTLE.TPU bővítmény a Logo-ból (és IS-BASIC-ből) ismert teknőcgrafikus utasításokat tartalmazza. A bővítmény használja a GRAFCS.TPU eljárásait, ezért azt is be kell illesztenünk a lefordítandó programba, még a TURTLE.TPU előtt. A bővítmény használja az integer típusú ANGLE változót, amely azt tartalmazza, hogy a rajzolósugár merre nézzen, szögekben kifejezve. A 0 fok a képernyő jobb széle felé, a 90 fok felfelé, a 180 fok balra és a 270 fok lefelé mutat. A bővítmény eljárásai:
A FORWD eljárás
Hívása: FORWD(ch,d)
A ch csatornaszámú videólapon a rajzolósugár d pozíciót halad előre (amerre az ANGLE változó "mutat"). A d integer, a ch itt és a továbbiakban is byte típusú érték.A BACK eljárás
Hívása: BACK(ch,d)
A ch csatornaszámú videólapon a rajzolósugár d pozíciót halad hátrafelé (ellenkező irányba, mint amerre az ANGLE változó "mutat"). A d integer típusú érték.A RIGHT eljárás
Hívása: BACK(a)
A rajzolósugár a fokkal jobbra fordul. a integer típusú érték.A LEFT eljárás
Hívása: LEFT(a)
A rajzolósugár a fokkal balra fordul. a integer típusú érték. A LEFT és RIGHT utasítás az adott szög többszörösét is elfogadja és értelmezi (pl. 10 fok helyett 370 fokot).A DEG függvény
Hívása: DEG(a)
Megadja az a radián szög értékét fokban.A RAD függvény
Hívása: RAD(a)
Megadja az a fok értékét radiánban.
Példaprogram:
Program FractalTree;
{$A-}
{$I grafcs.tpu}
{$I turtle.tpu}
Procedure Tree(n:integer);
begin
if n>24 then begin
Forwd(1,n);Right(25);
Tree(Trunc(n*0.75));
Left(50);
Tree(Trunc(n*0.75));
Right(25);Back(1,n)
end
end;
begin
Graf_ON(1,1,0,40,20);
Palette(1,0,170,0,0,0,0,0,0);
Display(1,1,1,20);
Plot(1,640,10);Beam(1,1);
angle:=90;
Tree(200);
repeat until KeyPressed;
Graf_OFF(1)
end.
Fordítás alatti hibák
1 Hiányzó ';' 2 Hiányzó ':' 3 Hiányzó ',' 4 Hiányzó '(' 5 Hiányzó ')' 6 Hiányzó '=' 7 Hiányzó ':=' 8 Hiányzó'[' 9 Hiányzó ']' 10 Hiányzó'.' 11 Hiányzó'..' 12 Hiányzó 'BEGIN' 13 Hiányzó 'DO' 14 Hiányzó 'END' 15 Hiányzó 'OF' 16 Hiányzó 'PROCEDURE' vagy 'FUNCTION' 17 Hiányzó 'THEN' 18 Hiányzó 'TO' vagy 'DOWNTO' 20 Hiányzó boolean típusú kifejezés 21 Hiányzó fájlváltozó 22 Hiányzó egész típusú konstans 23 Hiányzó egész típusú kifejezés 24 Hiányzó egész típusú változó 25 Hiányzó egész vagy valós típusú konstans 26 Hiányzó egész vagy valós típusú kifejezés 27 Hiányzó egész vagy valós típusú változó 28 Hiányzó mutató típusú változó 29 Hiányzó rekord típusú változó 30 Hiányzó elemi típus 31 Hiányzó elemi kifejezés 32 Hiányzó karakterlánc típusú konstans 33 Hiányzó karakterlánc típusú kifejezés 34 Hiányzó karakterlánc típusú változó 35 Hiányzó szövegfájl-azonosító 36 Hiányzó típusazonosító 37 Hiányzó elemtípus nélküli fájlazonosító 40 Definiálatlan címke 41 Ismeretlen azonosító vagy szintaxishiba |
42 Ismeretlen mutatótípus 43 Újradefiniált címke vagy azonosító 44 Hibás típus 45 Intervallumon kívüli konstansérték 46 Hibás konstanstípus vagy CASE-kiválasztó 47 Hibás argumentum vagy operátor 48 Hibás eredménytípus 49 Hibás karakterlánc-hossz 50 Hibás a karakterlánc-konstans mérete 51 Hibás az intervallumtípus alaptípusa 52 A felső határ kisebb az alsónál 53 Fenntartott szó 54 Hibás értékadás 55 A karakterlánc-konstans egy sornál hosszabb 56 Hibás egész típusú konstans 57 Hibás valós típusú konstans 58 Hibás karakter az azonosítóban 60 Konstans itt nem használható 61 Fájl és mutató típusú változók itt nem használhatók 62 Strukturált változók itt nem használhatók 63 Szövegfájlok itt nem használhatók 64 Szövegfájlok és elemtípus nélküli fájlok itt nem használhatók 65 Elemtípus nélküli fájlok itt nem használhatók 66 Bemeneti, ill. kimeneti műveletek itt nem használhatók 67 A fájlváltozók igénylik a VAR deklarációt 68 A fájlok nem lehetnek fájlelemek 69 Hibás mező-hozzárendelés 70 Túl nagy halmaz 71 Hibás GOTO 72 Az aktuális blokkon kívüli címke 73 Definiálatlan FORWARD eljárás 74 Hibás INLINE utasítás 75 Hibás az ABSOLUTE használata 90 Ismeretlen fájlváltozó 91 Váratlan programvég 97 Túl sok egymásba ágyazott WITH 98 Memóriatúlcsordulás 99 A fordítóprogram túlcsordult |
Futásidejű hibák
Egy program végrehajtásakor kétféle hiba fordulhat elő: fatális és beviteli,
ill. kiviteli hiba. Fatális hiba esetén a következő felirat íródik ki:
Run-time error NN, PC=addr
Program aborted
ahol NN a hiba kódja, az addr pedig a hibát előidéző utasítás memóriacíme.
Beviteli, ill. kiviteli hiba esetén az üzenet alakja:
I/O error NN, PC=addr
Program aborted
ahol NN és addr jelentése azonos az előbbivel.
Fatális hibák
01 - Fixpontos túlcsordulás
02 - Nullával való osztás
03 - Hibás az Sqrt argumentuma (negatív)
04 - Hibás az Ln függvény argumentuma (negatív vagy nulla)
10 - 255 karakternél hosszabb karakterlánc létrehozása, ill. 1 karakternél hosszabb
karakterlánc char típusú adattá konvertálása
11
- a Copy, Delete vany Insert eljárásokban megadott indexkifejezés értéke nem esik 1 és 255 közé
90 - Hibás tömbindex
91 - Hibás értékadás: az adat értéke a megengedett intervallumon kívülre esik
92 - A Trunc vagy a Round függvény argumentuma a megengedett intervallumon kívülre
esik
FF - Elfogyott a memória. New vagy rekurzív eljárást hívva nincs elég szabad memória
Beviteli, illetve kiviteli hibák
01 - A fájl nem létezik
02 - A fájl nincs nyitva olvasásra
03 - A fájl nincs nyitva írásra
04 - A fájl nincs nyitva
10 - Számábrázolási hiba
20 - Tiltott művelet
21 - Tiltott művelet
22 - Az Assign eljárás használata nem megengedett
90 - Összeférhetetlenség a rekordméreteknél
91 - Fájlon kívüli hozzáférés kísérlete
99 - Váratlan fájlvég
F0 - A mágneslemez írási hibája
F1 - Katalógustúlcsordulás
F2 - Fájltúlcsordulás
F3 - Túl sok fájl van már nyitva
FF - Hiányzó fájl
D. Függelék: Képernyős szövegszerkesztő
Alapfogalmak
A WordStar képernyős szövegszerkesztőt a MikroPro cég terjesztette el a mikroszámítógépes
piacon, 1977-től kezdve. A program fő előnye (és elterjedésének oka) a valódi
"full screen" (teljes képernyős) szerkesztési elv, és a program gépfüggetlen
installálásának lehetősége. Számos szövegszerkesztő vetélytárs megjelenése után
a WordStar megőrizte vezető pozícióját, és néhány "mutációja" a 8
és 16 bites számítógépeken is használható. A következőkben a Turbo Pascal rendszerbeli
implementációját mutatjuk be.
Több más szövegszerkesztőtől eltérően a WordStar program főleg a szövegbevitelt
támogatja, és kevésbé alkalmas a szövegfeldolgozó parancsok végrehajtására.
Ennek következményeként a szövegen végrehajtandó műveletek olyan karakterekkel
végezhetők, amelyek láthatóan közvetlenül nem ábrázolhatók. E karaktereket vezérlőkaraktereknek
nevezzük; bevitelükhöz a CTRL billentyűt egy vagy két betűjeles billentyűvel
együtt kell lenyomni. Mivel a továbbiakban gyakran hivatkozunk a vezérlőkarakterekre,
jelképes jelölésükben a ^ jel a CTRL billentyű lenyomását jelenti. Így pl. a
CTRL A vezérlőkarakter jelölése ^A, bevitele pedig a CTRL billentyű lenyomott
állapotában leütött A billentyűvel lehetséges. Azokban az esetekben, amikor
a szövegszerkesztőnek kiadandó parancs két vezérlőkarakterből áll (pl. ^KB),
lenyomjuk a CTRL billentyűt, és ezután ütjük le a K és a B billentyűt (a második
billentyű leütésekor már nem kell lenyomva tartani a CTRL billentyűt).
A szövegszerkesztő szokásos használata a főmenüből kiadott E paranccsal kezdődik.
Ennek hatására elindul a szövegszerkesztő program, amely "kiteríti"
a képernyőre az előzőleg W paranccsal azonosított munkaállomány tartalmát (kezdőrészét).
A szövegbevitel vagy -módosítás befejeztével a ^KD paranccsal visszatérhetünk
a főmenühöz, ahonnan kiadhatjuk az S parancsot, amely mágneslemezre menti ki
a munkaállományt.
A szövegszerkesztő program indítása után a számítógép többfunkciós írógépként
használható. Az írógép alapvető tulajdonsága, hogy minden bevitt karakter azonnal
megjelenik a képernyőn. A hibásan bevitt karaktereket a Backspace billentyűvel
törölhetjük. Ha a javítandó hibák a már korábban bevitt szavakban találhatók,
akkor a kurzormozgató billentyűkkel a kurzort elvihetjük a javítás helyére,
és a módosítást azonnal végre is hajthatjuk. A módosítás szabályait a következő
szakasz tartalmazza.
Szövegbevitel, -módosítás és -törlés
Az alábbiakban az alapértelmezés szerinti billentyűzetkiosztást ismerhetjük meg, ezután az ENTERPRISE-on beállított kiosztást.
Mint már említettük, a szövegszerkesztő program indítása után szöveget gépelünk
be vagy módosítunk. E tevékenységek lényegében új szavak bevitelét vagy a már
bevitt szavakon végzett műveleteket jelentik. Itt a szó fogalmán tetszőleges
karaktersorozatot értünk, amelyet egy szóköz vagy más elválasztó-karakter (pl.
vessző, pont, kettőspont, aposztróf) zár le. E definíció értelmében példaprogramunk
program JanB;
begin
Write('I am JanB')
end.
a következő szavakból áll:
program
JanB;
Begin
Write('
I
Am
JanB'
)
end.
A képernyőn megjelenített szövegrészen belül kitüntetett a kurzor feletti karakter
szerepe. A szövegmanipulációk mindig e karakterre (vagy az őt tartalmazó szóra,
ill. sorra) vonatkoznak. A kurzort karakterenként, szavanként, soronként és
laponként mozgathatjuk (a lap több sorból álló szövegrész, mérete egyenlő a
képernyő kapacitásával).
A kurzort egy pozícióval balra, jobbra, felfelé vagy lefelé a ^S, ^D, ^E és
^X parancsokkal mozgathatjuk. E parancsok betűjeles billentyűi négyzetet alkotnak.
Így könnyű megjegyezni, hogy az ^E parancs egy pozícióval felfelé, a ^X egy
pozícióval lefelé, az ^S és a ^D egy pozícióval balra, ill. jobbra mozgatja
a kurzort. Látható, hogy a kurzormozgató parancsok ilyen hozzárendelése nem
az egyes betűkhöz kapcsolódik, hanem a négy billentyű síkbeli elrendezésén alapul.
A szavankénti kurzormozgatást az ^A és az ^F parancs valósítja meg. Az ^A parancs
egy szópozícióval balra (az előző szóra), az ^F pedig egy szópozícióval jobbra
(a következő szóra) állítja a kurzort.
Laponkénti kurzormozgatásra (előre- és hátralapozásra) az ^R és a ^C parancs
való. Billentyűik az E-X billentyűk által kijelölt tengely jobb oldalán helyezkednek
el. E tengely bal oldalán viszont azok a billentyűk kaptak helyet, amelyek a
képernyő tartalmát egy sorral lefelé (^W) vagy felfelé (^Z) mozgatják.
Ez az elrendezés könnyen megtanulható, ezért nincs szükség külön billentyűfeliratokra
vagy magyarázó táblázatra. A fenti billentyűk jobb oldalán három újabb parancsbillentyűt
találunk: ^T, ^Y, ^G. A ^G parancs a kurzor feletti karaktert törli, a ^T parancs
a kurzor feletti és a tőle jobbra álló karaktereket a szó végéig, a ^Y parancs
pedig az egész sort. Végül megemlítjük a Backspace billentyűt, amely a kurzortól
balra eső karaktert törli.
Összefoglalás
^E | A kurzor mozgatása egy sorral felfelé; az oszloppozíció nem változik. |
^X | A kurzor mozgatása egy sorral lefelé; az oszloppozíció nem változik. |
^S | A kurzor mozgatása egy pozícióval balra; ha a kurzor a sor elején áll (bal szélső pozíció), akkor a parancs hatástalan. |
^D | A kurzor mozgatása egy pozícióval jobbra; ha a kurzor a sor végén áll (jobb szélső pozíció), akkor a parancs hatástalan. |
^A | A kurzor mozgatása az előző szó elejére. |
^F | A kurzor mozgatása a következő szó elejére. |
^R | Lapozás felfelé. |
^C | Lapozás lefelé. |
^W | A képernyőtartalom mozgatása egy sorral lefelé ("roll down"). |
^Z | A képernyőtartalom mozgatása egy sorral felfelé ("roll up"). |
^G | Karaktertörlés. |
^T | Karaktertörlés a szó végéig. |
^Y | Sortörlés. |
^N | Sorbeszúrás |
Backspace | A kurzortól balra eső karakter törlése. |
Ezeket a parancsokat egészíti ki az ^N parancs, amely egy üres
sort hoz létre, és az előbbi kurzormozgató billentyűkhöz hasonló hatású, de
nagyobb "lépéssel" értelmezendő parancsok: a ^Q vezérlőkarakter után
leütött E, R, S, D, X, C billentyűk valamelyike. A ^QE parancs a kurzort a képernyő
első sorába viszi, a ^QX parancs az utolsó sorba, a ^QS a sor elejére, a ^QD
pedig a sor végére. A ^QR és a ^QC parancs a szöveg elejére, ill. végére viszi
a kurzort.
Az itt felsorolt kurzormozgató parancsok lehetővé teszik a szöveghelyesség ellenőrzését
és a szöveg módosítását. Módosításkor előfordulhat a már begépelt szöveg kiegészítése
vagy a szöveg helyettesítése más karaktersorozatokkal.
Kiegészítéskor (beszúrás, ínsert) elegendő begépelni az új szöveget; a szövegszerkesztő
program automatikusan beszúrja (a kurzor pillanatnyi pozíciójától kezdve) úgy,
hogy az utána álló karaktereket jobbra tolja.
Módosításkor (felülírás, overwrite) a ^V paranccsal kikapcsolhatjuk ezt a szolgáltatást,
így a begépelt karakterek felülírják a régieket. A ^V parancs újbóli kiadása
visszaállítja a beszúrás üzemmódot.
Összetett szövegműveletek
Az eddig leírt parancsok nemcsak szöveges állományok létrehozására alkalmasak,
hanem a szövegfeldolgozást is lehetővé teszik. Mégis gyakran szükség van olyan
műveletekre, amelyek a szöveg egy részét egyszerre kezelik (pl. szövegmásolás
vagy -áthelyezés), vagy pedig képesek mintakeresésre és szöveghelyettesítésre.
Erre használhatjuk a következő parancsokat.
A ^QF parancs
Először a képernyőn megjelenő
FIND:
kérdésre adjuk meg a keresendő mondatot (mintát). A mondat tetszőleges karaktersorozat,
melyet az Enter billentyű zár le. A következő
OPTIONS:
kérdésre adott válasz meghatározza a keresés módját. A leggyakoribb esetben
(keresés a kurzor pozíciójától a szöveg végéig) elegendő az ENTER billentyű
leütése. Ha a keresett mondat szerepel a szövegben, akkor a kurzor megáll a
megtalált mondat utolsó karaktere mögött. Más keresési opciók pl. a következők:
B - visszafelé keres;
W - csak teljes szavakat keres;
U - a kis- és nagybetűket azonosnak tekinti.
Ha egy a számot adunk meg opcióként, akkor a program a megadott mondat n-edik
előfordulását keresi meg.
A ^QA parancs
A ^QA parancs a ^QF bővítése: a keresendő (helyettesítendő) mondat megadása
után megjelenik a
REPLACE WITH:
kérdés, amelyre válaszként írjuk be a helyettesítő mondatot. A keresés, ill.
helyettesítés módját meghatározó opció lehet még:
G - a művelet az egész szövegállományra vonatkozik, a kurzorpozíció közömbös;
N - feltétel nélkül keres és helyettesít.
Ha az N opciót adtuk meg, akkor minden megtalált mondat helyére a helyettesítő
mondat kerül. Ha nem adtuk meg az N opciót, akkor a program minden megtalált
mondatnál megkérdezi, hogy kérjük-e a helyettesítést. Az Y billentyű leütése
jelenti az igenlő választ; minden más billentyű hatására folytatódik a keresés.
A keresési, ill. helyettesítési folyamat az ^U paranccsal bármikor megszakítható.
A ^KB parancs
A ^KB parancs egy blokk kezdetének jelöli ki a pillanatnyi kurzorpozíciót; a
teljes szövegblokk meghatározásához szükség van még a ^KK blokkzáró parancsra.
A ^KK parancs
A ^KK parancs egy blokk végének jelöli ki a pillanatnyi kurzorpozícióit. A blokk
kijelölésének (a ^KB és a ^KK parancsokkal) pillanatában a blokk összes karaktere
inverz ábrázolásban vagy kisebb fényerővel jelenik meg. A következő ^Kx parancsok
az így kijelölt szövegrészre vonatkoznak.
A ^KC parancs
A ^KC parancs a ^KB és a ^KK paranccsal kijelölt blokkot átmásolja a pillanatnyi
kurzorpozícióba. E művelet után a kurzor az átmásolt blokk első karakterére
áll; a blokkmásolat kijelölése érvényben marad.
A ^KV parancs
A ^KV parancs a ^KB és a ^KK paranccsal kijelölt blokkot áthelyezi a pillanatnyi
kurzorpozícióba. E művelet után a kurzor az áthelyezett blokk első karakterére
áll; a blokk kijelölése érvényben marad.
A ^KY parancs
A ^KY parancs törli a ^KB és a ^KK paranccsal kijelölt blokkot. Megjegyzés:
a ^KB, ^KK, ^KY parancssorozat egyetlen hatása a blokk-kijelölés megszüntetése
(I. még ^KH parancsot).
A ^KR parancs
A ^KR parancs a mágneslemezes állományban található szöveget beszúrja a pillanatnyi
kurzorpozícióba. A feltett
Read block from file:
kérdésre válaszként a beillesztendő szövegállomány nevét kell megadni.
A ^KW parancs
A ^KW parancs mágneslemezes állományba menti ki a ^KB és a ^KK paranccsal kijelölt
blokkot. A feltett
Write block to file:
kérdésre válaszként annak a létrehozandó szövegállománynak a nevét kell megadni,
amelybe a kijelölt blokk kerül. Ha ilyen nevű állomány már létezik, akkor a
kimentés előtt törlődik és újból létrejön.
A ^KH parancs
A ^KH parancs megszünteti a ^KB és a ^KK parancs hatását (érvényteleníti a blokk
kijelölését).
Segédparancsok
Az ^N parancs
Az ^N parancs a kurzor pillanatnyi pozíciójába beszúrja a CR/LF karakterpárt,
azaz új sort hoz létre.
Az ^I parancs
Az ^I parancs a legközelebbi tabulátorpozícióba viszi a kurzort; a tabulátorpozíciókat
itt a kurzor feletti sor szavainak kezdőkarakterei jelentik.
Az ^L parancs
Az ^L parancs megismétli az utolsó ^QF parancsot.
Az ^U parancs
Az ^U parancs bármelyik parancs végrehajtását megszakítja.
A ^P parancs
A ^P parancs hatására az utána közvetlenül leütött vezérlőkarakter kódja bekerül
a szövegbe. Így pl. a ^P ^M ^P ^J karaktersorozat a sorokat lezáró CR/LF karakterpárokat
jelenti.
Összefoglaló az ENTERPRISE beállításhoz:
JOY fel | A kurzor mozgatása egy sorral felfelé; az oszloppozíció nem változik. |
JOY le | A kurzor mozgatása egy sorral lefelé; az oszloppozíció nem változik. |
JOY balra | A kurzor mozgatása egy pozícióval balra; ha a kurzor a sor elején áll (bal szélső pozíció), akkor a parancs hatástalan. |
JOY jobbra | A kurzor mozgatása egy pozícióval jobbra; ha a kurzor a sor végén áll (jobb szélső pozíció), akkor a parancs hatástalan. |
^W, balra | A kurzor mozgatása az előző szó elejére. |
^W, jobbra | A kurzor mozgatása a következő szó elejére. |
^S, fel | Lapozás felfelé. |
^S, le | Lapozás lefelé. |
^P, le | A képernyőtartalom mozgatása egy sorral lefelé ("roll down"). |
^P, fel | A képernyőtartalom mozgatása egy sorral felfelé ("roll up"). |
^L, jobbra | A kurzor mozgatása a sor végére. |
^L, balra | A kurzor mozgatása a sor elejére. |
^P, fel | A képernyőtartalom lapozása egy oldallal felfelé. |
^P, le | A képernyőtartalom lapozása egy oldallal lefelé. |
^F, fel | Ugrás a dokumentum első sorába. |
^F, le | Ugrás a dokumentum utolsó sorába. |
^B, fel | Ugrás a kijelölt blokk elejére. |
^B, le | Ugrás a kijelölt blokk végére. |
^C | Ugrás az előző művelet kurzorpozíciójába. |
^G | Karaktertörlés. (A jobbra álló karakterek balra lépnek.) |
^U | Karaktertörlés. (Ugyanaz, mint az előző.) |
^T | Karaktertörlés a szó végéig. |
^Y | Sortörlés. |
^N | Sorbeszúrás |
^D, L | Törlés a sor végéig. |
^D, ^\ | Törli a jobbra álló szót. |
TAB | Ugrás a következő tabulátor-pozícióba (ua., mint a ^I) |
ERASE | A kurzortól balra eső karakter törlése. |
INS | Beszúrás üzemmód váltása. |
ESC | Kilépés a szerkesztőből. |
Összetett szövegműveletek (ENTERPRISE-on):
^K, B | Blokk elejének kijelölése. |
^K, E | Blokk végének kijelölése. |
^K, S | A szó kijelölése, amelyen a kurzor áll. |
^K, H | A kijelölés megszüntetése. |
^K, C | A kijelölt blokk átmásolása az aktuális kurzorpozícióba. |
^K, M | A kijelölt blokk átmozgatása az aktuális kurzorpozícióba. |
^K, D | A kijelölt blokk törlése. |
^K, W | A kijelölt blokkot mágneslemezre menti. |
^K, R | A mágneslemezre mentett blokkot beilleszti az aktuális kurzorpozíciótól. |
^F, F | String keresése. |
^F, R | String keresése és cseréje. |
^F, L | A keresés folytatása. |
^P | Vezérlőkarakter beszúrása a szövegbe. |
E. Függelék: A fordító direktívák
A fordító direktívák a fordítóprogramnak adott utasítások, amelyekkel a keletkező lefordított program néhány tulajdonságát megváltoztathatjuk. Szintaxisuk pl: {$I+} ill.: {$I NEV.KIT}, ahol a '$' után és előtt nem állhat space. '$' jelzi, hogy fordító direktíva következik; ezt követi annak neve. A kapcsoló direktívák neve után csak '+', vagy állhat. '+' a direktíva aktív, bekapcsolt, a '-' passzív állapotát jelzi. A pataméteres direktívák neve után paraméter, pl. egy filenév áll. A direktívákat összevonva is felsorolhatjuk, pl. {$A-,K-,R-}. A következőkben felsoroljuk a 3.x verzióig érvényes fordító direktívákat.
A direktíva: abszolút kód
Csak 8 bites implementációban használhatjuk. Alapértelmezés: aktív. Aktív állapotban abszolút kód lesz generálva, passzív állapotban a lefordított program megenged rekurzív hívásokat. Ez utóbbi több memóriát és valamivel lassúbb végrehajtási időt is jelent.
B direktíva: logikai eszköz kiválasztása
A direktíva az alapértelmezett input-output eszköz kiválasztását végzi. Alapértelmezése: aktív. Ha aktív, akkor a standard input-output file-okhoz a CON: logikai eszköz van hozzárendelve; ha passzív, akkor a TRM: eszköz. A direktíva globális, értéke az egész programban csak egyszer állítható be.
A különbség az, hogy a CON: logikai eszköz pufferelt bemenetet ad, azaz a beírt információt szerkeszthetjük, törölhetjük mindaddig, amíg az ENTER billentyűvel le nem zártuk; a TRM: logikai eszköz viszont a leütött billentyű kódját azonnal továbbítja a programnak.
C direktíva: ^C és ^S karakterek értelmezése
A direktíva a ^C és ^S karakterek értelmezését végzi. Alapértelmezés: aktív. Ha aktív, akkor a Ctrl-C (^C) billentyűkkel a program futását megszakíthatjuk a Read illetve a Readln eljárások végrehajtása közben, ^S-sel pedig megállíthatjuk és újra bekapcsolhatjuk a képernyőre vonatkozó kiíratást. A direktíva passzív állapota mellett mindez hatástalan. A direktíva globális, értéke csak egyszer állítható be. Az aktív állapot lassítja a képernyőre való írás sebességét.
I direktíva: I/O hibakezelés, beszúrt file-ok
A direktíva kettős funkciót tölt be. Egyrészt az input-output hibakezelést, másrészt a beszúrt file-okat vezérli.
Ha a direktívát az input-output ellenőrzésre használjuk, akkor alapértelmezése: {$I+}. Ez azt jelenti, hogy egy hibás I/O művelet esetén a program futása I/O hibával megszakad, s visszakerül a vezérlés az operációs rendszerhez. A passzív állapot esetén az input-output hibát a programozónak kell lekezelnie, az IoResult standard függvény használatával (lásd a függvény leírását).
Ha a direktívát az include file-ok alkalmazására használjuk, a szintaxis a következő: {$I filenév.kit}. Tehát a beszúrandó file nevét írjuk a direktíva jele után.
K direktíva: stack ellenőrzése
Alapértelmezése: aktív. Ha a direktíva aktív, akkor a rendszer minden egyes alprogram hívása előtt ellenőrzi, hogy van-e elegendő hely a stack-ben az alprogram lokális változói számára. Ha nincs, akkor a program futási hibával leáll. Ha a direktíva passzív, akkor ez az ellenőrzés nem történik meg. Csak teljesen 'belőtt' programok esetén kapcsoljuk ki ezt a direktívát. Szintaxis: {$K+}.
R direktíva: érvényességi tartomány ellenőrzése
Ez a direktíva lehetővé teszi az indexek érvényességi tartományának, valamint a skaláris és résztartomány típusok értelmezési tartományának ellenőrzését. Alapértelmezése: passzív. Aktív állapotban a direktíva futás közben ellenőrzi az index-túlcsordulást; ha ilyen hibát talál, a program futási hibával megáll. Aktív állapotban a generált kód nagyobb, a program futása lassabb, mivel az ellenőrzés időt vesz igénybe. A program tesztelésekor azonban célszerű ezt az ellenőrzést igénybe venni. A már belőtt programnál viszont a futás gyorsítására célszerű a direktívát kikapcsolni.
U direktíva: felhasználói megszakítás
Ez a direktíva vezérli a program futásának felhasználói megszakítását. Aktív állapotban a program bárhol megszakítható a felhasználó által Ctrl-C billentyűvel. Ha a direktíva passzív, a billentyű leütése hatástalan. Alapértelmezés: passzív. Enterprise-on sajnos nem lehet bekapcsolni.
V direktíva: paraméterek típusellenőrzése
Ez a direktíva vezérli a string típusú változó-paraméterek típusellenőrzését. Alapértelmezés: {$V+}; ekkor az alprogramok hívásakor a formális és az aktuális paraméterek típusának és hosszának meg kell egyeznie, egyébként a program futási hibával leáll. Passzív állapotban ilyen ellenőrzés nincs, azaz a fordító azt az aktuális paramétert is elfogadja, melynek hossza nem egyenlő a formális paraméterével.
W direktíva: with utasítások mélysége
Csak 8 bites implementációban, használhatjuk. Ez a direktíva vezérli a With utasítások egymásba skatulyázásának maximumát, azaz az utasítással egyszerre 'felnyitható' rekordok maximális számát. Alapértelmezés: {$W2}. A direktíva jele mellett egy 1-től 9-ig terjedő számnak kell állnia.
X direktíva: tömbök optimalizálása
Csak 8 bites implementációban használhatjuk. Ez a direktíva vezérli a tömbök optimalizálását. Ha a direktíva aktív, akkor a fordító olyan kódot generál, amely a tömbök kezelését futási idő szerint optimalizálja. Passzív állapotban pedig olyan kódot generál, mely a tömbök kezelésnél a minimális helyfoglalású, lefordított kódot veszi igénybe. Alapértelmezés: aktív. Szintaxis: {$X+}.
F. Függelék: A keretrendszer installálása
A TINST (Turbo Pascal installation menu) program lehetőséget ad a Turbo Pascal keretrendszer beállítására az általunk használt CP/M kompatibilis számítógép paramétereihez. Ez magában foglalja a képernyő felépítésének beállítását (SCREEN INSTALLATION) és az előző pontban ismertetett billentyűfunkciók beállítását (vagy megváltoztatását igényeink szerint) (COMMAND INSTALLATION).
A SCREEN INSTALLATION menüpontban kiválaszthatjuk a már definiált beállításokat, vagy ha nem találjuk itt az általunk használt platform beállításait, újat hozhatunk létre (NONE OF THE ABOVE). Az ENTERPRISE-hoz két beállítás tartozik: egy monokróm, és egy színes (ENTERPRISE (COL)). Ez utóbbi beállításban az IS-DOS által használt piros szín jelenti az alacsony fényintenzitást, a zöld a normál és a magas színintenzitású szín. A kívánt géptípushoz tartozó beállítást a hozzá tartozó szám megadásával választhatjuk ki, ezután akár meg is változtathatjuk a beállításokat (nem javasolt).
A COMMAND INSTALLATION menüpontban valamennyi billentyűfunkciót sorban átdefiniálhatjuk. Az adott billentyűparancs megnevezése mellett megjelenik a jelenlegi beállítás. Ha ezt nem kívánjuk megváltoztatni, elegendő az ENTER megnyomásával továbblépni. Ha meg kívánjuk változtatni a beállítást, a kívánt billentyűket kell sorban megnyomni, majd az ENTER megnyomásával lezárni a definíciót. Megtehetjük azt is, hogy beírjuk az adott billentyűhöz tartozó decimális vagy hexadecimális kódot (kódolat), space-el elválasztva. A hexadecimális számok elé $ jelet kell írni (pl. 27 59 vagy $1B $2A). Ha a funkcióhoz tartozó billentyűparancsot törölni akarjuk, akkor a '-' karaktert kell megadni. Ezt a program a 'Nothing' üzenettel igazolja vissza, egyébként a definiált karakter (karakterek) kódját írja ki a képernyőre.
Ha végeztünk a beállítással, a program ellenőrzi van-e ütközés (ua. azt a billentyűparancsot állítottuk be két vagy több funkciónak). Ha van, kijelzi, hányas pontok ütköznek és meg kell ismételni a beállítást.
A főmenü QUIT (Q) funkciójával léphetünk ki a programból.
G. Függelék: ASCII kódtáblázat
Dec | Hex | Char | Dec | Hex | Char | Dec | Hex | Char | ||
0 | 00 | NUL | 43 | 2B | + | 86 | 56 | V | ||
1 | 01 | SOH | 44 | 2C | , | 87 | 57 | W | ||
2 | 02 | STX | 45 | 2D | - | 88 | 58 | X | ||
3 | 03 | ETX | 46 | 2E | . | 89 | 59 | Y | ||
4 | 04 | EOT | 47 | 2F | / | 90 | 5A | Z | ||
5 | 05 | ENQ | 48 | 30 | 0 | 91 | 5B | [ | ||
6 | 06 | ACK | 49 | 31 | 1 | 92 | 5C | \ | ||
7 | 07 | BEL | 50 | 32 | 2 | 93 | 5D | ] | ||
8 | 08 | BS | 51 | 33 | 3 | 94 | 5E | ^ | ||
9 | 09 | HT | 52 | 34 | 4 | 95 | 5F | _ | ||
10 | 0A | LF | 53 | 35 | 5 | 96 | 60 | ` | ||
11 | 0B | VT | 54 | 36 | 6 | 97 | 61 | a | ||
12 | 0C | FF | 55 | 37 | 7 | 98 | 62 | b | ||
13 | 0D | CR | 56 | 38 | 8 | 99 | 63 | c | ||
14 | 0E | SO | 57 | 39 | 9 | 100 | 64 | d | ||
15 | 0F | SI | 58 | 3A | : | 101 | 65 | e | ||
16 | 10 | DLE | 59 | 3B | ; | 102 | 66 | f | ||
17 | 11 | DC1 | 60 | 3C | < | 103 | 67 | g | ||
18 | 12 | DC2 | 61 | 3D | = | 104 | 68 | h | ||
19 | 13 | DC3 | 62 | 3E | > | 105 | 69 | i | ||
20 | 14 | DC4 | 63 | 3F | ? | 106 | 6A | j | ||
21 | 15 | NAK | 64 | 40 | @ | 107 | 6B | k | ||
22 | 16 | SYN | 65 | 41 | A | 108 | 6C | l | ||
23 | 17 | ETB | 66 | 42 | B | 109 | 6D | m | ||
24 | 18 | CAN | 67 | 43 | C | 110 | 6E | n | ||
25 | 19 | EM | 68 | 44 | D | 111 | 6F | o | ||
26 | 1A | SUB | 69 | 45 | E | 112 | 70 | p | ||
27 | 1B | ESC | 70 | 46 | F | 113 | 71 | q | ||
28 | 1C | FS | 71 | 47 | G | 114 | 72 | r | ||
29 | 1D | GS | 72 | 48 | H | 115 | 73 | s | ||
30 | 1E | RS | 73 | 49 | I | 116 | 74 | t | ||
31 | 1F | US | 74 | 4A | J | 117 | 75 | u | ||
32 | 20 | szóköz | 75 | 4B | K | 118 | 76 | v | ||
33 | 21 | ! | 76 | 4C | L | 119 | 77 | w | ||
34 | 22 | " | 77 | 4D | M | 120 | 78 | x | ||
35 | 23 | £ | 78 | 4E | N | 121 | 79 | y | ||
36 | 24 | $ | 79 | 4F | O | 122 | 7A | z | ||
37 | 25 | % | 80 | 50 | P | 123 | 7B | { | ||
38 | 26 | & | 81 | 51 | Q | 124 | 7C | | | ||
39 | 27 | ' | 82 | 52 | R | 125 | 7D | } | ||
40 | 28 | ( | 83 | 53 | S | 126 | 74 | ~ | ||
41 | 29 | ) | 84 | 54 | T | 127 | 7F | DEL | ||
42 | 2A | * | 85 | 55 | U |