TCL základy (2)

30. 9. 2004
Doba čtení: 7 minut

Sdílet

Ilustrační obrázek
Autor: Depositphotos – stori
Ilustrační obrázek
V minulém dílu jsem vás seznámil s datovými úložišti. Dále jsem uvedl některé konkrétní příkazy, které ovšem umožňují jen efektivnější používání takovýchto typů. V této části se zaměřím na příkazy k obecnějšímu použití, předtím vám ale ukážu, jak se Tcl vypořádal se základními programovými konstrukcemi.

Co by to bylo za jazyk, kdyby neobsahoval cykly, větvení a podprogramy. Takový jazyk by se v reálném použití jen těžko uplatňoval. Jazyk Tcl samozřejmě tyto konstrukce obsahuje.

Podmíněné větvení

Podmíněné větvení je zajištěno příkazy if a switch.

Příkaz if má následující tvar:

if výraz1 ?then? tělo1 elseif výraz2 ?then? tělo2 ... ?else? těloN 

Tato vcelku nesrozumitelná deklarace říká:

  • Klíčová slova then a else mohou být vynechána.
  • Výrazem je myšlen výraz jako v expr, nebo návratová hodnota příkazu, který vrací v případě úspěchu true, yes nebo nenulovou hodnotu, v případě neúspěchu false, no nebo nulu.
  • Tělo může obsahovat pouze jeden příkaz, výraz v hranatých závorkách nebo seznam příkazů.
  • Části elseif a else samozřejmě nemusejí být vůbec uvedeny.
set prom 4
if {$prom > 0} {
  puts "Kladne cislo"
} elseif {$prom < 0} {
  puts "Zaporne cislo"
} else {
  puts "Je rovno nule"
}

Příkaz switch, se také používá k řízení běhu programu, avšak povětšinou v případech, kdy je na výběr z mnoha možností. Má následující tvar:

switch ?volby? řetězec {vzor tělo ?vzor tělo ...?}

Příkaz switch můžete použít i bez složených závorek, nicméně doporučuji vám používat jej s nimi. Argument řetězec je určen pro vstupní data, se kterými se budou porovnávat jednotlivé vzory. Pokud se vzor shoduje s porovnávacím řetězcem, vykoná se tělo, které po něm následuje. Nepovinný argument volby vám umožňuje určit, jaká technika porovnání se použije:

Tabulka č. 602
-exact Implicitní volba. Shoda řetězce a vzoru musí být přesná.
-glob Použití porovnávání jako používá shell (* ? […])
-regexp Založeno na regulárních výrazech, jaké používá např. editor vi.
 – Indikuje konec voleb. V případě, že porovnávací řetězec začíná pomlčkou, tato volba pomůže switchi rozpoznat, kde končí volby a začíná porovnávací řetězec.

Vzor default vyhovuje všemu, co ještě nebylo zachyceno. Na rozdíl od C a jeho klonů, Tcl nepoužívá break, místo toho je switch ukončen při první shodě. Opět uvedu příklad použití:

set prom hello
switch -glob -- $prom {
  *a*   { puts "\$prom obsahuje pismeno <a>" }
  *e*   { puts "\$prom obsahuje pismeno <e>" }
  *i*   { puts "\$prom obsahuje pismeno <i>" }
  *o*   { puts "\$prom obsahuje pismeno <o>" }
  *u*   { puts "\$prom obsahuje pismeno <u>" }
}

Výsledek bude vypadat jen: $prom obsahuje pismeno <e>, následující větve se provádět nebudou.

Cykly

Cykly jsou v jazyce Tcl zastoupeny klasicky smyčkami for a while a navíc i příkazem foreach.

Příkaz for je prakticky stejný jako v jazyce C.

for start test další tělo

Na začátku for provede příkaz start, potom a při každém průchodu spouští příkaz test. Pokud vrací hodnotu udávající pravdu, vykoná příkaz tělo a další. Při návratové hodnotě nepravdy cyklus končí. Cyklus můžete také explicitně ukončit příkazem break, nebo opětovně spustit smyčku příkazem continue.

