Jak na pro­jek­ty v ja­zy­ce C

© Damig, 2004 – 2023
Koncept

Příkazový řádek a shell
Používání shellu

Programy s parametry

Spouštění prorgramů je základní činnost každého shellu. Protože všechny zde zmiňované operační systémy vycházejí ze stejných kořenů, fungují základní operace shellu dodnes všude stejným způsobem.

Každý program může při svém startu od shellu obdržet parametry, které budou ovlivňovat jeho činnost. Tyto parametry zadává uživatel tak, že je napíše za jméno spouštěného programu jako slova oddělená mezerami. Na programu samotném (resp. jeho autorovi) pak je, aby tomuto seznamu parametrů porozuměl a zařídil se podle nich.

Zkuste si ve svém unixovém terminálu spustit příkaz ls a pak příkaz ls -l -R --reverse. Pokud jste ve Windows, zkuste spustit například dir a pak příkaz dir /O /W. Jak jistě vidíte, parametry změnily chování obou příkazů. Tyto příkazy jsou totiž naprogramovány tak, aby těmto specifickým parametrům rozuměly. Pokud zadáte parametr, který program nezná, programy zřejmě vypíší chybové hlášení.

Jak ale zjistíme, jakým parametrům program rozumí? Dělá se to jednoduše tak, že v každém programu je naprogramována nápověda. Rozumný program rozumí parametru -h nebo --help (konvence v unixových systémech) nebo /? (konvence v MS DOSu a Windows). Uživatelé shellu to obvykle vědí a před spuštěním neznámého programu se na tuto nápovědu podívají. Nejsou pak překvapení, když spustí program a ten na ně jen bliká textovým kurzorem...

Parametry nejsou žádné tajemné kouzelné formule. Jsou to obyčejné textové řetězce, které shell uloží do paměti programu, kde k nim má program přístup (jde o pole textových řetězců). Programátor pak tyto parametry může přečíst a zpracovat.

To, že některé parametry začínají pomlčkou, jiné dvěma pomlčkami a ve Windows lomítkem, jsou pouze konvence. Díky nim můžeme v programu snadněji rozlišovat mezi přepínacími a jinými parametry jako jsou třeba číselné vstupy nebo jména souborů. Vše se předává jako text, takže když takto předáváme do programu číselné hodnoty, je potřeba je v programu nejprve vyčíslit (převést textový řetězec na číselnou hodnotu).

$ ls -l --reverse
celkem 96
-rw-rw-r-- 1 martinek martinek 62515 srp 14 00:22 test.o
-rw-r--r-- 1 martinek martinek   303 pro  9  2008 test.c
-rw-rw-r-- 1 martinek martinek 13759 srp 14 00:22 modul.o
-rw-r--r-- 1 martinek martinek   261 pro  9  2008 modul.c
-rw-r--r-- 1 martinek martinek   361 srp 14 00:21 Makefile
-rw-r--r-- 1 martinek martinek   151 pro  9  2008 konstanty.h
 
Program ls spouštěný se dvěma parametry. První parametr je -l, druhý je --reverse.

Standardní vstup a výstup (klávesnice / obrazovka)

Očekává-li program data na standardním vstupu, program se po spuštění zastaví, bliká kurzorem a čeká, až něco napíšete klávesnicí. Poté, co něco napíšete a stisknete klávesu Enter, se aktuální řádek pošle programu ke zpracování. To čekání na Enter dělá bufferování vstupu. O toto se programátor v jazyce C nestará, to má na starosti systém (knihovna). Můžete také rovnou skenovat kódy stisknutých kláves, což ale naštěstí není v jazyce C triviální problém, takže se k tomu začátečníci jen tak nedostanou.

Když program něco tiskne na standardní výstup, objeví se to za normálních podmínek na obrazovce (v okně terminálu). Problém nastává, když program takto realizuje standardní vstup a výstup a vy se rozhodnete zadávat vstup skutečně z klávesnice. Pak snadno dojde k tomu, že se vstup i výstup míchají spolu na jedné obrazovce (v jednom okně) a vy snadno ztratíte přehled, co je co. Začínající programátoři pak mají tendenci řešit různě formátování takového míchaného vstupu a výstupu a diví se, že to nefunguje, jak by chtěli.

Moje rada: nezadávejte vstup do takových programů ručně z klávesnice. Připravte si data do souboru, kde si je naformátujete, jak chcete (nebo jak to vyžaduje program) a pak je na vstup programu přesměrujte. Teď už to umíte.

Přesměrování souborů

Žádný CLI program s trochou sebeúcty si nepovídá s uživatelem. Představte si výše zmiňované programy lsdir, kdyby místo užitečné práce s vámi klábosily (Ahoj uživateli. Kolik chceš vypsat souborů ze složky? Můžu už skončit?). Tento způsob interakce s uživatelem se hodí jen pro velmi specifické účely (např. Turingův test), ale většinou to uživatele jen otravuje a zdržuje. Také to brání použití programu ve skriptech.

Jak ale jinak dostat do programu data, aniž bychom museli v programu otevírat a zpracovávat soubory? Dáme data do souboru a pošleme jej do programu. Ano, není to chyba. Každý program, který čte data ze standardního vstupu (např. z klávesnice) umí tato data číst i ze souboru. Stačí k tomu použít shell a jeho schopnost přesměrování souboru na vstup programu, přesměrování výstupu programu do souboru a propojení výstupu a vstupu dvou programů pomocí roury.

