Úvod
Jak jsme si řekli na konci minulého tutoriálu, tak v tomto tutoriálu budeme probírat smyčky a
podmínky. Pro ty z vás, kdo neví, o co jde dám malé vysvetlení. Vetšina programů dělá jednu věc
pořád dokola, akorát se mění nějaké hodnoty. Třeba CLI příkaz LIST. Ten si nejdřív načte adresář
a pak ho zobrazí. To může vypadat jako dvě operace. Ve skutečnosti je to mnohem složitější. Tento
příkaz musí načíst všechny soubory, a to jeden za druhým, a pak je všechny, a to jeden za druhým
vypsat do CLI. To už jsou dvě smyčky. Dá se z nich udělat jedna, která soubor načte, a hned ho
vypíše, ale o to nám tu teď nejde. Smyčka je prostě jen to, že program bude vykonávat nějakou
operaci opakovaně. Tak a teď se můžeme vrhnout na několik způsobů, jak smyčky používat. Pro
jednoduchost je naším jediným cílem, aby jsme do CLI vypsali 10x text "Hello world". Během tohoto
i všech dalších tutoriálů se bude objevovat spousta věcí, které bude potřeba vysvětlit podrobněji,
nebo jiné věci, které bude potřeba vysvětlit jen povrchově, ale k těm se v dalších částech ještě
vrátím, a popíší je podrobněji, podle potřeby. Takže mohu jen doporučit číst texty celé, protože
jinak se vystavujete riziku, že nebudete chápat, proč děláte to a to a začnete mít ve všem tom
programování pěkný zmatek. Dále ještě musím zopakovat informaci o tom, že PowerD vyžaduje u všech
klíčových slov a názvů funkcí, či proměnných dodržovat velikosti písmen, jinak vypíše při
kompilaci chybové hlášení.
FOR
Příkaz FOR zná snad každý z Basicu. Ani v PowerD se tolik neliší, nicméně pro úplného
začátečníka je potřeba vysvětlit, jak FOR uvést do chodu. Stejně, jako v Basicu potřebujete
nějakou proměnnou, která se bude po každém provedení smyčky přičítat o jedničku. Tady je ale
první rozdíl oproti Basicu. Tu proměnnou si totiž musíte nejdřív vytvořit. Když si chcete
vytvořit proměnnou třeba "a", tak prostě napíšete "DEF a". Pokud byste na toto zapoměli, tak
by vám kompilátor při kompilaci sdělil, že proměnná "a" neexistuje. No, a abysme si 10x
vypsali požadovaný text, stačí napsat nasledující prográmek:
PROC main()
DEF a
FOR a:=1 TO 10
PrintF('Hello world\n')
ENDFOR
ENDPROC
Z minulého tutoriálu již dobře známá procedura "main". Pak následuje definice proměnné "a", a
pak již naše vlastní smyčka. Všimněte si tam té dvojtečky před znaménkem "=". Tady se dostáváme
k dalšímu rozdílu oproti Basicu. PowerD používá operátor ":=" jako přiřazovací operátor, což
znamená, že to, co je na pravé straně tohoto operátoru se zapíše do toho, co je na levé straně
tohoto operátoru. Takže zapíšeme jedničku do proměnné "a". Naproti tomuto přiřazovacímu znaménku
zná PowerD ješte samotné znaménko "=", ale to je pouze porovnávací operátor. To si vysvětlíme u
jedné z dalších smyček. Pro vás je důležité, že pokud chcete něco zapsat do nejaké proměnné,
musíte k tomu použít operátor ":=" (samozřejmě, že bez těch uvozovek :).
Pak následuje klíčové slovo "TO", za kterým je maximální hodnota, které v této smyčce proměnná
"a" dosáhne. Pokud proměnná "a" tuto hodnotu překročí, bude smyčka na jejím začátku ukončena. Z
toho vyplívá, že tato smyčka vypíše jedno "Hello world" pro a=1, další "Hello world" pro a=2 a
tak dále, až po a=10, po němž se smyčka ukončí, a program bude pokračovat dále.
Pak následuje samotné vypsání textu, a nakonec ukončení smyčky. V Basicu se běžně používá
klíčové slovo "NEXT", ale v PowerD se používá klíčové slovo "ENDFOR". Výsledek je stejný.
Teď už jen zbývá si váš prográmek uložit, zkompilovat ho a pak už jen spustit :) Pokud jste
všechno provedli správně, měl by vám do CLI vypsat toto:
Hello world
Hello world
Hello world
Hello world
Hello world
Hello world
Hello world
Hello world
Hello world
Hello world
Pokud je vše jasné, můžeme se vrhnout na další smyčku, a tou je WHILE.
WHILE
Chceme, aby náš prográmek udělal úplně to samé, jako ten s příkazem FOR, jen k tomu použijeme
smyčku WHILE. Smyčka WHILE je již podmínková smyčka. To znamená, že pokud se má provése, musí
být splněna nějaká podmínka. Naše podmínka bude, že čislo musí být menší, nebo rovno deseti.
Nyní výpis prográmku, pak jeho detailní popis:
PROC main()
DEF a
a:=1
WHILE a<=10
PrintF('Hello world\n')
a++
ENDWHILE
ENDPROC
První řádek obssahuje, jak jinak, definici procedury "main". Pak, jako u první ukázka následuje
definice proměnné "a". Na dalším řádku přiřadíme do proměnné "a" hodnotu 1, což je výchozi
hodnota naší smyčky. Pak již následuje vlastní smyčka WHILE následovaná podmínkou. Tato podmínka
je "a<=10". Pokud je tato podmínka splněna, provede se obsah smyčky. Pokud tato podmínka není
splněna, smyčka skončí, a program bude pokračovat za smyčkou. Takže v doslovném překladu do
češtiny to znamená: "proveď příkazy ve smyčce, pokud je proměnná "a" menší, nebo rovna deseti".
Na dalším řádku je již dobře známé vypsání textu. Tak, jako se ve smyčce FOR zvyšuje obsah
proměnné "a", je potřeba to samé provést i zde, ale smyčka WHILE nic takového nedělá (což není
vůbec potřeba), takže si to musíme udělat sami. A to dělá řádek "a++". Myslím, že každý uhodne,
že operátor "++" přičte jedničku k proměnné, která je vlevo od tohoto operátoru. Klidně si tento
řádek můžete nahradit řádkem "a:=a+1", což dělá to samé, tedy že do proměnné "a" uloží obsah
proměnné "a" zvětšený o jedničku. Pak již následuje pouze konec smyčky ENDWHILE a úplný konec
procedury ENDPROC. Po úspěšné kompilaci a spuštění tohoto prográmku dostanete stejný výsledek
jako u předchozí ukázky.
REPEAT-UNTIL
Smyčka REPEAT-UNTIL je vlastně opakem smyčky WHILE. Za prvé je podmínka definovaná až na konci
této smyčky, to znamená, že i když podmínka smyčku ukončí, pořád se alespoň poprvé provede. Další
změna je ta, že tato smyčka se bude provádět, dokud nezačne platit daná podmínka. Takse je to
vlastně nekonečná smyčka, která se ukončí, až začne platit podmínka. To znamená, že dokud podmínka
neplatí, bude se smyčka provádět. Nyní ukázka:
PROC main()
DEF a
a:=1
REPEAT
PrintF('Hello world\n')
a++
UNTIL a>10
ENDPROC
Začátek je stejný, jako u předchozí ukázky, takže popis přeskočíme. První zmena je klíčové slovo
REPEAT. Tento příkaz začína smyčku, kterou chceme provádět. V této smyčce jsou prováděné příkazy,
jako v minulé ukázce je to vypsání textu a příčtení jedničky k proměnné "a". Pak následuje již
konec smyčky včetně podmínky ukončení. Takže se smyčka ukončí, pokud obsah proměnné "a" bude
větší, než číslo 10. Dokud je proměnná "a" menší, nebo rovna desítce, bude smyčka pokračovat. Po
jejím ukončení bude program pokračovat dále. Výsledek je opět totožný se obouma předcházejícíma.
LOOP
Smyčka LOOP je takzvaná nekonečná smyčka. To znamená, že se bude opakovat neustále. Samozřejmě
ale existuje možnost, jak tuto smyčku ukončit, a tím pádem ji můžeme ukončit třeba po deseti
opakováních, což znamená, že s ní můžeme udělat totéž, co u všech třech předchozích ukázkách.
PROC main()
DEF a
a:=1
LOOP
PrintF('Hello world\n')
EXITIF a=10
a++
ENDLOOP
ENDPROC
Myslím, že není potřeba popisovat vše opět tak do detailu. Vrhmene se na to důležité. Určitě vám
je jasné, že vše, co je mezi klíčovými slovy LOOP a ENDLOOP se bude provádět stále dokola. Nicméně
tam přibil ještě jeden podmínkový příkaz. Tim je EXITIF, což v doslovném překladu znamená "opustit,
jestliže". A v tomto případě to znamená "opustit smyčku LOOP, jestliže se proměnná "a" rovná 10".
Takže tento příkaz ukončí smyčku, pokud je splněna podmínka. Pokud podmínka není splněna, nic se
neděje, a program pokračuje na dalším řádku, takže na řádku "a++". Tady je také vidět ten výše
uvedený rozdíl mezi ":=" a "=". Samotné znaménko "=" nic nikam nezapisuje, pouze nám sdělí, jestli
jestli se pravá a levá strana tohoto operátoru rovnají. Pokud ano, je vrácena hodnota TRUE (-1)
(pravda), a pokud ne, je vrácena hodnota FALSE (0) (nepravda). Toto je možné použít i při jiných
podmínkách, jako třeba "a<=3", která vrací TRUE, je-li proměnná "a" menší, nebo rovna třem, a
která vrací FALSE, je-li proměnná "a" větší, než tři.
JUMP
Toto vlastně ani není smyčka, ale pouhé skákání v programu. V Basicu se ale hojně používá
(GOTO). V PowerD se používá více-méně stejně, jen se jinak jmenuje: JUMP. Použití je snadné, stačí
si někde v proceduře nadefinovat návěstí jako třeba "hop_sem", a přidat ze něj dvojtečku, aby
PowerD poznalo, že jde o návěstí. A pak už kdekoliv v této proceduře stačí napsat "JUMP hop_sem"
a program skočí na to návěstí.
PROC main()
DEF a
a:=1
smycka:
PrintF('Hello world\n')
a++
IF a<=10 THEN JUMP smycka
ENDPROC
Začátek je jako obvykle stejný. Pak následuje definice návěstí "smycka". Potom obvyklé vypsání
textu a přičtení jedničky v proměnné "a". Další řádek obsahuje jeden z nejdůležitějších
podmínkových příkazů, a sice IF. IF znamená v doslovném překladu "jestli". Takže přímí překlad
toho řádku zní "jestli je proměnná "a" menší, nebo rovna deseti, tak skoč na návěstí "smyčka"".
Klíčové slovo THEN znamená v tom mém překladu to slovo "tak", v přímém překladu to znamená "pak"
nebo "potom". Je to vlastně úplně stejné jako v Basicu. Jen pro úplnost musím dodat, že za THEN
můžé následovat jediný příkaz, který se provede, pokud platí daná podmínka (v tomto případě:
"a<=10"). Pokud podmínka neplatí, program bude pokračovat na dalším řádku. Takže dokud je "a"
menší, nebo rovno deseti, bude se smyčka opakovat.
A teď něco trošičku složitějšího:
Rekurze
Rekurze není klíčové slovo, je to pouze název toho, co v této ukázce budeme provádět. Podobně,
jako byl úkol v minulém tutoriálu, i zde použijeme dvě funkce. Z nich si jedna funkce volá funkci
druhou, a ta si pak volá sebe sama. Neztrácejte naději, všechno vysvětlím! Jako u všech ukázek v
tomto tutoriálu chceme zase vypsat desetkrát náš velmi oblíbený text "Hello world". Pomocí rekurze
to uděláme následovně:
PROC main()
hello(10)
ENDPROC
PROC hello(a)
IF a=0 THEN RETURN
PrintF('Hello world\n')
hello(a-1)
ENDPROC
Jako obvykle si vytvoříme proceduru "main". Z té potom voláme naší novou funkci, kterou jsem
nazval "hello", a která má jeden argument. V definice této procedury vidíme, že tento argument
se jmenuje "a". Ano, je to to samé "a" jako v předchozích ukázkách, s tím rozdílem, že jsme
ho nedefinovali jako samotnou proměnnou pomocí "DEF a", ale že jsme ho definovali jako argument
funkce (=procedury) "hello". Pro vysvetlení: Když zavoláme funkci hello(10), tak se ta desítka
nakopíruje do tohoto argumentu "a", takže je to to samé, jako bysme napsali: "DEF a" a pak
"a:=10". Jenže do takovéto proměnné nemůžeme zapisovat žádné hodnoty v nadřazených procedurách,
kdežto argumenty můžeme nastavovat podle libosti. (vysvětlení: nadřazená procedura je ta
procedura, ze které je volána aktuální procedura. Takže pokud procedura "main" volá proceduru
"hello", je "main" nadřazená proceduře "hello" atd.) Takže když zavoláme hello(10), spustí se
procedura "hello" a argument "a" se nastaví na hodnotu 10. Další důležitou záležitostí u rekurze
je fakt, že když voláme funkci ze sebe sama (jako v naší ukázce, kde voláma fuznkci "hello" na
konci funkce "hello"), tak se obsahy všech promenných, které jsou definovány uvnitř těchto funkcí
nijak nezmění, i když s nimi volaná funkce pracuje a mění je. Toliko (zatím) k rekurzi. Nyní k
vlastnímu popisu.
Jako v minulé ukázce zde použijeme podmínkový příkaz IF. A sice "jestliže se "a" rovná nule,
tak skonči proceduru". Ano správně, klíčové slovo RETURN okamžitě ukončuje proceduru, ve které
je spuštěno. To znamená, že jestliže se "a" nerovná nule, může program vesele pokračovat, a
protože jsme volali funkci pomocí hello(10), je proměnná "a" nastavena na hodnotu 10. To znamená,
že můžeme pokračovat na dalším řádku. Tam se vypíše náš text. Na dalším řádku se opět volá funkce
"hello", nyní ale s argumentem: hello(a-1). A protože "a" obsahovalo desítku, bude další funkce
"hello" volána s argumentem: hello(9), protože 10 - 1 je 9 :) Takže teď jsme opět na začátku
funkce "hello", ale nyní se "a" rovná 9. Vše se provádí stále do kola, ale pokaždé je argument "a"
zmenšen o jedničku. No, a až bude argument "a" roven nule, dojde konečně na klíčové slovo RETURN
a tím na předčasné ukončení procedury. Tato procedura (s "a" rovno nule) se vrátí do procedury,
která ji volala, tedy do procedury s "a" rovno jedné. Ale protože v této proceduře je již pouhé
ENDPROC, je i tato procedura ukončena a vrací se do procedury, která ji volala, to znamená, že se
vrací do procedury s "a" rovno dvěma. A tak dále, až se dostaneme zpět do procedury, kterou volala
funkce "main" a ta se na svém ENDPROC vrátí do procedury "main" a tam již čeká pouhé ENDPROC, aby
mohl program skončit. To jest vše.
Myslím, že jsme si v tomto tutoriálu užili smyček až až, takže v příštím již nějaké to
"opravdové" programování, kde to všechno, a ještě mnoho navíc zamotáme dohromady.
Pokud Vás tenhle článek zaujal, a máte hromadu dotazů, tak se mi ozvěte na martinkuchinka zavinac seznam tecka cz,
a já už z Vás programátory udělám.