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í.
O čem si budeme povídat?
Řekneme si, jak máme dát uživateli najevo, že má vložit data, a jak je můžeme přečíst poté, když je vložil. Ukážeme si načítání jak numerických dat, tak řetězců. Podíváme se také na to, jak můžeme získat údaje, zapsané v podobě parametrů na příkazovém řádku při spuštění programu.
Naše programy zatím používaly pouze statická data. Taková data jsme mohli, pokud jsme to potřebovali, prozkoumat ještě před spuštěním programu, takže jsme program mohli napsat tak, aby jim vyhovoval. Ale většina programů taková není. Většina programů očekává, že budou řízeny uživatelem. Přinejmenším očekávají, že jim uživatel sdělí jaký soubor mají otevřít, upravit jeho obsah a podobně. Jiné programy si v kritických místech od uživatele vyžádají vstup dat. Než půjdeme dál, ukážeme si, jak se toho dá dosáhnout.
Jak můžete pozorovat[1],
raw_input jednoduše zobrazí zadanou výzvu a zachytí
vše, co uživatel napíše jako odpověď. Příkaz print pak tuto
odpověď zobrazí. Odpověď bychom ale mohli místo zobrazení přiřadit do
proměnné:
odpoved = raw_input("Jak se jmenuješ? ")
print "Tak ty se jmenuješ %s! Jsem rád, že jsem tě poznal." % odpoved
Příkaz raw_input má bratrance jménem input.
Rozdíl spočívá v tom, že raw_input sesbírá uživatelem napsané
znaky a chápe je jako textový řetězec, zatímco input se z nich
bude snažit vytvořit číslo. Pokud například uživatel napíše znaky
'1', '2' a '3', pak
input tyto tři znaky přečte a převede je na číslo
123.
Použijme nyní příkaz input k tomu, aby uživatel rozhodl,
která tabulka násobků se má tisknout:
nasobitel = input("Vyberte hodnotu násobitele: ")
for j in range(1, 13):
print "%d x %d = %d" % (j, nasobitel, j * nasobitel)
Použití příkazu input je naneštěstí velmi záludné. Je to
dáno tím, že input se nesnaží vyhodnocovat jen čísla, ale snaží
se na libovolný vstup pohlížet jako na kód v jazyce Python a snaží se jej
provést. To znamená, že by znalý uživatel se zákeřnými úmysly mohl napsat
příkaz jazyka Python, který by například vymazal nějaký soubor na vašem PC!
Z tohoto důvodu bude lepší, když se budete držet příkazu
raw_input a výsledný řetězec si budete převádět na potřebný
datový typ použitím zabudovaných konverzních funkcí jazyka Python. Ve
skutečnosti je to velmi jednoduché:
nasobitel = int(raw_input("Vyberte hodnotu násobitele: "))
for j in range(1, 13):
print "%d x %d = %d" % (j, nasobitel, j * nasobitel)
Vidíte? Volání raw_input jsme jednoduše obalili voláním
int. Efekt je stejný, jako kdybychom použili
input, ale je to mnohem bezpečnější. Existují i jiné konverzní
funkce, takže uživatelský vstup můžete stejně dobře převádět na reálná čísla
a na další typy.
V jazyce BASIC se vstup zadávaný uživatelem čte příkazem
INPUT. Takže můžeme psát:
INPUT "Vyberte hodnotu násobitele: ";M
FOR J = 1 to 12
PRINT M "x" J "= " M*J
NEXT J
Jak vidíte, velmi se to podobá vstupu v jazyce Python až na to, že
proměnnou uvádíme až na konci příkazu. BASIC navíc používá
INPUT jak pro načítání čísel, tak pro řetězce. Příkaz
INPUT má obvykle ještě některé další vlastnosti, proto byste u
každé verze jazyka BASIC měli nahlédnout do příslušné části dokumentace.
Tcl má svůj vlastní mechanismus vstupu založen na souborech (které
zahrnují i standardní vstupní a standardní výstupní soubor) a na příkazu
zvaném gets. Ten načítá vstup z předepsaného souboru. V našem
případě to bude stdin.
Poznámka: Následující program nebude pracovat, pokud se jej budete snažit zadat ze standardního příkazového řádku tclsh80 nebo wish80. Místo toho jej budete muset napsat do souboru (řekněme input.tcl) a spustit jej z příkazového řádku:
C:\PROJECTS\Tcl>tclsh80 input.tcl
Tcl verze našeho programu vypadá nějak takto:
puts -nonewline stdout "Vyberte hodnotu násobitele: "
flush stdout
set nasob [gets stdin]
for {set j 1} {$j <= 12} {incr j} {
puts [format " %d x %d = %d" $j $nasob [expr $nasob * $j] ]
}
Volba -nonewline příkazu puts zabrání kurzoru,
aby se po zobrazení výzvy přesunul na další řádek. Příkaz flush
donutí standardní
výstup stdout aby svůj obsah zapsal ihned — tím
zajistíme, aby se objevil na obrazovce. Cyklus for je téměř
shodný s verzí, kterou jsme viděli, když jsme se bavili o cyklech.
Poznámka: Slovem stdin se v žargonu označuje standardní vstupní zařízení (obvykle klávesnice). Abychom mohli využít kód pro práci se soubory, je to zařízeno tak, aby se standardní vstupní zařízení chovalo jako soubor.
V systému Python je stdin součástí modulu sys a
nazývá se sys.stdin. Funkce raw_input() používá
stdin automaticky. Tcl může číst z libovolného souboru příkazem
gets (což je zkratka pro getstring). Totéž můžeme
zapsat i v jazyce Python. Vyzkoušejte:
import sys print "Zadej hodnotu: ", # čárka zabrání přechodu na další řádek hodnota = sys.stdin.readline() # explicitní použití stdin print hodnota
Funkčnost se téměř shoduje s chováním příkazu:
print raw_input("Zadej hodnotu: ")
Výhodou explicitního použití stdin je to, že standardní vstup můžeme svázat se skutečným souborem, takže program svůj vstup nebude číst z klávesnice, ale z daného souboru. Tento obrat je užitečný při realizaci dlouhých testů programu, kdy místo ručního vkládání vstupních údajů v okamžiku, kdy je program požaduje, necháme vstup přečíst z předem připraveného souboru. (Další výhodou je v takovém případě skutečnost, že test můžeme spouštět opakovaně, přičemž jsme si jisti, že vstup bude pokaždé stejný, takže by tomu měl odpovídat stejný výstup. Tuto techniku opakovaného spouštění dřívějších testů, které mají ověřit, že se nic nepokazilo, programátoři nazývají regresní testování.)
Na závěr uveďme, že existuje i 'soubor' sys.stdout, který
můžeme rovněž přesměrovat — tentokrát do fyzického souboru.
Příkaz print můžeme zapsat jako:
sys.stdout.write("Ahoj, vy tam!\n") # \n = nový řádek
Pokud tedy stdout nebude svázán s obrazovkou, zapíše se
výstup do souboru. Tímto způsobem fungují i příkazy operačního systému,
pokud u nich na příkazovém řádku zapíšeme přesměrování do souboru:
C:\> dir C:\> dir > dir.txt
První z příkazů tiskne obsah adresáře na obrazovku. Druhý tiskne do
souboru. Použitím znaku > programu říkáme, že chceme
stdout přesměrovat do souboru dir.txt.
Další typ vstupu představuje příkazový řádek. Dejme tomu, že nějak takto spustíte svůj textový editor:
EDIT Foo.txt
Jak editor zjistí jméno souboru?
Ve většině jazyků systém poskytuje pole nebo seznam řetězců, které obsahují slova z příkazového řádku. Takže první prvek bude obsahovat jméno příkazu, druhý prvek bude obsahovat první argument, atd. Obvykle máme k dispozici nějakou magickou proměnnou, ve které je uložen počet prvků uvedeného seznamu.
V systému Python je zmíněný seznam součástí modulu sys a
nazývá se argv (z anglického argument
values, čili hodnoty argumentů). Obsah prvků můžeme získat
odkazem přes index nebo iterací, čili postupným průchodem, přes
jednotlivé prvky seznamu. Můžeme tedy psát:
import sys
for polozka in sys.argv:
print polozka
print "První argument byl:", sys.argv[1]
Poznamenejme, že to bude fungovat jen v případě, kdy uvedený kód uložíte
do souboru (dejme tomu args.py) a spustíme jej z příkazového
řádku operačního systému, například takto:
C:\Python\Projekty> python args.py 1 23 fred args.py 1 23 fred První argument byl: 1 C:\Python\Projekty>
Tcl používá podobný přístup se třemi proměnnými:
argv0 — název příkazu,argv — řetězec obsahující zbytek příkazové řádky aargc — obsahuje počet slov v argvV Tcl zapíšeme příklad demonstrující přístup k argumentům z příkazového řádku takto:
puts "Příkaz byl: $argv0" puts "První argument byl: [lindex $argv 0]"
A opět — uvedený kód budeme muset spustit jako skript (musí být umístěn v souboru) z příkazového řádku operačního systému s tím, že současně zadáme nějaké argumenty.
Zatímco u Tcl se ukazuje, že nemá ekvivalent příkazu input,
zdá se, že BASIC zase nemá ekvivalent argv. I když k
zpřístupnění argumentů z příkazového řádku by bylo možné využít vlastností
operačního systému. Tak například hodnoty argumentů jsou uloženy v
proměnných prostředí (environment variables), takže je můžeme získat
použitím funkce GETENV. Z pohledu tohoto kurzu však již jde o
příliš pokročilou tématiku. Doporučuji, abyste se v BASICovských programech
na hodnoty vyptávali uživatele interaktivně.
A to je k tématu uživatelského vstupu opravdu vše, co budeme v tomto kurzu potřebovat. Je to sice velmi primitivní, ale přesto s tím vystačíte při psaní užitečných programů. V počátcích systému Unix nebo u prvních osobních počítačů představovala tato podoba interakce s uživatelem jedinou dostupnou možnost. V jazycích Python, Tcl a BASIC (ve své inkarnaci označované jako Visual) lze psát i náročné programy s grafickým uživatelským rozhraním, s okny, s dialogy, atd…, ale to je pro tento kurz příliš pokročilá tématika. V případové studii si přesto ukážeme krátký příklad uživatelského vstupu s grafickým uživatelským rozhraním, zapsaný v jazyce Python. Ale nebudeme si vysvětlovat detaily toho, jak to funguje. Jakmile na solidní úrovni zvládnete základy, můžete se zaměřit na webové kurzy, které se touto problematikou zabývají. Některé z nich uvedu na stránce s odkazy na literaturu.
Zapamatujte si
input, pro čtení znaků či
řetězců použijeme raw_input.input tak raw_input mohou zobrazit
řetězec s výzvou pro uživatele.INPUT použít pro vstup libovolného
typu dat.argv, který v systému Python můžeme importovat z modulu
sys. První prvek seznamu obsahuje jméno programu.argv, ale pro jméno programu je vyhrazena proměnná
argv0.__name__ nastavena na
řetězcovou hodnotu "__main__". (O tomto rysu se zde zmiňujeme
poprvé.)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: cztutinput.html,v 1.2 2004/05/14 10:22:46 prikryl Exp $