Nazdar všichni!
Tak po delší odmlce, kterou způsobyl nákup mého Pegasose jsem opět zde, a píšu v pořadí již pátý
tutoriál. Už ne na Amize, nýbrž na Pegasosovy, ale nemyslim, že byste to poznali :) Po shlédnutí
konce minulého tutoriálu jsem zjistil, že jsem na sebe ušil pěknou boudu, protože musím popsat
soubory a requestery. No co, hurá do toho, a půl je hotovo ;)
Soubory:
Jak začít. Soubory jistě každý z vás zná, takže jen pro úplnost doplním, že v podstatě jsou dva
typy souborů, binární, a textový. Textový je obvikle dělaný tak, aby si v něm mohl člověk číst, a
binární tak, aby si v něm mohl číst zase počítač. Záleží jen na vás, co vám bude víc vyhovovat ve
vašich programech. Binární soubory se obvikle zpracovávají mnohem rychleji, a snáze, než soubory
textové, ale to si všechno vysvětlíme později. Nejdřív si nejaký ten soubor musíme vytvořit. V
PowerD k tomu není žádna funkce, protože se na to krásně hodí systémová funkce "Open" z
dos.library. Ta má dva parametry, prvním je název souboru, a tím druhým je zpusob, jakým budeme
k souboru přistupovat:
DEF soubor
soubor:=Open('ram:soubor',NEWFILE)
Z tohoto výpisu je zřejmé, že než si nejaký ten soubor vytvoříme, nebo otevřeme, musíme pro něj
mít nějakou tu proměnnou, v tomto případě je to proměnná "soubor". Hned potom můžeme soubor
otevřít, či vytvořit. V příkladě se otevírá soubor jménem 'ram:soubor', a přistupujeme do něj
jako do nového souboru (NEWFILE), což znamená, že se ten soubor vytvoří! Pokud již soubor stejného
jména existuje, bude nemilosrdně přepsán. Pokud chcete otevřít již existující soubor, stačí místo
konstanty NEWFILE použít konstantu OLDFILE, která se pokusí soubor s daným názvem otevřít pro
čtení. Takže NEWFILE se používá pro zápis souboru na disk, a OLDFILE se používá pro čtení souboru
z disku. Po pokusu o otevření/vytvoření souboru je nutné otestovat, jestli se soubor opravdu
povedlo otevřít/vytvořit. Protože takový soubor nemusí být na disku, nebo se můžete pokoušet
zapsat soubor na disk, který je chráněn proti zápisu atd. Takže:
IF soubor<>NIL
to za nás udělá. Dojde-li totiž k chybě, vrací funkce Open nulu, neboli konstantu NIL. Takže pokud
se soubor nerovná nule, můžeme s ním pracovat. K tomu nám slouží tři základní funkce, Read, Write
a Seek. Přičemž funkce Read lze použít pouze při otevření souboru pomocí OLDFILE, a Write pouze
při vytvoření souboru pomocí NEWFILE. Jedině funkce Seek se dá použít v obou případech.
Funkce Write zapisuje data do souboru. Tato funkce má tři argumenty, první je vždy soubor, do
kterého se zapisuje, druhý argument obsahuje data, která se musí zapsat, a třetí argument je počet
bajtů, který se má z daných dat uložit. Pokud ukládáme text, je to počet znaků, které se uloží do
souboru:
Write(soubor,'Nazdar lidi!\n',STRLEN)
Tento příkaz zapíše do souboru daný text, ale pozor, musíte zadat správnou délku tohoto textu. To
za vás částečně reší PowerD svou speciální konstantou STRLEN, která vždy obsahuje délku posledního
použitého stringu, pokud použijete místo přímého zadávání textu proměnnou, tato konstanta již
nefunguje, a musí se použít:
Write(soubor,string,StrLen(string))
Kde string může obsahovat libovolný text, a takto bude uložen o celé své délce. Funkci Write
můžeme používat úplně pro všechny způsoby zápisu, jak text, tak binární data. Protože ale tato
funkce potřebuje "pole", ze kterého má zapsat určitý počet počet bajtů, nemůžeme použít proměnnou
s číslem přímo, ale musíme použít jeho adresu:
DEF cislo=1234
Write(soubor,&cislo,4)
Tato funkce uloží do souboru binárně číslo 1234, které bude mít 4 bajty, neboli long. Funkci Write
lze používat opakovaně dle potřeby. Jsou-li všechny zápisy do souboru hotové, musíme soubor
zavřít. To uděláme následovně:
Close(soubor)
Pokud soubor není správně uzavřen, nebude soubor přístupný ke čtení přinejmenším do resetu
počítače, v horším případě (FFS) dojde po restartu k validaci disku, v lepším případě (SFS/PFS...)
bude po resetu všechno v pořádku a v souboru bude zapsáno to, co jsme do něj zapsali, takže
nezapomínejte za sebou soubor vždy zavírat. Toto všechno byly funkce, které lze provádět pouze v
případě, že se nám povedlo soubor vytvořit, což nám zajišťuje řádek s "IF soubor<>NIL". Nyní, když
jsme soubor zavřeli, musíme ještě ukončit tuto podmínku:
ENDIF
Takže prográmek, který nám zapíše text do souboru vypadá asi takto:
PROC main()
DEF soubor
soubor:=Open('ram:soubor',NEWFILE)
IF soubor<>NIL
Write(soubor,'Nazdar lidi!',STRLEN)
Close(soubor)
ENDIF
ENDPROC
Pokud jde o čtení souboru, je použití velice podobné, jenom namísto konstanty NEWFILE použijeme
konstantu OLDFILE. Hned po otevření souboru musí opět následovat test, jestli se opravdu povedlo
soubor otevřít, pokud ne, nesmíme se pokoušet z něj číst, pokud ano, můžeme pokračovat, se čtením
ze souboru je to krapet složitější, než se zápisem, protože je potřeba si hlídat mnohem víc věcí.
Tak předem musíte vedět, kolik toho budete ze souboru vlastně načítat. Nejjednodušší cesta je, si
do paměti načíst kompletní soubor, k tomu ale potřebujeme paměť, do které se nám celý soubor
vejde. To se dá udělat v PowerD snadno použitím funkce FileLength, která vrací délku souboru v
bajtech:
DEF len
len:=FileLength('ram:soubor')
Tato funkce bude zapíše do proměnné len délku souboru 'ram:soubor'. Pokud se soubor nepodaří
otevřít, vrací zápornou hodnotu. Teď je na řadě si alokovat dostatek paměti, aby jsme do ní mohli
soubor pěkně načíst k tomu slouží v PowerD funkce New:
DEF pamet:PTR TO BYTE
pamet:=New(len+1)
Tato funkce alokuje blok počítačové paměti o velikosti len+1. Pokud se alokace nezdaří (třeba
kvůli nedostatku paměti), vrací funkce New nulu, naboli NIL, takže s alokovanou pamětí můžeme
pracovat pouze v případě, že se alokace podařila:
IF pamet<>NIL
Takže nyní máme alokovanou paměť o správné délce, do které nyní můžeme načíst data ze souboru:
DEF nacteno
nacteno:=Read(soubor,pamet,len)
pamet[nacteno]:="\0"
Funkce Read přečte ze souboru "soubor" "len" bajtů, a uloží je do paměti, jejíž ukazatel jsme
uložili do proměnné "pamet". Jistě jste si všimli, že to ještě není všechno, že je tam ještě jedna
věc, a to je použití proměnné "nacteno", do které funkce Read uloží počet bajtů, které načetla
ze souboru do paměti. Pokud je všechno v pořádku, musí se hodnoty "len" a "nacteno" rovnat, jestli
ne, pravděpodobně je soubor kratší, než je udávaná délka pro načítání, nebo došlo k chybě při
načítání z disku, zkrátka nebylo možné načíst všechny bajty, jak bylo zadáno. Pak ještě následuje
ukončení stringu, protože funkce Read načte přesně ten počet bajtů, který jsme zadali, a tudíž
není tento string korektně ukončen nulovým bajtem. To je také důvod, proč jsme alokovali len+1
bajtů, a ne jen len bajtů. Prostě jsme si udělali místo na tento nulový bajt. Takže poslední znak
vynulujeme. Takže zadáme ještě jednu podmínku:
IF len=nacteno
A pokud je tato podmínka splněna, máme jistotu, že všechno klaplo, a v proměnné "pamet" máme
kompletní obsah souboru "ram:soubor". A vzhledem k tomu, ze tento soubor obsahuje pouze text,
který jsme tam zapsali minulým příkladem, můžeme si vz pekně vypsat:
PrintF('Soubor obsahuje text: "\s"\n',pamet)
Teď už zbývá jen korektně uzavřít všechny podmínky, a uvolnit pameť, kterou jsme si alokovali, to
provedeme pomocí funkce Dispose, která je opakem funkce New, tedy že uvolní paměť, kterou jsme
alokovaly. Ukazatel na tuto paměť musí být argumentem této funkce, a protože ukazatelem je právě
proměnná "pamet", zadáme jako argument právě ji:
Dispose(pamet)
A nakonec ještě zavřít za sebou soubor, pomocí funkce Close, stejně, jako u zápisu do souboru a
prográmek je hotov:
PROC main()
DEF soubor
soubor:=Open('ram:soubor',OLDFILE)
IF soubor<>NIL
DEF len
len:=FileLength('ram:soubor')
IF len>0
DEF pamet:PTR TO BYTE
pamet:=New(len+1)
IF pamet<>NIL
DEF nacteno
nacteno:=Read(soubor,pamet,len)
pamet[nacteno]:="\0"
IF len=nacteno
PrintF('Soubor obsahuje text: "\s"\n',pamet)
ELSE PrintF('chyba pri nacitani souboru!\n')
Dispose(pamet)
ELSE PrintF('nedostatek pameti!\n')
ENDIF
Close(soubor)
ELSE PrintF('soubor se nepovedlo otevrit!\n')
ENDPROC
Je vidět, že je to už krapet složitější, ale není v tom nic, co by se člověk nedočetl v
dokumentaci k dos.library. Jestě jsem dodělal maličké vylepšení, které v případě, že nastane
chyba vypíše chybové hlášení, to jsem udělal záměnou "ENDIF" za "ELSE", které je následováno
funkcí, která se provede, není-li splněna podmínka "IF", k němuž "ENDIF" patřilo.
Requestery:
Další na řadě jsou requestery. To je jednoduché, ale nejdřív něco teorie pro ty, kteří nevědí o co
jde. Requestery jsou informační okna, která obsahuji nejaký text, a obyčejně i volbu, kterou nám
počítač dává na výber. V systému se s nimi setkáváte pořád, ale jak si takový requester vytvořit?
To si pravě teď vysvětlíme. Ke všemu nám stačí jediná funkce EasyRequestArgs. Je to funkce
intuitionu, takže se o nic nemusíte starat, protože PowerD si knihovnu intuition.library otevírá
automaticky. Detailní informace o této knihovně se dozvíme v autodokumentaci k intuitionu.
EasyRequestArgs(NIL,[20,0,'uff','bla bla','bezva'],NIL,NIL)
Tohle je v podstatě nejjednodušší requester, jaký si můžeme vytvořit. Při spuštění této funkce se
otevře okno, které bude mít název 'uff', uvnitř bude zpráva 'bla bla', a dole bude tlačítko s
nápisem 'bezva'. Docela jednoduché, že? Ale teď detailněji. První NIL, je argument okna, pokud
totiž udete chtít otevřít requester na vlastní obrazovce, budete muset místo tohoto prvního NIL
použít ukazatel, na okno dané obrazovky, jinak se otevře na Workbenchi. Pak následuje pole, které
musí obsahovat pět položek. První dvě musí být pořád stejné, a to 20 a 0. Pokud vás tyto hodnoty
zajímají blíže, podívejte se na autodokumentaci k této funkci. Další položkou v tomto poli je
titul requesteru, dalším je text, který bude obsažen v těle okna, a poslední je seznam tlačítek,
které v okně budou. Pak je tam další NIL, které vás také zatím nemusí zajímat, a poslední NIL,
které by mělo obsahovat seznam arguemntů, které chceme použít v těle okna a v tlačítkách. Použití
je stejné, jako u funkce PrintF. Co se týče textu, který bude obsažen v okně, lze používat znaky
pro odřádkování, abyste se dostali na další řádek jako pomocí PrintF('\n'), takže:
EasyRequestArgs(NIL,[20,0,'uff','ahoj\n\s','bezva'],NIL,['vole'])
Otevře requester s názvem "Uff", a okno bude obsahovat text o dvou řádcích, kde na prvním bude
"ahoj", a na druhém bude "vole". Určitě si ale budete chtít vytvořit třeba requester s několika
tlačítky. To se udělá velice snadno, místo textu 'bezva' použijete třeba 'bezva|nikdy', a hnedle
bude mít okno dvě tlačítka, kde levé bude osahovat text "bezva", a pravé "nikdy":
EasyRequestArgs(NIL,[20,0,'hlaska','chces pokracovat?','ano|ne'],NIL,NIL)
Tento příkaz otevře okno s názvem "hlaska", s textem "chces pokracovat?", a dá vám na výběr dvě
možnosti, buď "ano", nebo "ne". Teď už zbývá jen rozlišit, jaké tlačítko jsme si zvolili, a podle
toho pokračovat v programu:
DEF volba
volba:=EasyRequestArgs(NIL,[20,0,'hlaska','chces pokracovat?','ano|ne'],NIL,NIL)
Ano správně. Funkce EasyRequestArgs vrací hodnotu, a touto hodnotou je právě tlačítko, které jsme
si zvolili. Ale pozor, první tlačítko vrací číslo 1, druhé tlačítko vrací číslo 2, atd, ale
poslední tlačítko vrací číslo 0, takže pokud zvolíme "ano", bude proměnná "volba" obsahovat číslo
1, ale pokud zvolíme tlačítko "ne", bude proměnná "volba" obsahovat číslo 0.
PROC main()
DEF volba
volba:=EasyRequestArgs(NIL,[20,0,'hlaska','co chces?','pomerance|rajcata|svestky|nic'],NIL,NIL)
SELECT volba
CASE 1 PrintF('pomerance???\n')
CASE 2 PrintF('proc rajcata?\n')
CASE 3 PrintF('svestky jsou dobra volba ;)\n')
CASE 0 PrintF('taky dobry...\n')
ENDSELECT
ENDPROC
Tak. To by pro dnešek stačilo. Příště si konečně řekneme něco o polích, a uvítal bych, kdybyste
se mi ozvali, a řekli mi, co by vás zajímalo, abych o tom něco mohl napsat. Můj email je
mark@tbs-software.com.
Baj, MarK.