You are on page 1of 38

A BASIC nyelvű programozás alapjai

Kedves Lóri!
Ebben az irományban megpróbálok neked némi segítséget nyújtani abban, hogy el tudd kezdeni a
programozást. Előrebocsátom, hogy ez a dolog egyáltalán nem könnyű, így eleinte túlságosan gyors
előrehaladásra nem lehet számítani. Az olyan okosan kialakított programnyelvek, mint amilyen a
Rapid-Q Basic, nagyon sok dolgot megkönnyítenek a programozó számára, de ezek a könnyítések
csak akkor használhatók ki, ha az ember már tisztában van az alapokkal. Nagyon egyszerű például
megterveznünk azt az ablakot, amelyben a programunk fut majd, de magát a programot nekünk kell
megírni a működtető elemek „mögé”. Könnyen, egy-két kattintással helyezhetünk el az ablakban
mindenféle hasznos elemet: képmezőt, gombokat, szövegbeolvasó ablakocskákat, stb. – de amikor a
programot lefordítjuk, ezek az elemek csak ott vannak, maguktól semmit sem fognak csinálni. Az
ablakocskákba csakugyan írhatunk szövegeket, a gombokat nyomkodhatjuk, de ha nem közöltük a
programmal, hogy mit kezdjen a szöveggel, mit csináljon gombnyomás esetén, magától sohasem
fog rájönni. Ezért nem is ugrom rögtön neki a Rapid-Q Basicnek, hanem egy hagyományosabb
BASIC-változattal indítok. Az átküldött fájlok között mellékelem ezt a „gyakorlónyelvet” is.

Némi történeti áttekintés


(Unalmas, de nem bánnám, ha elolvasnád)
Mielőtt azonban bármiféle nyelvbe belekapnék, jó, ha tisztázunk bizonyos alapfogalmakat, amelyek
a programnyelvektől függetlenül szükségesek a számítógép működésének megértéséhez. A valódi
alapokkal, nevezetesen, hogy ez a rakás alkatrész hogyan tudja megcsinálni mindazt, amit majd
elmondok róla, nem foglalkozom, sok esetben magam sem tudom, a programozás szempontjából
nem is érdekes.
Elsőként szokás megemlíteni, hogy a gép, legalábbis emberi értelemben, nem ért semmit a
feladatból. A legfontosabb része – a processzor, vagyis a műveletvégző egység – egy bonyolult
szerkezet, amely sokféle egészen egyszerű feladat elvégzésére képes. Azt, hogy mit csináljon, úgy
határozhatjuk meg, hogy elküldünk neki egy számot. Ha ez a szám mondjuk a 283, akkor a
processzor a számtalan lehetőség közül a kettőszáznyolvanharmadik műveletet végzi el.
Gyakran kábítják a hozzá nem értőket azzal, hogy a számítógép tulajdonképpen csak kétféle számot
ismer (a jelöléstől függően 0 vagy 1, igaz vagy hamis, stb.), és ebből épül fel az egész rendszer, de
ez csak félig igaz. Azon például senki sem csodálkozik, hogy mindössze tíz számjeggyel be lehet
számozni egy hosszú utcát: Igaz ugyan, hogy csak a 0,1,2,3,4,5,6,7,8,9 számjegyet használjuk, de
amikor ezek elfogynak, nem áll meg a tudomány, hanem ezeket többször írjuk egymás mellé,
keverjük, így akármilyen nagy számokat ábrázolhatunk velük. A kettes számrendszer csak két
számjegyet ismer, de ugyanúgy használhat sok helyiértéket, mint a tízes, így semmi sem
akadályozza a nagy számok használatát. A processzor tehát nem 0 vagy 1 értéket kap, hanem
egyszerre egy nagy, nullákból és egyesekből álló számot, így sokezer utasítás közül lehet választani.
Mit jelent az, hogy ezeket a számokat elküldjük a processzornak? Rendszerint azt, hogy a számokat
a számítógép valamely erre alkalmas helyén tároljuk, és valami módon közöljük a géppel, hogy az
értékeket éppen onnan töltse be a processzorba. A processzor azután végrehajtja a kapott utasítást,
azután beolvassa a következőt, azt is elvégzi, és így tovább. Így, a sok egyszerű kis utasításból
bonyolult, összetett műveletsorok állíthatók össze, amelyek együtt már komolyabb feladatot is
elvégezhetnek. Az ilyen műveletsorokat, illetve az azokból összefűzött, még bonyolultabb
rendszereket nevezzük programnak. Persze, a dolog nem mehet a végtelenségig, valahol minden
programnak vége kell, hogy legyen, ennek jelzésére is vannak megfelelő utasítások.
Mi történik, ha egy program véget ér? Ugyebár, tapasztalatból tudjuk, hogy a gép nem áll le, hanem
várakozik, és új programokat indíthatunk. Eltekintve attól, hogy az egésznek a megvalósítása a
számunkra elképesztően bonyolult, az alapja jól elképzelhető: Van egy hatalmas program, amely a
számítógép bekapcsolásakor elindul, és utána körbe-körbe jár. Amíg megy, sorban ellenőrzi, hogy
talál-e elvégezhető feladatot – például leütöttek-e egy billentyűt, vagy a CD-lejátszó jelzi-e, hogy
beleraktak egy lemezt –, és ha igen, elindít egy olyan programot, amely a feladatot megoldja. Ha az
ellenőrzés végére ér, kezdi az egészet elölről, mindaddig, amíg egy általunk megadott jel át nem
irányítja a befejezésre. Ekkor egy újabb utasítássort kezd beolvasni, amely olyan műveletekből áll,
amelyek felkészítik a gépet a kikapcsolásra. Ennek a programrészletnek a vége egy olyan szám,
amelynek hatására a processzor a tényleges kikapcsolást hajtja végre: jelet küld a kapcsolónak, és
az megszünteti az áramellátást. Amikor mi programot indítunk, ez a központi program az általunk
megadott címről kezdi olvasni az utasításokat, és amikor a programunk végére ér, visszatér a
főprogram végrehajtásához. A dolog valójában sokkal bonyolultabb, ugyanis a processzor időnként
abbahagyja a mi programunk olvasását, hogy közben más fontos dolgokkal is foglalkozzon, de ez a
mi szempontunkból nem érdekes, mivel magától elvégzi.
Ezt a bizonyos nagy, központi programot nevezik operációs rendszernek. Manapság a legismertebb
efféle a Windows, de sok egyéb is létezik, mint például a Unix (kiejtése angolosan junix, ezért csak
„a” a névelő) alapú rendszerek (köztük a Linux), az AIX, a BSD, Irix, Minix, Oberon, Macintosh,
DOS, ésatöbbi. Ezeknek a szervezése teljesen eltér egymástól, így ugyanazok a számsorok általában
nem ugyanazt jelentik a számukra – ennek megfelelően az egyik rendszer számára megírt
programok nem működnek a másikban.
Fontos még, hogy a számítógép nemcsak utasításokat tárol, hanem olyan adatokat is, amelyeknek
egészen más lehet a feladatuk, például képet, hangot, szöveget vagy a munkához szükséges
számokat. Ezeket a gép ugyanolyan számsorok formájában tudja csak kezelni, mint az utasításokat.
Hogy a kétféle dolog ne keveredjen egymással, a programnak azt is közölnie kell a processzorral,
hogy a megfelelő helyen lévő számokat ne próbálja meg végrehajtani, csak használja fel a
műveleteihez. Elvileg azonban rá lehet irányítani a programot mondjuk egy képet leíró
adatcsoportra, ami persze rendszerint végzetes következményekkel jár: Először is, a gép elkezd
értelmetlen műveleteket végrehajtani, hiszen nem valódi programrészt talál, hanem olyan számokat,
amelyek véletlenül megegyeznek ezzel vagy azzal az utasítással. Végül azután eljut valami olyan
számhoz, amelynek mondjuk az a jelentése, hogy „ugorj vissza ötöt”, akkor öttel hátrább ugorva
újra olvasni kezdi, megint eljut a számig, megint visszaugrik, és így tovább, a végtelenségig... Ettől
fogva a gép semmi értelmeset nem csinál, csak ezen a néhány számon lépked, így nem olvassa a
billentyűket sem, tehát le sem lehet állítani. Ezt nevezik úgy, hogy a gép „lefagy”. Bonyolultabb
programok esetén a programozók figyelmetlenségéből is előadódhat, hogy a vezérlés efféle
nemkívánatos helyre kerül, ezért a mai rendszereket igyekeznek úgy kialakítani, hogy bizonyos
jelek (például a Ctrl+Alt+Delete gombok egyszerre történő lenyomása) még az ilyen reménytelen
kátyúból is kirántsák az operációs rendszert, anélkül, hogy a nagy kikapcsológombot meg kellene
nyomni – az erőszakos kikapcsolás ugyanis, amikor a főprogram nem tudja elvégezni a leállítás
műveletét, károsíthatja a gépet.
Ha idáig eljutottál, lehet, hogy azt gondolod, hogy az egész programozás olyan zűrös, hogy nem is
érdemes megpróbálni, de várj egy kicsit, jönnek a jó hírek!
Az, hogy a gépnek az ember közvetlenül számokat küldözgessen, az 50-60 évvel ezelőtti ősidők
módszere. Ahogy a gépek és az operációs rendszerek bonyolódtak, egyre kevésbé lehetett
hibamentesen megcsinálni. Ezért a puszta számokból álló gépi kód helyett kitalálták a
programnyelveket. Első volt az assembly nyelv: Minden, a processzor számára érthető számkódot
egy-egy többé-kevésbé megjegyezhető angol rövidítéssel helyettesítettek, és írtak egy olyan
programot (assembler), amely ezt a forráskódot vissza tudta fordítani gépi kódra, tehát a rövidítések
alapján az azoknak megfelelő számot írta a program megfelelő helyére. Ez még mindig nem könnyű
mesterség, hiszen a processzor utasításkészlete nem tartalmaz olyanféle összetett dolgokat, hogy
„rajzolj ablakot a képernyőre”, hanem csak ilyesmiket: „olvass be egy számot” vagy „döntsd el,
hogy az egyik beolvasott szám nagyobb-e, mint a másik”. Az is igaz viszont, hogy ezzel az icipici
részekre bontott programnyelvvel tökéletesen pontosan meg lehet mondani a processzornak, hogy
milyen utasításokat hajtson végre, így az assembly nyelvet a mai napig használják olyan esetekben,
amikor fontos a hatékonyság, például nagyon gyorsan kell sok adatot feldolgozni vagy a képernyőre
vinni. A legtöbb esetben azonban nem kell a folyamatot ilyen pontosan ellenőrizni. Tételezzük fel,
hogy már jól kidolgozták, hogy hogyan lehet egy szöveget a képernyőre írni hatvan gépi utasítás
segítségével. Ki az a bolond, aki ezt a hatvan utasítást minden alkalommal a programba akarja
gépelni, valahányszor szükség van rá? Ráadásul a programszöveg áttekinthetetlenül hosszú is lenne,
jóformán javíthatatlan, ha valami mégsem stimmel. Mennyivel egyszerűbb, ha a programozónak
csak annyit kell írnia: print "kakuk" vagy write('hű, de kafa!'), a program pedig szépen beírja
helyette azt a bizonyos hatvan számot a megfelelő helyre! Az efféle megoldásokból jöttek létre a
magas szintű programnyelvek, amelyekben a programozó a tényleges feladatra koncentrálhat, nem
kell a gép számára olvasható formával foglalkoznia – azt a fordítóprogram elvégzi helyette.
Ennek a megoldásnak van még egy előnye. Említettem, hogy a különféle operációs rendszerek gépi
kódú utasítássorai törvényszerűen eltérnek egymástól. Ha tehát ugyanazt a feladatot egy másik
rendszerben is meg kellett oldani, az egész programot újra kellett írni másképpen. Ha viszont több
rendszerre is elkészítik egy magas szintű nyelv fordítóprogramját, akkor a programozónak nem kell
azzal foglalkoznia, hogy éppen melyiken akarja futtatni a programját. Lefordítás után ugyan minden
esetben más gépi kód kerül a számítógépre, de a programozó – maradva az előző példánál – csak
mondjuk azt írja a forráskódba, hogy write('tessék parancsolni!'), amikor ezt a szöveget akarja látni
a képernyőn.
Amíg a számítógépek nagyok, drágák, és nehezen kezelhetők voltak, lehetett mondani, hogy a
programozás módja a programozók magánügye. Amikor Laci nagypapa a Tákiban dolgozott, az
ottani számítógép egy egész szobát elfoglalt, minden indításkor végig kellett ellenőrizni, mert tele
volt villanykörtékre emlékeztető elektroncsövekkel, amelyek könnyen kiégtek. Ennek megfelelően
a működtetése is olyan drága volt, hogy külön össze kellett gyűjteni a sok számolást igénylő fontos
feladatokat, szakemberek által lefordítani, és egyszerre elvégeztetni, amikor végre eljött a beindítás
ideje. Azonban a gépek gyorsan fejlődtek, kicsik, biztos működésűek és olcsóbbak lettek, így egyre
több olyan ember is hozzájuk férhetett, aki nem számítástechnikus volt ugyan, de a munkájában
hasznukat látta. Aki segítséget vár a géptől, joggal bosszankodik, ha az nem hajlandó működni
olyasmik miatt, mint hogy véletlenül kisbetűvel írt valamit a programszövegben, vagy elfelejtett
külön helyet készíteni valamelyik számnak, amelyet használni akar. Ezért a programozás többek
között a nem szakértők számára is érthető programnyelvek irányában fejlődött tovább. Ezek
próbáltak a természetes angol nyelvhez igazodni, és minél kevesebb szigorú szabályt alkalmazni, ha
az a feladat szempontjából szükségtelen volt.
Az egyik ilyen programnyelv a BASIC. A név egy hosszabb angol kifejezés rövidítése (nem
emlékszem rá, hogy mi is az), egyszerűen kiolvasva viszont „alapszintű” a jelentése. Az olcsóbb
számítógépekbe rendszerint be is építették valamelyik változatát, és ez nagyban hozzájárult a
számítástechnika népszerűségéhez. Könnyen tanulható, az egyszerűbb feladatok jól megoldhatók
benne, ezért a mai napig általában ez az a nyelv, amellyel a programozást elkezdik az érdeklődők.
A dolognak van egy kis szépséghibája. Amikor a BASIC megszületett, a számítógépek korántsem
voltak olyan okosak, mint manapság. Bekapcsoláskor általában egy fekete képernyő jelent meg,
villogó fehér kurzorral, és már lehetett is szöveget beírni – közvetlen parancsokat, programkódot,
akár írógép helyett is használható volt. Mindenféle hasznos programokat is indíthatott a tulajdonos,
amelyek bonyolult számítások elvégzésében vagy egyébben segítették. Arra azonban álmában sem
gondolt senki, hogy egy-két évtized múlva a zenehallgatástól a filmvetítésen át a könyvtervezésig
az égegyadta világon mindenre használni fogják... Csakhamar azonban szükségessé vált, hogy
legalább egyszerűbb ábrák rajzolására alkalmas legyen, azután az Apple-Macintosh cég kitalálta az
ablakozó rendszert, amelyben egy képernyőn több program is futtathatóvá vált. Ezt azután a híres-
neves Bill Gates nem egészen tiszta módon lekoppintotta, és Microsoft nevű vállalkozásán keresztül
az egész világon elterjesztette – a ma már nem egészen ismeretlen Windows néven. A BASIC
követte a fejlődést, de a sokféle gép- és monitortípusnak megfelelően az eredeti, viszonylag
egységes programnyelv számtalan változatra, „tájszólásra” bomlott. A nyelv alapjai általában
megmaradtak, de az újabb igények kielégítésére sokféle eltérő megoldás született.
A Windows kezdetben a DOS operációs rendszer alprogramja volt, így aki BASIC-ben
programozott, megtehette, hogy a Windows elindítása nélkül, a szokott betűs képernyőn írhatta meg
a programját. A fejlődés azonban úgy hozta, hogy a rendszert „kifordították”: Ma a Windows az
alaprendszer, amely a régi programok futtatása érdekében még képes a DOS-képernyőhöz hasonló
ablakot nyitni. Ezért a hagyományos BASIC-programozással való ismerkedés bonyodalmasabb.
Bevezetés

A Windows-programozás látható része a képernyőre rajzolandó elemek kezelése. A valódi


működtető rész azonban maga a programnyelv, amelynek megismerésekor az úgynevezett grafikus
felület csak zavaró tényező. Először tehát hasznosabbnak látom, ha egy olyan basic-nyelvet mutatok
be, amely a szokott képernyőelemeket nem használja. Ennek a nyelvnek csak egy részével
foglalkozom, azzal, amelyik vagy még a mostani programozásban is érvényes, vagy divatjamúlt
ugyan, de a régies programhoz elengedhetetlen.
Csak mellékesen jegyzem meg, hogy bár a BASIC voltaképpen kezdőbetűkből összerakott
mozaikszó, manapság már senki nem törődik az eredeti jelentésével, ezért egyszerűen kisbetűvel
szokás írni – a továbbiakban én is így használom.

Interpreterek és compilerek
A sokféle programnyelv egyik lehetséges csoportosítása az interpreter és a compiler típusú
nyelvekre való felosztás. Az interpreter-nyelvek esetén tulajdonképpen a nyelv lefordítására
alkalmas programot futtatjuk, és abba töltjük be a programszöveget. Ezek után a program beolvassa
a programsorokat, a maga számára lefordítja, és végrehajtja a kapott utasításokat. A compilerek a
program megírása után úgy fordítanak, hogy létrehozzák a gépet közvetlenül működtető kódot, és ez
a továbbiakban már önállóan futtatható, attól függetlenül, hogy a létrehozó program jelen van-e a
gépen. A két típus nem mindig válik el élesen egymástól: Van olyan fordítóprogram, amely
kipróbáláskor a saját rendszerén belül futtatja a programunkat, de amikor már elégedettek vagyunk
a működésével, önálló kódot is készíttethetünk vele. Az interpreterek tehát egyrészt lassúbbak,
hiszen menet közben fordítanak, másrészt igénylik, hogy a futtatáskor jelen legyen az általában
tekintélyes méretű fordítóprogram. Ezért én például jobban szeretem a compilereket, hiszen a kész
program gyors, és nem kell a futtatásához egyéb segítség. Az a helyzet azonban, hogy az egyre
gyorsabb gépek megjelenésével és a tárolóhely olcsóbbá válásával az interpreterek újra divatba
jöttek: A viszonylagos lassúság nem jelent igazi hátrányt, hiszen így is milliószor gyorsabb, mint az
ember, és ugyanaz a programszöveg többféle operációs rendszeren is futtatható. Igaz ugyan, hogy a
fordítóprogram nagy méretű, de cserébe a programszövegek sokkal kisebb helyet foglalnak el, mint
egy önálló program – annak ugyanis tartalmaznia kell a teljes működtető részt. Ha száz programot
készítünk, akkor százszor, míg az interpreterbe olvasandó programok mind ugyanazt az egy
programot használják. Efféle modern interpreterek például a Java vagy a Python programnyelv,
amelyek amúgy sem árt, ha a gépünkön vannak, hiszen sok profi program is ki tudja aknázni a
jelenlétüket.
A Rapid-Q Basic compiler típusú, azonban a tanuláshoz hasznosabb egy olyan interpreter, amelyet a
DOS-ablakban úgy tudunk futtatni, hogy a programunk lefutása után az ablak nem záródik be
azonnal, hanem nyitva marad, így szemügyre vehetjük az eredményt. Ezért telepítünk egy basic
interpretert. Ha ez már a gépünkön van, a futtatásával belépünk a basic-rendszerbe.

