Níže uvedený text pochází z prvního vydání. Nad tímto textem se nachází aktuální stav po revizi směřující k druhému vydání.

Větvení, aneb nechť padne rozhodnutí

O čem si budeme povídat?

Třetím z našich základních stavebních kamenů je větvení nebo také podmíněný příkaz. Jde jednoduše o pojmy, které popisují schopnost provést jednu z několika možných posloupností příkazů (jednu z větví) a to v závislosti na nějaké podmínce.

Dříve, v době assemblerovských programů, bylo větvení realizováno nejjednodušším možným způsobem — použitím instrukce JUMP. Program v tomto místě doslova skočil na určenou adresu v paměti. Obvykle to bylo podmíněno tím, že výsledkem předchozí instrukce byla nula. I když nebylo možné použít jiný způsob realizace podmíněného příkazu, byly takto napsány úžasně složité programy. To potvrzovalo správnost Dijkstrových tvrzení o minimálních požadavcích potřebných pro programování. Když se objevily vyšší programovací jazyky, objevila se i nová podoba instrukce JUMP pod názvem GOTO. V jazyku BASIC (i v jiných vyšších programovacích jazycích) lze GOTO stále používat. Vyzkoušejte si následující úsek kódu:

10 PRINT "Začínáme na řádku 10"
20 J = 5
30 IF J < 10 GOTO 50
40 Print "Tento řádek se nevytiskne"
50 STOP

Povšimněte si, že dokonce i u tak krátkého programu trvá několik sekund, než přijdete na to co se stane. Kód nemá žádnou strukturu. Musíte si ji během čtení doslova vytvořit. U velkých programů to začne být prakticky nemožné. Z tohoto důvodu moderní programovací jazyky buď nemají příkazy skoku JUMP nebo GOTO, nebo vás od jejich používání odrazují.

Příkaz if

Intuitivně nejzřejmější podobou podmíněného příkazu je konstrukce if, then, else. Sleduje logiku anglické věty v tom smyslu, že if (jestliže) je nějaká boolovská podmínka splněna, then (pak) se provede blok příkazů, v opačném případě (nebo else (jinak)) se provede jiný blok.

V jazyce BASIC se příkaz if používá takto:

PRINT "Začínáme zde"
J = 5
IF J > 10 THEN
    PRINT "Toto se nikdy nevytiskne"
ELSE
    STOP
END IF

Takový zápis se ve srovnání s předchozím příkazem s GOTO lépe čte a je srozumitelnější. Za slovo if můžeme samozřejmě dosadit libovolnou podmínku testu za předpokladu, že ji lze vyhodnotit jako True nebo False — to znamená jako boolovskou hodnotu.

V jazyce Python vypadá zápis docela podobně:

import sys  # jen proto, abychom mohli program ukončit
print "Začínáme zde"
j = 5
if j > 10:
    print "Toto se nikdy nevytiskne"
else:
    sys.exit()

Vždyť je to téměř shodné, že ano?

Příkazy if/then/else můžete spojovat tím, že vnoříte jeden do druhého — třeba takto:

# Předpokládajme, že sirka již byla dříve vytvořena...
if sirka == 100:
    plocha = 0 
else:
    if sirka == 200:
        delka = delka * 2
    else:
        if sirka == 500:
            sirka = sirka / 10
        else:
            print "Šířka má neočekávanou hodnotu!"

Poznámka: V uvedených příkazech if jsme pro test na shodnost použili operátor ==, zatímco pro přiřazování hodnot proměnným jsme použili operátor =. Při programování v jazyce Python je situace, kdy použijeme = v místě, kde jsme měli použít ==, jednou z běžných chyb. (Tento problém se týká i jiných jazyků. Například v jazycích C a C++ se používají stejné operátory.) Python vás naštěstí varuje, že jde o syntaktickou chybu. Ale někdy se stává, že se na to musíte podívat pořádně, než příčinu problému zpozorujete.

Boolovské výrazy

Možná si ještě vzpomínáte, že jsme se v kapitole o datech zmínili o datovém typu boolean. Řekli jsme si, že má pouze dvě hodnoty: True a False. Boolovské proměnné vytváříme velmi zřídka[1], ale dočasné boolovské hodnoty často vznikají jako výsledek vyhodnocení výrazů. Výrazem rozumíme kombinaci proměnných a hodnot, spojených operátory s cílem vyprodukovat výslednou hodnotu. V následujícím příkladu

if x < 5:
  print x

je zápis x < 5 výrazem. Výrazy mohou být libovolně složité s tím, že výsledkem jejich vyhodnocení musí být vždy jediná koncová hodnota. V případě větvení musí být výsledkem pravdivostní hodnota true nebo false[2]. Nicméně, definice těchto dvou pravdivostních hodnot se jazyk od jazyka liší. V mnoha jazycích je hodnota false ztotožněna s hodnotou 0 nebo s hodnotou vyjadřující neexistenci (té se často říká NULL, Nil nebo None). Takže v boolovském kontextu bude například prázdný seznam nebo prázdný řetězec vyhodnocen jako false. To znamená, že například můžeme využít cyklu while pro zpracování seznamu, které má skončit v okažiku, kdy je seznam prázdný.

Větvení v Tcl

V jazyce Tcl je příkaz if velmi podobný:

if {$x < 5} {
   puts $x
}elseif {$x == 5} {
   puts "Je to pětka!"
}else{
   puts "Hodnota je větší, než pět."
   }

