# Moje malé muzeum > BASIC > Expresní kurs BASICu
 

Kdysi dávno jsem asi dva roky vymýšlel co možná nejstručnější návod na programování v QBASICu. Hlavní příkazy, jak to funguje, prostě úplný základ pro člověka který si chce rychle napsat jednoduchý prográmek pro vyřešení nějaké úlohy (tedy to, k čemu byl BASIC od začátku určen) a neví jak. Párkrát jsem se pokusil něco napsat, ale celkem bez valného výsledku. Až mě konečně jednoho dne popadl záchvat tvořivosti a během odpoledne jsem to sepsal. Původně jsem si myslel že by se to mohlo vejít tak na čtyři stránky, ale někde na páté nebo šesté jsem uznal, že osm stran je tak akorát :) Takže ve stručnosti pár rad a zkušeností od amatéra:

Expresní kurs BASICu
--------------------------------

BASIC (bejzyk) je zkratka z názvu "Beginners All purpose Symbolic Instruction Code", neboli "Všeobecný symbolický instrukční kód pro začátečníky". Vznikl počátkem šedesátých let a šířil se od roku 1964 jako prostředek pro zadávání jednoduchých programů přímo uživatelem z terminálu. Obešlo se tím náročné a zdlouhavé překládání programů do strojového kódu.
Největšího rozšíření ale dosáhl až s rozmachem osmibitových domácích počítačů na konci sedmdesátých a začátku osmdesátých let, které měly BASIC takřka bez vyjímky v základním vybavení, takže příkazový řádek byl pro většinu tehdejších nadšených uživatelů první věc se kterou se po zapnutí počítače setkali.
Příkazy BASICu jsou anglická slova nebo jejich zkratky, například PRINT (tiskni) píše na obrazovku - to je pozůstatek z doby, kdy se s velkými počítači komunikovalo přes elektrický psací stroj či dálnopis, INPUT (vstup) zase umožňuje uživateli pomocí klávesnice vložit údaje pro zpracování a CLS je zkrácené CLear Screen, neboli vyčisti (vymaž) obrazovku.
BASIC umí pracovat se dvěma druhy dat, s čísly a řetězci. Co jsou čísla není třeba vysvětlovat, řetězec je sled znaků, prostě nějaký text. Každý znak je v paměti uložen jako číslo od 0 do 255, např. A je 65, a je 97, á je 160. Obvykle se pro jejich kódování používá tabulka ASCII (American Standard Code for Information Interchange).
Čísla se do programu zadávají přímo, řetězce musí být v uvozovkách aby si je počítač nepletl s názvy proměnných, takže 123 je číslo, "Ahoj" je řetězec, ale "456" je také řetězec, protože je v uvozovkách.


Proměnné a konstanty
----------------------

Proměnná je místo v paměti, kam si program ukládá data se kterými pracuje. Kostanty jsou údaje zapsané přímo v programu a nelze je při jeho běhu měnit. Hodnoty se do proměnných vkládají příkazem LET (ať).
LET x = 10 vloží do proměnné s názvem x číslo 10.
LET y = 3 * x vynásobí obsah proměnné x třemi a výsledek uloží do proměnné y. Čísla 3 a 10 jsou tedy konstanty, názvy x a y zastupují v programu proměnné stejně jako písmena ve vzorcích nebo matematických rovnicích.
Názvy proměnných mohou být písmena nebo slova, mohou obsahovat i číslice ale začínat musí vždy písmenem, nesmí v nich být mezery ani písmena s čárkami a háčky a nesmí být shodná s příkazy BASICu. Například:
LET cislo1 = 28.4
LET cislo2 = -4
LET soucet = cislo1 + cislo2

