VII. Adat be- és kivitel (input/output) alapfokon

Szöveg megjelenítése

Tanfolyamunk kezdete óta használjuk az egyik legalapvetôbb REXX parancsot, a SAY-t, amellyel karakterláncokat, változókat vagy összetett mûveletek eredményeit jelentethetünk meg az alapértelmezés szerinti kimeneti eszközön. A legtöbb számítógép esetében ez az eszköz a képernyô, így a SAY kimenete itt fog megjelenni. Érdemes észbentartani, hogy a képernyô a legtöbb esetben 80 karakter széles, így ha nem ügyelünk a megjelenítendô szöveg hosszára, akkor az a 81. karaktertôl kezdve a következô sorban fog megjelenni. A sorok száma is korlátozott, és a legtöbb esetben maximum 25 sort írhatunk egy ablakba. Ha ezt túlhaladjuk, akkor a legfelsô sor ki fog gördülni az ablakból és a felhasználó számára már nem lesz látható. Ha ezeket a dolgokat észben tartjuk, akkor nagyon esztétikus kimenetet kölcsönözhetünk programunknak a SAY és néhány más REXX függvény kombinálásával. A Center (vagy Centre) függvénnyel pl. egy adott szélességen belül középre igazíthatjuk a megjeleníteni kívánt karakterláncot. A Center alapesetben szóközökkel tölti fel a karakterlánctól jobbra és balra elterülô pocíziókat. Ha azonban a kedvünk úgy kívánja, akkor arra is megkérhetjük, hogy általunk tetszôlegesen megadott karaktert használjon tölteléknek. Az alábbi sorban például a Hello szöveget jelenítjük meg a sor közepén és * karakterekkel töltjük ki a többi pozíciót:

SAY Center(' Hello ', 79, '*')

Gyakran van arra is szükség, hogy egy karaktert megismételve jelenítsünk meg. Pontosan erre jó a Copies függvény:

SAY Copies('*', 79) /* Itt 79 db. csillagot nyomtatunk ki */

A Copies nem korlátozódik egyetlen karakterre, mivel bemenetként karakterláncokat is megadhatunk:

SAY Copies('OS/2 Rulez ', 7)

Számok megjelenítése

A REXX a számok megjelenítésénél a következô alapszabályokat használja. Minden karakterláncként bevitt szám pontosan úgy jelenik meg, ahogyan azt bevittük. A mûveletek eredményeként kapott számokat alapértelmezett esetben 9 tizedesjegyre kerekítve látjuk viszont. Az esetleges kezdô nullákat az értelmezô eltávolítja, s ha szükséges, a tizedespont elé nullát szúr be. Ha nulla az eredmény, akkor azt mindig egyetlen helyiértéken ábrázolja. Ha ezektôl a szabályoktól el akarunk térni, akkor a Format függvényt kell használnunk. A használat módja a következô:

Format(szám [, elôtte, mögötte, exp, határ])

A Format függvény a bemenetként megadott szám-ot adja vissza kerekítve és formázva. Az opcionális elôtte és mögötte paraméterek a tizedespont elôtt és mögött megjelenített helyiértékek számát jelentik. Az exp az exponenciális kitevô szélességét (más szóval az ábrázoláshoz használt helyiértékek számát), a határ pedig azt a számot adja meg, amely felett már exponenciális formátumban kérjük a megjelenítést. Ha az elôtte paraméter nem elég nagy, akkor hibaüzenetet kapunk. Ha nagyobb, akkor a felesleges pozíciókat szóközökkel pótolja ki a REXX. Amikor a határnak nullát adunk meg, akkor mindig exponeciális formában történik a megjelenítés, hacsak a kitevô nem éppen nullára jön ki. Abban az esetben, amikor a decimális rész szélessége nagyobb, mint a határ kétszerese, szintén exponenciális megjelenítés történik. Amikor nem exponenciális a megjelenítés, viszont az exp paraméter meg van adva, a REXX szóközökkel fogja megtoldani az eredményt, hogy a végeredmény szélessége megegyezzen az exponenciális formában történô megjelenítés szélességével. Most pedig lássunk egy példaprogramot a Format és paramétereinek használatára:

/* Format teszt */