A Blassic interpreter telepítése


Első dolgunk tehát, hogy telepítsük a basic-interpretert. Annak ellenére, hogy az imént jajgattam az
interpreterek nagy mérete miatt (a Pythonra, Javára ez bizony igaz), a közönséges, szöveges basic
esetén nincs okunk panaszra. Az általam kiválasztott Blassic alig több, mint 1 megabájt.
A Blassic név a „basic classic” vagyis klasszikus basic kifejezés összevonása. Amikor kipróbáltam,
egészen meghatódtam a régi emlékektől, olyan bámulatosan utánozza a hajdani kisgépek basicjét.
A „telepítése” több, mint egyszerű: Készítesz egy mappát a számára, azután belemásolod a ZIP-
fájlban található egyetlen, blassic.exe nevű fájlt. A futtatására a legegyszerűbb módszer, ha küldesz
egy parancsikont az asztalra (Jobb egérgomb => Küldés => Asztal(parancsikon létrehozása)), és a
továbbiakban onnét indítod. A megírandó programok majd ugyanabba a mappába kerülnek,
mellesleg ez is jól felidézi a régi gépek világát, amikor még nem volt mindenféle bonyolult
könyvtárrendszer, egyszerre úgyis csak egy program lehetett a gépben.
Az első program
Elindítjuk a Blassic programot. A képernyőn megjelenik a DOS-ablak, amelyet ma inkább konzol
névvel illetnek, és a program várja, hogy begépeljünk valamit, amit végre tud hajtani. Írd be a basic
egyik leggyakoribb utasítását: PRINT. (Említettem, hogy a nyelv ezen a téren nagyon engedékeny,
így mindegy, hogy kis- vagy nagybetűvel írod, én csak azért nagybetűsítem, hogy jól felismerhető
legyen a programszöveg.)
Amikor a sor végén megnyomod az Enter gombot, az interpreter nyomban végre is hajtja a
műveletet. Látszólag azonban nem történt semmi, csak egy sorral lejjebb kerültünk, és egy Ok
üzenet jelzi, hogy minden rendben, ezért a dolog némi magyarázatra szorul. A PRINT utasítás azt
jelenti: nyomtass, tehát a basic kinyomtatja a szöveget, amelyet kértünk tőle, egyéb pontosítás
nélkül egyszerűen a képernyőre. Mit is kértünk? Semmit! Az üres PRINT parancs tehát a nagy
semmit írja ki, azután annak rendje-módja szerint lezárja a sort, ugrik a következőre, és várja az
újabb teendőket. Ha valamit tényleg ki akarunk íratni a képernyőre, akkor közölnünk kell, hogy mi
legyen az, tehát adatot kell átadnunk a programunknak. Föntebb említettem, hogy a gépnek
voltaképpen mindegy, hogy mit irkálunk bele, mindent számok formájában tárol, akkor is, ha mi
betűket vagy képet látunk. Emiatt az esetünkben külön jeleznünk kell, hogy a PRINT utasítás után
nem egyéb, mint egy meghatározott betűsor következik. Ezt a basicben úgy oldjuk meg, hogy a
szöveget két felső idézőjel közé fogjuk:
PRINT "galagonya"
Ha ezt a sort beírod, és utána megnyomod az Entert, a képernyőn csakugyan megjelenik a
galagonya felirat. Ezen a ponton illendő gratulálnom, ugyanis megírtad az első olyan
működőképes programodat, amely csinál is valami látható dolgot. Na jó, a dolog még nem mérhető
Lara Croft kalandozásaihoz, de egy régi kínai közmondás szerint az ezer mérföldes út is egyetlen
kicsi lépéssel kezdődik...
Lépjünk még egyet. Az iménti sort nagyvonalúan programnak tituláltam, de ez valójában pontatlan
meghatározás. Igaz, a program akárhány sorból állhat, tehát miért is ne lehetne egyetlen az az
akárhány? Az ilyen azonnal végrehajtandó és elfelejtendő sorokat azonban parancsoknak nevezik.
Ahhoz, hogy kiérdemeljék a program nevet, az kell, hogy a gép meg is jegyezze őket, és kérésre
újra meg újra el tudja végezni a kért feladatot. A hagyományos basic nyelvben a valódi
programsorokat vagyis utasításokat az különbözteti meg a rögtön végrehajtandó parancsoktól, hogy
sorszámmal kezdődnek, így:
10 PRINT "galagonya"
Írd csak be! Az Enter leütése után máris fölfigyelhetsz a különbségre: A basic nem írta ki a
galagonyát, csak az Ok-t. A magyarázat mindjárt következik, csak előbb szót ejtek a sorszámokról.
A számozás tetszés szerinti értékről indulhat, és nem kell, hogy egyesével kövessék egymást a
számok. Sőt, a régi típusú basicekben ajánlatos jó nagy különbséget hagyni a számok között: Ez
biztosítja, hogy a program fejlesztése során újabb sorokat tudjunk beszúrni a már meglévők közé.
Később megoldották, hogy a program utólag átszámozható legyen, ha már nem fér be több sor a
rosszul megválasztott sorszámok közé, és a modern változatokban már egyáltalán nincs szükség
sorszámokra, de a Blassic még ragaszkodik a hagyományhoz.
A sorszámmal jeleztük az interpreternek, hogy most nem parancsról, hanem programsorról van szó.
Ezért azután nem is hajtotta végre, hanem csak megjegyezte. Futtatni csak akkor fogja, amikor majd
megkérjük rá. Mindezt akár becsszóra is elhihetnéd, de nem árt, ha a tanulóban van egy kis
egészséges kétkedés. Később ráadásul még bonyolódhat a program, és mondjuk 5 sor után ki a
csuda emlékszik rá, hogy minek is kéne pontosan a gépben lennie? Nem ártana megnézni, hogy
tényleg ott van-e valahol az állítólagos program... Ezt a LIST paranccsal (listázz) teheted meg. Ha
beírod, hogy LIST, a basic a sorok számozása szerint kiírja a program szövegét, esetünkben az
egyetlen 10 PRINT "galagonya" sort. Minthogy tudjuk, hogy ez a sor tulajdonképpen egy
működő programszöveg, akár ki is próbálhatjuk, de hogyan? Erre való a RUN (fuss) parancs. Írd be,
és Enter után megjelenik a galagonya. Most azonban a basic nem felejti el, mint az imént, hanem
akárhányszor beírod a RUN-t, mindig elő tudja szedni a PRINT "galagonya" utasítást, hogy
végrehajtsa.
Építsük tovább a programot: Most már egy helyett több utasítássort helyezzünk el benne:
20 PRINT "kakuk"
30 PRINT "kalap"
40 PRINT "ragacs"
25 PRINT "szerda"
Két dologra hívnám fel a figyelmedet. Az egyik, hogy tartózkodtam az ékezetek használatától.
Bizonyos okok miatt az ékezetes betűk várhatólag nem úgy jelennek meg, ahogyan beírjuk őket. Te
ettől függetlenül nyugodtan kipróbálhatod, semmi baj nem származik belőle. A másik dolog, hogy
az utolsó sorba 25-ös sorszámot írtam, mintha utólag jutott volna eszembe, hogy ezt a sort a 20-as
és a 30-as közé szúrjam be. Természetesen egy ilyen rövid programot akár teljesen átírhattam volna
a megfelelő sorrend érdekében, de jóval hosszabb forráskód esetében ez már nem menne
egykönnyen. Listázzuk ki a programot:
LIST
10 PRINT "galagonya"
20 PRINT "kakuk"
25 PRINT "szerda"
30 PRINT "kalap"
40 PRINT "ragacs"
Ok
A program tehát emelkedő számsorrendbe rendezte a sorokat, és tud az előzőleg beírt 10-es számú
sorról is. Futtatás:
RUN
galagonya
kakuk
szerda
kalap
ragacs
Ok
Ez idáig nagyszerű. Van azonban egy bökkenő, ami idáig nem zavart bennünket. Az interpreter
megjegyezte ugyan a programunkat, de ez mit jelent? Ha most bezárjuk, akkor mindent elfelejt, és
legközelebb kezdhetjük a gépelést elölről?
A dolog bizony így áll. A program most a gép memóriájában van, és törlődik, amint az interpretert
kikapcsoljuk. Ahhoz, hogy később is használni tudjuk, valami maradandóbb tárolásra van szükség,
például a merevlemezre kell mentenünk. Ez a SAVE (mentsd) parancssal végezhető el. Írd be a
következőt:
SAVE "szavak.bas"
Mint látható, ennek a parancsnak szintén egy szöveget (a számítástechnikában inkább úgy mondják,
hogy karakterláncot vagy karakterfüzért) adtunk át, ez határozza meg, hogy mi legyen az
elmentendő fájl neve. A régi számítógépeken a fájlnév legföljebb nyolc karakter lehetett, és nem
tartalmazhatott szóközt. Én itt tartottam magam ehhez a szabályhoz, de a Blassic már nem követeli
meg. A .bas a basic-programok hagyományos kiterjesztése, de ehelyett is lehet akármit írni. Az
ékezetek viszont itt is problémásak, úgyhogy azoktól érdemes őrizkedni.
Enter megnyomása után az adatok a lemezre íródnak, tehát nem vesznek el a számunkra.
Legközelebb a LOAD (töltsd) utasítással olvashatjuk be a programot:
LOAD "szavak.bas"
Érdekesség, hogy a programszöveg megírható a Jegyzettömbbel is, a Blassic úgy is be tudja
olvasni. Ha viszont a Blassicből mentett fájlt nézed meg a Jegyzettömbbel, láthatod, hogy az nem
ugyanolyan formában ment, emiatt azután már nehézkes lenne kívülről továbbfejleszteni. Ez annak
köszönhető, hogy a Blassic a saját maga számára legkényelmesebb formába rendezve menti el az
adatokat. Az ismertetőjét lapozgatva azonban megtudható, hogy ha a mentősor végére egy
vesszővel leválasztott A betűt írunk, az arra utasítja az interpretert, hogy közönséges szövegként
mentsen. Így már minden jól látszik, remekül használható a kényelmesebb Jegyzettömb:
SAVE "szavak.bas", A
Búcsúzóul érdemes megemlíteni, hogy az interpreter nem hagyja magát csak úgy bezárni:
Windows-hibaüzenet jelzi, hogy még futna tovább. Természetesen választhatjuk az Erőszakos
bezárás lehetőségét, de a tisztességesebb megoldás, ahogy látom, a következő:
Az interpreterbe beírod az STOP parancsot (vége), utána pedig az EXIT parancsot (kilépés),
mindkettőt Enterrel lezárva. Ez normálisan befejezi a program futását.
Megjegyzés: A fenti program az úgynevezett „Helló, világ!” programocskának egy változata. A
programozásban kialakult játékos hagyomány szerint egy programnyelvvel való ismerkedéskor első
próbaként a „Hello word!” szöveget kiíratni a képernyőre. Gondolom, ezt már a segítségem nélkül
is meg tudod tenni...

Újabb adalékok
Tekintsük át, hogy eddig mit tudunk. Először is megtanultál néhány parancsot, amely a basic-
program általános működtetéséhez szükséges: A begépelt programot ki tudod listázni (LIST), el
tudod indítani (RUN), elraktározhatod (SAVE), és újra betöltheted (LOAD). Tudod, hogy az
utasítások sorrendjét a sor elejére írt sorszámmal határozhatod meg, illetve, hogy a sorszám közli a
basic-interpreterrel, hogy egyáltalán programsorról, nem pedig azonnal végrehajtandó parancsról
van szó.
Másodszor: Megírtál egy kis programot, amely szavakat ír a képernyőre. Erre a PRINT utasítást
használtad, amelynek idézőjelek közé fogott karakterláncot adtál át adatként.
Mehetünk tovább. A program fejlesztése állandó változtatgatást jelent. Ezt külső szerkesztőben,
például a Jegyzettömbben könnyű megtenni, de láttuk, hogy a Blassic által mentett szöveg ott már
nemigen módosítható, például azért, mert nem látszanak a sorszámok. Bemutattam, hogy a kellően
ritkán számozott sorok közé milyen egyszerűen szúrhatunk be újabbakat, közéjük eső sorszámmal.
De mi történjen, ha egy már meglévő sort szeretnél módosítani? Mondjuk, ha a „galagonya” helyett
a „vadkan” szót íratnád ki? Írd be:
10 PRINT "vadkan"
Listázás után láthatóvá válik, hogy az azonos számmal beírt új sor felülírta a régit. Megeshet
viszont, hogy a sor teljes egészében fölöslegessé válik, törölni szeretnéd. Ekkor csak ennyit írj:
10
Az egyéb szöveg nélkül megadott sorszám törli az adott sort, tehát a programban nem fognak üres
sorok kuksolni, hanem csakis azokat tekinti létezőnek, amelyek valamit tartalmaznak. Ez hasznos,
viszont egy egyelőre még nem feltűnő kellemetlenségre vezet. Amikor már alaposan felhizlaltunk
egy programot, a mázsaszámra begépelt szöveg egyre áttekinthetetlenebbé válik. Szükségünk lesz
arra, hogy részekre tagoljuk, így jobban elkülönülnek egymástól a program különböző feladatai.
Továbbá, amíg dolgozunk, nagyjából tudjuk, hogy mire való a programunk, de fél év múlva már
vakarhatjuk a fejünket, hogy mi is ez a nagy kupac művelet voltaképpen. Ezt valahogyan fel kellene
tüntetni a programban, de ha csak úgy beírunk valamit, az interpreter azonnal hibát jelez. Nem
csoda: Beolvassa ugyan, hogy Lóri programja, de hiába, nem tudja lefordítani, mert ilyen
utasítások nem léteznek. Utasításként ugyanis nem írhatunk be bármit. A basic megalkotói a
programozás céljára összeállítottak egy szókészletet, és a feladatok leírására csak ezeket a szavakat
használhatjuk. Nincs ez egyébként másképpen a természetes nyelvekben sem: Akármilyen tisztán,
szépen hangsúlyozva mondom, hogy „prunc”, senki sem fogja megérteni – ilyen magyar szó nem
létezik. A programnyelvek persze jóval kevesebb szót használnak, így végképp nem várható, hogy
minden általunk beírt dologgal kezdjenek valamit. A problémára a REM utasítás a megoldás. A REM
a remark (megjegyzés) szó rövidítése, a programba írva pedig azt jelenti: „Amit ide írtam, csak
megjegyzés, nem a program része, ne foglalkozz vele”. Így használható:
1 REM szokiiro program
2 REM (a megadott szavakat print utasitasokkal a kepernyore irja)
3 REM
10 PRINT "galagonya"
20 PRINT "kakuk"
24 REM a kovetkezo sort utolag szurtam be:
25 PRINT "szerda"
30 PRINT "kalap"
40 PRINT "ragacs"
Futtatás:
RUN
galagonya
kakuk
szerda
kalap
ragacs
Ok
A program tehát a szokott módon lefut, anélkül, hogy törődne a számára ismeretlen szavakkal.
Fölhívnám a figyelmedet a 3. sorra, amikor a REM után nem írtam semmit. Ez nem tartalmaz
útmutatást, egyszerűen csak egy üres sor, amellyel jobban elkülöníthetem a programszöveg részeit.
A REM szó begépelése azonban mégiscsak munka, sőt a program megértését is nehezíti, hogy
elolvassuk, ezért aposztróffal helyettesíthető. Így még jobban át lehet tekinteni a szöveget:
1 ' szokiiro program
2 ' (a megadott szavakat print utasitasokkal a kepernyore irja)
3 '
10 PRINT "galagonya"
20 PRINT "kakuk"
24 ' a kovetkezo sort utolag szurtam be:
25 PRINT "szerda"
30 PRINT "kalap"
40 PRINT "ragacs"

Néhány szó a memóriáról.


Az imént már szóba került a memória, de akkor még nem foglalkoztam vele, mert nem volt
különösebb jelentősége. A későbbiek megértéséhez azonban szükség lesz rá, ezért most vázlatosan
megmagyarázom, mi az. A szó eredetileg emlékezetet jelent, és némely hasonlóság miatt így
nevezték el a számítógépnek azt a részét, amelyben ideiglenesen adatokat helyezhetünk el. Ebből a
szempontból adatnak tekinthető a program is, hiszen ugyanúgy számértékek sorozata, mint minden
egyéb, amivel a gép dolgozik. A memória adatainak tárolása, változtatása vagy törlése tisztán
elektromos folyamatok formájában történik, mint ahogy maguk az itt kezelt adatok is villamos
jelek. Ezért a memória működése sokkal gyorsabb az egyéb tárolókénál, ahol valamely maradandó
változást kell előidézni a jelek elraktározásakor, és ez az áram sebességéhez mérten nagyon sok időt
vesz igénybe. Azonban éppen ezért, amint az elektromosság megszűnik benne – például a gép
kikapcsolásakor, vagy áramszünetkor –, a memóriában lévő minden adat eltűnik. De amikor egy
programot bezárunk, általában az operációs rendszer is törli a program által elhelyezett adatokat,
hogy helyet csináljon más programok adatainak. Ezért fontos tehát, hogy legkésőbb a munka végén
mindenképpen elmentsük a fontos dolgokat, vagyis maradandó jelekké alakítva tároljuk, például a
gép merevlemezén. A memória valódi felépítése sokféle lehet, de ezzel itt nem érdemes
foglalkoznunk – nem mintha egyáltalán értenék hozzá. A számítástechnika tele van a hétköznapi
elme számára felfoghatatlan dolgokkal, amelyek működésének lényegét sokkal jobban megértjük
egy leegyszerűsített és hamis, de jól elképzelhető hasonlat alapján, mint az igaz, de érthetetlen
magyarázatból. A memória például úgy képzelhető el szemléletesen, mint valami hatalmas
iratszekrény, rengeteg beszámozott fiókkal. Minden fiókban egy szám lehet. Amikor a programnak
szüksége van egy adatra, megnézi, hogy hányadik fiókból kell azt elővennie. A fiókok számozását
nevezik memóriacímnek. Amikor még a régi gépeken csak egy program lehetett a memóriában,
egészen pontosan lehetett tudni, hogy az melyik címen volt megtalálható, így az akkori
programozásban jelentős szerepe volt a PEEK és POKE utasításoknak, amelyekkel közvetlenül
lehetett kiolvasni és beírni a memória számértékeit. Így nagyon trükkös módszerekkel lehetett
beavatkozni a program lefutásába. Bonyolultabb módon ugyan, de a mai gépeken is meg lehet tudni
a memóriacímeket – sőt, bizonyos célokra a Blassicban is használhatók a PEEK és POKE utasítások
–, ám a mi szintünkön semmi szükségünk nem lesz ilyesmire.