BASIC používá desetinnou tečku místo čárky, znaménko pro sčítání je +, pro odečítání -, pro násobení * (hvězdička) a pro dělení / (lomítko). Příkaz LET je nejdůležitější ze všech příkazů BASICu, přesto nebo právě proto ho není nutné do příkazového řádku psát. Takže příkaz
alfa = 153.8 má úplně stejný význam jako příkaz
LET alfa = 153.8
To vše byly číselné proměnné, řetězcové proměnné se od nich odlišují tím, že mají na konci názvu znak $ (string). Takže příkazový řádek vypadá třeba takhle:
LET text$ = "Ahoj lidi"
S řetězci se samozřejmě nedají provádět matematické operace, ale je možné je spojovat - "sčítat":
LET a$ = "123"
LET b$ = "456"
LET c$ = a$ + b$

Pozor, proměnná c$ teď obsahuje řetězec 123456 a nikoliv matematický součet. Číselné a řetězcové proměnné nelze míchat, program v takovém případě nahlásí chybu a skončí.


Obrazovka
-----------

Pro výpis na obrazovku slouží příkaz PRINT (tiskni). Je to druhý nejdůležitější příkaz, protože výsledky výpočtů je přeci nutné nějak zobrazit. Takže výše uvedené prográmky by na konec potřebovaly doplnit ještě o tyto řádky, abysme se dozvěděli, co nám vlastně vyšlo:
PRINT soucet
PRINT c$

A aby uživatel věděl co které číslo znamená, šlo by příkazový řádek takto doplnit o komentář:
PRINT "Výsledek sčítaní:"; soucet
Středník mezi údaji způsobí, že se budou vypisovat hned za sebou. Pokud by tam místo něj byla čárka, vypíše se druhá část s odstupem, od sloupce s číslem 15, 29, 43 nebo 57. Pokud první část skončila za 57. sloupcem, pokračuje výpis na dalším řádku.
Když chceme začít na čisté obrazovce, vymažeme ji před začátkem výpisu příkazem CLS (clear screen).
Příkaz PRINT může zobrazit i výsledek nějaké operace, takže
PRINT 145 + 91 / 7
nevypíše matematický výraz, ale pouze jeho výsledek, 158. BASIC "umí" prioritu operátorů, takže násobení a dělení má přednost před sčítáním nebo odečítáním. Proto výsledek operace 1 + 2 * 3 nebude 9 jako na jednoduchých kalkulačkách ale 7 jako na vědeckých kalkulátorech. Pro výstup dat na tiskárnu se používá příkaz LPRINT, který funguje stejně jako PRINT pro obrazovku.


Vstup dat
-----------

Abysme nemuseli pro každý výpočet psát nový program nebo upravovat starý jako v počítačovém pravěku počátku padesátých let, můžeme pomocí třetího nejdůležitějšího příkazu INPUT vkládat čísla i řetězce při běhu programu. Ten pak vypadá třeba takhle:
CLS
INPUT delenec
INPUT delitel
LET podil = delenec / delitel
PRINT podil

U příkazů INPUT se program zastaví, napíše otazník a čeká až uživatel něco napíše a "odentruje". Pokud ten vloží třeba řetězec místo čísla, počítač nahlásí chybu a žádost opakuje.
Mohli bychom také napsat rovnou PRINT delenec / delitel, pokud nebudeme potřebovat výsledek dělení pro nějakou další operaci.
Aby uživatel věděl co má právě napsat, je možné do příkazu vložit komentář v uvozovkách, který se vypíše místo otazníku:
PRINT "Výpočet plochy obdélníku"
INPUT "strana a: ", a
INPUT "strana b: ", b
PRINT "plocha:"; a * b

Chce-li programátor napsat za výzvou otazník, nemusí ho psát do komentáře, stačí před proměnnou místo čárky napsat středník. Je také možné zadávat více údajů najednou, hodnoty se při vkládání musí oddělit čárkou:
INPUT "5 čísel: ", a, b, c, d, e
Když uživatel vloží špatný počet čísel, počítač nahlásí chybu a začne znovu. Stejně jako čísla lze vkládat i řetězce do řetězcových proměnných:
INPUT a$
INPUT "text", t$