Zápis by vám měl být jasný. Části elseif a else samozřejmě nejsou povinné. Ale to vás již pravděpodobně napadlo.

Příkazy typu Case

Posloupnost zanořených if/else/if/else… patří k tak běžným konstrukcím, že některé jazyky poskytují speciální způsob větvení. Konstrukce tohoto typu se často označují jako konstrukce typu Case nebo Switch. V jazyce Tcl ji zapisujeme takto:

switch $sirka {
    100 { set plocha 0} 
    200 { set delka [expr {$delka * 2}] }
    500 { set sirka [expr {$sirka / 10}] }
    }

V moderních verzích jazyka BASIC tato konstrukce existuje také:

SELECT CASE sirka 
 CASE 100
   LET plocha = 0
 CASE 200
   LET delka = delka * 2
 CASE 500
   LET sirka = sirka / 10
 ELSE PRINT "Šířka má neočekávanou hodnotu!"
END SELECT

Python explicitní konstrukci typu case nepodporuje. Místo toho nabízí kompromis v podobě if/elif/else:

if sirka < 100:
   plocha = 0
elif sirka < 200:
   delka = length * 2
elif sirka < 500:
   sirka = sirka / 10
else:
   print "Šířka má neočekávanou hodnotu!"

Povšimněte si použití elif a skutečnosti, že se odsazení (které je v jazyce Python důležité) nemění. Za zmínku stojí i to, že obě verze — jak tato, tak dříve uvedený příklad v jazyce Python — jsou funkčně shodné. Druhý způsob pouze zvyšuje čitelnost v případech, kdy použijeme větší množství testů.

O něco těžkopádnější podobu stejné konstrukce naleznete i v jazyce BASIC v podobě ElseIf...THEN. Používá se naprosto stejným způsobem, jako elif v jazyce Python, ale setkáte se s ní zřídka, protože použití alternativního příkazu CASE je jednodušší.

K čemu je to tedy dobré?

Až dosud byly naše příklady velmi abstraktní. Podívejme se nyní na příklad, který používá větvení pro něco hmatatelnějšího a který současně představuje další běžnou programovací techniku, konkrétně použití menu pro vymezení uživatelského vstupu.

Zde máme kód, za kterým následuje krátká diskuse. Poznámka překladatele: Abychom se zatím vyhnuli problémům s českými znaky, použijeme texty bez diakritických znamének. Způsob řešení, kdy používáme i české znaky s diakritikou, můžete nalézt v dalších kapitolách.

#################################
# Povšimněte si, že pro vytvoření menu bylo použito ztrojených uvozovek.
print """
Vyberte si tvar z nasledujiciho seznamu:
1) Trojuhelnik
2) Ctverec
3) Kruh
"""

tvar = raw_input("Ktery tvar volite? [1, 2, 3] ")

# Povšimněte si, že při testování musíme použít řetězec '1' 
# a ne číslo 1, protože raw_input() vrací řetězce a nikoliv čísla.

if tvar == '1':     # trojúhelník
    vyska = input('Jaka je vyska vaseho trojuhelniku? ')
    zakladna = input('Jaka je delka jeho zakladny? ')
    print "Plocha trojuhelniku je: ", 0.5 * zakladna * vyska

elif tvar == '2':   # čtverec
    strana = input("Jak dlouhe jsou strany strany ctverce? ")
    print "Plocha ctverce je: ", strana * strana

elif tvar == '3':   # kruh
    polomer = input('Jaky je polomer vaseho kruhu? ')
    print "Plocha kruhu je: ", 3.14159 * polomer * polomer

else:
    print "Lituji. Byla vybrana neplatna volba."

Uživateli tedy předkládáme nabídku voleb. V závislosti na tom, co si zvolí, požádáme o vstup odpovídajících hodnot a vypočítáme plochu zvoleného útvaru. Pokud uživatel nevybere jednu z nabídnutých voleb, pak závěrečný příkaz else jednoduše zobrazí chybové hlášení.

Program tedy uživateli vytváří iluzi, že ví, co uživatel potřebuje. Na základě jeho volby se chová různým způsobem a správně provede odpovídající činnost. Uživateli se v podstatě zdá, že postup řídí, zatímco ve skutečnosti má řízení v rukou programátor, který předvídal, jak mají vypadat všechny platné vstupy a jak má na ně program reagovat. Projevovaná inteligence tedy patří programátorovi, nikoliv stroji. Počítače jsou ve své podstatě hloupé!

Smysl větvení tedy spočívá v tom, že může naše programy vybavit inteligentním chováním. V závislosti na hodnotách proměnných, které se vyskytují v podmínkách (ve výše uvedeném případě je to proměnná tvar), se program ubírá různými cestami uvnitř kódu.

Na závěr byste možná rádi zkusili obalit tento program cyklem, který by způsobil opakované zobrazení menu až do té doby, než by uživatel vybral volbu Konec. Tu byste samozřejmě museli do menu přidat. Pokud se vám to podaří, pak získáte základní šablonu (framework) pro celou řadu programů — zobrazit menu a zachovat se podle výběru uživatele.

Zapamatujte si

Pokud vás napadne, co by se dalo na překladu této kapitoly vylepšit, zašlete e-mail odklepnutím tohoto odkazu. Tím bude do subjektu dopisu automaticky vložena informace o jméně a verzi tohoto HTML dokumentu.

$Id: cztutbranch.html,v 1.2 2004/05/14 10:22:45 prikryl Exp $