A második program
(játék a konstansokkal)

Az elmondottak mind hasznos ismeretek, de a program még valójában nem fejlődött semmit. Arról
még nem esett szó, hogy mi is az a „galagonya” vagy egyéb, amit a PRINT utasítás kezel. Azt már
tudod, hogy adat, mégpedig szöveges adat, más néven karakterlánc. Említsük meg, hogy azért nem
betűkről szokás beszélni, mert a szöveg tartalmazhat egyebet is – számjegyeket, írásjeleket –
amelyek hagyományos értelemben nem betűk, ezért a külföldi szakirodalomból átvett összefoglaló
kifejezéssel karaktereknek nevezzük őket.
Amikor a programot beolvassa az interpreter, keres a szövegeknek a memóriában egy alkalmas
helyet, és futtatáskor az itt található adatok alapján írja a betűket a képernyőre. Nem véletlenül
kerülöm azt a pongyola kifejezést, hogy „az itt található adatokat írja a képernyőre”. Mint tudjuk, a
memóriában számok találhatók, nem pedig karakterek. Hogy lehet, hogy a program számokat kap,
és betűket ír ki? Úgy, hogy valahol a gépen van egy táblázat, ahol egy bizonyos sorrendben föl
vannak sorolva a karakterek. Ha a program „tudja”, hogy betűt kell írnia, akkor a memóriából
szerzett szám mutatja meg a számára, hogy hányadik karaktert kell kiválasztania a táblázatból. Ha
például a 65-ös számot találja, akkor a hatvanötödik karaktert írja ki, amely történetesen a nagy A
betű.
Itt a kiírt szövegeknek arra a tulajdonságára szeretném felhívni a figyelmedet, hogy a program során
nem változnak meg. Az efféle változatlan adatokat állandóknak, más néven konstansoknak
mondjuk. Éppen azért, mert nem változnak, túl sok izgalmas dolgot nem várhatunk tőlük. Ugyan,
mit kezdhet az ember néhány egymás alá írt szöveggel? Nos, például rajzolhat velük:

Ezen a kis ábrán nem feltűnő, de éppenséggel látható, hogy a különböző betűk nem egyformán
fedik a képernyőt: a pont csak alig, a bonyolultabb rajzolatú X, M vagy W viszont erősebben
látszik. Megfelelően kiválasztott betűkkel egészen tűrhető árnyékolást lehet megvalósítani. Amikor
az ilyesféle mókák divatban voltak, a programozók jobb ügyhöz méltó buzgalommal készítettek
mindenféle képet, népszerű színészek portréjától a pucér nőcis rajzokig.
A szövegeket össze is lehet adni, ekkor a karakterfüzérek egybekapcsolódnak:
PRINT "kard"+"hal"
kardhal
Ok
PRINT "csavar"+"anya"
csavaranya
Ok
Nemcsak szöveges konstansok léteznek. Beírhatunk a parancsba számokat is, ennek már igazi
számolás lesz az eredménye:
PRINT 100+25
125
OK
Számok esetén az összeadáson kívül egyéb műveletek is elvégezhetők. A szorzás és az osztás jele
különbözik attól, amit a számtanórákon megszoktunk: A szorzást pont helyett csillag (*), az osztást
kettőspont helyett jobbra dőlő ferde vonal (/) jelöli. Például tízet osztunk kettővel, beszorozzuk
hárommal, és kivonunk belőle kettőt:
PRINT 10/2*3-2
13
Ok
Most húszból kivonunk ötöt, és megszorozzuk hárommal. Ez, ugyebár, 45 lesz:
PRINT 20-5*3
5
Ok
Hoppá, dehogy oké! Mi történt? Elromlott a számítógép?
Nem, csak éppen van egy különleges szabály, amit elfelejtettem megemlíteni... A program bizonyos
műveleteket fontosabbnak ítél, ezért azokat a beírás sorrendjétől függetlenül előbb végzi el. A
szorzást és az osztást például előbbre valónak tartja, mint az összeadást és a kivonást. Ezt úgy is
mondják, hogy nagyobb a precedenciájuk. Hogy ez miért van így, most közömbös, hasznosabb, ha
a helyzet megoldását közlöm. Az egybe tartozó kifejezést zárójelek közé kell fogni, akkor a
program azt számolja ki előbb:
PRINT (20-5)*3
45
Ok
Így már stimmel. Erre a szabályra (precedenciaszabály) mindig gondolni kell, amikor
programnyelven fogalmazunk meg egy matematikai műveletet, különben nehezen földeríthető
hibák forrása lehet.
Még egy lehetőség a melléfogásra:
PRINT "100"+"200"
100200
Ok
Ejnye! Nem háromszáznak kellett volna kijönnie véletlenül? Nem bizony, ugyanis a látszat ellenére
nem számokat adtunk meg! Az idézőjelek azt jelzik a programnak, hogy karakterfüzéreket kell
összeadnia. Ezek, mint föntebb szó volt róla, nemcsak betűket, hanem bármiféle a gép által leírható
dolgot tartalmazhatnak, itt történetesen csupa számjegyet. Ennek megfelelően a számoknak nem az
értékét, hanem csak a leírt képét adjuk össze, mint amikor betűkből álló szavakat kapcsoltunk
egybe. Úgy lehet elképzelni, mintha a két számot felírtuk volna két cetlire, utána egymáshoz
ragasztottuk volna.

Játék a változókkal
A konstansokkal való kísérletezésnek hamar a végére értünk. Az, hogy szövegeket írunk ki, esetleg
ragasztunk egymáshoz, végső soron eléggé sekélyes mulatság. A számokkal végzett műveletek
valamivel hasznosabbak, csak éppen mindig át kell írni a programot, ha újabb számokkal
dolgoznánk – a példákat én nem is raktam programba, csak parancsok formájában mutattam be.
Tulajdonképpen miért is olyan változtathatatlan a konstans? Hiszen a gép könnyedén beírja a
memóriába, és éppolyan egyszerűen törli is! A fő gond az, hogy nem ismerjük az adatok
memóriacímét. Ha megtudhatnánk, és valahogy más értékeket tudnánk beírni, érdekes dolgokat
művelhetnénk.
Szerencsére a megoldás nem ilyen bonyodalmas, mivel a leggyakoribb ügyek egyikéről van szó.
Nincs szükségünk arra, hogy memóriacímeket bújjunk, azt a program elvégzi helyettünk. Mi csak
kérünk magunknak némi helyet a memóriában, ezt a helyet elnevezzük, és e névre hivatkozva
tehetünk oda adatokat, kedvünk szerint. Ha a memóriát továbbra is fiókos szekrénynek gondoljuk
el, arra kérjük az operációs rendszert, hogy biztosítson a számunkra annyi fiókot, amennyire
szükségünk van, és címkézze fel az általunk megadott névvel. Innentől fogva édesmindegy a
számunkra, hogy az a fiók végül is hányadik a sorban. Elég, ha mondjuk, azt kérjük, hogy az ADAT
nevű fiókba rakjon valamit, az operációs rendszer tudni fogja, hogy teszemazt a 116834. fiók
jelölésére használta ezt a nevet. Mivel az így elhelyezett adatokat bármikor megváltoztathatjuk,
ezeket a tárolóhelyeket változóknak nevezzük. Érdemes megemlíteni, hogy a változók
elnevezésekor tartanunk kell magunkat bizonyos szabályokhoz. A változónév nem tartalmazhat
szóközt, ékezetet, és az elejére nem kerülhet számjegy. Leghelyesebb csak az angol ABC betűit és
(ugyebár nem első karakterként) számjegyeket alkalmazni. Ezen kívül fontos szerepe van néhány
különleges karakternek, amelyek közül itt csak a dollárjelet ($) fogjuk használni, mert a modern
basicben ez a dolog elveszítette a jelentőségét. A nehézkes magyarázat után térjünk rá az üdítően
egyszerű gyakorlatra. Noha sorrendben végrehajtva parancsként is működnének a következő dolgok
(vagyis a változókat akkor is megjegyzi az interpreter), írjunk rögtön rendes, elmenthető programot
Változókat úgy hozhatunk létre, hogy egyszerűen hivatkozunk rájuk:
40 PRINT SZAMLALO
Így, külön jelzés nélkül, a basic az integer, vagyis egész típusú számok tárolására biztosít helyet.
Hogy ez ténylegesen mennyit foglal le a memóriából, az most közömbös, egyelőre elég annyit
tudnunk, hogy egy viszonylag nagy pozitív vagy negatív, de feltétlenül egész számot tudunk
beletenni (egy memóriarekeszbe egyébként csak 256 különféle számérték tehető, ha ennél többre
van szükség, több helyet foglal le a program).
A fenti utasításban hivatkoztunk a SZAMLALO nevű változóra, mivel azt mondtuk az interpreternek,
hogy van egy ilyen nevű kiírható szám – ha tehát eddig nem volt ilyen, most kaptunk egy számnak
való helyet. Nézzük meg, mi van benne:
RUN
0
Ok
A program tehát nullát rakott a változónkba. Ez a basicben így történik, de fontos tudni, hogy más
programnyelvek általában sokkal szigorúbbak. Ott általában egyáltalán nem hivatkozhatunk nem
létező változókra, de ha mégis, megeshet, hogy a megcélzott memóriacímeken valami véletlenül ott
maradt érték lesz, ezért érdemes megszokni, hogy használat előtt először mindig adjuk meg a
változó értékét, a basicben egyszerűen így:
30 SZAMLALO=1
Az az igazság, hogy ez is lezser megoldás, mivel a jelentése: SZAMLALO legyen 5, vagyis ez egy
értékadás, és hamarosan látni fogjuk, hogy ugyanígy írjuk azt az állítást is, hogy SZAMLALO értéke
5, ami azután vizsgálható, hogy igaz-e vagy sem. Ha pontosak akarunk lenni, az értékadásra létezik
is egy utasítás, a LET, amely ilyenformán használható: LET SZAMLALO=5, de ezt el lehet hagyni,
mert az interpreter mindig el tudja dönteni, hogy értékadásról vagy állításról van-e szó. Listázással
és futtatással ellenőrizzük, mit végeztünk:
LIST
30 SZAMLALO=1
40 PRINT SZAMLALO
Ok
RUN
1
Ok
Tehát a SZAMLALO nevű változó kezdőértékét csakugyan 1-re tudtuk állítani, s a következő utasítás
már ezt az értéket írta ki. Változtassuk meg menet közben az értékét! Egészítsd ki a programot a
következő sorokkal:
50 SZAMLALO=2
60 PRINT SZAMLALO
70 SZAMLALO=3
80 PRINT SZAMLALO
Vagyis új értékeket adunk a SZAMLALO-nak, így ugyanaz a PRINT SZAMLALO utasítás mindig
más értéket ír ki. Lássuk:
RUN
1
2
3
Ok
Ez már egészen formás kis program, érdemes lesz elmenteni, de adjuk meg a módját. Írjunk neki
címet is:
10 ' 1. SZAMLALOPROGRAM
20 '
Lehet menteni:
SAVE "SZAMLALO1.BAS", A

Mivel egyre hosszabb futási eredményekre számíthatunk, most vegyük elejét annak, hogy a
programunk fél oldalakat használjon el néhány szám kinyomtatására. Ehhez új dolgot tudunk meg a
PRINT utasításról. Ha a sor végére nem írunk semmit, az történik, amit láttunk, a következő sorra
ugrik, és a következő PRINT onnét indul. Ha azonban a sort vesszővel zárjuk, érdekes dolog
történik. Írd át a következő sorokat így:
40 PRINT SZAMLALO,
60 PRINT SZAMLALO,
Hadd fusson:
RUN
1 2 3
Ok
A program tehát némi helyet hagyva a számok közt, de egy sorba írta őket. Természetesen, ha
elérnénk a sor végére, új sort indítana. A nyolcvanas sor végét azért nem írtam át, hogy az Ok
felirat, amely nem tartozik a programhoz, mégiscsak eggyel lejjebb kerüljön. Most írj a vesszők
helyére pontosvesszőt!
40 PRINT SZAMLALO;
60 PRINT SZAMLALO;
Futtatás:
RUN
123
Ok
A számok most kihagyás nélkül, közvetlenül egymás mellé kerültek. Így már jóval több szám elfér
egy sorban. Szükségünk is lesz rá.

Mielőtt tovább mennénk szeretném felhívni a figyelmedet valamire, ami megkönnyíti a program
szerkesztését. Ha nem akarsz minduntalan a Jegyzettömbre átugrálni, hanem a Blassic ismertetett
szövegszerkesztési módszereit alkalmazod, már ebben a kis szövegben is eléggé idegesítő lehetett,
hogy teljes sorokat újra kellett gépelned egyetlen vacak írásjel miatt. Azonban, ha megnyomod a
felfelé-nyíl billentyűt, látod, hogy megjelenik az előzőleg beírt sor, így visszalépkedhetsz a
megváltoztatni kívánt utasításig, amelyben a jobbra-balra nyilakkal a változtatás helyére tudsz állni.
Itt beírod, ami szükséges, és Enterrel már érvényesítheted is a módosítást. Ha visszalépkedéskor
túlszaladtál, lefelé-nyíllal az ellenkező irányba is mehetsz. Ha mindezt szegényes segítségnek
tartod, vigasztald magad azzal, hogy a régi programozóknak még ennyi sem jutott...
Ez az a pont, ahonnét felpörögnek az események. Az eddigi program eredményét jóval rövidebben,
egyetlen PRINT 123 paranccsal is produkálhattuk volna. Természetesen nem ez a gyengécske
produkció a célunk, hanem a tanulás, és a továbbiak megértéséhez való átvezetésként írtuk ilyen
hosszadalmas formában. Ami most jön, azt már csak a változókkal csinálhatjuk meg. Kezdetben
majdnem az iménti kódot írjuk be:
10 ' 2. SZAMLALOPROGRAM
20 '
30 SZAMLALO=1
40 PRINT SZAMLALO;
50 SZAMLALO=SZAMLALO+1
60 PRINT SZAMLALO;
70 SZAMLALO=SZAMLALO+1
80 PRINT SZAMLALO
A futtatás eredménye ugyanaz, mint az előbb, de nem is ez az érdekes, hanem az ötvenes és
hetvenes sorba írt rejtélyes SZAMLALO=SZAMLALO+1 utasítás. Hogyan lehet egy szám egyenlő
egy saját magánál nagyobb számmal? Csakis úgy, hogy ez tulajdonképpen egy csonka LET
SZAMLALO=SZAMLALO+1 utasítás, vagyis értékadás, nem pedig állítás! A jelentése tehát:
A SZAMLALO változó értéke legyen az eddigi értéknél eggyel nagyobb.
A dolog eredményeképpen az 50-60-as utasítások tökéletesen megegyeznek a 70-80-assal. Ez
azt jelenti, hogy a hetvenes és nyolcvanas sor fölösleges, ha rá tudjuk venni a gépet, hogy az előző
kettőt megismételje! Ha mondjuk a hatvanas sor után azt kérjük, hogy ugorjon vissza az ötvenesre,
akárhányszor kiírhatunk mindig eggyel nagyobb számot. Ennek semmi akadálya, csak van egy kis
bibi. Ha csak ennyit tudunk, az „akárhány” végtelen sokat fog jelenteni, mivel a program sohasem
jut el a végéig, hanem állandóan visszalép az ötvenes sorra. Mielőtt tehát bolond módon
nekiugranánk, foglalkozzunk azzal, hogy hogyan ellenőrizzük azt, kell-e még növelni a számot.
Tételezzük fel, hogy mondjuk tízig akarunk elszámolni, ha tehát a szám ezt eléri, már nem
ismételgetjük a növelést és kiírást, hanem befejezzük a programot. Ezt magyarul például így
fogalmazhatjuk meg:
Hogyha SZAMLALO kisebb, mint 10, menj az 50-es sorra.
Azt, hogy a SZAMLALO kisebb, mint 10, feltételnek nevezzük. Ha ez a feltétel teljesül, az 50-es
sorra ugrunk, ha nem, akkor lépünk tovább, esetünkben egyszerűen elérjük a program végét. Mi
azonban nem magyarul írjuk a programot, hanem a félig-meddig angol basic nyelven. Készítsük elő
a fordítást:
A kisebb, mint matematikai jelölése <, tehát a feltételünket így írjuk: SZAMLALO<10.
A hogyha angolul IF, az akkor szó (legalábbis ebben az értelmében) pedig THEN. Ez a kettő lesz a
kívánt utasításpár. Azért pár, ugyebár, mert csak együtt van értelmük.
A menj valahova angolul GO TO, de mivel egy utasítást szerencsésebb egy szóval megoldani, basic
nyelven GOTO válik belőle. A teljes sor tehát a következő lesz:
70 IF SZAMLALO<10 THEN GOTO 50
A nyolcvanas sorba elég egy üres PRINT, a soremeléshez. Nézzük, hogy fest most a program:
LIST
10 ' 2. SZAMLALOPROGRAM
20 '
30 SZAMLALO=1
40 PRINT SZAMLALO;
50 SZAMLALO=SZAMLALO+1
60 PRINT SZAMLALO;
70 IF SZAMLALO<10 THEN GOTO 50
80 PRINT
Ok
Futtatás:
RUN
12345678910
Ok
A program prímán működik, de a jó programozó sosem elégedett magával. Mindig az a jó, ha a
program a lehető legegyszerűbb, hiszen úgy a legkevesebb a hibalehetőség, és általában a futása is
akkor a leggyorsabb. Némi vizsgálódás után észreveheted, hogy a negyvenes sor fölösleges. Ha
törlöd, a program rendben lefut – igaz, hogy a számolás 2-ről indul, de miért is? Mert előzőleg
egyet állítottunk be kezdőértéknek, és az ismétlődő programrész rögtön egy növeléssel indul.
Adjunk meg tehát nullát a harmincas sorban:
30 SZAMLALO=0
A futtatást már ki sem írom... lehet menteni. Az efféle ismétlődő programrészeket ciklusoknak
nevezzük. Azt talán már nem is kéne hangsúlyoznom, hogy nemcsak eggyel növelhetünk, hanem
más számmal is, mint ahogy az IF feltétel határértéke is tetszés szerint megváltoztatható, például
28947-ig is számolhatsz négyszáztizenhármasával, természetesen nem várható, hogy az utolsó szám
mindig éppen a határérték lesz – általában valamivel túllépi, mivel a vizsgálat előtt növeltük.
A feltételvizsgálat nagyon fontos része a programozásnak, nem csoda hát, hogy sokféle megoldása
lehet. Ennek megfelelően vizsgálhatjuk, hogy valami nagyobb-e (>) a másiknál, éppen egyenlő-e
vele (=), de azt is hogy hátha nem egyenlő (<>, tehát vagy kisebb vagy nagyobb, de nem ugyanaz).
Az utóbbi kettővel csínján kell bánni, csak akkor használható, ha egészen biztos vagy benne, hogy a
feltétel bekövetkezik. Az előbbi program működik akkor is, ha a 70-es sorát így írtuk volna:
70 IF SZAMLALO<>10 THEN GOTO 50
Tehát, ha SZAMLALO nem egyenlő tízzel, lépj vissza. Mivel egyesével növelünk, előbb-utóbb
okvetlenül belebotlunk a 10-be. Ha azonban, mondjuk, hármasával akarunk elszámolni százig,
pórul járunk, mert a számláló nem talál bele a százasba, hanem átlép rajta (...96, 99, 102...), és
értelemszerűen utána sem lehet vele sohasem egyenlő, tehát ugyanolyan végtelen ciklus alakul, ki,
mintha az egész feltételvizsgálatot bele sem építettük volna a programba. Ezért a pontosan
meghatározott érték vizsgálata helyett, amikor csak lehet, mindig tartományt vizsgálunk – például,
hogy kisebb vagy nagyobb-e egyik a másikánál. Sőt, mi több, a fentieken túl lehet kisebb vagy
egyenlő(<=, más szóval nem nagyobb) és nagyobb vagy egyenlő (>=, tehát nem kisebb) is.