Pozor, pokud uživatel napíše do textu čárku, bude jej BASIC brát jako dva různé texty. Takový text by musel být ohraničen uvozovkami. Aby k této chybě nedošlo, je pro vstup textů vhodnější použít příkaz LINE INPUT, který vloží celý napsaný text do proměnné tak jak je a navíc nevypisuje otazník:
LINE INPUT "Napiš větu: ", a$


Cykly a smyčky
----------------

Někdy je nutné část programu nebo výpočtu opakovat několikrát po sobě. Aby se taková část nemusela psát do programu opakovaně, používají se programové smyčky. Je několik možností, například podmíněné větvení, o kterém bude řeč později. Pro předem známý počet opakování cyklu je nejvhodnější příkaz FOR (pro). Ten ale samotný nestačí, ještě jsou k němu potřebné příkazy TO (do), NEXT (další) a někdy STEP (krok):
FOR a = 1 TO 10
  PRINT a
NEXT a

V překladu do češtiny by první řádek říkal: pro proměnnou a opakuj od 1 do 10, druhý vypíše aktuální stav proměnné a, třetí přičte jedničku a zkontroluje jestli už proměnná nepřesáhla stanovenou horní hranici. Pokud ne, vrátí běh programu za příkaz FOR, pokud ano, pokračuje dalším řádkem za příkazem NEXT. Program tedy vypíše pod sebe čísla od jedné do deseti.
Pokud je potřeba jiný krok než 1, použijeme příkaz STEP, který ho určí, takže první řádek by vypadal třeba takhle:
FOR a = 25 TO 0 STEP -2.15
Program teď bude odečítat číslo 2.15 od vstupní hodnoty tak dlouho, dokud se nedostane pod výstupní hodnotu. Pomocí smyček lze počítat třeba třetí mocninu:
PRINT "Výpočet třetí mocniny"
INPUT "číslo: ", x
LET y = 1
FOR a = 1 TO 3
  LET y = y * x
NEXT a
PRINT "výsledek:"; y

Uživatel může předem zadat i počet opakování cyklu, což se použije například při počítání faktoriálu:
PRINT "Výpočet faktoriálu"
INPUT "číslo: ", x
y = 1
FOR a = 1 to x
  y = y * a
NEXT a
PRINT "výsledek:"; y

Posunutí začátků řádků uvnitř smyčky nemá žádný praktický význam, slouží jen k tomu, aby programátor snadno rozpoznal, kde smyčka začíná a kde končí. To je důležité zejména při vkládání smyček do sebe, protože smyčky se nesmí křížit:
PRINT "Malá násobilka"
FOR a = 1 to 10
  FOR b = 1 to 10
  PRINT a * b;
  NEXT b
  PRINT
NEXT a

Rozsáhlejší programy v BASICu jsou obvykle dost dlouhé a nepřehledné nudle řádků, takže každý prostředek, který umožňuje programátorovi lépe se v něm vyznat, je užitečný. O tom bude ještě řeč v dalších kapitolách.
Řídící proměnnou je možné uvnitř cyklu měnit, ale obvykle je to dobrý způsob na "zacyklení" programu, tedy jeho uvrhutí do nekonečné smyčky. Počítač se pak zdánlivě zastaví nebo naopak začne vyvádět psí kusy a běh programu je nutné přerušit klávesou Break. To právě udělá tenhle program:
FOR a = 1 TO 10
  PRINT a;
  a = 5
NEXT a

Místo aby vypsal vedle sebe čísla od 1 do 10, napíše jedničku a po ní bude psát nekonečnou řadu šestek... Dokud mu to někdo neutne nebo nevypne počítač.


Podmínky
----------

Umožňují něco udělat nebo naopak neudělat na základě porovnání výsledku předchozích operací nebo vstupu od uživatele nebo z jiného zdroje. Slouží k tomu příkazy IF (když), THEN (tak) a ELSE (jinak).
INPUT "Zadej x a y: ", x, y
IF x > y THEN PRINT "x je větší než y"
IF x < y THEN PRINT "y je větší než x"
IF x = y THEN PRINT "čísla jsou stejná"

Například když uživatel má po skončení výpočtu určit, jestli program skončí nebo bude počítat znovu:
INPUT "Opakovat? (a/n) ", a$
IF a$ = a THEN RUN ELSE END