p = 22 / 7 * 100
SAY Format(p, 4, 4) Format(p, 6, 2) Format(p, 6, 0) ,
    Format(p, 3, 2, 4, 0) Format(p, 3,,, 0) p

p = 5
SAY Format(p, 4, 4) Format(p, 6, 2) Format(p, 6, 0) ,
    Format(p, 3, 2, 4, 0) Format(p, 3,,, 0) p

p = 85.555
SAY Format(p, 4, 4) Format(p, 6, 2) Format(p, 6, 0) ,
    Format(p, 3, 2, 4, 0) Format(p, 3,,, 0) p

EXIT

A Format függvény által visszaadott eredményt mindig befolyásolja a NUMERIC DIGITS beállítás, amely az aritmetikai mûveletek pontosságát szabályozza. Az alapértelmezés szerinti beállítás a már korábban is említett 9 helyiértékes pontosság. Ez az beállítás eredményezi pl. azt is, hogy a Format('1234567890', 11) exponenciális formátumban jeleníti meg az eredményt. Ha ezt nem szeretnénk, akkor a Format végrehajtása elôtt 10-re kell állítanunk a pontosságot a NUMERIC DIGITS 10 utasítással. A pontosságot ne növeljük indokolatlanul, mivel egy nagy érték beállítása jelentôsen (és valószínüleg teljesen feleslegesen) lassítaná programunk futását. Az exponenciális számok ábrázolására van hatással a NUMERIC FORM parancs. Az alapértelmezett beállítás a SCIENTIFIC, amely azt jelenti, hogy a tizedespont elôtt csak egy, nem nulla digit állhat (pl. 1.234E8). Ha viszont a NUMERIC FORM ENGINEERING paranccsal átváltunk a másik lehetséges beállításra, akkor a tizedespont elôtt már három nem nulla digit is állhat (123.4E6).

Adatbevitel

A leggyakrabban használt adatbeviteli eszköz a billentyûzet. Valószínüleg ezért is választották az alapértelmezett beviteli eszköznek (standard input) is. A REXX-ben több módja is van az adatbevitelnek, amelyek közül most a PULL utasítást fogjuk megvizsgálni. Az alapértelmezésnek megfelelôen a PULL is a billentyûzetrôl várja az adatot, amelyet aztán nagybetûs alakra alakítva a paramétereként megadott változóban tárol el. Ha tehát a felhasználó a PULL data parancs hatására a ValaMi adatot gépeli be és ENTER-t üt, akkor a data változó tartalma VALAMI lesz. Ha azt szeretnénk, hogy a begépelt adat egy az egyben kerüljön bevitelre, akkor a PARSE PULL data utasítást kell használnunk. Ennek az a magyarázata, hogy a PULL utasítás tulajdonképpen a PARSE UPPER PULL rövid formája, amely viszont kötelezôen elôírja a konvertálást. Paraméterként egynél több változót is megadhatunk, s ekkor az elsô begépelt szó az elsô változóban, a második a másodikban és így tovább kerül elraktározásra. Ha több változó van mint szó, akkor a felesleges változók üres karakterláncot fognak tartalmazni. Ha az ellenkezô eset áll fenn, vagyis több szó kerül bevitelre, mint változó, akkor a felesleges szavak mind az utolsó változóba kerülnek. Próbáljuk ki az itt leírtakat az alábbi példaprogramon:

/* Névbevitel */

SAY 'Add meg a teljes nevedet!'
PARSE PULL vezeteknev keresztnev
SAY 'A vezetékneved: 'vezeteknev
SAY 'A keresztneved: 'keresztnev
EXIT

Az ARG utasítás

Az ARG segítségével azokat a paramétereket tudjuk programunkba beolvasni, melyeket a program indításakor a parancssorban paraméterként megadtak. A parancssorból leggyakrabban kapcsolókat vagy állományok neveit szokás bevinni. Az ARG-ot a PULL-hoz hasonlóan használhatjuk:

ARG 
PARSE ARG 
PARSE UPPER ARG 