Ennek kapcsán érdemes megemlíteni, hogy a programozás során előadódó hibákat két nagy
csoportra szokás osztani. Az első a szintaktikai hibák csoportja, amikor valami olyat írsz a
programba, amit az interpreter nem ért meg. Ezt a fordító hagyományosan a SYNTAX ERROR
(nyelvi hiba) hibaüzenettel jelzi (a Blassic SYNTAX HORROR-t, vagyis „nyelvi rémséget” ír,
nyilván viccből). Ezekkel a hibákkal van a kisebbik baj, hiszen olyannyira észrevehetők, hogy a
programot általában nem is tudjuk futtatni, míg ki nem javítjuk. A másik csoport a logikai hibáké.
Ezen az értendő, amikor programnyelvileg ugyan tökéletesen fogalmazunk meg valamit, csak
rosszul mérjük fel a következményeit. A fenti példa tipikus logikai hiba: Az interpreter érti, amit
kérünk, kifogástalanul végre is hajtja, csak a feltételt olyan ügyetlenül szabtuk meg, hogy a
vizsgálata semmit sem ér, így a program használhatatlan. A logikai hibák sokszor nagyon nehezen
találhatók meg, főleg azért, mert éppen a saját gondolkodásunknak attól az irányától kell eltérnünk,
amely előidézte őket. Nem is mindig vezetnek végzetes következményekhez, esetleg csak
meghamisítanak egy eredményt, vagy nem jutunk el bizonyos programrészekhez. Az is
előfordulhat, hogy a hiba csak különleges esetekben bukkan fel, amelyre a programozó nem is
gondol. Bonyolultabb program közzétételét ezért mindig próbaváltozatok előzik meg, amelyeken a
felhasználók is kipróbálhatják annak képességeit. Mire a program eljut a „stabil” tehát
megbízhatóan használható változatig, általában több tucat oldalnyi hibát javítanak ki benne. Ezt
csak biztatásul mondom, hogy ne kámpicsorodj el, ha beüt valami gikszer, és nem azt csinálja a
program, mint amit szeretnél.

A kitérő után térjünk vissza a feltételvizsgálathoz. Egy feladatot többféleképpen is meg lehet oldani,
így a feltételek is átfogalmazhatók. Az előbb az IF..THEN utasításpárról beszéltem, de valójában
ez kiegészíthető az ELSE (egyébként) harmadik taggal. Az így kialakított szerkezet jelentése:
HA a feltétel teljesül, AKKOR csináld ezt, EGYÉBKÉNT amazt.
Amíg feltételt nem szabunk, a program fut a maga útján, a választáskor viszont több út is
lehetséges, ezért az efféle programrészeket feltételes elágazásoknak mondják.

Példaként bemutatom az előbbi program ELSE taggal módosított változatát:


10 ' 3. SZAMLALOPROGRAM
20 '
30 SZAMLALO=0
50 SZAMLALO=SZAMLALO+1
60 PRINT SZAMLALO;
70 IF SZAMLALO>9 THEN PRINT " Befejeztem." ELSE GOTO 50
80 PRINT
Futtatás:
RUN
12345678910 Befejeztem.
Ok
Itt tehát azt vizsgáltam, hogy a számláló nagyobb-e kilencnél (ha igen, akkor nyilván elérte a tízet).
Ha igen, akkor nem tesz mást, csak kiírja, hogy „Befejeztem” (egy szóköz után, hogy ne tapadjon a
számokra), majd a feltételvizsgálat utáni részre fog lépni, ami most a program vége. Minden más
esetben, vagyis, amikor még nem haladta meg a kilencet, visszaugrik az ötvenes sorra, növelve és
kiírva SZAMLALO értékét. Ebben az esetben ez a megoldás semmit sem javított a programon, csak
azt kívántam bemutatni, hogy ugyanaz a feladat egy kissé más logikával is megoldható. Egyéb
helyzetekben viszont sok múlhat azon, ha ki tudjuk választani a legszerencsésebb módszert.

Említettem, hogy olyan lépésköz esetén, amely nem érkezik pontosan a határértékre, az utolsónak
leírt szám mindig nagyobb lesz annál, mert a program először végrehajtja a növelést és a kiírást, és
csak azután ellenőrzi, mi is történt. Ezt a szerkezetet, mivel az esemény után vizsgál, hátultesztelős
ciklusnak hívják. Általában azonban azért szabunk meg egy határértéket, mert nem szeretnénk, ha a
program átlépné azt. Mi a megoldás? Az elöltesztelős ciklus, vagyis, hogy előbb megvizsgáljuk a
változás eredményét, és attól tesszük függővé, hogy mit műveljen a program. Esetünkben kétféle
akció közül választhatunk: Vagy növelünk és kiírunk, vagy befejezzük a programot, attól függően,
hogy meghaladtuk-e a határértéket. Először is válasszunk egy olyan lépésközt és határértéket,
amelyek garantáltan nem találkoznak, azután próbáljuk meg átrendezni a programot a
következőképpen:
10 '4. SZAMLALOPROGRAM
20 '
30 SZAMLALO=0
40 SZAMLALO=SZAMLALO+7
50 IF SZAMLALO>40 THEN PRINT " Befejeztem." ELSE PRINT SZAMLALO;
GOTO 40
60 PRINT
Keletkezett ugyebár egy gyanúsan hosszú sor, amely annyira zavarosnak tűnik, hogy alighanem
meggyűlik vele a bajunk, de csak futtassunk:
RUN
Syntax horror in 50
Ok
Na ugye! Ez a bizonyos ötvenedik sor béli rémség nem egyéb, mint az, hogy nem írhatunk egymás
után több utasítást. Az eddigi szerkezetben a THEN és ELSE után is egy-egy utasítás következett,
így nem volt velük baj. Most azonban az egyik esetben többet is végre kellene hajtanunk. Erre
azonban ez az ős-basic nem képes, tehát más megoldás kell, mondjuk ilyenformán:
50 IF SZAMLALO>40 THEN GOTO 80
60 PRINT SZAMLALO,
70 GOTO 40
80 PRINT
90 PRINT " Befejeztem."
Lám, az ELSE nem is kell, elég egyetlen THEN: Amikor SZAMLALO átlépi a határt, átugorja a
következő három sort, addig viszont végrehajtja, és rendben visszakerül a negyvenesre.
Megjegyzem, a programozók azonban kissé berzenkednek a GOTO utasításoktól. Az egyik ok a régi
basic-programozás esetlenségéből adódott: Ha a programot át kellett sorszámozni, nagyon könnyen
benne maradhatott egy régi sorszámra mutató GOTO, amelyet azután verejtékfakasztó munka volt
megtalálni. A modern basic az egész sorszámozást a szemétre vetette, és sokkal biztosabb módon
határozza meg a GOTO célját, így ez a probléma megszűnt. A másik ok viszont ma is érvényes: Az
ide-oda ugrálás áttekinthetetlenné teszi a programokat. Ezért azután mindig arra törekedtek, hogy
ezt az utasítást kiküszöböljék – mára ezt is sikerült megoldani. Egy darabig vitáztak is arról,
egyáltalán benne hagyják-e a nyelvben, végül a régi programok futtathatósága érdekében nem
bántották. Nem is baj, mert néha ez a legjobb megoldás. Ugye, most is segített?
Később az IF elágazásnak megjelent egy ügyesebb több soros formája is, ezért voltaképpen nem
örülök, hogy a Blassic esetleg rákapat a GOTO használatára. Az elöltesztelős ciklust viszont
mindenképpen be akartam mutatni, mert a következő utasítás is ilyen lesz. Nézzük tehát egészében
programot:
LIST
10 '4. szamlaloprogram
20 '
30 SZAMLALO=0
40 SZAMLALO=SZAMLALO+7
50 IF SZAMLALO>40 THEN GOTO 80
60 PRINT SZAMLALO,
70 GOTO 40
80 PRINT
90 PRINT " Befejeztem."
Ok
Mint láthatod, a 60-as sor végére vesszőt tettem, hogy jól elváljanak egymástól a kétjegyű számok.
RUN
7 14 21 28 35
Befejeztem.
Ok
A feltételvizsgálatokra még vissza-visszatérek majd, de nem árt, ha egyéb dolgokkal is
foglalkozunk közben. Végül is azt ígértem, hogy most a változókkal foglalkozunk...

Már szó volt róla, hogy a programozók lusták gépelni, és a sűrűn előadódó programrészleteket
igyekeznek tömörebben megfogalmazni. Az előző program feladata – hogy valamettől valameddig
elszámoljon – olyan gyakori, hogy külön utasítás készült rá. Ez a FOR..NEXT ciklus (talán tól-ig
ciklusnak lehetne magyarítani). Először is kell egy változó, amelynek az értékét módosítani fogjuk
a ciklusban. Mivel a szerepe szorosan összefügg a ciklus működésével, ciklusváltozónak szokás
nevezni. A programozásban ugyan hasznos megoldás a beszélő nevek használata (vagyis, hogy
olyan nevet válasszunk egy programelemnek, amelyből rögtön látjuk, mi a szerepe), de itt most
nincs különösebb jelentősége, ezért megelégszem a szikárabb C elnevezéssel, hogy lásd, nem csak
értelmes szó lehet a változónév. A ciklussal az iménti programot fogom utánozni, tehát 7-től 40-ig
számolok, hetes lépésközzel:
FOR C=7 TO 40 STEP 7
PRINT C,
NEXT C
Mielőtt rendes programot írnánk belőle, megmagyarázom a szerkezetét. A FOR jelenti, hogy a
következő értéktől számolunk, ezután a szokott módon be is állítjuk a ciklusváltozó kezdőértékét. A
TO után adjuk meg, hogy meddig számoljon a program, a STEP (lépés) pedig a lépésköz. Ezután
kiírjuk a ciklusváltozó értékét. Itt azonban csak ebben a programban áll egyetlen utasítás, általános
esetben viszont bármennyi következhet. Mivel azonban a programnak tudnia kell, hogy végül is
hány sort akarunk megismételni, valahogyan jeleznünk kell a ciklus végét. Erre szolgál az utasítást
lezáró NEXT (következő) kulcsszó, amely után a ciklusváltozó nevét kell írnunk. Ebből tudja az
interpreter, hogy ennek a változónak az értékét kell a megadott lépésközzel megnövelnie, és miután
ezt megtette, visszaugrik a ciklus elejére, mindaddig, amíg csak el nem éri a határértéket. A NEXT
ilyenfajta értelmezésével van egy kis probléma. A ciklus közepében – úgy mondjuk, hogy a
ciklusmagban – bármiféle utasítások lehetnek, többek között akár egy másik ciklus. Ebben az
esetben tehát a ciklus például így épül fel:
FOR EGYIK=1 TO 10 STEP 10
FOR MASIK= 5 TO 25
NEXT MASIK
NEXT EGYIK
Ezt a ciklusok egymásba ágyazásának szokás nevezni. Természetesen mindkét cikluson belül
lehetnek még egyéb utasítások is, csak nem akartam elvonni a figyelmedet a lényegről. A lényeg
pedig az, hogy az első cikluson belül indított másik ciklust teljes egészében be kell tenni az elsőbe,
vagyis még az első cikluson belül le kell zárni. Tételezzük fel, hogy egy figyelmetlen vagy
urambocsá' komisz programozó a következőt írja be:
FOR EGYIK=1 TO 10 STEP 10
FOR MASIK= 5 TO 25
NEXT EGYIK
NEXT MASIK
Vagyis a külső ciklust előbb zárja le, mint a belsőt. Mi van ilyenkor? Baj. Az interpreter nem tudja
értelmezni, hogy melyik ciklust mikor kell lezárnia. Ezért a modern basicben már nincs szükség a
NEXT utáni ciklusváltozóra, elég csak magában hagyni. Éppenséggel beírhatod, ha úgy szoktad
meg, csak éppen az interpreter nem veszi figyelembe, hanem egyszerűen a legutóbb indított ciklust
zárja le. Ha tehát nem a Blassicben programozol, jó eséllyel számíthatsz rá, hogy elég az üres
NEXT, de ha azt írod, hogy NEXT NYENYERE, az sem okoz galibát. Itt azonban ajánlatos mindig
odafigyelned, ha egymásba ágyazott ciklusokat alkalmazol.
Három dolog még megemlítendő. Ha a lépésköz csak egy, akkor a STEP elem elhagyható: FOR
A=3 TO 444 ugyanazt jelenti, mint FOR A=3 TO 444 STEP 1. Továbbá, visszafelé is
számolhatsz, ha a STEP értéke mínusz szám: FOR VALAMI=80 TO 12 STEP -2. Végül, ha a
kezdőérték már eleve eléri a határértéket, a ciklus egyszer sem hajtódik végre. Például:
FOR A=100 TO 20
Ez a példa nagyon butának tűnhet, hiszen ki az a mamlasz, aki fölfelé számlálással kisebb értékhez
akar eljutni? Azonban a ciklus értékei maguk is lehetnek változók:
FOR A=B TO C STEP D
Ilyen esetben nem mindig tudjuk, hogy a máshonnan (például egy számtani művelet
eredményeképpen) kapott értékek nem vezetnek-e valami hasonlóra, ezért jó, hogy az interpreter
erre is föl van készítve.
Jöjjön a számlálóprogram új változata:
10 '5. szamlaloprogram (for..next ciklussal)
20 '
FOR C=7 TO 40 STEP 7
PRINT C,
NEXT C
80 PRINT
90 PRINT " Befejeztem."
Ok
Elegánsabb, ráadásul a változót nullázni sem kellett a ciklus előtt, mint az imént.
RUN
7 14 21 28 35
Befejeztem.
Ok

Egy fontos dologról még nem ejtettem szót, mégpedig a ciklusváltozó kitüntetett szerepéről. A
ciklus ugyanis ennek az értékéből tudja megállapítani, hogy hol tart. A ciklusváltozó a
ciklusmagban ugyanúgy megváltoztatható, mint a többi, és ez néha rafinált programozói
trükközésre ad lehetőséget, de jobb nem babrálni. Elvileg például megtehetjük ezt:
10 FOR I=10 TO 20 STEP 2
20 I=I-2
30 NEXT I
Máris kész az undok végtelen ciklus. A ciklusmagban levonunk kettőt, a NEXT hozzáad
ugyanennyit, tehát a ciklusváltozó egy tapodtat sem mozdul. A hasonló helyzetek elkerülése végett
megjegyzendő ökörszabály: A ciklusváltozót nem illik módosítani.

A fenti programocskában még mindig a ciklusváltozó értékét írattuk ki, ezért úgy tűnhet, hogy a
ciklusmagban okvetlenül foglalkoznunk kell vele. Erről azonban szó sincs. A ciklusváltozó
egyszerűen egy számláló, amely a programnak mutatja, hogy hányadik ismétlésnél tart. A
ciklusmag pedig bármi lehet, amit ismételni akarsz. Példának okáért egy régivágású tanár rád
parancsol, hogy büntetésből írd le százszor: „Nevelőimnek mindig előre köszönök, és nem
huzigálom a lányok haját matematika órán.” A feladat basic nyelvű megoldása a következő:
10 FOR SOKSZOR=1 TO 100
20 PRINT "Nevelőimnek mindig előre köszönök, és"
30 PRINT "nem huzigálom a lányok haját matematika órán."
40 PRINT
50 NEXT SOKSZOR
Futtatás:
RUN

(stb.)
Ok
Ha nem a Jegyzettömböt használod a szerkesztéshez, a kiírás a valóságban nem fog így sikerülni
azok miatt az átok ékezetek miatt... A következőkben erre találunk majd megoldást.
Jöjjenek hát az ékezetes betűk. Ha a programot nem a Jegyzettömbben, hanem a Blassicen belül
írtuk meg, hiába gépeltük be tökéletesen a 20-30-as sorokat, már a listázáskor kiderül a disznóság:

Ha pedig abban reménykednénk, hogy majd a futáskor helyrezökken a világ rendje, csalódunk:

Elnézést, hogy nem közlöm mind a száz mondatot, az összes ilyen... A program tehát nem a beírt
szöveget jeleníti meg, hanem önkényesen megváltoztatja az ékezetes betűket, mégpedig láthatólag
értelmesen, vagyis nem valamiféle szemetet, hanem létező jeleket írva a képernyőre, és
következetesen, vagyis az azonos ékezetes betűk helyére mindig ugyanazt a jelet teszi, például
minden á betűt a fura német s-sel, a ß karakterrel helyettesít. A dolognak az lehet a magyarázata,
hogy a Blassic végül is Windows-program, így beíráskor a Windows karakterkészletét használja,
értelmezéskor viszont a sajátját, amely alkalmasint valamely régi szabványhoz igazodik. Az is lehet,
hogy ugyan a Windows valamelyik készletét használja, de más számozással.
Ez a magyarázat egyszerű és rövid, de a számodra nyilván nem egészen kerek... Legfőképpen: Mi a
búbánat az a karakterkészlet? Nos, ez az a táblázat, amelyről már szóltam. Az, amelyben le van írva,
hogy melyik szám hatására melyik betűt rajzolja ki a gép. Úgy lehet elképzelni, hogy valahol a
gépen egy csomó apró képen le vannak rajzolva a betűk, és a táblázat alapján a gép mindig előhúzza
a memóriában talált szám által kijelölt képet. Azonban a gépen nemcsak egyetlen ilyen képsorozat
van, hanem sokféle, aszerint, hogy valaki milyen nyelven akar írni. Amikor a billentyűzetet átállítod
angolra, azt kéred az operációs rendszertől, hogy a továbbiakban ne a magyar, hanem az angol
betűk képsorát használja. Így lehet elérni, hogy ugyanazzal a billentyűzettel orosz, japán vagy tamil
írásjegyeket rajzoljunk a képernyőre. Bár, ha meggondoljuk, a mi írásunk nagyon hasonlít az egyéb
latin betűs írásokhoz, így joggal merül fel a kérdés: Azt az egy-két eltérő betűt miért nem csapták
még hozzá a készlethez?
Erre is van magyarázat, de úgy döntöttem, hogy a terjengősebb ismertetéseket ezentúl függelékben
közlöm, amit vagy elolvasol, vagy sem, de itt inkább a ne szakítsuk meg állandóan a
gondolatmenetet. Ha érdekel, ott nézz utána!
El kell tehát fogadnunk, hogy az ékezetes betűk helyén mindenféle furcsa dolgok jelennek meg. Én
a DOS-os időkben sokat játszadoztam a betűk átrajzolásával, de ott tudni lehetett a karakterek
mintájának a pontos memóriacímét, meg nem is basicet használtam, hanem valami gépközelibb
nyelvet, úgyhogy most ne erőltessük ezt a megoldást. Viszont az tudható, hogy a nyugati
nyelvekben használatos karakterek között is vannak, amelyek megegyeznek a magyar ékezetes
betűkkel, vagy legalább hasonlítanak hozzájuk. Ha ezeket a képernyőre tudnánk csalogatni, máris
beljebb volnánk. Különleges karaktereket ugyan kapunk az AltGr billentyű hatására, de a printelés
ugyanúgy eltér a beírt szövegtől, mint eddig, úgyhogy nem ez a megoldás. Bár előre megmondom,
ha sikerül megtalálnunk a módszert, az aligha lesz valami kényelmes, úgyhogy nagyregények
írására inkább mást válassz majd...
A vizsgálódáshoz nem árt, ha van egy olyan szövegünk, amely az összes magyar ékezetes betűt
tartalmazza. Persze, írhatnánk azt, hogy „áéíóöőúüű”, de szórakoztatóbb, ha keresünk valami
szavakból álló kifejezést, ezt megjegyezni is egyszerű, és így nem felejtünk ki egy ékezetet sem. Ha
az ékezet nélküli magánhangzókat el akarjuk hagyni, az ékezetesek közt pedig nem tűrjük a
fölösleges ismétlést, a feladat nem is olyan egyszerű, viszont annál jópofább szóösszetételekre
vezet. Karakterkészletek kipróbálására széltében ismert tesztkifejezés például az „árvíztűrő
tükörfúrógép”, de énnekem tetszik az általam gyártott „hűs füvön túrázó színésznő”, „félúton
tülkölő fűnyírógép” vagy az „üvöltő szűzlányt kínzó kényúr” is.
Írjunk be valami hasonlót:
PRINT "rémítő üstökű kútásó"
rÚmÝt§ Řst÷kű k˙tßsˇ
Ok
Az én számomra kissé furcsa, hogy éppen a legzűrösebbnek vélt hosszú ű stimmel, de örüljünk
neki. Egy gonddal kevesebb. A többi közül csak egy-kettőt tudunk megtalálni a billentyűzet AltGr
gombos végignyomkodásával, meg őszintén szólva, nem is ez a célom, így hát mást próbálunk ki.
Megtudjuk, melyik számérték milyen betűt ír le, és azokból összeállítjuk a szöveget. Mivel ugyebár
még mindig a változókkal foglalkozunk, csináljunk a szövegünkből is egy változót, amelyben majd
összeadhatjuk a megtalált betűket:
30 SZOVEG="rémítő üstökű kútásó"
RUN
Type mismatch in 30
Ok
Most meg mi van? Pedig nem felejtettük el az idézőjeleket, ezért nem hiheti utasításnak a beírt
szavakat. A hibaüzenet persze elárulja, hogy nem is erről van szó: „típuskeveredés a 30-as sorban”.
Nincs különösebb baj, csak eddig még nem ismerjük a szöveges változókat. Azt ugye, tudjuk, hogy
valójában a szöveg is egy számsor. Ha az interpreter csak úgy hagyná, hogy egy közönséges
változóba beírjuk, akkor a memóriából való kiolvasáskor valami számot kapnánk, amit a szokott
számméretre használt értékekből rakna össze a rendszer (azzal, hogy a memória maximum 256
értékű rekeszeiből hogyan állít össze nagyobb számokat a gép, itt nem foglalkozom). Ezért
valamivel jeleznünk kell a számára, hogy ebben az esetben szövegről van szó. Az idézőjel itt nem
segítene, mert az maga is egy számmal leírt karakter, és egy számváltozó miért ne egyezhetne meg
vele? A memóriába való beíráskor azonban még észreveszi az idézőjelet, ezért leáll, ha egy
közönséges számváltozóba (pontosabban integer változóba, lásd jóval fentebb) szöveget próbálunk
betenni. A basic nyelv ezt úgy oldja meg, hogy már a változó elnevezésekor jelezzük, hogy nem
akármit, hanem szöveget akarunk benne tárolni, mégpedig a végére írt dollárjel segítségével:
30 SZOVEG$="rémítő üstökű kútásó"
Ilyenkor az interpreter megjegyzi, hogy arra a helyre szöveget pakolt, és helyesen tudja majd
kiolvasni. Tulajdonképpen az integer típusnak is van megkülönböztető jele, a százalékjel (%), de
mivel alapesetben ezt a típust hozza létre, alig van szükség rá, hogy külön hangsúlyozzuk a fajtáját,
így a nyelv szabványa megengedi, hogy elhagyjuk. Még többféle jelölés létezik különböző
típusokra, de egyelőre ezeket nem használjuk, a modern basic pedig másképp oldja meg a kérdést,
és a Rapid-Q-ban majd aszerint dolgozunk.
Futtatáskor ugyan még semmit sem látunk, de az interpreter nem jelez hibát, tehát a változónkat
elfogadta. Mentsd el a programot valami néven, és most egy kicsit félretesszük, hogy egy másik
programmal megnézzük a karakterkészletet.
Ehhez azonban megint tanulnunk kell valami újat. Kellene egy olyan módszer, amellyel
megtudhatnánk, hogy az emlegetett táblázatnak hányadik helyén mi jelenik meg. Ezt egy eddig nem
ismertetett fajta programelem, a CHR$() függvény teszi lehetővé számunkra. A neve a character
szó rövidítése. Hogy a függvény az iskolában pontosan mit jelent, az nem ide tartozik – a
programozásban olyan programrészleteket jelöl, amelyeknek adatot adhatunk át (a basicben ezt a
függvénynév utáni zárójelben kell megadnunk), és ő attól függően ad vissza nekünk valami más
adatot. Némely függvényeknek csak egy adatot adunk át, másoknak többet, a visszakapott adatok
típusa is változhat. A lényeg, hogy a visszakapott adat lesz a függvény értéke, amelyet azután
ugyanúgy használhatunk fel, mintha közvetlenül adtuk volna meg. Használat közben ez mindjárt
világosabb lesz, csak még a CHR$() név végén ékeskedő dollárjelre szeretném fölhívni a
figyelmedet. Mivel a függvény meghívása egy érték megszerzését jelenti, ismernünk kell az érték
típusát is, hogy használni tudjuk. Ennek a függvénynek a nevéből rögtön tudjuk, hogy egy szöveges
típusú értéket ad vissza, magyarán: szövegként lehet kezelni, például egy szöveges változóba
beolvasni:
BETU$=CHR$(65)
A CHR$() feladata pontosan az, amire szükségünk van: A zárójelek között megadunk egy 0-255
közötti számot, mire ő felveszi a számnak megfelelő karakter értékét, amely 65 esetén a nagy A
betű. A fenti sor tehát ugyanazt jelenti, mintha BETU$="A" parancsot írtunk volna be, azzal a
különbséggel, hogy a zárójelek között megadott adat (úgy mondják, hogy a függvény
argumentuma) változó is lehet! Például a következő programocska az ABCDEF szöveget írja ki:
10 FOR SZAM=65 TO 70
20 BETU$=CHR$(SZAM)
30 PRINT BETU$;
40 NEXT SZAM
50 PRINT
Észreveheted, hogy a BETU$=CHR$(SZAM) értékadásra valójában nincs szükség, CHR$(SZAM)
értékét azon nyomban ki lehetett volna íratni egy PRINT CHR$(SZAM) utasítással, de a
későbbiekben valami hasonlót fogunk csinálni, érdemes begyakorolni. A következő változatnál
azonban már szükség lesz az értékadásra. Azt aknázzuk ki, hogy a szövegek is összeadhatók:
10 BETU$=""
20 FOR SZAM=65 TO 70
30 BETU$=BETU$+CHR$(SZAM)
40 NEXT SZAM
50 PRINT BETU$
Magyarázatot kíván a BETU$="" értékadás. Ha szükségünk van egy szöveges változóra, de azt
szeretnénk, hogy egyelőre ne legyen benne semmi, akkor az idézőjelek közé semmit sem írunk.
Úgy lehet tekinteni, hogy ez a szöveges változók „nullázása”. Az eredetileg üres BETU$ változóhoz
azután a ciklusmagban mindig hozzáadjuk a ciklusváltozó által meghatározott sorszámú betűt, és
csak a program legvégén nyomtatjuk ki az így összerakott szöveget.
Mindez szép, de esetleg eltöprenghettél azon, hogy miféle varázslatos dolog folytán képes a
függvény egy egész számot „átalakítani” betűvé. Hogy lásd, mennyire nincsen benne csoda,
megmutatom, hogy az eddigi fogyatékos tudásunkkal is megtehetünk valami hasonlót:
10 BETU$=""
20 FOR SZAM=65 TO 70
30 IF SZAM=65 THEN BETU$=BETU$+"A"
30 IF SZAM=66 THEN BETU$=BETU$+"B"
30 IF SZAM=67 THEN BETU$=BETU$+"C"
30 IF SZAM=68 THEN BETU$=BETU$+"D"
30 IF SZAM=69 THEN BETU$=BETU$+"E"
30 IF SZAM=70 THEN BETU$=BETU$+"F"
40 NEXT SZAM
50 PRINT BETU$
Egy programozó persze a haját tépné, és joggal, ha ilyesmit látna, de a lényeg, hogy mi is
könnyedén képesek voltunk egy számérték alapján betűket hozzáadni a szöveghez. Valamikor mi is
írunk valódi saját függvényeket, de azt inkább a modernebb változatban mutatom majd be,
Blassicben maradjunk a basic beépített függvényeinél. Az ezelőtti program szövegösszeadásával
egyébként már a távolabbi jövőbe kacsingatunk, a most készülőnek a váza már a kettővel előbbiben
megvan, csak a kezdő- és határértékeket kell megváltoztatnunk:
10 FOR SZAM=0 TO 255
20 BETU$=CHR$(SZAM)
30 PRINT BETU$;
40 NEXT SZAM
50 PRINT
Futtatáskor fura dolgok is történnek. Próbáld ki!

A legfeltűnőbb az, ami itt a képen nem reprodukálható, hogy csúnyán dudálgat a gép, mintha valami
komoly baja lenne. Másodszor: néhány karakter után új sorban folytatódik a kiírás. Harmadszor: a
sok jel elején feltűnnek a franciakártya színei, a kőr, káró, treff – hát a pikk hol marad? Negyedszer:
bizonyos karakterek láthatólag ismétlődnek, ami nyilván nem igazodik a helytakarékosság szép
eszméjéhez. Az utóbbi talán a több tárhelyen raktározott szám csonkításából ered (lásd a
függelékben), így nem tudunk rajta változtatni, a többire mindjárt rátérek. Örömmel állapíthatjuk
meg viszont, hogy az idegen betűk közt hiánytalanul megvannak a magyar ékezetesek is, így nincs
más dolgunk, mint figyelmesen leszámolni, hogy melyik betű hanyadiknak jelent meg, és máris ki
tudjuk nyomtatni a CHR$() függvény segítségével. Azt is észreveheted, hogy amikor nagybetűt
írsz, akkor a gép nem a kisbetűt „nagyítja meg” valami rejtelmes módon, hanem egyszerűen külön
ábrákon vannak rögzítve a nagybetűk. Ezt azért jó tudni, mert a basic nyelvben (és a Windows
kezelésében általában) közömbös, hogy kis- vagy nagybetűt használsz, így olyan érzésed alakulhat
ki, mintha a két forma azonos lenne. Most azonban láthatod, hogy valójában egészen más
sorszámok jelzik őket – a Linux például figyel a különbségre, ott nem szabad összetéveszteni a
kettőt, de bizonyos programnyelvek (mondjuk a C) szintén szigorúan megkülönböztetik, Windows
alatt is.
Ha csakugyan elszánjuk magunkat a számolásra, érdemes először mindjárt az összes karaktert
megszámlálni – és mindjárt láthatjuk, hogy hiba van a kréta körül: Akárhogy számolgatjuk, nem
lesz meg a 256 karakter. Jóval kevesebbet találunk, ha jól számolom, csak 244-et. Mivel nem
tudhatjuk, hogy honnan hiányoznak az eltűnt karakterek, nyilvánvaló, hogy nem reménykedhetünk
megbízható eredményben, és az ujjunkon való számlálgatást más módszerrel kell helyettesítenünk.
Először azonban meg kell értenünk, hogy miből származnak a rendellenességek. A számítógép nem
magától találja ki, hogy egy bizonyos számra egy kis ábrát jelenítsen meg. Ezt a programozók írták
neki elő. A programozók azonban fortélyos emberek. Úgy gondolták, hogy hasznosabb, ha a
táblázat némely értéke hatására a gép más feladatot végez el. A sor elejére vagy a következő sorba
ugrik, visszatöröl egy karaktert, vagy éppen figyelmeztető hangot ad ki. Mindez nyilván egyéb
módon is megoldható volna, de mennyivel egyszerűbb, ha ez a sokféle feladat ugyanazzal a PRINT
utasítással elvégezhető! Mondjuk, hogy a program futtatója egy szöveget gépel be: A billentyűk
leütésekor általában megjelenik a kívánt betű rajza, de ha az Enter gombot nyomja meg, kiírás
nincs, viszont a kurzor a következő sor elejére ugrik. Vagy megjelenik a szöveg: „Folytatja? I/N”, és
erre a felhasználó lenyomja a T gombot. A program pedig se nem folytatja, se be nem fejezi, hanem
sípol egyet, jelezvén, hogy nem érti. Az efféle feladatokat mind meg tudjuk oldani azzal, hogy egy
szöveges változóba olvassuk a megfelelő értéket, és egy PRINT CHR$(valami) utasítást hajtunk
végre. Ily módon sokféle különböző út helyett egyetlen, általánosabb megoldást találunk a
leggyakoribb helyzetekre. Megint csak a takarékosság... Ügyes, nem? Az efféle, nem
megjeleníthető, hanem egyéb feladatot ellátó karaktereket vezérlőkaraktereknek hívjuk. A
képernyőn azért nem tudunk 256 karaktert megszámlálni, mert a vezérlőkarakterek nem láthatók,
sőt, van, amely még az előző karaktert is törli azzal, hogy visszaugrik egyet a sorban (ahá, a
hiányzó pikk!). A CHR$(0), ha jól emlékszem, éppenséggel semmit sem csinál – néha éppen erre
van szükség a programban. Mivel több sípolást is hallottunk, valószínű, hogy a sípszó-karakter
(hivatalosan a CHR$(7)) többször is szerepel a táblázatban, mint ez látható karakterek esetén is
megesett. A vezérlőkarakterekkel hamarosan még próbát tehetünk, de térjünk vissza az eredeti
feladatunkhoz.
A kiíráskor meglehetősen zavaró, hogy már nem férünk el egyetlen sorban. Az sem közömbös, hogy
a zsúfoltság miatt néha nehéz eldönteni, hogy melyik ábra melyik karakterhez tartozik. Például van
egy szokatlan dupla felkiáltójel: ez most egy karakter vagy kettő? Jobb lenne valami átláthatóbb
formába rendezni a táblázatot. Jó megoldás lenne, ha egy sorba csak annyi karaktert írnánk,
amennyi kényelmesen elfér, azután egy PRINT utasítással a következő sorba ugranánk. Így mindig
pontosan tudnánk, hogy egy sorban hány karaktert találunk, könnyebb lenne a számolás is. Vajon
hány karaktert írjunk egy sorba? Mivel azt szeretnénk, hogy ne tapadjanak egymáshoz, ezentúl nem
pontosvesszőt, hanem csak vesszőt írunk a BETU$ változó után, azt már tudjuk, hogy így
valamennyi helyet hagy a következő kiírás után. Eddig azonban nem volt szó arról, hogy pontosan
mennyi az a valamennyi. Nos, úgy lehet elképzelni, mintha a képernyő 8 karakter széles oszlopokra
lenne felosztva, és a következő kiírás mindig a következő oszlop elején indulna. Ha tehát a
szövegünk csak egy betűből áll, a következő kiírás 7 betűnyi távolságra lesz, 2 betű esetén 6-ra és
így tovább. Nyolc betűs szavak között nincs kihagyás, ha ennél hosszabb a szó, akkor nem a
következő, hanem az utána jövő oszlopra ugrik a program. A mi szövegeink egyelőre 1 betűsek,
tehát minden oszlopba kényelmesen írhatunk. A képernyő szélessége 80 karakter, kínálkozik tehát,
hogy az így kialakuló 10 oszlopnak megfelelően 10 karaktert írjunk egy sorba. A 256 azonban nem
osztható maradék nélkül tízzel, így a végén egy csonka sor maradna, amit külön kell kezelnünk:
minden sort végig tudunk írni egy 1-től 10-ig tartó ciklussal, csak éppen az utolsóhoz kéne egy
rövidebb. A 256 azonban nem egy légből kapott szám, hanem a számítástechnika egyik „bűvös”
alapszáma, amely a kettes számrendszer törvényszerűségeiből adódik (nem merülök bele a
részletekbe), ezért bizonyosan el lehet rendezni csonka sorok nélkül. Voltaképpen 16 2, vagyis 16
második hatványa, egyszerűbben szólva 16*16. Tizenhat karaktert viszont már nem tehetünk a
sorba, tehát fele olyan hosszú sorokból csinálunk kétszer olyan hosszú táblázatot, magyarán 8*32
méretű táblázatban helyezzük el a karaktereket.
Egy sort nagyon könnyen elkészíthetnénk a ciklusváltozó használatával. Minthogy a karakterek
száma 0-ról indul, mi sem az átláthatóbb FOR=1 TO 8, hanem az ugyanennyi lépést eredményező
FOR=0 to 7 beállítást használhatnánk. Csakhogy mi lenne a következő lépés? Ugyanezt a sort
egyszerűen megismételhetnénk harminckétszer, ha a ciklusunkat egy másikba beágyaznánk, ekkor
mondjuk ezt a programot kapnánk:
10 FOR KULSO=1 to 32
20 FOR BELSO=0 TO 7
30 PRINT CHR$(BELSO),
40 NEXT BELSO
50 PRINT
60 NEXT KULSO
Sietek megjegyezni, hogy ez hülyeség, hiszen nem az a cél, hogy mindig ugyanazt írjuk le 32-ször.
Azonban, ha megadjuk a módját, a hülyeségeinkből is tanulhatunk. Itt például fölfigyelhettél arra,
hogy nem minden sort kezdek a sor elején. Erről eddig nem volt szó, de ahogyan a programjaink
bonyolódnak, úgy lesz egyre nagyobb szükség arra, hogy jól átláthassuk őket. Ez a fogás is erre
való. A számítógépnek mindegy, hogy talál-e fölösleges szóközöket, nem veszi őket figyelembe,
nekünk azonban segítség, hogy így első ránézésre látjuk: A külső ciklus ciklusmagja a belső
ciklusból és egy üres PRINT utasításból, a belsőé pedig egy olyan PRINT utasításból áll, amely a
belső ciklusváltozó éppen érvényes értékének megfelelő karaktert írja ki. Értelmezzük emberi
nyelven. Összesen harminckétszer hajtjuk végre a következőket: A 0. számútól a 7. számúig egy
sorba kiírjuk a karaktereket, és a következő sorra ugrunk. Hát ez nem is olyan bonyolult. Az
egyetlen probléma, hogy a belső ciklus minden indításánál nulláról indul. Erre többféle orvoslat
létezhet, maradjunk a legegyszerűbbnél: Felejtsük el, hogy a ciklusváltozóval akarjunk dolgozni!
Először mégiscsak alakítsuk vissza a belső ciklus beállításait, nem, mintha számítana, de így jobban
látható, hogy meddig számolunk egy sorban:
20 FOR BELSO=1 TO 8
Ugyebár, a továbbiakban úgysem ezt fogjuk kiíratni. De akkor mit is? Szúrjunk be az elejére egy 0
értékű változót, ez lesz a számláló:
5 SZAM=0
Ez írja majd ki a karaktert a 30-as utasításban, tehát:
30 PRINT CHR$(SZAM),
A program tökéletes lenne, ha mindig a nulladik karaktert akarnánk kiíratni. A SZAM változó értéke
azonban magától nem fog megváltozni, hiszen nincs FOR..NEXT ciklushoz kötve, mint a
ciklusváltozók, ezért nekünk kell gondoskodnunk róla, hogy minden egyes léptetéskor (tehát a belső
ciklusmagban) növekedjen az értéke:
35 SZAM=SZAM+1
Készen is vagyunk, de futtatás előtt még megint gondoljuk végig, hogy mit csinál a program. A
külső ciklus harminckétszer kiír egy-egy sort, utána a következőre ugrik. A kiírandó sorok úgy
készülnek el, hogy a belső ciklus nyolcszor egymás után írja a számláló által mutatott karaktert, és
megnöveli a számlálót, tehát a táblázat nyolc egymás utáni karakterét írja ki. Amikor a belső ciklus
egy újabb sor összeállításába kezd, a ciklusszámlálója nullázódik, de ez nem befolyásolja a mi
számlálónk működését, az továbbra is az előző értékről növekedik. Nézzük meg egyben a
programot:
LIST
5 SZAM=0
10 FOR KULSO=1 to 32
20 FOR BELSO=1 TO 8
30 PRINT CHR$(SZAM),
35 SZAM=SZAM+1
40 NEXT BELSO
50 PRINT
60 NEXT KULSO
OK
Futtatás:

Majdnem tökéletes, de mielőtt számlálgatni kezdünk, még néhány jelentéktelen csinosítást


megejtünk rajta. Először is: Hol van a beígért BETU$ változó? Jó-jó, semmi szükségünk nem volt
rá, de ha már előbb használtam, majdcsak találunk neki valami értelmes feladatot...
Engem például meglehetősen idegesít a sok sípolás, pláne, hogy az éjszaka közepén a
szomszédokra is tekintettel kell lennem... Jó volna elébe vágni a dolognak, és csak akkor kiíratni, ha
SZAM értéke nem egyezik meg a sípszót jelentő kóddal. Ezt az előbbi programban is megtehettük
volna egy feltételes elágazással, ilyenformán:
30 IF SZAM<>sípszó THEN PRINT CHR$(SZAM) ELSE PRINT "duda"
Ha tudjuk, hogy az ideiglenesen használt sípszó helyére milyen számot kell írnunk, a program
éppen azt csinálja, amit szeretnénk: Ha ehhez a számhoz érkezik, sípolás helyett csak a duda szót
írja a képernyőre, egyébként pedig a számnak megfelelő karaktert. Ezek után azonban könnyen
vérszemet kaphatunk, és esetleg más vezérlőkaraktereket is hasonlóan helyettesítenénk. Ekkor
azonban nemcsak két lehetőségünk van, így a kényelmes ELSE helyett valamivel összetettebb
szervezésre van szükségünk. Megpróbálom úgy beírni, hogy az előző helyen elférjen:
21 IF SZAM<>sípszó THEN GOTO 24
22 PRINT "duda",
23 GOTO 35
24 IF SZAM<>vissza THEN GOTO 27
25 PRINT "törlés",
26 GOTO 35
27 IF SZAM<>soremelés THEN GOTO 30
28 PRINT "ugrik",
29 GOTO 35
30 IF SZAM<>soreleje THEN GOTO 34
32 PRINT "eleje",
33 GOTO 35
34 PRINT CHR$(SZAM),
35 SZAM=SZAM+1
Hát, éppen csak hogy be tudtam nyomni! Hogy érthető legyen: Sorban megvizsgáljuk, hogy a
karakter megegyezik-e valamelyik vezérlőkóddal. Ha nem, ugrunk a következő vizsgálatra. Ha
igen, kiírjuk a jelentését, utána mindent átugorva a SZAM változó növelésére lépünk, stb. Ha
egyetlen vezérlőkaraktert sem találtunk, megérkezünk a 34-es sorba, ahol közvetlenül kiíratjuk a
megfelelő karaktert, és ez után is a növelés jön. Mindez egyébként hibátlanul működne, és akár így
is megírhatjuk a programot, ha nem vagyunk az áttekinthetőség és a takarékosság megszállottjai. Mi
azonban figyelembe vesszük, hogy nem vezet jóra, ha ide-oda ugrálunk, továbbá, hogy a PRINT
utasítás tulajdonképpen egy viszonylag bonyolult gépi kód beillesztését illeszti, míg az egyszerű
értékadás sokkal rövidebb és gyorsabb. Ezért úgy intézzük a dolgot, hogy minden esetben a BETU$
változónak adunk valami értéket, és a kiírást egyetlen PRINT-tel intézzük el. Nézzük tehát az elvi
felépítést:
Írjuk be tehát:
6 BETU$=""
25 BETU$=CHR$(SZAM)
26 IF SZAM=sípszó THEN BETU$="duda"
27 IF SZAM=vissza THEN BETU$="vissza"
28 IF SZAM=soremelés THEN BETU$="ugrik"
29 IF SZAM=soreleje THEN BETU$="eleje"
30 PRINT BETU$,
Valamivel rövidebb és egyszerűbb... Tehát: Először beállítjuk BETU$ értékét a számértéknek
megfelelőre, ha azonban később kiderül, hogy vezérlőkarakter, megváltoztatjuk a PRINT utasítás
előtt. Az az igazság, hogy a megoldás nem egészen precíz. Amikor egy vezérlőkaraktert találunk,
rögtön ugornunk kéne a nyomtatásra – így teljesen fölöslegesen még megvizsgáljuk a többi
lehetőséget is, amelyek pedig nyilvánvalóan nem következhetnek be, és ez lassítja a programot.
Esetünkben azonban ez elhanyagolható apróság az egyszerűség előnyeihez képest. Ezután már
hajlandó vagyok elárulni a kódok tényleges értékét: sípszó=7, egy lépés vissza=8, soremelés=10,
ugrás a sor elejére=13.
Listázzunk:
LIST
5 SZAM=0
6 BETU$=""
10 FOR KULSO=1 TO 32
20 FOR BELSO=1 TO 8
25 BETU$=CHR$(SZAM)
26 IF SZAM=7 THEN BETU$="duda"
27 IF SZAM=8 THEN BETU$="vissza"
28 IF SZAM=10 THEN BETU$="ugrik"
29 IF SZAM=13 THEN BETU$="eleje"
30 PRINT BETU$,
35 SZAM=SZAM+1
40 NEXT BELSO
50 PRINT
60 NEXT KULSO
Ok
Futtatás:
No, elég szép, mindenesetre történt egy furcsaság: a második sor végén látunk valami bogárkát.
Némi vizsgálódás után észrevesszük, hogy az eltolódást egy elfelejtett vezérlőkarakter okozza:
CHR$(9) ugyanis egy oszloppal továbbküldi a kurzort. Mi sem egyszerűbb! Beszúrunk mondjuk
egy IF SZAM=9 THEN BETU$="előre" sort... De hova is? Igen, a 25-30 sorok közé kéne
valahová, csakhogy oda már nem fér több! Rémes! Át kell számoznunk a programot. Ez persze
most nem túl nagy munka, de mi volna, ha nyolcvan oldalnyi szövegben történik mindez?
Szerencsére közben olvasgatom ám a dokumentációt, és abból kiderül, hogy a Blassic nem olyan
kezdetleges, mint feltételeztem, mégiscsak ismeri az átszámozás lehetőségét. Ez a RENUM parancs:
RENUM új számozás eleje, számozás kezdete a régi programszövegben, lépésköz
Mi az egyszerűség kedvéért az egészet (vagyis 5-től kezdve) átszámozzuk:
RENUM 10, 5, 10
Most már be tudjuk szúrni:
75 IF SZAM=9 THEN BETU$="előre"
Akár újra átszámozhatnánk, hogy szép szabályos legyen, de még nem vagyunk készen. Futtatáskor
persze látjuk, hogy minden stimmel, eltekintve a továbbra is felharsanó dudaszótól: Lehet, hogy ez
nem is az, aminek gondoltam, hanem csak a program jelzi, hogy az adott karaktereket nem tudja
kinyomtatni. Majd mindjárt kikerüljük ezeket is, most tegyük félre a kérdést.
Lehet számolni. De végül is mi a csudának fárasszuk magunkat? Számoljon a számítógép, az a
dolga! A számlálónk már készen van, csak ki kell íratnunk az értékét. A mostani változatban éppen a
századik sorban nyomtatjuk ki a karaktert, de előtte van még helyünk, ahova beírhatnánk:
98 PRINT SZAM;
99 PRINT "=";
Mivel a pontosvessző egymás után rakja a kiírandó dolgokat, ilyesforma kiírást kapnánk:
65=A
Ugye, kényelmesnek ígérkezik? Ráadásul a basic egymás utáni PRINT utasítások esetén nem
ragaszkodik a külön sorokhoz, megengedi a következő tömörebb formát:
100 PRINT SZAM; "="; BETU$,
Futtatáskor persze látjuk, hogy a második sor megint túl hosszú – a szavakkal való leírás túlnyúlt
egy-egy oszlopon. Csakhogy már mi vagyunk nyeregben: megtudtuk a karakterek kódját, így a
szavak helyett ábrácskákat írhatunk a vezérlőkarakterek helyére, mondjuk egy utána írt
felkiáltójellel utalva arra, hogy ez csak magyarázat, nem a karakter képe, például:
75 IF SZAM=9 THEN BETU$=CHR$(16)+"!"
80 IF SZAM=10 THEN BETU$=CHR$(20)+"!"
90 IF SZAM=13 THEN BETU$=CHR$(27)+CHR$(27)+CHR$(27)+"!"
A sípolás megszüntetésére pedig PRINT CHR$(beírt szám) parancsokkal kipróbálhatjuk a gyanús
karaktereket, ahol semmit sem látunk megjelenni:
PRINT CHR$(32)
Ez téves próbálkozás, mivel a szóközt jelenti, de a 133, 149, 183 számú karakterekkel nagyobb
szerencsénk van. Itt, mivel nem tudjuk, hogy mi idézte elő a sípolást, nem írjuk ki a hangjegyet,
csak három felkiáltójellel figyelmeztetjük magunkat arra, hogy ezeket nem használhatjuk. Ez
ugyebár a következő utasításokat jelentené:
IF SZAM=133 THEN BETU$="!!!"
IF SZAM=149 THEN BETU$="!!!"
IF SZAM=183 THEN BETU$="!!!"
Azonban a basic képes arra, hogy a kifejezések igazságtartalmát összevonva vizsgálja. Erre több
művelet használatos, leggyakrabban a nem, és, vagy összefüggések, amelyeknek basic megfelelői a
NOT, AND, OR kulcsszavak. Ezek voltaképpen matematikai műveletek, de az értelmük jobban
elképzelhető hétköznapi példák alapján:
Ha NEM esik az eső, fölösleges az ernyő.
Ha nyitva a bolt ÉS van rá pénzem, veszek újságot.
Ha fel tudom hívni a barátomat, VAGY összefutok vele a koncerten, megbeszélem vele a teendőket.
A számtani igazságok hasonlóan értékelhetők ki, esetünkben:
Ha SZAM=133 vagy SZAM=149 vagy SZAM=183, akkor BETU$ legyen "!!!".
Basicül:
IF SZAM=133 OR SZAM=149 OR SZAM=183 THEN BETU$="!!!".

Megjegyzendő, hogy ezeknek a műveleteknek magas a precedenciájuk, így összetettebb kifejezések


esetén mindig érdemes zárójelezni, hogy a gép tudja a helyes sorrendet:
IF (A*24>80) AND (B+2=17) OR (PUFI>=100) THEN PRINT "miskulancia"

Egy szó mint száz, a beszúrt sorunk a következő lesz:


95 IF SZAM=133 or SZAM=149 or SZAM=183 THEN BETU$="!!!"
Végül még egy picit szépítünk a táblázaton azzal, hogy a sorok közé még egy üres printet berakunk:
135 PRINT

Futtatás előtt újra átszámozzuk, és megnézzük. Mivel az első sorunk most 10, elhagyhatjuk a
RENUM parancs paramétereit, ilyenkor ugyanis a 10, 10, 10 értékeket állítja be magának:
RENUM
Ok
LIST
10 SZAM=0
20 BETU$=""
30 FOR KULSO=1 TO 32
40 FOR BELSO=1 TO 8
50 BETU$=CHR$(SZAM)
60 IF SZAM=7 THEN BETU$=CHR$(14)+"!"
70 IF SZAM=8 THEN BETU$=CHR$(17)+"!"
80 IF SZAM=9 THEN BETU$=CHR$(16)+"!"
90 IF SZAM=10 THEN BETU$=CHR$(20)+"!"
100 IF SZAM=13 THEN BETU$=CHR$(27)+CHR$(27)+CHR$(27)+"!"
110 IF SZAM=133 OR SZAM=149 OR SZAM=183 THEN BETU$="!!!"
120 PRINT SZAM; "="; BETU$,
130 SZAM=SZAM+1
140 NEXT BELSO
150 PRINT
160 PRINT
170 NEXT KULSO
100 IF SZAM=13 THEN BETU$=CHR$(27)+CHR$(27)+CHR$(27)+"!"
110 IF SZAM=133 OR SZAM=149 OR SZAM=183 THEN BETU$="!!!"
120 PRINT SZAM; "="; BETU$,
130 SZAM=SZAM+1
140 NEXT BELSO
150 PRINT
160 PRINT
170 NEXT KULSO
Ok

És végre-valahára jöjjön a kész program futtatása:

Természetesen te alkalmazhatsz más, neked jobban megfelelő jeleket a vezérlőkarakterek helyett, a


sorok elejére még beszúrhatsz szóközöket, hogy ne tapadjon a táblázat az ablak széléhez, de a
lényeg megvan. És most térhetünk vissza a kútásóhoz:
30 SZOVEG$=" r"+CHR$(233)+"m"+CHR$(237)+"t"+CHR$(245)+" "+CHR$(252)+"st"+CHR$(246)+"k"+CHR$(251)+" k"+CHR$(250)+"t"+CHR$(225)+"s"+CHR$(243)
40 PRINT SZOVEG$

Hát igen, rendes betűmérettel már nem fért volna ki egy sorban, de az interpreter elfogadja, ha szép
folyamatosan beírod. Lehet futtatni.
Én mondtam, hogy nem lesz kényelmes módszer... De remélem, tanulságos volt. Most már a
Blassicből elmentve és visszatöltve is ugyanez lesz az eredmény. Azért az szerencsére nem túl
gyakori eset, hogy a „csábítón dülöngélő műút”, „sárízű túrón ülő döglégy”, „lúdlábért vívó szörnyű
hüllők”, „őrült színű új sövényvágó” vagy a „rücskös bőrű vérszívó búvár” kifejezéseket jelenítjük
meg a képernyőn, inkább csak efféléket: „Melyiket választod?” vagy „Írj be egy számot 1-10-ig”.
Ha csak egy-két ékezetre van szükség, akkor viszont nem olyan elviselhetetlen a dolog, és szebb a
program, ha tisztességes magyar szövegeket ír ki.