Příkaz RUN (běž) spustí program od začátku, příkaz END (konec) ho ukončí dříve než doběhne na konec programového kódu. To je vhodné třeba při použití podprogramů. Porovnávat se mohou proměnné mezi sebou nebo proměnná s konstantou, porovnávat lze i řetězce, což slouží k řazení podle abecedy.
V podmínkách lze použít tyto operátory:
= rovná se
> větší než
< menší než
>=    větší nebo rovno
<=    menší nebo rovno
<>    nerovná se

V QBASICu je navíc možné rozepsat podmínku na víc řádků, takže se do ní vejde víc příkazů i bez skákání:
PRINT "Absolutní hodnota"
INPUT "číslo: ", x
IF x > 0 THEN
  PRINT "číslo je kladné"
ELSE
  x = -x
  PRINT "číslo je záporné, absolutní hodnota je"; x
END IF

Důležité je ukončení podmínky příkazem END IF, jinak bude počítač všechny další řádky považovat za součást podmínky. Pro posunutí počátků řádků platí to samé jako u smyček, zvyšují přehlednost programu, podmínky je také možné vnořovat do sebe, ale nelze je stejně tak jako smyčky křížit.


Podmíněné větvení
-------------------

Pomocí příkazů IF a GOTO (GO - jdi, TO - na) lze běh programu poslat různými cestami. Starší verze BASICu měly očíslovaný každý řádek, řádky se pak podle čísel řadily a postupně vykonávaly. Příkaz GOTO 120 v programu prostě skočí na řádek s číslem 120.
10 INPUT "Zadej x a y ", x, y
20 PRINT x * y
30 INPUT "znovu? (a/n) ", a$
40 IF a$ = "a" THEN GOTO 10
50 IF a$ <> "n" THEN GOTO 30
60 END

Program vypočítá součin čísel x a y, potom se zeptá jestli má pokračovat. Když dostane odpověď a, skočí na řádek 10, když dostane jiný znak který není n, skočí na řádek 30 a ptá se znovu, jinak skončí. V QBASICu není třeba řádky číslovat, vykonávají se prostě tak, jak je programátor napíše po sobě. Aby počítač věděl kam má skočit, vkládají se do programu návěští (label), která se pak uvádějí jako parametr příkazů pro skok. Stejný program by pak vypadal takhle:
start:
  INPUT "Zadej x a y ", x, y
  PRINT x * y
dotaz:
  INPUT "znovu? (a/n) ", a$
  IF a$ = "a" THEN GOTO start
  IF a$ <> "n" THEN GOTO dotaz
END

Návěští je vlastně nějaké slovo na začátku řádku, oddělené od dalšího kódu dvojtečkou, které ukazuje začátek části programu. Platí pro ně stejná pravidla jako pro názvy proměnných, mohou obsahovat čísla ale musí začínat písmenem, nesmí to být příkazy BASICu a nesmí obsahovat mezery a písmena s čárkami a háčky.
V BASICu je možné na jeden řádek zapsat několik příkazů oddělených dvojtečkou (což přispívá k celkové nepřehlednosti programu, takže se nedoporučuje), proto i návěští je odděleno dvojtečkou od dalšího příkazu, který může být na stejném řádku:
label1: PRINT "Tady jsem!"
Do příkazu pro skok se proto samozřejmě dvojtečka nepíše. Příkaz GOTO použitý jen tak bez podmínky je další dobrý způsob jak program zacyklit. Proto je při jeho používání potřeba dost opatrnosti, jinak může program skončit tím, že bude skákat tam a zpátky bez rozumného výsledku a bez konce.


Podprogramy
-------------

Někdy se stává, že stejný postup (algoritmus) výpočtu se opakuje na několika místech programu. Takovou část programu lze uložit odděleně, obvykle za příkazem END, a z oněch míst ji volat příkazem GOSUB (go to subroutine). Počítač odtud odskočí do podprogramu, vykoná ho, a když na jeho konci narazí na příkaz RETURN (návrat), vrátí se tam odkud si odskočil a pokračuje dál.
PRINT "Výpočet mocnin a odmocnin"
start:
  INPUT "číslo", n
  INPUT "exponent", e