for { set i 1} { $i <= 10 } { incr i } {
  puts "ahoj po $i."
}

Příkaz incr inkrementuje proměnnou. Jeho druhým volitelným argumentem je číslo, o které se má zvýšit.

Příkaz while je také nápadně podobný klíčovému slovuwhile jazyka C.

while test tělo

Vykonává argument tělo, dokud příkaz test vrací hodnotu nepravdy (tedy opačně než u for), přičemž i zde fungují příkazybreak a continue jako v cyklu for.

Dalším typem smyčky je příkaz foreach.

foreach názevproměnné seznam tělo

Příkaz foreach postupně přiřazuje hodnoty seznamu seznam proměnné názevproměnné a vykonává tělo. Můžete ho použít i s více proměnnými a seznamy, kdy foreach přiřazuje hodnoty proměnným napřeskáčku, nebo každá proměnná má svůj vlastní seznam. Využití těchto technik můžete najít v dokumentaci dodávané s jazykem Tcl. I zde fungují příkazy break a continue. Základní využití a využití s více seznamy může vypadat takto:

foreach prom { prvni druhy treti ctvrty } {
  puts $prom
}

foreach ciselne { 1 2 3 4 } slovne { jedna dva tri ctyri } {
  puts "$ciselne je slovy $slovne"
} 

Podprogramy

Tuto činnost zajišťuje také příkaz a sice proc.

proc název argumenty tělo

Argument název je názvem procedury. Část argumenty je seznam argumentů, které bude procedura vyžadovat ke svému spuštění. Ty samozřejmě lze použít uvnitř bloku tělo, což je seznam příkazů určených k vykonání. Procedury vrací návratovou hodnotu posledně vykonaného příkazu, nebo je lze explicitně ukončit příkazem return, kterému můžete předat návratovou hodnotu (resp. návratový řetězec).

proc secti { x y } {
  return [expr $x + $y]
}

puts [secti 2 2]

Procedura secti sečte své argumenty pomocí expr a vrátí výsledek příkazem return. Všimněte si, že použití nově definovaného příkazu se nijak neliší od použití vestavěných příkazů jazyka Tcl. Také je dobré mít na paměti, že Tcl automaticky nezpřístupňuje proměnné z vyššího oboru platnosti, včetně globálních proměnných. Ke zpřístupnění existují příkazy upvar ?úroveň? staráprom nováprom, kde můžete definovat i počet vynoření, a příkaz global názevprom1 ?názevprom2 …?, který zpřístupní globální proměnnénázevpromN.

Práce s řetězci

Jak jste si mohli všimnout, Tcl pracuje se vším včetně programového kódu jako s řetězci. Proto málokoho může překvapit kompletní podpora pro práci s nimi.

Základní množinu operací s řetězci zajišťuje příkaz string, který jako druhý argument přijímá volbu, jež určí konkrétní zacházení.

string volba ?arg ?arg? ...

Příkaz string obsahuje následující volby s argumenty:

Tabulka č. 603
compare řetězec1 řetězec2 Porovnává řetězce, přičemž vrací –1, 0, nebo 1, když řetězec1je menší, stejný, nebo větší než řetězec2.
match vzor řetězec Použití porovnávání jako používá shell (* ? […]). V případě shody vrací 1, v opačném případě 0.
lenght řetězec Vrací délku řetězce řetězec.
index řetězec číslo Vrací znak z řetězce řetězec na pozici číslo.
is třída řetězec Zjišťuje, zdali řetězec řetězec je typu třída. Pokud ano, návratová hodnota je rovna 1, v opačném případě 0. Můžete ověřovat množství typů, např.: alnum pro vyjádření alfanumerických znaků, integer pro celá čísla, falsepro nějaké vyjádření booleanovské nepravdy atd.

Významným příkazem pro vyhledávání shody v řetězcích je příkaz regexp. Ten zpracovává výrazy tak, jak to dělá např. editor vi. Deklarace vypadá následovně:

regexp ?volby? výraz řetězec ?promShody? ?promDílčíShody ...? 