Adatok bevitele
Arra, hogy a változóink csakugyan változzanak, eleddig egyetlen módszert ismertünk: a programon
belüli értékadást. Ahhoz viszont, hogy a program ne mindig ugyanazokat a változtatásokat hajtsa
végre, minduntalan át kellett írnunk a forrást. Nem, mintha ez olyan nehéz dolog lenne, de hát azt
szeretnénk, hogy a program önmagában is alkalmas legyen valamely feladat végrehajtására, akkor
is, ha a programszöveghez nem nyúlunk. Végső célunk amúgy is az önállóan futó programok
készítése, amelyek akkor is működnek, ha semmiféle interpreter vagy egyéb támogatás nincs a
gépen. Ha pedig valóban nincs, ezekbe a programokba már akkor sem tudunk belenyúlni, ha
akarunk. De az interpreter-nyelvek esetén is gondolnunk kell arra, hogy nem okvetlenül mi fogjuk
használni a programot, a másik jámbor felhasználó pedig esetleg egyáltalán nem is ért a
programozáshoz. Gondoskodnunk kell tehát arról, hogy futás közben is be lehessen vinni adatokat a
programba. A bevitel angol és basic neve INPUT. Ennek több változata létezik, mi itt csak az
alapesettel foglalkozunk, amely a változó értékének begépelését jelenti. Így használható:
INPUT VALTOZO
Mindjárt írjunk is egy kis programot, amely két számot ad össze:
10 INPUT A
20 INPUT B
30 PRINT A+B
Vagyis beolvassuk először A, majd B változó értékét, azután kiíratjuk az összegüket. A program
„kezelőfelülete” módfelett letisztult, ezért nem árt némi útmutatás. Futtatáskor először egy kérdőjel
jelenik meg, ez mutatja, hogy várja az első számot. Begépeled tehát, majd leütöd az Entert, ezzel
jelzed a bevitel végét. Újabb kérdőjel, újabb szám, és Enter után megjelenik az összeg.
A kezelés tehát igen egyszerű, mindamellett számíthatunk rá, hogy a kevésbé tájékozott felhasználó
csak báván mered majd a képernyőre, ha szembesül a művünkkel. A programot „fel kell
öltöztetnünk”, hogy beépített magyarázatot is adjunk a működésére. A következő változatban
bőséges szövegezéssel biztosítjuk az útmutatást:
10 ' osszeado program INPUT utasitasokkal
20 '
30 PRINT "***************************"
40 PRINT "K";CHR$(201);"T SZ";CHR$(193);"MOT ";CHR$(214);"SSZEAD";CHR$(211);" PROGRAM"
50 PRINT "***************************"
60 PRINT
70 PRINT CHR$(205);"rd be az els";CHR$(245);" sz";CHR$(225);"mot: ";
80 INPUT A
90 PRINT CHR$(205);"rd be a m";CHR$(225);"sodik sz";CHR$(225);"mot: ";
100 INPUT B
110 PRINT "A megadott sz";CHR$(225);"mok ";CHR$(246);"sszege: ";A+B
Tehát először is, a magunk számára írunk egy fejlécet, hogy a későbbi fejlesztés során tudjuk, hogy
mire szolgál a program. Utána kezdődik a tényleges kód:
A karaktertáblából ellesett CHR$()-értékekkel jól láthatóan a képernyőre írjuk a program feladatát.
Az INPUT utasítások előtt közöljük, hogy milyen adatra számítunk.
A végeredmény kiírása előtt megmondjuk, hogy miféle szám következik.
A hosszú utasításokat itt is kisebbel szedtem, hogy kiférjenek egy sorban, de ennek az igazi
forrásszövegben sem szerepe, sem lehetősége nincs, egyszerűen csak írd be.
Most tehát a program nem egy előre megadott összeadást végez el, hanem azokat a számokat adja
össze, amelyeket tőlünk kap. Egyelőre csak egy összeadást tud, azután véget is ér, de nyilván
ügyesebb, ha leállás nélkül annyiszor számoltathatunk vele, amennyiszer a kedvünk tartja. Ehhez a
végrehajtás után megint a beolvasások elé ugrunk, azaz ciklust szervezünk. A FOR..NEXT típusú
ciklus értelemszerűen nem jöhet szóba, hiszen nem tudjuk előre, hogy a felhasználó hány számolást
akar elvégeztetni, ezért maradunk a legelőször megismert GOTO-s módszernél:
120 GOTO 60
Hát ez nem volt bonyolult... Ha most futtatod a programot, a végtelenségig adogathatsz vele össze
számpárokat. Persze nem kell ezentúl napjaid fogytáig összeadással foglalkoznod: elég, ha a bekért
számérték helyére bármilyen nem-szám adatot írsz be, a típuskeveredés miatt azonnal leáll a
program. Ez azonban nem elegáns megoldás, pláne, hogy egy másik felhasználó esetleg nem olyan
okos, mint te, és őszbe csavarodik a szakálla, mire végre eltéveszti egyszer a számok beírását. Az
tehát a tisztességes, ha egy feltétellel biztosítjuk a számára a szabályos kilépés lehetőségét. Eddig a
feltételeket mindig a programon belülről kaptuk, itt viszont a felhasználó döntésétől kell függnie. Ez
megoldható például úgy, hogy minden számolás végén megkérdezzük, akarja-e folytatni:
115 PRINT "Folytassuk";
116 INPUT A$
120 IF A$="i" GOTO 60 ELSE PRINT "Vége. A viszontlátásra!”
Mint látható, nem küzdök tovább a CHR$() függvénnyel, mert nagyon meghosszítja a sorokat, már
úgyis tudod, hogyan kell használni illetve a Jegyzettömbbel kikerülni.
Mivel a felhasználó számtalan módon adhat meg elfogadhatatlan értéket, a gyakorlatban jobban ki
kellene dolgozni a feltételt. Hogy hogyan, azt egyelőre nem közlöm, mert a cél az, hogy mielőbb
áttérjünk a Rapid-Q-ra, ott pedig gyökeresen másképpen intézzük a kilépést. Most mindenesetre
feltételezzük, hogy a felhasználó tudja: a folytatáshoz kis i betűt, majd Entert kell lenyomnia. Ha
mégis érdekelne egy tisztességesebb megoldás, írd meg, és akkor azt is megmutatom. A fenti
sorokat nem használjuk majd, de két tanulság miatt érdemes volt kipróbálni. Egyrészt látható, hogy
megfelelő fogalmazással úgy is intézhetjük, hogy az INPUT kérdőjele értelmet kapjon, vagyis
tényleg egy kérdés végére kerüljön. A programban is írhattuk volna így:
70 PRINT "Mi legyen az első szám";
90 PRINT "Mi legyen a második szám";
Ízlés dolga. Másrészt észreveheted, hogy a szöveges változónak lehet ugyanaz a neve, mint egy
számváltozónak (esetünkben A), mivel a végére írt dollárjel egyértelműen megkülönbözteti tőle.
Tehát a típusjelzés maga is a név része, vagyis a két név mégsem azonos – az egyik A, a másik A$.
Hosszú távon ez az állandó rákérdezgetés kissé idegesítő, ezért más megoldáshoz is
folyamodhatunk. Nem kérünk külön útmutatást, csak a bevitt számértékeket figyeljük, de azokat
megvizsgáljuk, hogy nem egy bizonyos, jelzésként meghatározott műveletet kaptunk-e. Ha igen,
kilépünk. Például:
120 IF A<>3000 AND B<>5999 THEN GOTO 60 ELSE PRINT "Vége. A viszontlátásra!”
Ebben az esetben a felhasználó úgy tudja befejezni a programot ha első számként háromezret,
másodikként ötezerkilencszázkilencvenkilencet ad meg, minden más esetén újra kezdi. Ha csak az
egyik azonos, akkor még nincs vége, erről az AND (és, tehát, ha mindkét feltétel igaz) művelet
gondoskodik. Mivel erre a módszerre magától nehezen jön rá a felhasználó, legalább a program
elején illik róla tájékoztatni...
Valójában ilyen hasraütéssel választott feltételt nem érdemes szabni. Mi van, ha az illető nem akarja
befejezni, de pont ezt a két számot adná össze? Ezért válasszunk olyan feltételt, ami kevesebb
problémával jár. Bármilyen számhoz nullát hozzáadni nem túl értelmes dolog, de ha szükséges,
akkor sem kell hozzá a számítógép – ezt a műveletet fenntarthatjuk programvége-jelzésnek. Lehet
tehát az a feltétel, hogyha legalább az egyik összeadandó nulla, akkor lépjünk ki. Itt nem egyszerre
kell teljesülnie a kettős feltételnek, hanem bármelyik fele a program végét jelenti, tehát az OR
műveletet használjuk:
120 IF A<>0 OR B<>0 THEN GOTO 60 ELSE PRINT "Vége. A viszontlátásra!"
Mivel egy szám nullával való szorzata nulla, a feltételt a következőképpen is megfogalmazhatjuk:
120 IF A*B<>0 THEN GOTO 60 ELSE PRINT "Vége. A viszontlátásra!"
Ez egyébként valamivel lassúbb, de itt nincs jelentősége, hogy az utasítás mondjuk 25 vagy csak 4
ezredmásodpercig tart. A feltétel meg is fordítható, például ilyenformán:
120 IF A*0 THEN GOTO 140
130 GOTO 60
140 PRINT "Vége. A viszontlátásra!"
Az értelme ugyanaz. Nézzük egyben az egészet:
10 ' osszeado program INPUT utasitasokkal
20 '
30 PRINT "***************************"
40 PRINT "KÉT SZÁMOT ÖSSZEADó PROGRAM"
45 PRINT "A program bármelyik összeadandó"
46 PRINT "0 értéke esetén fejeződik be."
50 PRINT "***************************"
60 PRINT
70 PRINT "Írd be az első számot: ";
80 INPUT A
90 PRINT "Írd be a második számot: ";
100 INPUT B
110 PRINT "A megadott számok összege: ";A+B
120 IF A*B=0 THEN GOTO 140
130 GOTO 60
140 PRINT "Vége. A viszontlátásra!"
A program – eltekintve az ékezetproblémáktól – IS-Basicben csak az aposztrófok (helyettesítsd
REM-mel) és a 110-es utasítás végére csapott A+B miatt nem fut, a PRINT eltérő szabályozása
miatt. Ha kettészeded a sort, már jó:
110 PRINT "A megadott számok összege:";
120 PRINT A+B
Azt is megteheted, hogy A+B értékét karakterlánccá alakítod, akkor maradhat egy sorban:
110 PRINT "A megadott számok összege: "&STR$(A+B)
Az IS-Basic azonban különbet is tud. Ha megfigyeled a program szerkezetét, a végrehajtó rész
leegyszerűsítve valahogy így néz ki:
ELEJE
utasítások
VÉGE: feltétel szerint az elejére vagy tovább
Ez, mint már tudjuk, egy ciklus, mégpedig feltételes ciklus, mivel a végén található feltételtől
tesszük függővé, hogy ismétlünk, vagy abbahagyjuk, és továbbmegyünk a programban. Látható,
hogy a szerkezete voltaképpen nagyon hasonló a FOR..NEXT cikluséhoz, azzal a különbséggel,
hogy nem egy előre megadott ciklusváltozóhoz értékéhez kötjük a lefutását. A modernebb basic
nyelv ezért – meg a GOTO kiküszöbölésére – ennek a ciklusfajtának is külön utasításokat adott. A
két kulcsszó a ciklus elejét jelző DO (csináld) és a végét mutató LOOP (ismételd), így:
DO
utasítások
LOOP
Ez végtelen ciklus, mivel feltételt nem adtunk meg. Ez is megtehető azonban a LOOP-hoz kapcsolt
UNTIL (mígnem) kiegészítéssel:
LOOP UNTIL feltétel
Így a ciklus addig fut, mígnem egyszer csak bekövetkezik a feltétel igaz állapota. Arról
természetesen nekünk kell gondoskodnunk, hogy a feltétel valamikor teljesüljön, egyébként tovább
zakatol a végtelenségig. Mielőtt az ennek megfelelően átalakított programot bemutatnám, még egy
apróság következik.
Az inputok előtt – helyesen – egy PRINT utasítással mindig megmagyaráztuk, hogy mit kérünk:
70 PRINT "Írd be az első számot: ";
80 INPUT A
Ez annyira gyakori fordulat, hogy az ENTERPRISE basicje hasznosnak tartotta egy különleges INPUT-
változat bevezetését, amellyel egyszerre intézhetjük a kiírást és a beolvasást:
70 INPUT PROMPT "Írd be az első számot: ":A
Hála és köszönet az IS-Basic megalkotóinak, amiért egyúttal az INPUT eddig kötelezően
megjelenő, idétlen kérdőjelét is elhagyták! Beíráskor ügyelj a PROMPT szóra, még az eredeti
ENTERPRISE-kézikönyvben is több helyütt PROMT-ot írnak helyette.
Akkor most nézzük a módosított programot:
100 ' összeado program INPUT utasitásokkal
110 '
120 PRINT "***************************"
130 PRINT "KéT SZÁMOT ÖSSZEADO PROGRAM"
140 PRINT "A program bármelyik összeadando"
150 PRINT "0 értéke esetén fejezödik be."
160 PRINT "***************************"
170 DO
180 PRINT
190 INPUT PROMPT "Ird be az elsö számot: ":A
200 INPUT PROMPT "Ird be a második számot: ":B
210 PRINT "A megadott számok összege: "&STR$(A+B)
220 LOOP UNTIL A*B=0
230 PRINT "Vége. A viszontlátásra!"
A DO..LOOP ciklus ez esetben, mint megfigyelhetted, hátultesztelős. Az elöltesztelős változat
hasonló, csak a ciklus elejére tennénk a feltételt:
170 DO UNTIL A*B=0
ekkor a 220-as sorban nem kéne a feltétel, csak egy LOOP. A két változat között ugyebár az a
különbség, hogy most az utasítások előtt vizsgáljuk a feltételt, így, ha az teljesül, a ciklus egyszer
sem fog lefutni. Ebben a programunkban például éppen ezért marhaság volna az elöltesztelős
változat, hiszen induláskor a létrejövő A és B értéke egyformán nulla, így a feltétel rögtön igaz
lenne.
Az UNTIL-nak van egy hasonló testvérkéje, a WHILE (amíg). Ez ugyanolyan módon használható,
de nem azt vizsgálja, hogy a feltétel mikor következik be, hanem éppen ellenkezőleg, hogy meddig
érvényes, más szóval, hogy mikor válik hamissá. Ennek megfelelően a fenti ciklust így is
szervezhettük volna:
170 DO
...
220 LOOP WHILE A*B<>0
Vagyis addig ismétlünk, amíg A*B nem nulla. Ha ez a feltétel nem teljesül, vége a ciklusnak. Itt
egyszerűen meg tudtuk fordítani a feltételt, más programban esetleg okkal döntünk egyik vagy
másik megoldás mellett.