volba:
  INPUT "1 - mocnina, 2 - odmocnina", v
  IF v = 1 THEN
  GOSUB vypocet
  ELSE
  IF v = 2 THEN
e = 1 / e
GOSUB vypocet
  ELSE
GOTO volba
  END IF
  END IF
  PRINT x
  INPUT "Chceš počítat další? (a/n) ", a$
  IF a$ = "a" then GOTO start
END
vypocet:
  x = n ^ e
RETURN

Znak ^ je operátor pro umocňování, takže n ^ e znamená ne. Používání podprogramů je také jeden ze způsobů jak program zpřehlednit, protože hlavní část programu se tím podstatně zkrátí a jednotlivé procedury je možné naprogramovat a odladit zvlášť, což zkrátí i dobu tvoření programu a hledání chyb. O ladění programu neboli odstraňování chyb bude řeč na závěr.
Podprogram zpracovává stejné proměnné jako hlavní program, takže ten pro něj připraví data která chce zpracovat a dostane zpět výsledky. Podprogram je možné volat i z jiného podprogramu, podobně jako se vnořují smyčky a podmínky.
Podprogram může dokonce volat i sám sebe, to se nazývá rekurze a je to velice silný programátorský nástroj, ale je nebezpečí že po větším počtu vnoření dojde k přeplnění zásobníku kam si program odkládá adresu na kterou se má vrátit a skončí chybou.
Podprogramy musí být uloženy až za hlavním programem ukončeným příkazem END, protože kdyby tomu tak nebylo, počítač by po proběhnutí hlavního programu pokračoval ve vykonávání právě toho podprogramu, který by byl první na řadě a až by narazil na příkaz RETURN, zjistil by že se nemá kam vrátit protože se tam nedostal příkazem GOSUB a skončil by chybovým hlášením.


Pole
------

Pole je zvláštní typ proměnné, která má více položek. Proto je třeba pro něj před jeho použitím vyhradit místo v paměti. To se děje příkazem DIM:
DIM x(24)
FOR a = 0 TO 24
  INPUT x(a)
  IF a = 0 THEN
  min = a
  max = a
  END IF
  IF x(a) < min THEN min = x(a)
  IF x(a) > max THEN max = x(a)
NEXT a
PRINT "nejmenší:"; min
PRINT "největší:"; max

Program si nejprve vytvoří v paměti pole o velikosti 25 prvků (indexy od 0 do 24). Potom do něj uživatel zadá 25 čísel. Nakonec program vypíše nejmenší a největší z nich. Je možné zadat i jiný rozsah indexů podle potřeby, jediná podmínka je, že index musí být vždy celé číslo (prostě nemůže být šuplík číslo pět a půl):
DIM p(-10 TO 10) vytvoří pole s indexy buněk od -10 do 10,
DIM p(50 TO 70) vytvoří pole s indexy buněk od 50 do 70.
Dalším omezením je, že pole se musí vejít do jednoho segmentu paměti, to znamená, že nesmí mít více než 64 KB. Protože jedno číslo zabírá v paměti obvykle 4 bajty, může mít numerické pole maximálně 16384 položky. Pole mohou mít i více indexů, mohou být dvourozměrná, třírozměrná i vícerozměrná, například pole:
DIM a(5, 5, 12, 1, 8) bude mít 6x6x13x2x9 tedy 8424 buňky, a pracovat se s ním bude takto:
LET a(k, l, m, n, o) = -179.5
Stejně jako číselná se používají i řetězcová pole, kde každá buňka obsahuje jeden řetězec libovolné délky:
DIM a$(4, 4)
Takové pole obsahuje pětadvacet řetězců, se kterými je pak možné libovolně pracovat, spojovat je nebo třeba řadit. Ani řetězcové pole nemůže být větší než 64 KB.
Velikost pole už není možné během vykonávání programu měnit, počty buněk zůstávají stejné až do jeho ukončení nebo nového spuštění příkazem RUN, který všechna pole i proměnné vymaže z paměti. Až pak může dojít k nové deklaraci s jinými parametry. Pokud se o to program pokusí dříve, skončí chybovým hlášením.
Stejně tak skončí chybou pokus o vložení čísla do řetězcového pole nebo opačně, právě tak jako u obyčejných proměnných. Pro názvy polí platí to samé jako pro názvy proměnných a návěští, musí začínat písmenem, mohou obsahovat čísla ale nesmí mezery, čárky a háčky a nesmí být shodná s příkazy BASICu.