Argument výraz nahradíte regulárním výrazem, který má být vyhledán v řetězci řetězec. Proměnná promShody je v případě úspěchu nastavena na hodnotu shody, a jsou-li uvedeny proměnné promDílčíShody, pak jsou nastaveny na dílčí shody uvedené ve výrazu. Zápis regulárních výrazů je nad rámec tohoto článku, proto máte-li zájem, nahlédněte do dokumentace dodávané s editorem vi, utilitou grep nebo podobným nástrojem. Také nezapomeňte, že s největší pravděpodobností budete muset výraz vložit mezi složené závorky, abyste zamezili interpreteru v jeho vyhodnocení.

Vstup, výstup a práce se soubory

Jazyk Tcl používá k identifikaci datových toků tzv. kanály (channel), pomocí nichž můžete přistupovat k jednotlivým zdrojům dat. Při spuštění interpreter automaticky otevírá tři kanály: stdin, stdouta stderr. Další kanály si již musíte otevřít sami, a to pomocí příkazu open.

open názevSouboru ?přístup? ?práva?

Argument přístup určuje způsob, jakým se otevře soubor názevSouboru. K tomu můžete použít hodnoty, které používá céčkovská funkce fopen, nebo systémové volání open. Pokud má dojít k vytvoření souboru, argument práva určí k němu počáteční práva. Návratovou hodnotou je otevřený kanál.

Dalšími příkazy jsou:

close kanál

Uzavře kanál kanál.

read kanál ?početZnaků?

Načítá početZnaků znaků z kanálu kanál. Pokud argument početZnaků není uveden, načítá veškerý dostupný vstup.

gets kanál ?názevprom?

Načítá řádek z kanálu kanál do proměnné názevprom. Vrací počet načtených znaků, při detekci konce souboru –1, a pokud není uvedena proměnná názevprom, vrací načtená data.

puts ?-nonewline? ?kanál? řetězec

Do kanálu kanál zapisuje řetězec, a pokud není uvedena volitelná volba -nonewline, přidá za něj znak nového řádku. Následující příklad zkopíruje soubor řádek po řádku.

set in [open "file.in" "r"]
set out [open "file.out" "w"]
while { [gets $in tmp] != -1 } {
  puts $out $tmp
}
close $in
close $out

To byly příkazy pro práci se samotným obsahem souborů. Příkaz file ovšem pracuje s jeho zevnějškem.

file volba názevSouboru ?arg arg ....?

Argument volba určuje, jakou vlastnost hodláte zjistit o souboru názevSouboru. Těchto voleb existuje velké množství, proto se pro bližší informace obraťte na dokumentaci k jazyku Tcl.

Práce v síti

O tuto dříve velmi složitou oblast programování můžete své programy v jazyce Tcl velmi snadno rozšířit. K tomu slouží příkaz socket, se kterým je možno vytvořit jak soket na klientské, tak i na serverové straně. Prakticky jej budete používat jako příkaz open, neboť také otevírá nový kanál, který je identický s kanálem vytvořeným příkazem open. Deklarace se liší v závislosti na straně použití. Pro klientskou stranu:

socket host port

Vytvoří TCP spojení s hostitelem host na portu port. Vytvoření soketu na serverové straně:

zabbix_tip

socket -server příkaz port

Tento příkaz nastaví obslužnou rutinu pro příchozí spojení na portu port. Pokud se takové vyskytne, vykoná se příkaz, který spojení obslouží. Je důležité si pamatovat, že toto volání nezablokuje chod programu. Musíte použít příkaz vwait, kterému předáte kanál vytvořený příkazem soket -server. Teprve tento příkaz zablokuje chod programu.

Do tohoto dílu jsem zahrnul zbytek základních prostředků jazyka Tcl. Tím jsem ukončil pojednání o samotném jazyku a nyní bych se chtěl konečně zaměřit na rozšíření Tk, které nabízí velmi výkonný model pro vytváření grafického uživatelského prostředí (GUI).

Seriál: TCL základy

Autor článku