Řekněme, že máte textový soubor text.txt, kde je na každém řádku jedno slovo (pokud jej nemáte, vytvořte si jej a zkopírujte do něj třeba obsah tohoto odstavce). Pro demonstraci přesměrování použijeme příkaz sort, který najdete v Linuxu i ve Windows. Pokud jej spustíme bez parametrů, čte řádky ze standardního vstupu (klávesnice) a řadí přečtené řádky podle abecedy. My mu ale klávesnici nahradíme skutečným souborem. Nechme zatím stranou, že příkaz sort umí zpracovat soubor i bez přesměrování, když mu jeho jméno dáme jako parametr příkazového řádku.

Nyní můžeme přesměrovat soubor text.txt na vstup programu pomocí operátoru shellu <. Výstup programu se do nového souboru přesměruje operátorem >. Můžete si to zkusit sami podle ukázky 2. Všimněte si, co se kdy tiskne na obrazovku.

Pozor! Operátory < a > nejsou parametry programu. Jde o záležitost shellu, který je odchytí a zařídí vše potřebné.

$ sort < text.txt
dve
jedna
tri
$ sort < text.txt > vysledek.txt
$ dir
text.txt vysledek.txt
Soubor text.txt je přesměrován na standardní vstup programu sort. V prvním případě výsledek vypíše na standardní výstup (obrazovku). Ve druhém případě je výstup přesměrován do souboru vysledek.txt. V tomto případě už program nic na obrazovku netiskne, ale v aktuální složce se objeví nový soubor vysledek.txt, který obsahuje přesně to, co by program sort jinak tisknul na obrazovku.

Roury

Co když chceme výsledek jednoho programu rovnou zpracovat jiným programem? Není potřeba vytvářet pomocný soubor, do něhož bychom přesměrovali výstup jednoho programu a pak jej posílali na vstup druhého programu. Jde to udělat elegantněji rourou.

Ukážeme si to na jednoduchém příkladu sort < text.txt | more. Výstup programu sort se tady posílá rourou (|, svislítko) do programu more. Program more čte text ze vstupu a tiskne jej na výstup tak, že pokud je text delší než by se vešlo do okna terminálu, zobrazí jej stránkovaně, tj. po vypsání jedné stránky čeká na stisk klávesy, aby zobrazil další stránku.

Přesměrování souborů i roury fungují stejně v unixových systémech i ve Windows. Bude to fungovat i s vaším programem, pokud umí zpracovávat standardní vstup (z klávesnice) a tisknout výsledky na standardní výstup (na obrazovku). Takto mohou fungovat programy napsané téměř v libovolném jazyce, nejen v C.

Zkuste si to. Na obrázku 4 v předchozí kapitole jsem takto spustil svůj program otoc, který tiskne řádky získané ze vstupu s opačným pořadím znaků.

Proměnná prostředí PATH

Chování shellu lze ovlivnit proměnnými prostředí. Proměnná PATH slouží k vyjmenování složek v nichž jsou programy, které lze spouštět jménem bez uvedení cesty. Ve Windows sem takto například můžete přidat složku s nainstalovaným překladačem jazyka C, abyste nemuseli při ručním spouštění programátorských nástrojů používat dlouhé příkazy s cestou (například když si nainstalujete Code::Block i s překladačem a chcete si ručně hrát s jednotlivými nástroji přímo z příkazového řádku).

V Linuxu se proměnná PATH tradičně nastavuje v domovské složce uživatele v souboru .bashrc tak, že do něj přidáte řádek PATH=$PATH:~/bin. Složky jsou v proměnné odděleny dvojtečkou, $PATH je původní hodnota proměnné a ~/bin je nová složka, kterou přidávám do proměnné PATH. Jde o složku bin v mé domovské složce (domovská složka má v Linuxu zkratku ~).

Chcete-li zjistit, jakou skutečně hodnotu tato proměnná obsahuje, napište v shellu příkaz echo $PATH.

Ve Windows se proměnná PATH nastavuje pomocí dialogového okna (ve starém DOSu byla nastavována v dávkovém souboru AUTOEXEC.BAT). V různých verzích se to naneštěstí nastavuje trochu jinde. Samotné okno, kde se to nastavuje, se jmenuje Proměnné prostředí (Environment variables), které je dostupné v rozšířených vlastnostech systému v Control Panelu. Oproti Linuxu se zde jednotlivé cesty neoddělují dvojtečkou (protože dvojtečka se používá za názvem disku), ale středníkem.

V okně příkazového řádku Windows se obsah proměnné PATH zjistí spuštěním příkazu path.

Ve Windows XP: Tento počítač → kontextové menu (pravým tlačítkem myši) → Vlastnosti → záložka Upřesnit → tlačítko Proměnné prostředí.
Ve Windows 7: Menu Start → Počítač → Vlastnosti → Upřesnit nastavení systému.
Tohle je ve Windows 7 skoro stejné, jako ve Windows XP.
Toto je ve Windows XP – Windows 7 stejné. Pro nastavení proměnných prostředí musíte mít práva administrátora.
Úpravy systémové proměnné Path. Jednotlivé cesty se oddělují pomocí středníků (;).