A tömbök
Noha a gyors haladás érdekében a basic nyelvnek sok igen fontos elemét említetlenül hagyom, a
változókkal való ismerkedésből nem maradhat ki a tömbök bemutatása. Térjünk vissza a legelejére,
a szókiíró programunkhoz. Ebben, mint emlékezhetsz, a galagonya, kakuk, szerda, kalap és ragacs
szavakat írtuk ki a képernyőre, akkor egyszerűen szövegkonstansok formájában. Most, hogy már
tudunk egyet-mást a változókról, kipróbálhatjuk, hogy ez esetben is tudjuk-e őket használni
valamire. Megtehetjük például, hogy bevezetünk egy szövegváltozót, és annak az értékét
módosítgatva íratjuk ki a szavakat:
1 ' szokiiro program egy valtozoval
2 ' (a megadott szavakat print utasitasokkal a kepernyore irja)
3 '
5 SZO$="galagonya"
10 PRINT SZO$
15 SZO$="kakuk"
20 PRINT SZO$
25 SZO$="szerda"
30 PRINT SZO$
35 SZO$="kalap"
40 PRINT SZO$
45 SZO$="ragacs"
50 PRINT SZO$
Megfigyelheted, hogy a dolog teljesen haszontalan, a konstansokat ugyanolyan módon használjuk,
csak fölöslegesen megbonyolítottuk az egészet. Ez tehát nem vezetett értelmes eredményre. Az
állandóan visszatérő PRINT SZO$ utasítás azonban azzal kecsegtet, hogy ciklusba szervezhetnénk
a kiíratást, ha a konstansok bevitelét másképpen tudnánk megoldani. Ha például valahol sorban el
tudnánk helyezni a szavakat, és mindig a soron következőt olvasnánk be, akkor a kiíró rész a
következő FOR..NEXT ciklusra egyszerűsödne:
FOR I=1 to 5
SZO$=következő szó
PRINT SZO$
NEXT I
A dolgot meg tudjuk csinálni! Éppen a fent elmondottakat oldja meg a DATA (adat) utasítás. Ha egy
sor ezzel kezdődik, az azt jelenti, hogy ott nem végrehajtható kódot találunk, hanem a program
futtatásához szükséges adatokat. Ha ilyen úgynevezett DATA-blokkot talál a fordító, akkor azt
átlépi, mintha REM utasítás volna ott. A különbség csak annyi, hogy amikor viszont szükségünk van
rájuk, ezeket az adatokat az erre szolgáló READ utasítással el tudjuk érni. A DATA-sorok adatait
vesszővel választjuk el egymástól. A mostani esetben ez így néz ki:
DATA "galagonya", "kakuk", "szerda", "kalap", "ragacs"
Látható, hogy rendesen idézőjelek közé fogtam a szavakat, minthogy szöveges adatok, egyébként
így jelezhető az interpreternek, ha szövegen belüli vesszőt használunk, nem pedig az adatokat
elválasztóról van szó. Ugyanígy tárolhatnék számokat, sőt matematikai kifejezéseket is, de a
dologban nem szeretnék elmerülni, ugyanis a DATA fölött eljárt az idő. A modern basic már nem
használja, a Rapid-Q például már nem is ismeri. Itt még az adatok betöltéséhez jól használható, de
holt tudásnak tekinthető az ismerete.
Az így tárolt adatok kezelése szokatlan. Akárhová írjuk őket a programban, mindig a legelsőnél
kezdi az olvasásukat, és a következővel folytatja. Emiatt alaposan át kell gondolnunk, hogy hogyan
szervezzük meg őket: Ha például egy szövegváltozó után számváltozót akarunk beolvasni, a
következő adatnak számnak kell lennie, különben leáll a program. Belátható, hogy sok adat esetén
könnyen tévedhetünk, nem csoda, hogy a későbbiekben megszabadultak ettől a nehézkes
megoldástól. Ez a sorban való hozzáférés egyébként meg is nehezíti az adatok elérését. Ha egy
bizonyos adatra van szükségünk, akkor az egyetlen lehetőségünk, hogy az adatok elejére ugrunk –
erre a RESTORE utasítás szolgál –, és az adatokat egymás után kiolvassuk, amíg a kívánt
bejegyzéshez nem érünk. Ez, mivel a szükségtelen adatokat semmire sem használjuk, igencsak
gazdaságtalan és lassú. Az ENTERPRISE basicje ezen annyit finomított, hogy a RESTORE utasítás után
kiadott sorszámmal meghatározhatjuk, hogy melyik sorban kezdje az újraolvasást. Így nem kell
elölről kezdeni, hanem épp a kívánt blokkra ugorhatunk, ami rendkívül nagy segítség az eredeti
kínosan suta megoldáshoz képest.
Noha a DATA-blokkok bárhol lehetnek a programban, hagyományosan a program legvégén szokás
összegyűjteni őket. Nézzük tehát a program mostani állását:
1 ' szokiiro program egy valtozoval
2 '
10 FOR I=1 TO 5
20 READ SZO$
30 PRINT SZO$
40 NEXT I
50 DATA "galagonya", "kakuk", "szerda", "kalap", "ragacs"
Ez kétségtelenül szebb, mint az iménti változat, de még mindig semmire sem használható. Ha már
változót alkalmaztunk, az egész akkor kapna értelmet, ha a beállított értékével valamit kezdhetnénk.
Most viszont a kiírás után rögtön meg is változtatjuk az értékét – ha pedig azt nem őrizzük meg,
semmivel sem tartunk előbbre, mint a konstansos verzióban. Olvassuk be inkább mindegyik szót
külön változóba, akkor megmarad az értéke, és azt csinálhatunk vele, amit akarunk, például azt
íratjuk ki közülük, amelyiket a felhasználó szeretné. Ezt az eddigi tudásunk alapján például így
oldhatnánk meg:
1 ' szokiiro program tobb valtozoval
2 '
10 READ SZO0$
20 READ SZO1$
30 READ SZO2$
40 READ SZO3$
50 READ SZO4$
60 PRINT "Az adattáramban a következő szavak vannak"
70 PRINT "0: ";SZO0$
80 PRINT "1: ";SZO1$
90 PRINT "2: ";SZO2$
100 PRINT "3: ";SZO3$
110 PRINT "4: ";SZO4$
120 PRINT "Gépeld be annak a szónak a számát,"
130 PRINT "amelyet szeretnél újra kiírni:"
140 INPUT SZAM
150 IF SZAM=0 THEN PRINT SZO0$
160 IF SZAM=1 THEN PRINT SZO1$
170 IF SZAM=2 THEN PRINT SZO2$
180 IF SZAM=3 THEN PRINT SZO3$
190 IF SZAM=4 THEN PRINT SZO4$
200 DATA "galagonya", "kakuk", "szerda", "kalap", "ragacs"
Már említettem, hogy ez a feltételkezelés olyan messze van a tökéletestől, mint Makó
Jeruzsálemtől. Ennek ellenére most békén hagyjuk (pontosabban: a Függelékben majd ejtek szót a
helyesebb megoldásokról, ha jut rá időm), mert egészen máshová szeretnék kilyukadni. Láthatod,
hogy az újabb változók bevezetése teljesen szétzilálta a program már-már összeálló szerkezetét.
Miért is nem lehet a változókra is sorszámmal hivatkozni a névadás helyett! – akkor mindent
ciklusokkal lehetne intézni: Az első változó kapná az első adat értékét, a második a másodikét és
így tovább. Persze, sejthetted, hogy a sok hasznavehetetlen, béna próbálkozás irányult valamire...
Nos, pontosan erre. Ugyanis azonos típusú változókból csakugyan létrehozható az áhított
adatszerkezet. Egy ilyen változócsoporton belül csak meg kell mondanunk, hogy hányadik elemet
kezeljük, és az interpreter, tudván, hogy egy elem mekkora helyet foglal el a memóriában,
könnyedén a kért változóra áll. Tételezzük fel, hogy egy szám tárolásához 4 memóriarekeszre van
szükségünk, és az ötödik változóba akarunk írni. Ekkor az interpreter kiszámolja, hogy a
változócsoport kezdetétől számítva a huszadik (5*4) memóriacímen kezdődő értékkel kell
foglalkoznia. Az efféle csoportokat nevezzük tömböknek. A tömbök kezelése különleges feladat.
Magányos változót bármikor létrehozhatunk a programban, az interpreter keres a memóriában egy
akkora szabad helyet, ahová befér, és kész is van. A tömbhöz viszont nem adogathatunk elemeket
ötletszerűen, mert lehet, hogy az új elem már nem férne el az eddigiek mellé, ha pedig máshová
írnánk, nem lehetne a címét a fenti módon kiszámolni. Ezért a tömbnek minden elemét egyszerre
kell létrehoznunk. Ez úgy történik, hogy megadjuk a tömb nevét (a végén a szokásos módon
különleges karakterrel jelezvén a típusát), azután zárójelben utána írjuk, hogy hány elemből áll. Így
az interpreter tudja, hogy a teljes tömbnek mekkora lesz a kiterjedése, és akkora helyet biztosít a
számára a memóriában. A kiterjedést idegen szóval dimenziónak hívjuk (angolul dimension), ennek
rövidítése a basic DIM kulcsszava, amellyel a tömbváltozók helyigényét közöljük. Úgy is mondjuk,
hogy a tömböt dimenzionáljuk. Itt egy öt szövegváltozóból álló tömbre van szükségünk, tehát ezt
írjuk:
DIM SZO$(5)
Ez a gyakorlatban azt jelenti, hogy a tömb a következő öt elemből áll össze:
SZO$(0), SZO$(1), SZO$(2), SZO$(3), SZO$(4)
Tehát a számozás nulláról indul, az előző programban én is ezért neveztem SZO0$-nak az első
elemet, noha ott bármi lehetett volna a neve. A számozás ennek megfelelően a megadott határérték
előtt eggyel fejeződik be, vagyis SZO$(5) változó nincs a tömbben! Ez a köznapi gondolkodás
számára kissé zavaró hiszen az elsőtől az ötödik tömbelemig terjedő tartományban dolgozunk. Ezért
más basicek megengedik a következő fajta dimenzionálást is:
DIM SZO$(1 TO 5)
Sőt, ha valami miatt úgy hasznos, akár DIM(387 TO 401) vagy hasonló is lehet. A Blassic még
nem ismeri ezt a módszert.
Amikor a basic létrehoz egy tömböt, az elemeknek rögtön értéket is ad: Számtömbök esetén nulla,
szövegtömbök esetén "", vagyis üres string lesz az elemek kezdőértéke. Más programnyelvekben
ez nem feltétlenül van így, ott a létrehozott tömböket külön fel kell töltenünk a kívánt
kezdőértékkel, más szóval inicializálni kell őket.
A tömbelemek zárójelben megadott sorszámát indexnek, vagyis mutatónak nevezzük. Az indexet
nemcsak számkonstanssal, hanem változóval is megadhatjuk – például, hogy „hazabeszéljek” egy
kissé, egy ciklusváltozó is lehet. A ciklusváltozók ilyenfajta használata is indokolhatja azt a
hagyományt, hogy a C (counter, vagyis számláló) mellett az I rövidítés (index) is gyakran használt
ciklusváltozónév. Most pedig nézzük, hogy a programunk milyen elegánsan oldható meg
tömbhasználattal.
1 ' szokiiro program tombvaltozoval
2 '
10 DIM SZO$(5)
20 PRINT "Az adattáramban a következő szavak vannak"
30 FOR I=0 TO 4
40 READ SZO$(I)
50 PRINT I;": ";SZO$(I)
60 NEXT I
70 PRINT "Gépeld be annak a szónak a számát,"
80 PRINT "amelyet szeretnél újra kiírni:"
90 INPUT I
100 PRINT SZO$(I)
110 DATA "galagonya", "kakuk", "szerda", "kalap", "ragacs"
A 90-es sor INPUT I utasítása mellé még kívánkozik egy megjegyzés. Az előző programban itt
egy SZAM nevű változóba kértük az adatot, de az I voltaképpen egy közönséges változó. Mivel
ciklusváltozóként véget ért a szerepe, bátran felhasználhatjuk a bevitelre is, nincs szükség újabbra.
Utána ugyanúgy indexelhetünk vele, mint a ciklusban.
Mint említettem, az átlagos gondolkodás számára némiképp idegen a nulladik sorszám használata.
Ezt elrejtheted a felhasználó elől, ha az 50-es utasításban a gép által használt értéknél eggyel
nagyobbat íratsz ki:
50 PRINT I+1;": ";SZO$(I)
Ekkor viszont a felhasználó is nagyobb számot ír be, tehát az indexből le kell egyet vonni, hogy
igaz legyen: 100 PRINT SZO$(I-1)
Minden működik, de még adós vagyok az ENTERPRISE-változattal. Íme:
1 ' szokiiro program tombvaltozoval
2 '
10 DIM SZO$(5)
20 PRINT "Az adattáramban a következö szavak vannak"
30 FOR I=0 TO 4
40 READ SZO$(I)
50 PRINT STR$(I-1)&": "&SZO$(I)
60 NEXT
70 PRINT "Gépeld be annak a szonak a számát,"
80 PRINT "amelyet szeretnél újra kiirni:"
90 INPUT I
100 PRINT SZO$(I-1)
110 DATA "galagonya", "kakuk", "szerda", "kalap", "ragacs"
Ha a fentieket jól megértetted, szemedbe ötölhet egy furcsaság: Amikor kötött hosszúságú számokat
helyezünk el egy tömbben, könnyű elképzelni, hogy a program egyszerűen megtalálja egy-egy elem
kezdetét. De a szövegek hossza különbözik. Honnan tudja a program, hogy a „galagonya” elejétől
kilenc tárcímet kell átugornia a következő elemig, a „kalap”-étól meg csak ötöt? A Blassic válasza
egyszerű: nem tudja. A régi basicben egy szöveges elem hossza 256 bájt lehetett (az elején egy bájt
mutatta, hogy hány karakter a megjelenítendő szöveg, utána maximum 255 karakter következett). A
basic minden szövegváltozó részére lefoglalta ezt a hosszt, attól függetlenül, hogy végül milyen
hosszú szöveg került bele. Így mindig 256 bájtot kellett ugornia a következő elemig. A modern
basicben megszűnt ez a korlátozás, gyakorlatilag bármilyen hosszú szöveg kerülhet egy
tömbelembe. Viszont így már nem volna túl gazdaságos, ha az egyik tömbelem ugyanakkora lenne,
mint a másik. Képzeld csak el, ha mondjuk egy kételemű tömbben az egyik elembe a Háború és
béke nagyregény kerül, a másikba meg csak annyi, hogy „hé!”. Világos, hogy kár lenne annak is
ugyanakkora memóriaterületet lefoglalni. Ezért az új basic egészen másképpen szervezi meg az
adatok tárolását – hogy pontosan hogyan, ne firtassuk, mindenesetre a szöveghosszhoz igazodva.
Amikor a SZO$ változóit együttesen tömbnek nevezem, nem vagyok egészen pontos. Ha a
változókat szemléletesen kis dobozokként képzelem el, akkor úgy tekinthetem, mintha ezek a

Persze, nem szabad elfelejteni, hogy valódi, gépbe szerelt memória szerkezetéről úgysem tudunk
semmit, úgyhogy csupán a szándékunk dönti el, hogy milyen irányúnak tekintjük a sort: Valójában
nincs vízszintes, függőleges vagy ferde, az egymásutániság a lényeg. A kijelölt hármas számú
dobozban esetünkben a „kalap” szó van. Az egy sorban elhelyezett adatokat változókat
pongyolábban egydimenziós tömböknek, hivatalosan vektoroknak nevezik. Az adatok azonban
nemcsak egy sorban rendezhetők el, hanem táblázatban is. Hogy a basic ezt a saját maga számára
hogyan oldja meg az egymást sorban követő memóriacímeken, azzal ne foglalkozzunk, mi úgy
képzelhetjük el, hogy egymás alá írt sorokban és oszlopokban rendeződnek el az adatok. Ekkor
viszont nem elég egy kiterjedést megadnunk, hanem vesszővel elválasztva, mind a két irányban
meghatározzuk, hogy hány adat méretű legyen a tömb. Egy 4*5 kockás táblázatot például így
adhatunk meg:
DIM TABLAZAT$(4,5)
Itt négy sorban elhelyezett öt-öt adatot tárolhatunk. Az voltaképpen mindegy, hogy melyik méretet
melyik kiterjedésnek tekintjük (tehát jelenthetne öt négyoszlopos sort is), csak az adatok
kezelésekor már következetesen kell tartanunk magunkat az általunk megadott rendszerhez, tehát
bármelyik irányban csak akkora számmal címezhetünk, amekkora a dimenzionáláskor megadott
értékbe belefér. A fenti tömb például hiába 20 elemű, nem hivatkozhatunk például a
TABLAZAT$(4,2) helyre. Ez ugyan akár egy kisebb tömbben is benne lehetne, de a TABLAZAT$
tömbben nincs négyes számú sor (csak nullától háromig, lásd fentebb). A fenti kétdimenziós tömböt
így képzelhetjük el:

Feltöltésére két egymásba ágyazott ciklust használhatunk. Figyeld meg, hogy az adatokat a tömb
szerkezetének megfelelően rendezem el a DATA-sorokban. Ez nem kötelező, ömlesztve is lehetne a
húsz szó, de így jobban áttekinhető:
1 ' ketdimenzios tomb hasznalata
2 '
10 DIM TABLAZAT$(4,5)
20 FOR SOR=0 TO 3
30 FOR OSZLOP=0 TO 4
40 READ TABLAZAT$(SOR,OSZLOP)
50 NEXT OSZLOP
60 NEXT SOR
70 PRINT TABLAZAT$(2,1)
80 DATA "Ancsa","Bella","Cili","Dorka","Elli"
90 DATA "Friderika","Gabi","Hédi","Juli","Kata"
100 DATA "Lola","Manci","Nóra","Olga","Petra"
110 DATA "Rozi","Sári","Tamara","Vera","Zsófi"
A program tehát először feltölti a tömböt a nevekkel, azután a hetvenes sor kiírja az ábrán is jelölt
TABLAZAT$(2,1) tömbelem értékét, amely a Manci név.
Hasonlóan hozhatunk létre háromdimenziós tömböt is, például:
DIM HAZ(10,3,3)
Ezt úgy is képzelheted, mintha három 3*10 méretű táblázatot tettél volna
egymás mögé. Ez jelentheti mondjuk egy nagy ház lakásait. Most a
harmadik kiterjedés a mélységet jelöli. Megfigyelheted, hogy a kockák
száma most fölfelé növekszik. Ezt nem azért rajzoltam így, mert így van,
hanem éppen azt akartam jelezni, hogy a változók tartalmának értelmezése
tőlünk függ. Ha egy ház adatait tároljuk bennük, a tömb magasabb számú
lapjai (itt az első index) emeleteket jelenthetnek, talajrétegek esetén pedig
egyre mélyebb szinteket, ekkor a tömböt lefelé növekvőnek képzelhetjük
el. Természetesen címzéskor is három adatot kell megadni, mint a képen
kijelölt elemen látható:
PRINT HAZ(5,0,1)
Az utasítás a tömbelemben tárolt számot fogja kiírni, amely lehet példának
okáért a lakás száma. Egy ilyen tömb jól használható például térben
értelmezhető adatok tárolására, mint itt is.
Említettem, hogy a Blassic sajnos nem ismeri a tömbök tól-ig jellegű megadását, de más basicekben
mínusz indexxel értelmesen kezelhető lenne a pinceszintek kérdése is:
DIM HAZ(-2 to 9,3,3)
A Blassicben, ha az egész ház adatait egy tömbben akarnánk kezelni, eszerint egy (12,3,3)
kiterjedésű tömböt kellene definiálni a két pinceszint hozzáadására, és kénytelenek lennénk úgy
tekinteni, hogy a kettes első indexű elemek vannak a földszinten, ami kissé idétlen megoldás.
Az az igazság, hogy amikor a magasságnak nincs kitüntetett szerepe – mint az emeletek esetében –,
akkor térbeli helyek indexeit nem ebben a sorrendben szokás megadni, hanem a mértanban
használatos módon : DIM TOMB(x,y,z)
Az x, y, z

A rajzról leolvasható, hogy a kis lila gömb középpontjával jelzett hely a térben a
TOMB(7,4,5)elemmel célozható meg. Bár ilyen bonyolult dolgokkal egyelőre nem foglalkozunk,
elképzelhető egy olyan program, amely éppen így, egy tömb segítségével tárol egy térrészletet, és
aszerint, hogy a megcélzott kockában mondjuk 0 vagy 1 értéket talál, üresen hagyja az adott
térkockát vagy valamit rajzol belé. A következő kép éppen ilyen módszerrel készült, igaz, hogy nem
basic, hanem POV-Ray nyelven, amely kifejezetten térbeli rajzolásra való:

Itt tehát egy tömböt töltöttem föl véletlenszerűen 0 és 1 értékekkel. A


program ezután végigolvasott minden elemet, és ahol nullánál nagyobb
értéket talált, ott a tömbindexeket egyben a golyók helyének
meghatározására is felhasználva kirajzolt egy-egy gömböcskét. Ahol a
golyók sűrűbben helyezkednek el, jól kivehetők a (10,10,10) méretű
háromdimenziós tömb határai.

Az adatok áttekinthetetlensége miatt a gyakorlatban ritkán használják ki, de alkalmazhatunk még


több dimenziós tömböket is. Ezekről valahol olvastam azt a lemondó véleményt, hogy ezeket már
úgysem tudjuk szemléletesen elképzelni, így nem is érdemes használni őket, legfeljebb valami
tudományos számításnál, ahol egyáltalán értelme van mondjuk a negyedik dimenziónak. Azonban
nem egészen ez a helyzet. A baj a szerző gondolkodásával van, aki az iménti rajzokhoz hasonlóan
mindenképpen térbeli irányként akarja elképzelni a megadott dimenziókat. Vegyük viszont a
következő példát: Egy nagy egyetem hármas számú épületében, a tizenötödik terem negyedik
szekrényében, a második polcon lévő tizenhetedik könyv érdekel bennünket. Ezt egy rafinált
nyilvántartó rendszerben egy ilyen tömbbejegyzés jelképezheti: KONYV$(3,15,4,2,17)
Ez bizony, akárhogy nézzük, egy ötdimenziós tömb egyik eleme, és – ha a rendszert ismerjük –
egyáltalán nem nehéz elképzelnünk, hogy mit jelent, mint ahogyan magában az adatban sincs
semmi csodálatos, az egy egyszerű szövegváltozó, mondjuk A két Lotti vagy Mesék Mátyás
királyról. Ez a példa elég szerencsésen rámutat arra, hogy érdemes néha a dolgokat a megszokottól
eltérő szemszögből is megvizsgálni, hátha nem is a világ bonyolult, csak mi vagyunk
tökkelütöttek...

You might also like