Az elsô forma a legegyszerûbb használati módot mutatja, amelyben a parancssori paraméter mindig nagybetûs formában kerül eltárolásra a helyén megadott változóban. Ha nem akarjuk a nagybetûs konverziót, akkor a második formát kell használnunk. A harmadik sorban az elsô használati mód "szószátyárabb" megadása található. Ugyanúgy, mint a PULL, az ARG is képes egyszerre több paraméter beolvasására is. Lássunk egy egyszerû példát az ARG használatára:

/* Meghajtó és könyvtárváltás egy lépésben */

ARG ujdir
SAY Directory(ujdir)
EXIT

A program indításakor a parancssorban megadott paraméter az ujdir változóban kerül eltárolásra, amellyel aztán meghívjuk a Directory függvényt. A hívás eredményét egyben a képernyôre is kiíratjuk. Ha az ujdir értéke egy létezô könyvtár, akkor átváltunk ebbe a könyvtárba és a könyvtár neve jelenik meg eredményként a képernyôn. Ha nem adunk meg paramétert, akkor a jelenlegi könyvtár nevét kapjuk vissza. A Directory számára nem értelmezhetô paraméter megadásakor nem történik semmi, csak egy üres karakterláncot íratunk ki. Ha begépeljük a programot és valamilyen rövid nevet adunk neki, pl. CHD.CMD, akkor akár a parancssorban való navigálás hasznos eszköze is lehet.

Segítô üzenetek beépítése

Amikor programot írunk, sohase tételezzük fel, hogy a program mûködése és használata mindenki számára nyílvánvaló lesz. Mindig gondoskodjunk valamilyen beépített segítségrôl, amely útmutatást nyújt majd a használathoz. Egy bevett szokás, hogy ha a parancssorban a /? vagy -? paramétert adjuk meg, akkor rövid magyarázatot (Usage) kapunk a program használatáról. A legjobb, ha egy program készítését a használati üzenet megírásával kezdjük. Ez egyben arra is jó, hogy még egyszer átgondoljuk programunk mûködését, mielôtt nekiugranánk az írásnak. Ugyanakkor nem kell túlzásokba sem esnünk, és nem kell a felhasználót egy több oldalas üzenettel ijesztgetni. A részletes használati utasításnak a programhoz mellékelt információs (readme) fájlban a helye. Végül lássunk egy példát használati utasítás beépítésére:

/* A CHD.CMD kibôvítése segítséggel */

ARG ujdir
IF ujdir = '?' | ujdir = '/?' | ujdir = '-?' THEN
  DO
    SAY 'Ezzel a programmal egy lépésben válthatunk meghajtót és könyvtárt.'
    SAY ''
    SAY 'Használat: CHD [meghajtó][könyvtár]'
    SAY 'Példa: CHD C:\TEMP'
    EXIT
  END
SAY Directory(ujdir)
EXIT


REXX GYÍK:

K1: A programom 80 karakteres sorokat jelenít meg és megfigyeltem, hogy minden sor után kihagy egy üres sort. Ez miért történik?
V1: Amikor egy sort jelenítünk meg, akkor a REXX sor végére mindig odatesz két láthatatlan karaktert, az ún. kocsi vissza (carriage return) és az új sor (new line) karaktereket. A kocsi vissza hatására a kurzor visszaugrik a sor elejére, az új sor karakter hatására pedig egy sorral lejebb kerül. Amikor 80 karakter hosszú szövegeket nyomtatunk, akkor a kurzor kénytelen visszaugrani a következô sor elejére, tehát a kocsi vissza karakternek semmi hatása nem lesz. Az új sor karakter miatt viszont keletkezni fog egy üres sor. Ha csak 79 karakter hosszú sorokat nyomtatunk, akkor nem fog sor kimaradni.

K2: Mi történik, ha az ARG utasítást nem a program kezdetén, hanem csak sokkal késôbb használom?
V2: Semmi. Az ARG utasítást akárhol használhatjuk a programon belül.


Gyakorlatok:

1. Mi lesz az alábbi példákban a Format eredménye?
a. Format('12.1', 3, 2)
b. Format('995', 2, , , 0)
c. Format('0.9', 2, 0)
d. Format('1000', 2, 3, 3, 0)

2. Készítsünk egy programot, amely visszaírja a parancssorban megadott paramétereket!

Kádár Zsolt
1998. 01. 16.
[ Elôzô lecke | Következô lecke | Tartalom ]