Příkaz, který nic nedělá
--------------------------

To je příkaz REM (remark - poznámka). Vlastně nic nedělá jen zdánlivě, ve skutečnosti způsobí, že co je na příkazovém řádku za ním, to počítač ignoruje. Může to být libovolný text, čísla, nebo i příkazy, prostě cokoliv:
REM Tady je text.
Příkaz REM je možné nahradit znakem ' (apostrofem), který má pro BASIC stejný význam. Za tento příkaz si může programátor napsat co která část programu dělá, co k svojí činnosti potřebuje nebo jaké budou její výsledky. Může to být také poslední příkaz na řádku, za nímž je popis, co daný řádek provádí. Je to také velice užitečný příkaz při odlaďování chyb v programu:


Odlaďování programu
---------------------

Žádný trochu rozsáhlejší program není možné napsat bez chyb. Ani ten nejlepší profesionál se neubrání omylům, ať v samotné syntaxi příkazů nebo v logické struktuře programu. Na syntaktické chyby obvykle upozorňuje překladač už při psaní programu, použití špatného typu proměnné nebo překřížení smyček vede k ukončení běhu programu chybovým hlášením, ale jsou chyby, které na sebe upozorní až nesprávným výsledkem výpočtu, a dokonce jsou takové, které se vytrvale ukrývají v hloubi programového kódu a projeví se jen při splnění určitých podmínek, obvykle v nejneočekávanějším okamžiku, když už to vypadá že program pracuje bezchybně. Právě takové chyby, které se projevují jen občas, se hledají nejhůře.
U složitějších programů zpracovávajících velké objemy dat ani není možné vyzkoušet všechny možné kombinace vstupních údajů, takže zdánlivě správně pracující program může najednou dostat nevysvětlitelný "záchvat šílenství." Proto je vhodné program tvořit po částech a každou z nich otestovat zvlášť pomocí vhodných dat i vhodných chyb, aby se zjistilo jak na ně bude reagovat. To umožní udržet počet kombinací v "rozumných mezích".
Je možné třeba zkoušet jednotlivé části výpočtu a po každé operaci vypsat mezivýsledky na obrazovku, takže se snadno pozná, ve kterém okamžiku se chyba (třeba špatné znaménko ve výpočtu) projevila. K tomu slouží pomocné řádky, vložené mezi řádky programu, které se během odlaďování postupně odstraňují. Není vhodné zrušit je hned po odstranění chyby, stačí je nejprve "vypnout" příkazem REM, takže když se objeví jiná chyba, nemusí je programátor vymýšlet znovu, stačí odstranit příkazy REM nebo apostrofy, které je blokovaly. Stejným způsobem je možné "vypnout" některou část programu, nebo nastavit proměnné před nějakou operací. Po odstranění všech nalezených chyb se vymažou i nepotřebné pomocné řádky, a program se znovu otestuje.
Pokud se projeví nějaká další chyba, obvykle je nutné vrátit se o krok zpět a zjistit "kdo to tentokrát zvoral". Proto se postupně vytvářené verze programu ukládají zvlášť, aby se k nim bylo možné vracet, nebo jejich porovnáním odhalit další chyby, které se jinak neprojevují.


(C)2004 FARAON


Stáhnout celý text: expbasic.pdf 74,7 KB

 
# Moje malé muzeum > BASIC > Expresní kurs BASICu