[[:oktatas:programozás:pascal|< Pascal]] ====== Pascal tananyag ====== * **Szerző:** Sallai András * Copyright (c) Sallai András, 2008, 2012, 2013, 2014, 2015, 2018 * Licenc: GNU Free Documentation License 1.3 * Web: http://szit.hu ===== Bevezetés ===== A Pascal nyelv **általános célú** nyelv, amely minden területen megállja a helyét. Az **oktatásban** különösen hasznos, de megállja a helyét **vállalati** környezeteben is. Igaz sokan lekicsinylik, mert valaki azt mondta nekik, hogy a Pascal nyelv "elavult". A Pascal nyelv azonban köszöni jól van. A Pascal nyelv temetése egyébként onnan ered, hogy eredetileg a Borland cég fordítóját használtuk e nagyvilágban, amelynek neve Turbo Pascal volt, viszont annak a fejlesztésével felhagyott a cég és az utolsó kiadás 1992-es. Mivel nagyon népszerű volt, és nem fejlesztik tovább, néhányan a Pascal nyelv halálának gondolják. A Pascal nyelvet azért Borland cég is tovább támogatja BorlandPascal fejlesztői környezet néven, amelyből később a Delphi nevű fejlesztői környezet növi ki magát. A Delphi viszont már vizuális fejlesztői környezet, alapja azonban ennek is Pascal. Valaki azt mondja "Delphi nyelv". Ez azonban csak a Pascal nyelv egy változata. Azóta azonban lett nekünk **FreePascal**, amely folyamatos fejlesztés alatt áll, és a Delphi rendszernek is lett egy klónja a **Lazarus**. A Lazarus a FreePascal fordítóját használja, tulajdonképpen a FreePascalnak egy vizuális fejlesztői felülete. Mindkettő nyílt forráskódú szoftver rendszer. A Lazarus erőssége a nyílt forráskód és a könnyű használhatóság mellett, hogy több platformra létezik. Windows, MacOS, Linux és még más rendszerek is. Néhány ismert Pascal nyelven írt program: * Total Commander (Delphi) * Skype (Delphi és Objecitve-C és C++) Más programok: * http://wiki.freepascal.org/Projects_using_Lazarus ===== Helló Világ ===== Helló Világ nevű program: program hello; begin WriteLn('Helló Világ!'); end. Az első sorban a "program" a program nevét vezeti be. Utána megadjuk az általunk kitalált nevet. A programnévben nem lehet szóköz, nem lehet ékezetes karakter és nem kezdődhet számmal. A begin és end. közzé írjuk saját utasításainkat. Minden utasítást pontosvesszővel zárunk. A Pascalban minden karaktersorozatot, amelyet megadunk aposztrófok közzé kell tenni: 'Helló Világ' A programozás során elkészítjük a program forráskódját. A forráskódból tárgykód, vagy más néven objekt fájl készül, abból pedig a futtatható, vagy más néven bináris állomány. {{:oktatas:programozás:pascal:a_forditas_menete.png|}} A Linux rendszereken a futtatható fájloknak nincs kiterjesztésük alapértelmezetten. A Windowsos programok esetén viszont kötelező a .exe kiterjesztés. A fordító így Linuxon egy kiterjesztés nélküli állományt hoz létre, míg Windowson egy .exe kiterjesztésű fájlt hoz létre. ===== Megjegyzések ===== A Pascal nyelven többsoros megjegyzést tehetünk a kapcsos zárójel párossal vagy szimpla zárójele csillaggal. Egy soros megjegyzést tehetünk a két perjellel (A régi TurboPascalban nem működött): program Program01; { Több soros megjegyzés } (* Több soros megjegyzés *) //Egy soros megjegyzés begin {Több soros megjegyzés} (* Több soros megjegyzés *) //Egy soros megjegyzés end. ===== Kivitel ===== Fentebb láttuk, hogy a karaktersorozat állandók meghatározásakor azokat aposztrófok közzé kell tenni. WriteLn('karakter sorozat'); A karaktersorozatban természetesen lehetnek számok is. Ha számot adunk, meg azt nem szükséges aposztrófok közzé írni. WriteLn(382); A számok is megadhatók karaktersorozatként: WriteLn('382'); Ha viszont nem karaktersorozatként adom meg, akkor számításokat is végezhetek vele. A következő utasítás például kiszámítja 8 * 2 értékét: WriteLn(8 * 2); Amikor leírom, hogy 8, ez egy egész szám. Dolgozhatunk azonban valós számokkal is. A magyar nyelvben egy valós számot így írok le: 382,82 Az angolban azonban a vessző helyett pontot használunk, ennek megfelelően a Pascal nyelvben az előbbi szám: 382.82 A képernyőre íráshoz használható a Write() utasítás is. A Write() nem tesz sortörést a kiírt adatok végén. Próbáljuk ki a következő utasítás: Write('egy'); Write('ketto'); WriteLn('harom'); Write('negy'); A Write() és WriteLn() eljárásoknak több paraméter is megadható: Write(3+5, " ", 8 * 7); **Literálisnak** nevezzük a forráskódba írt szám, karakter és karaktersorozat állandókat. Ha leírom 'alma', akkor megadtam egy literálist. Ha leírom Write(354), a 354 egy számliterális. ===== Különleges karakterek ===== Láttuk, hogy az aposztróf, vagy felső-vessző, speciális szerepet tölt be, mivel ezzel adunk meg egy karaktersorozat literálist. Akkor hogyan íratunk a képernyőre egy ilyen felső-vesszőt? A következőkben két megoldást látunk a kiíratásra. begin WriteLn(''''); end. A másik megoldás: BEGIN WriteLn(#39); END. A második megoldásban egy # kettős-kereszt után írtuk a felső-vessző ASCII kódját, decimálisan megadva. Ezzel a módszerrel más különleges karakterek is a képernyőre írathatók. Ilyenek lehet a sortörés, tabulátor, stb. Tabulátor: WriteLn('alma'#9'szilva'); Sortörés: WriteLn('alma'#13#10'szilva'); Unicode karakter kódját is megadhatjuk a $ dollárjellel bevezetve: WriteLn('alma'#$0065'körte'); A program egy "e" betűt ír a két gyümölcs neve közzé. A # kettős-kereszttel megadott karaktereket **kontrollkarakternek** nevezzük. A kettős-kereszt után megadható egy ASCII kód vagy egy UTF-8 kód. ^ néhány karakter ASCII kódja ^^ ^ karakter ^ decimális ASCII kód ^ | # | 35 | | $ | 36 | | ' | 39 | | ( | 40 | | ) | 41 | | ^ | 94 | | { | 123 | | | | 124 | | } | 125 | ===== Változók, állandók és típusok ===== ==== Változók ==== A változó tulajdonképpen egy memóriahely amelyet lefoglaltunk azzal a céllal, hogy valamilyen értéket fogunk ott eltárolni. "Változó" néven azért említjük mert a program további részében értéke bármikor megváltoztatható. Változók deklarálása (példa): var a : integer; b : real; begin a := 3; b := 4; WriteLn(a + b); end. ==== Típusok ==== ^ Egész típusok ^^^ | shortint | -128..127 | 1 bájt | | smallint | -32768..32767 | 2 bájt | | longint | -2147483648..2147483647 | 4 bájt | | int64 | -9223372036854775808..9223372036854775807 | 8 bájt | | integer | smallint, shortint vagy int64 | előjeles 2, 4 vagy 8 bájt | | byte | 0..255 | 1 bájt | | word | 0..65535 | 2 bájt | | longword | 0..4294967295 | 4 bájt | | qword | 0..18446744073709551615 | | cardinal | word, longword vagy qword | 2, 4 vagy 8 bájt | ^ Valós típusok ^^^ | real | single vagy double | 4 vagy 8 bájt | | single | 1.5e-45 .. 3.4e+38 | 4 bájt | | double | 5.0e-324 .. 1.7e+308 | 8 bájt | | extended | 3.4e-4932 .. 1.1e+4932 | 10 bájt | | comp | -263 + 1 .. 263 - 1 | 8 bájt | | currency | -922337203685477.5808..922337203685477.5807 | 8 bájt | ^ Logikai típusok ^^^ | Boolean | false..true | 1 bájt | | ByteBool | false..true | 1 bájt | | WordBool | false..true | 2 bájt | | LongBool | false..true | 4 bájt | ^ Karaktere típusok ^ | char | | AnsiChar | | WideChar (WChar) | ^ Karaktersorozat típusok ^^ ^ Típus ^ Max hossz ^ | ShortString | 255 | | AnsiString | platformfüggő | | String | 255, illetve \\ platformfüggő | | WideString | platformfüggő | | PChar | platformfüggő | | PAnsiChar | platformfüggő | | PWideChar | 1 gigabájt | ==== Állandók ==== Állandókat eddig is használtunk a programjainkban, hiszen amikor leírjuk például 'alma', ez is állandó. Állandó, mert a program futása során, a számítógép memóriájában ez az érték már biztosan nem változik. Ezeket neveztük **literális állandóknak**. Most egy újabb fajta állandóval ismerkedünk meg, ezek a nevesített állandók. Mint nevük is mutatja van nevük. A programozó azt vállalja, hogy ezeket a memóriahelyeket a program további részében nem fogja megváltoztatni. Állandókat a Const kulcsszó után hozhatunk létre, hasonlóan a változókhoz, de itt kettőspont helyett, egyenlőségjelet teszünk, mivel azonnal meg kell adnunk az állandó értékét. const Azonosito1 = value; Azonosit2 = value; Azonosit3 = value; const Nev = 'Nagy József'; Betu = 'a'; Ev = 1997; pi = 3.1415926535897932; UsingNCSAMosaic = TRUE; Az állandókat a Pascal nyelvben a változók előtt vezetjük be: const max = 30; var a : integer; begin a := max; WriteLn(a); end. ===== Formázott kimenet ===== ==== Pascal formázás ==== A Pascal nyelv lehetővé teszi az értékek kiírásának szélességét megadni. var a : Real; BEGIN a := 323.1234567; WriteLn(a:20:2); END. Az "A" változó tartalmát 20 szélesen, két tizedesjegy pontossággal írjuk ki. Egész számok esetén a második szám értelemszerűen nem adható meg: var a : Integer; BEGIN a := 323; WriteLn(a:20); END. Bár a precizitás megadása valós szám esetén sem kötelező. ==== Format függvény ==== A **format()** függvény az eddigieknél kifinomultabb beállítást tesz lehetővé, a **sysutils** unitban található a FreePascal rendszerekben. A format() függvények minimum két paramétere van. Az első paraméter kötelezően a formátum-karaktersorozat, amit értelemszerűen aposztrófok között adunk meg. A második paraméter szögletes zárójelek között megadott, számok, változók vagy állandók, vesszővel szeparálva. format('formátum-karaktersorozat', [45]) format('formátum-karaktersorozat', [45, 20]) format('formátum-karaktersorozat', [45, 20, 63]) A formátum-karaktersorozat tartalmazhat egy úgynevezett formátumkódot. Formátumkódot akkor teszünk a formátum-karaktersorozatba, ha írunk minimum egy következő paramétert is. A formátumkódot mindig % százalékjellel kezdjük: format('%d Ft', [450]) A második paraméterhez, és az azt következő paraméterekhez szükség van egy-egy formátumkódra. Ha van harmadik paraméter is, akkor újabb formátumkódot írunk: format('%d kg %d Ft', [12, 450]) A formátumkód annál többet tud, mint szimpla megjelenítés. A formátumkód általánosan így néz ki: '%' [[index]':'] ['-'] [szélesség] ['.' precizitás] ArgumentumTípusa | '%' | A formátum string így indul | | index ':' | A megjelenítés sorrendje | | '-' | balra igazítás | | szélesség | A kiíratás szélessége | | '.' precizitás | Precizitás | ^ Formátumkód ^ Leírás ^ | D | Decimális formátum. | | E | Tudományos formátum | | F | Fixpontos formátum | | G | Elsődleges számformátum | | M | Pénznem formátum | | N | Számformátum (megegyezik a fixpontos formával) | | S | String formátum | | U | Előjel nélküli decimális formátum | | X | Hexadecimális formátum | uses sysutils; var a : Real; BEGIN a := 3438.1234567; WriteLn(Format('%.3F', [a])); ReadLn; END. uses sysutils; var a , b : Real; BEGIN a := 3438.1234567; b := 2234.56789; WriteLn(Format('%.3F %.1F', [a, b])); ReadLn; END. ===== Matematikai függvények ===== WriteLn(Pi()); Az eredmény tudományos alakban kapjuk: 3.1415926535897932E+0000 Egy kis formázással fixpontos alakra hozhatjuk: WriteLn(Pi():0:4); Számok szinuszát szeretnénk megkapni. Paraméterként meg kell adni az adott szöget radiánban: WriteLn(Sin(1 * Pi() / 180):0:4); Számok négyzetgyöke: WriteLn(sqrt(9)); * Abs Abszolút érték számítása * Arctan Arkusz tangens számítása * Cos Koszinusz fok számítása * Dec Egy változó értékének csökkentése * Exp Exponenciális * Frac Az argumentum tizedes részével tér vissza * Hi Egy byte/word érték felső részével tér vissza * Inc Egy változó értékének növelése * Int Lebegőpontos érték egész része * Ln Logaritmus számítása * Lo Egy byte/word érték alsó részével tér vissza * Odd A szám páratlan-e * Pi Pi értékével tér vissza * Random Véletlen szám generálása * Randomize A véletlen szám generátor inicializálása * Round Lebegőpontos számot a legközelebbi egészre kerekíti * Sin Szinusz fok számítása * Sqr Érték négyzetének számítása * Sqrt Érték négyzetgyökének számítása * Swap Az alsó és a felső byte/words érték alsó és felső részének cseréje * Trunc A szám egész részével tér vissza Néhány függvény fejléce function sqr( l: LongInt ):LongInt; function sqrt( d: ValReal ):ValReal; function trunc( d: ValReal ):Int64; function odd( l: LongInt ):Boolean; function round( d: ValReal ):Int64; function frac( d: ValReal ):ValReal; function sin( d: ValReal ):ValReal; function cos( d: ValReal ):ValReal; function swap( X: Word ):Word; function swap( X: Integer ):Integer; function swap( X: LongInt ):LongInt; function swap( X: Cardinal ):Cardinal; function swap( X: QWord ):QWord; function swap( X: Int64 ):Int64; ==== A math unit ==== Hatványozáshoz szükségünk van a math unitra: program Program01; uses math; BEGIN WriteLn(Power(2,5):0:0); ReadLn; END. ^ math unit függvényei (nem teljes) ^^ | power() | hatvány | | ceil() | kerekítés felfelé | | floor() | kerekítés lefelé | | log10() | Tízes alapú logaritmus | | log2() | Kettes alapú logaritmus | | logn() | N alapú logaritmus | | radtodeg() | Radián átalakítása fokba | | degtorad() | Szög átalakítása radiánba | A logn() függvény a következő formában használható: logn(n, x) ===== Vegyes függvények ===== * Assert -- Feltételes program megszakítás hibával (ha a paraméter igaz értéket ad, akkor a program megszakad) * Break -- Az aktuális ciklus megszakítása * Continue -- Az aktuális ciklusban a következő ciklus kerül végrehajtásra. * Exclude -- Egy elem kizárás egy halmazból * Exit -- Kilépés az aktuális függvényből és eljárásból * Include -- Egy elemet tesz egy halmazba * LongJmp -- Ugrás a végrehajtási ponthoz * Ord -- Sorszámozott típus sorszámát adja * Pred -- A felsorolt típus előző értékével tér vissza * SetJmp -- A végrehajtási pont megjelölése ugráshoz * SizeOf -- Visszatér az adott változó vagy típus méretével * Succ -- A felsorolt típus következő értékével tér vissza Néhány függvény/eljárás fejrésze function SizeOf(X: TAnyType):LongInt; procedure Assert(Expr: Boolean); procedure Assert(Expr: Boolean; const Msg: String); procedure Exit(const X: TAnyType); procedure Exit; procedure Break; procedure Continue; function Ord(X: TOrdinal):LongInt; function Pred(X: TOrdinal):TOrdinal; function Succ(X: TOrdinal ):TOrdinal; ===== Véletlen számok ===== A Random() egy egész számot vár paraméterként. Ha például 5-öt írunk, akkor egy egész számot kapunk 0 és 4 között. program Program01; BEGIN Randomize; WriteLn(Random(5)); ReadLn; END. Ha szeretnénk 1 és 5 között egy számot megkapni, egyszerűen adjunk hozzá mindig 1-t. A véletlen szám generálása előtt használjuk a Randomize nevű eljárást, ami biztosítja, hogy minden futtatáskor más számot kapjunk. ===== Operátorok és precedenciájuk ===== ==== Operátorok ==== Az operátorok lehetnek egyoperandusú: not a -b Lehetnek kétoperandusúak: a + b a and b a < b * aritmetikai * relációs (összehasonlító) * logikai * bit- * sztring- * halmaz- * egyéb (@, is, as) ^ Aritmetikai műveletek ^^ | -a | előjelváltás | | +a | előjel megerősítés | | a + b | összeadás | | a - b | kivonás | | a * b | szorzás | | a / b | osztás | | a div b | egész osztás | | a mod b | maradékképzés | ^ Logikai műveletek ^^ | not a | tagadás | | a and b | ÉS | | a or b | VAGY | | a xor b | kizáró VAGY | ^ Bitműveletek ^^ | not a | tagadás bitenként | | a and b | ÉS bitenként | | a or b | VAGY bitenként | | a xor b | kizáró VAGY bitenként | | a shl b | biteltolás balra | | a shr b | biteltolás jobbra | ^ Sztringműveltek ^^ | a + b | karaktersorozat összefűzése | ^ Halmazműveletek ^^ | a + b | unió | | a * b | metszet | | a - b | különbség | | a in b | eleme-e, vizsgálat | ^ Relációs műveletek ^^ | a = b | egyenlő | | a <> b | nem egyenlő | | a < b | kisebb mint | | a > b | nagyobb mint | | a <= b | kisebb vagy egyenlő | | a >= b | nagyobb vagy egyenlő | ==== Precedencia ==== A precedencia a műveletvégzés elsőbbségi sorrendjét jelenti. Ha több operátorunk van, akkor valamilyen szabály alapján el kell dönteni, melyik műveletet hajtjuk végre először. ^ Művelet ^ Precedencia ^ | @, not, -, + | első, legmagasabb | | *, /, div, mod, and, shl, shr, as | második | | +, -, or, xor | harmadik | | =, <>, <, >, <=, >=, in, is | negyedik, legalacsonyabb | Ha több azonos szintű művelet van egy kifejezésben, akkor általában balról jobbra haladva hajtódnak végre. A kiértékelési sorrend szabályozható zárójelekkel is. ===== Konverzió ===== Konverzióhoz a FreePascal **sysutils** unitját használjuk. ==== Egész Sztringgé ==== program Program01; uses sysutils; var szam : integer; str : string; BEGIN szam := 3; str := IntToStr(szam); END. ==== Valós Sztringgé ==== program Program01; uses sysutils; var szam : Real; str : String; BEGIN szam := 3.5; str := FloatToStr(szam); END. ==== Sztring valóssá ==== str := '3.5'; szam2 := StrToFloat(str); ==== Sztring egésszé ==== str := '3'; szam2 := StrToInt(str); ===== Bevitel ===== var a : Integer; BEGIN Write('Szam: '); ReadLn(a); END. program test1; var nev : String; BEGIN Write('Név: '); ReadLn(nev); END. ===== Szelekció ===== ==== if ==== Egy ágú, egy utasításos szelekció: if feltétel then utasítás; Egy ágú, több utasításos szelekciós: if feltétel then begin utasítás_1; utasítás_2; ... utasítás_n; end; program Program01; var a : Integer; begin Write('Szám: '); ReadLn(a); if a > 100 then WriteLn('Száznál nagyobb számot írtál'); end. Az if használata or és and logikai operátorokkal: program Program01; var a, b : Double; begin Write('Valós szám: '); ReadLn(a); Write('Másik valós szám: '); ReadLn(b); if (a > 0) and (b > 0) then WriteLn('Mindkét szám Pozitív'); if (a > 0) or (b > 0) then WriteLn('Egyik szám Pozitív'); end. ==== if..else ==== Két ágú szelekció: if feltétel then utasítás_1 else utasítás_2; Kát ágú szelekció több utasítással: if feltétel then begin utasítás_1; utasítás_2; ... utasítás_n; end else begin utasítás_50; utasítás_51; ... utasítás_m; end; program Program01; var a : Integer; begin Write('Szám: '); ReadLn(a); if a > 100 then WriteLn('Száznál nagyobb számot írtál') else WriteLn('Száznál kisebb számot írtál'); end. ==== if..else..if ==== Az if..else..if szerkezettel többágú szelekciót valósíthatunk meg. program Program01; var a : Integer; begin Write('Szám: '); ReadLn(a); if a > 0 then WriteLn('Pozitív') else if a = 0 then WriteLn('Nulla') else WriteLn('Negatív'); end. program Program01; var a : Integer; begin Write('Szám: '); ReadLn(a); if a > 0 then begin WriteLn('Pozitív'); WriteLn('Pozitív'); end else if a = 0 then begin WriteLn('Nulla'); WriteLn('Nulla'); end else begin WriteLn('Negatív'); WriteLn('Negatív'); end; end. ==== case .. of ==== A case .. of szerkezettel többágú szelekció valósítható meg. A többágú szerkezet természetesen megvalósítható a már fentebb ismertetett if-el is, ez csak egy plusz lehetőség. Néha a case .. of utasítással egyszerűbb szerkezet valósítható meg. program Program01; var a : Char; begin Write('Betű: '); ReadLn(a); case a of 'a' : WriteLn('Ez a'); 'b' : WriteLn('Ez b'); 'c' : WriteLn('Ez c'); 'd' : WriteLn('Ez d'); 'e' : begin WriteLn('Ez e'); WriteLn('Még mindig e'); end; 'f' : WriteLn('Ez f'); end; end. A case használata String típussal: program Program01; var gy : String; begin Write('Gyümölcs: '); ReadLn(gy); case gy of 'alma' : WriteLn('Ez alma'); 'körte' : WriteLn('Ez körte'); 'szilva' : WriteLn('Ez szilva'); 'málna' : WriteLn('Ez málna'); 'barack' : WriteLn('Ez barack'); end; end. ===== Iteráció ===== ==== for ==== A Pascal nyelv for ciklusutasítása növekményes (számlálós) ciklusok létrehozására használható. A működéshez szükség van egy ciklusváltozóra. A ciklusváltozó legyen például "i". Értékadással mondjuk meg, hogy a ciklus hányszor forduljon. Például 1-től - 10-ig: 1 to 10 A for utasítás fejrésze a do kulcsszóval fejeződik be. A do uátn lehet egy vagy több utasítást megadni. Ha a több utasítást adunk meg, akkor kötelező a begin-end kulacsszavak használata. Számok kiíratása 1-től - 10-ig. for i := 1 to 10 do WriteLn('alma'); A ciklusok alatt végrehajtódó utasítások alkotják a ciklus törzsét. A fenti példában WriteLn('alma'); A ciklus törzsébe csak begin és end; között írható több utasítás. for i := 1 to 10 do begin WriteLn('alma'); WriteLn('körte'); end; A begin természetesen írható a do után is: for i := 1 to 10 do begin WriteLn('alma'); WriteLn('körte'); end; A teljes program, ebben az esetben így nézhet ki: var i : integer; begin for i := 1 to 10 do begin WriteLn('alma'); WriteLn('körte'); end; end. A ciklusváltozó értékére hivatkozhatok ciklustörzsében. Például kiírathatom annak értékét: for i := 1 to 10 do begin WriteLn(i); end; A fenti program 1-től - 10-ig kiírja a számokat a képernyőre. Számok kiíratása 10-től - 1-ig. for i := 10 downto 1 do begin WriteLn(i); end; A ciklus törzsében az i változó tartalmával, különböző műveleteket végezhetek. Például megszorozhatom mindig kettővel. for i := 1 to 20 do begin WriteLn(i * 2); end; Így megkapjuk a páros számokat -- itt például -- 20-ig. A ciklusok egymásba ágyazhatók. A következő program háromszor hajtja végre a belső ciklust. A belső ciklus pedig mindig ötször írja ki az "a" betűt. for i := 1 to 3 do begin for j := 1 to 5 do Write('a'); WriteLn(); end; ==== while ==== A while, azt jelenti amíg. Azt is mondjuk "amíg típusú" ciklus. Akkor használjuk, ha nem tudjuk hányszor fog fordulni a ciklus. Ha felhasználói beavatkozástól, vagy egyéb külső körülménytől függ a ciklusok száma, akkor a while segít ennek megvalósításában. A while ciklus fejléce így néz ki: while feltétel do A feltétel helyére beírunk egy állítást. ha az állítás igaz, a ciklus törzse végrehajtódik. Ha hamis, a vezérlés a ciklus utáni utasításra adódik át. A while ciklus esetén (a forhoz hasonlóan) egy utasítás esentén nem kötelező a begin-end blokk jelölés. Több utasítás esetén, azonban meg begin és end; közzé írjuk az utasításainkat. program Program01; var i : byte; begin i := 0; while i<5 do begin WriteLn('Körte'); Inc(i); end; end. Az Inc(i) függvény eggyel növeli az i változó értékét (increment). ==== repeat .. until ==== A repeat-until a Pascal hátul tesztelő ciklusa. Alapvetően amíg típusú ciklus. Akkor használjuk, ha egyszer biztosan végre szeretnénk hajtani a ciklus törzsét. A feltételt, vagyis a ciklus fejrészt a ciklus törzs után helyezzük el. A while ciklussal szemben, ez az utasítás akkor hajtódik végre, ha feltétel igaz. program Program01; var i : byte; begin i := 0; repeat WriteLn('Körte'); Inc(i); until i>=5; end. ===== Tömbök ===== Több azonos típusú elem tárolására alkalmas változó. Tömb deklarálása: tomb : array [1..5] of integer; Egy egész típusokat tárolni képes tömböt deklaráltunk, melynek indexei 1 és 5 között lehetnek. Tömb kezdő értéke: tomb : array [1..5] of integer = (3, 6, 2, 1, 10); A tömb indexhatárainak meg kell egyezni a kezdőértékek számával. A tömb kezdőértékét csak a FreePascal fordító teszi lehetővé. A Turbo Pascalban a tömböknek nem adható kezdőérték! Tömb mérete: var tomb : array [1..5] of Integer = (3, 5, 8, 4, 6); meret : Integer; begin meret := Length(tomb); end; Tömb bejárása: var tomb : array [1..5] of Integer = (3, 5, 8, 4, 6); i : Integer; begin for i := 1 to 5 do WriteLn(tomb[i]); end; A FreePascalban tömbök esetén bevezették a for ciklus használatának egy újabb technikáját. A ciklus fejrészében (az for és a do között) egy változót, az "in" kulcsszót és a tömböt adok meg. A for ciklus segítségével ilyen formán bejárhatom a tömböt, elejétől a végéig. program Program01; var a : array [1..3] of byte = (2,4,7); b : byte; begin for b in a do WriteLn(b); end. A FreePascal objektumorientált módba kapcsolható a objfpc mód bekapcsolásával: {$mode objfpc} Ezzel elérhetővé válik egy TStrings típus, ami valójában egy lista típus. A listák tulajdonképpen speciális tömbök, mert méretük dinamikusan, vagyis automatikusan változik, ha hozzáadunk egy elemet, vagy kiveszünk belőle egy elemet. Az ilyen típusú lista használatára látunk egy rövid példát, a következő programban. program Program02; {$mode objfpc} uses classes; var st : TStrings; s : String; begin st := TStringList.Create; try st.Add('Első'); st.Add('Második'); st.Add('Harmadik'); for s in st do WriteLn(s); finally st.Free; end; end. A dinamikus listák bejárására is használhatjuk a for változó in lista do formát, ahogy a programban is látjuk. ===== Rekord ===== Több különböző típusú elem tárolására alkalmas változót deklarálhatunk vele. Rekord deklarálása: var szemely : record nev : String; tel : String; cim : String; fiz : LongInt; end; Rekord használata: begin szemely.nev := 'Pék Elemér'; szemely.tel := 'Szolnok'; szemely.cim := 'Kék u. 32.'; szemely.fiz := 380000; end. A példában a szemely nevű változó négy értéket képes eltárolni, amelyeknek lehet különböző típusuk. A négy értéket tulajdonságoknak, vagy tagoknak is szoktuk nevezni. ===== Halmazok ===== Szintaxisa: SET OF alaptípus var halmaz : Set Of 1..10; ... halmaz := [8, 3, 2, 5, 4]; h1 := [1..5]; h2 := []; {üres halmaz} h3 := [4, 6, 12..15]; ch := 'r'; h4 := [ch, 'g', 'h']; ^ Halmazműveletek ^^ | * | metszet | | + | egyesítés | | - | különbség | ^ Logikai típusú eredményt szolgáltató műveletek ^^ | = | egyenlőség | | <> | különbözőség | | <=, >= | tartalmazás (részhalmaz) | | IN | elemvizsgálat | type szin = (sarga, kek, piros, zold); szinek = set of szin; var valamiSzinei : szinek; var halmaz : set of 1..10; num : integer; BEGIN halmaz := [3, 4]; halmaz := [5]+halmaz; for num in halmaz do begin WriteLn(num); end; END. ===== String kezelés ===== ==== A Pascal sztringekről ==== A Pascal karaktersorozatai a memóriában úgy tárolódnak, hogy a karaktersorozatot megelőzi annak hossza. {{:oktatas:programozás:pascal:pascal_string.png|}} Ezzel szemben a C nyelvben nem a hosszát tároljuk, helyette a végét jelezzük egy NULL értékkel. {{:oktatas:programozás:pascal:c_string.png|}} String típus úgy tudunk létrehozni, ha string kulcsszót használom a típus megadásnál: var nev : string; varos : string; Ilyenkor a memóriában egy 255 bájt hosszú string számára foglaltunk helyet. Amikor értéket adunk maximum 255 karaktert írhatunk az aposztrófok közé. str := 'sokkarakter...'; Ha túllépem a maximális hosszt, akkor a fordító figyelmeztetést ad, a program persze ettől lefordul. Azok a karakterek amelyeknek nem volt hely foglalva azok elvesznek. Kiíratásnál már nem is látjuk őket a képernyőn. A 255 bájt helyett kisebb helyet is foglalhatok a karaktersorozatok számára, ha szögletes zárójelben a string kulcsszó után megadom a maximális hosszt: var nev : string[20]; varos: string[50]; A SizeOf() függvénnyel lekérdezhetjük a lefoglalt memóriaterületet. Ha egy karaktersorozatnak lefoglalok öt helyet, a méret eggyel nagyobb lesz: var str : string[5]; ... WriteLn(SizeOf(str)); A plusz egy bájt, a karaktersorozat előtti méret. ==== System unit ==== ==== A System unitról ==== A System unitot nem szükséges a uses utasítással használatba venni, mivel ez a unit alapértelmezésként használva van. Ebben található a Write(), WriteLn() és a ReadLn() utasítás is. === Val === String számmá konvertálása A Val() függvény szintaktikája: procedure Val( const str: String; var szam; var kod: Word ); A fenti szintaktikából látjuk, hogy a Val() függvénynek három paramétere van. Az első paraméter egy bemenő adat, a string, amit átkonvertálunk számmá. A második és harmadik paraméterben egy-egy számot kapunk értékül. A második paraméterben a magát a számot kapjuk meg. A második paraméter lehet Longint, Real és Byte vagy valamilyen felsorolt típus. A harmadik paraméterben beírt változóban hibakódot kapjuk meg, ha gond volt a konvertálással. Ha konvertálás hiba nélkül megtörtént, akkor a hibakód 0. szamStr : String; szam, kod : integer; ... szamStr := '48'; Val(szamStr, szam, kod); WriteLn('Dupla: ', szam * 2); === Str === A szám stringgé konvertálása procedure Str( var X: TNumericType; var S: String ); === Pos === Adott string első előfordulási helyét adja visza function Pos( const substr: shortstring; const s: shortstring ):SizeInt; === Copy === String adott pozíciójától, adott számú karaktert add vissza function Copy( S: AStringType; Index: Integer; Count: Integer ):String; === Delete === String adott pozíciójától, adott számú karakter törlése procedure Delete( var s: shortstring; index: SizeInt; count: SizeInt ); ==== StrUtils unit==== === Delchars === Egy adott karakter törlése a string összes előfordulási helyén: uses StrUtils; var s : String = 'alma:körte:barack:szilva'; begin s := Delchars(s, ':'); end; A fenti program törli a ":" karaktereket az s stringből. === Numb2USA === Egy számot tartalmazó stringben USA ezredeselválasztókat tesz: uses StrUtils; var s : String = '1234567'; begin WriteLn(Numb2USA(s)); end; === NPos === Adott string n-dik előfordulását adja vissza function NPos( const C: String; S: String; N: Integer ):Integer; === ExtractWord === Adott sorszámú szót adja vissza, a megadott stringből, a szóhatároló karaktereket harmadik paraméterként megadva. type TSysCharSet = set of Char; var s : String = 'Első:Második:Harmadik:Negyedik'; dc : TSysCharSet; begin dc := [':']; WriteLn(ExtractWord(3, s, dc); end. A fenti program a "Harmadik szöveget írja a képernyőre. A dc változó helyett írhattam volna a következő állandót is: [':'] Értelemszerűen megadható több szóhatároló is: [':',';'] A fenti esetben a ":" kettőspont és a ";" pontosvessző karakter is szóhatároló. A függvény fejléce: function ExtractWord( N: Integer; const S: String; const WordDelims: TSysCharSet ):String; === Copy2Space === Adott stringből olvasunk az első szóköz karakterig. function Copy2Space( const S: String ):String; === Copy2Symb === Adott stringből olvasunk az első megadott karakterig function Copy2Symb( const S: String; Symb: Char ):String; === WordCount === Szavak megszámolása egy stringben. Az elválasztó karaktert meg kell adnunk. function WordCount( const S: String; const WordDelims: TSysCharSet ):Integer; ===== Eljárások ===== Az eljárások a főprogramtól különálló, önálló programrészek, csinálnak valamit, de nem adnak vissza értéket, a programban mindig a procedure szóval kezdjük. Általánosan: procedure fuggvenynev(paraméter1 : tipus; paramteren : tipus); begin utasitasok; end; Példa: procedure osszead(szam1, szam2: real); begin WriteLn(szam1 + szam2); end; vagy: procedure nevjegy(); begin WriteLn('Nagy János'); WriteLn('Szolnok'); WriteLn('Tel: +36 48 123-4567'); end; Az eljárásokat a főprogram elé helyezzük el. procedure nevjegy(); begin WriteLn('Nagy János'); end; BEGIN nevjegy(); END. Ha a főprogramban van egy változó az hova kerül? var a : byte; procedure nevjegy(); begin WriteLn('Nagy János'); end; BEGIN nevjegy(); a := 35; WriteLn(a); END. Természetesen az eljárásnak lehet lokális saját változója. var a : byte; procedure nevjegy(); var kor : byte; begin kor := 45; WriteLn('Nagy János'); WriteLn(kor); end; BEGIN nevjegy(); a := 35; WriteLn(a); END. ===== Függvények ===== A függvények a főprogramtól különálló, önálló programrészek. A függvénynek az eljárással ellentétben mindig van egy visszatérési értéke. function fuggvenynev(paraméter1 : tipus; paramteren : tipus):visszateres_tipusa; begin utasitasok; fuggvenynev := visszateresietek; end; Példa: function osszead(szam1, szam2: real): real; begin osszead := szam1 + szam2; end; ===== Fájlkezelés ===== ==== System ==== === Assign === Az operációs rendszer állományának összekötése egy pascal változóval procedure Assign( var f: file; const Name: String ); === Append === Fájl megnyitása hozzáfűzésre procedure Append( var t: Text ) === Close === Egy fájl bezárása procedure Close( var f: file ); === EOF === A függvény a igazzal tér vissza, ha elértük a fájlvégét function EOF( var f: file ):Boolean; function EOF( var t: Text ):Boolean; === Reset === Fájl megnyitása olvasásra procedure Reset( var f: file; l: LongInt ); procedure Reset( var f: file ); procedure Reset( var f: TypedFile ); procedure Reset( var t: Text ); === Rewrite === Állomány megnyitása írásra procedure Rewrite( var f: file; l: LongInt ); procedure Rewrite( var f: file ); procedure Rewrite( var f: TypedFile ); procedure Rewrite( var t: Text ); ==== SysUtils ==== === FileExists === Az állomány létezésének ellenőrzése function FileExists( const FileName: String ):Boolean === DiskFree === A háttértáron található szabadhely function DiskFree( drive: Byte ):Int64; A függvénynek egy szám paramétere van, amely a kívánt meghajtó száma. * 0 az aktuális meghatjó * 1 az első floppy meghajtó * 2 a második floppy meghajtó * 3 az első merevlemez partíció * 4-26 az összes több meghajtó és partíció ==== Fájlkezelés példa ==== === Szöveges fájlok kezelése === Fájlba írás: var f : text; begin Assign(f, 'adat.txt'); ReWrite(f); WriteLn(f, 'alma'); WriteLn(f, 'körte'); Close(f); end. A példában az adat.txt fájlba írjuk az alma és a körte szavakat. Olvasás fájlból: var f : text; sor : String; begin Assign(f, 'adat.txt'); Reset(f); ReadLn(f, sor); WriteLn(sor); ReadLn(f, sor); WriteLn(sor); Close(f); end. A példában az adat.txt fájlt megnyitjuk olvasásra, majd a ===== Saját típus ===== A type kulcsszó után saját típusokat vehetünk fel. A létrehozott saját típusok a var kulcsszó után hagyományos módon használhatók. type TEgesz = integer; TNagyEgesz = LongInt; TSzoveg = String; var szam : TEgesz; i, j : TEgesz; nagyszam : TNagyEgesz; nev : TSzoveg; begin nev := 'Pék Elemér'; i := 1; j := 0; szam := 2; nagyszam := 300000; end. A példában egy TEgesz, egy tNagyEgesz és egy TSzoveg nevű típust deklarálunk rendre. A var kulcsszó után ezeket úgy használjuk, mint a normál típusokat. ===== Rekord típus ===== type Tszemely = record nev : String; tel : String; cim : String; fiz : LongInt; end; var szemely : Tszemely; begin szemely.nev := 'Nagy Elemér'; szemely.tel := 'Szolnok'; szemely.cim := 'Tél u. 3.'; szemely.fiz := 350000; end. A rekordot nem változónak, hanem típusnak deklaráljuk. Az új típusunk neve Tszemely. Ezek után deklarálhatok egy szemely nevű változót, amelynek Tszemely a típusa. Használata pedig úgy lehetséges, ahogy szimpla rekord használata is. ===== Tömb típus ===== type Ttomb = array [1..5] of integer; var tomb : Ttomb; begin tomb[1] := 35; tomb[2] := 47; tomb[3] := 87; end. A tömböt először egy saját típusként deklarálom a type kulcsszó után, a típus neve Ttomb. Ezt követően hozok létre egy tomb nevű változót, amelyet a saját tömb típusunkkal deklarálunk. Ezek után a tomb nevű változó ugyanúgy használható, mint a fentebb használtuk a tömböket. ===== Rekord tömbként, saját típussal ===== type Tszemely = record nev : String; tel : String; cim : String; fiz : LongInt; end; Tszemelyek = array[1..5] of Tszemely; var szemely : Tszemelyek; begin szemely[1].nev := 'Nagy Elemér'; szemely[1].tel := 'Szolnok'; szemely[1].cim := 'Tél u. 3.'; szemely[1].fiz := 350000; szemely[2].nev := 'Tér Béla'; szemely[2].tel := 'Debrecen'; szemely[2].cim := 'Nyár u. 45.'; szemely[2].fiz := 450000; end. A fenti példában deklarálunk egy Tszemely nevű rekordtípust. A Tszemelyek nevű tömb típus pedig Tszemely típusú rekordokat tartalmazhat, konkrétan 5-öt. A var részben a szemely változó ezek után egy tömböt deklarál. A tömbben öt személy adatait tudjuk eltárolni. A példában két személy adatait vettem fel. ===== Dátum ===== uses dos; var year, month, mday, wday : word; begin GetDate(year, month, mday, wday); WriteLn(year, ' ', month,' ',mday, ' ' , wday); end. uses SysUtils; begin WriteLn(DateTimeToStr(Now)); end. uses Dos; const NapStr:array[0..6] of string[3]=('Hétfő','Kedd','Szerda','Csütörtök','Péntek','Szombat','Vasárnap'); HonapStr:array[1..12] of string[3]=('Jan','Feb','Mar','Ápr','Máj','Jún', 'Júl','Aug','Szept','Okt','Nov','Dec'); var Ev,Honap,Nap,HetNapja : word; begin GetDate(Ev,Honap,Nap,HetNapja); WriteLn(NapStr[HetNapja],', ',Nap,' ',HonapStr[Honap],' ',Ev,'.'); end. ===== Hang generálása ===== Windows XP alatt a különböző hangok generálására a wincrt unit utasításai adnak lehetőséget. uses wincrt; begin Sound(800); delay(5); nosound; end. ===== Könyvtárkezelés ===== Az aktuális könyvtár kiíratása var s : string; begin GetDir(0,s); WriteLn(s); end. Az aktuális könyvtár kiíratása a SysUtils felhasználásával. uses SysUtils; begin WriteLn(GetCurrentDir); end. ===== Operációs rendszer eljárásai, függvényei ===== * Chdir -- A munkakönyvtár cseréje * Getdir -- Az aktuális könyvtárral tér vissza * Halt -- A program futás befejezése * Paramcount -- A program hívásakor megadott paraméterek száma * Paramstr -- A program hívásakor megadott paraméterek kinyerés * Mkdir -- Könyvtár létrehozása * Rmdir -- Könyvtár "Remove" * Runerror -- A program megszakítása hibával procedure getdir(drivenr: Byte;var dir: shortstring);