| Kurz jazyka C - 4. dílPavel Čížek
 Vítám Vás u další části kurzu, kterou můžeme nazvat "poslední úvodní". Dnes 
dokončíme rychlý průřez jazykem C, od příště začínáme hezky od začátku (skoro), 
tentokrát pomalu a podrobně. To je příležitost, aby se k nám připojili ti, kteří 
tak ještě neučinili. A kdo to umožnil? Měsíčník AMIGA Review, který Vám bude 
přinášet informace dvakrát častěji a poskytne nám tak více prostoru a času i pro 
náš seriál. Úvodní průřez berte jako seznámení se s Céčkem přehled, který nám bude 
užitečný právě v dalších částech kurzu, kdy budeme postupovat pomalu a od 
základů, vše budeme demonstrovat na vývoji nějaké konkrétní menší aplikace. Tyto 
úvodní kapitoly nám umožní postupovat dále, aniž bychom stále škobrtali (jistou 
představu o jazyce jste snad získali). Řídící strukturyV této části (poslední přehledové, jak jsme ji již v úvodu nazvali) na nás 
zaútočí řídící struktury Céčka (příkazy). Samozřejmě si na závěr vše ukážeme na 
příkladech. Minule jsme se probrali spoustou nejrůznějších operátorů; s nimi 
úzce souvisí výrazy, neboť operátory slouží právě k vytváření složitějších 
výrazů. Základem výrazů (primárním výrazem) jsou např. identifikátory 
proměnných, konstanty, řetězce, indexový výraz (což je primární výraz 
následovaný výrazem v hranatých závorkách, který slouží například k odkazu na 
položku pole, a[i]), volání funkce a také výběr položek struktur či unionů. 
Složitější výrazy lze vytvářet z těchto základních pomocí operátorů, klasickým 
příkladem je např. součet dvou proměnných a + b či násobení konstantou 3 * 
a[5]. Chtěl bych upozornit na jednu podstatnou věc z tohoto vyplývající: 
přiřazení je také operátor, a proto a = b + 3 je také výraz!
 Ve výrazech samozřejmě nelze kombinovat náhodně cokoli, příslušné části musí být 
stejných typů (lze např. sčítat dvě celá čísla ale těžko sečtete strukturu a 
položku pole). Samozřejmě proměnné typu long a short nejsou téhož typu, ale 
sčítat je chceme; proto Céčko provádí automaticky některé konverze. Pokud není 
konverze prováděna automaticky, můžeme ji přikázat (to si musíte ovšem dobře 
rozmyslet!). Implicitní konverze vypadá například tak, že vyskytne-li se ve 
výrazu proměnná typu long int, je i druhá proměnná konvertována na tento typ. 
Podrobněji o konverzích a podobných záležitostech pojednáme později.
 Příkazy:Výrazový příkaz se tvoří z výrazu připojením znaku ; (středník) za výraz. 
Středník (jak už víme) se používá pro ukončení řídících konstrukcí Céčka. Takže 
připojíme-li ho za výraz b + 5, dostaneme výrazový příkaz
 
 b+5;
 
 Nejčastěji samozřejmě použijete výrazový příkaz ve spojení s operátorem 
přiřazení; to je obdoba přiřazovacího příkazu z jiných programovacích jazyků. 
Nezapomeňme ani na volání funkce - se středníkem také tvoří samostatný příkaz, 
například
 
 a = funkce f(x, 2);
 printf("Ahoj!
");
 
 Další konstrukcí je blok. Blok umožňuje vytvářet z jednoduchých příkazů příkazy 
složené. V nejjednodušší podobě se jedná o prostou posloupnost příkazů uzavřenou 
ve složených závorkách:
 
 { příkaz_1, příkaz_2, ..., příkaz_n }
 
 V Céčku máte navíc možnost připojit na počátek posloupnosti příkazů posloupnost 
deklarací. Obecný tvar bloku tedy je
 
 { #deklarace_1 #... #deklarace_n # #příkaz_1 #... #příkaz_n }
 
 Každá deklarace je samozřejmě ukončena středníkem, příkazy končí středníkem nebo 
koncovou } jedná-li se o vnořeny blok. Poznáváte ho? Ano, jak je vidět, tělo 
každé funkce není tvořeno ničím jiným než jedním blokem. Poznamenejme, že 
proměnné deklarované na počátku bloku jsou v tomto bloku lokální, lze je tedy 
využívat pouze v rámci tohoto bloku. Asi jste si už všimli také toho, že blok, 
resp. jeho ukončovací závorka nemusí být následována středníkem.
 Dalším důležitým příkazem je podmíněný příkaz. Jak název napovídá, slouží k 
podmíněnému vykonávání příkazu. Podmíněný příkaz může mít dva tvary, vždy je 
uvozen klíčovým slovem if:
 
 kratší varianta: if (výraz) příkaz_1;
 delší varianta: if (výraz) příkaz_1;
 else příkaz_2;
 
 Podmínkou je výraz, který musí být uzavřen v závorkách a který je vyhodnocen 
před provedením příkazu; je-li jeho hodnota nenulová (TRUE, jak již víme), bude 
vykonán příkaz_1, v opačném případě bude vykonán případný příkaz_2 (je-li 
uveden). Pomocí tohoto příkazu lze pak již snadno napsat např. funkci pro výběr 
maxima ze dvou čísel:
 
 int max(int x, int y)
 {
 if (x < y) return(y);
 else return(x);
 }
 
 Pozor! Jsou li příkazy if vložen do sebe, vztahuje se else vždy k 
nejbližšímu předchozímu.
 Užitečnou konstrukcí je také přepínač, který slouží pro větvení výpočtu podle 
hodnoty celočíselného výrazu. Obecný tvar přepínače vypadá následovně:
 
 switch (výraz)
 {
 case hodnota_1: příkaz_1;
 ...
 case hodnota_n: příkaz_n;
 default: příkaz;
 }
 
 Přepínač vyhodnotí celočíselný výraz uvedený na jeho počátku (opět v závorkách) 
za klíčovým slovem switch. Pak se výsledek postupně srovnává s hodnotami za 
klíčovými slovy case; dojde-li ke shodě, provede se příslušný příkaz. Pokud 
výraz není roven žádné hodnotě za slovem case a je uvedena i část s klíčovým 
slovem default (není povinná), provede se příkaz za tímto klíčovým slovem. 
Důležité upozornění: po zpracování příkazu u case se provádí vykonávání 
příkazů také následujících case větví až do vyčerpání seznamu přepínače nebo 
zpracování příkazu break! Chceme-li tedy, aby se přepínač choval podobně jako 
v ostatních jazycích, tj. aby se vykonal vždy právě a pouze příkaz uvedený za 
nalezeným case, použijeme přepínač tvaru:
 
 switch (výraz)
 {
 case hodnota_1: příkaz_1; break;
 ...
 case hodnota_n: příkaz_n; break;
 default: příkaz;
 }
 
 Ukažme si jednoduchý příklad demonstrující možnosti uvedených příkazů. K zadané 
známce vypíšeme slovní hodnocení.
 
 #include <stdio.h>
 /*funkce vrací ukazatel na znak - takto se předávají řetězce v C; posíláme si 
ukazovátko na první písmeno, konec je označen znakem   */
 char *Hodnoceni(int znamka)
 {
 char *text;
 /*sem uložíme hodnocení */
 /*otestujeme, je-li známka ve známém rozsahu, || je logický OR - "nebo" */
 if ((znamka < 1) || (znamka > 5))
 text= "Známka mimo rozsah 1 .. 5"
 else /* jinak použijeme přepínač podle známky dáme do text hodnocení */
 switch (znamka)
 {
 case 1: /*případy 1, 2 hodnotíme společně */
 case 2: /* u case 1 není žádný příkaz, pokračuje se příkazem pro case 2*/
 text = "Výborný výsledek";
 break; /* zde se ukončí zpracování case 1 i 2 */
 case 3: text = "Není to nejhorší ";
 break; /*konec zpracování case 3 */
 case 4; /*jako u case 1 a 2 - společně 4 */
 case 5:
 text= "S tím se asi chlubit nebudeš";
 break; /*zde se ukončí zpracování case 4 a 5 */
 }
 /* vrátíme ukazatel na hodnocení */
 return(text);
 }
 void main()
 {
 int znamka;
 /*načteme známku do proměnné znamka; scanf už známe */
 printf "
Zadejte známku: ");
 scanf("%d", &znamka);
 /* a vytiskneme hodnocení; znak %s říká, že parametr je řetězec */
 printf("Hodnoceni: %s
", Hodnoceni(znamka));
 }
 
 Příklad je poměrně jednoduchý, ale využili jsme if i switch. Pomocí 
podmíněného příkazu vyloučíme nesmyslné případy, přepínač nám pak umožní určit 
hodnocení v závislosti na hodnotě známky. Zde jsou dobře patrné výše popsané 
vlastnosti přepínače - bude-li známka 1 nebo 2, pak (protože u case 1 není 
uveden žádný příkaz, pokračuje se tedy příkazy u následujících návěští, zde tedy 
u case 2) se vykoná přiřazení téhož textu "Výborný výsledek" a vykonávání 
skončí, neboť narazíme na break. Podobné je to u ostatních známek, u case 3 
je za přiřazovacím příkazem uveden hned break, nebudou se tedy příkazy dalších 
větví provádět.
 CyklyCyklus slouží pro řízené opakování nějaké činnosti, výpočtu. V jazyce C 
existují tři typy cyklů: while, do .. while a for. Hned se s nimi seznámíme.
 Cyklus while (while je klíčové slovo, znamená dokud) má tvar: while (výraz) 
příkaz;
 V této konstrukci tvoří výraz podmínku provedení příkazu příkaz. Dokud má 
vyhodnocený výraz nenulovou hodnotu (TRUE), provádí se příkaz; při nulové 
hodnotě (FALSE) se cyklus ukončí. Podmínka se tedy testuje před provedením cyklu 
cyklus nemusí být proveden ani jednou. Cyklus můžeme číst jako "dokud je splněna 
podmínka, prováděj příkaz".
 Cyklus do .. while (do je také klíčové slovo) má tvar do #příkaz while 
(výraz);
 I zde výraz určuje podmínku provádění cyklu. Tato podmínka se však vyhodnocuje 
až po provedení těla cyklu (a opět, je-li podmínka splněna, opakuje se provádění 
těla cyklu, má-li nulovou hodnotu provádění cyklu je ukončeno). Tělo cyklu se 
proto provede alespoň jednou. Použití tohoto cyklu si můžeme demonstrovat na 
předchozím příkladě se známkami a hodnocením pokud bychom chtěli hodnocení pro 
více známek, museli bychom vždy program znovu spustit. To lze snadno vyřešit 
použitím cyklu do .. while. Stačí tělo funkce main() upravit následovně:
 
 do
 { /* načteme známku do proměnné mamka */
 printf(" 
Zadejte známku:);
 scanf("%d"; &znamka);
 /* a vytiskneme hodnocení; znak %s říká, že parametr je řetězec */
 printf("Hodnoceni: %s
, Hodnoceni(znamka));
 } while (znamka !=0);
 
 Pak se bude dotaz na známku a výpis příslušného hodnocení opakovat, dokud 
nezadáme známku 0. Po té se program ukončí.
 Posledním, velice výkonným, je cyklus for, který se na rozdíl od předchozích 
nepodobá příliš cyklům v jiných programovacích jazycích. Tento cyklus má obecně 
tvar
 
 for (výraz_1; výraz_2; výraz_3) příkaz;
 
 Přitom výraz_1 se vyhodnotí jen jednou, před vlastním započetím provádění 
cyklu; obvykle slouží pro nastavení počátečních hodnot. výraz_2 se vyhodnotí 
před každým provedením těla cyklu; má-li hodnotu TRUE, provádí se příkaz, je-li 
nulový (FALSE), cyklus se ukončí. Je to tedy podmínka se stejným významem jako 
podmínka u while cyklu. výraz_3 se vyhodnotí po provedení těla cyklu; slouží 
obvykle pro změnu řídící proměnné cyklu. Význam cyklu for lze ekvivalentně 
zapsat pomocí cyklu while takto:
 
 výraz_1;
 while (výraz_2)
 {
 příkaz;
 výraz 3;
 }
 
 Jak je patrné, je cyklus for velice obecný a lze ho tedy použít téměř všude. 
Jeho praktické využití si můžeme ukázat např. na vytvoření funkcestrlen() to 
je standardní Céčkovská funkce pro určení délky zadaného řetězce.
 
 int strlen(char *retezec)
 { int delka;
 for(delka = 0; *retezec != ; retezec++)
 delka++;
 }
 
 Jak je vidět, inicializační výraz_1 používáme pro nastavení délky na nulu, 
podmínka vykonávání cyklu platí, dokud nenarazíme na znak   (což značí konec 
řetězce), a na konci každého cyklu posuneme ukazatel na řetězec o 1 znak dále 
(příkaz retezec++). Vlastní tělo cyklu pak obsahuje jediný příkaz delka++ 
který při každém opakování cyklu zvýší hodnotu delka o 1.
 Pro porovnání jednotlivých cyklů si uveďme funkci faktorial(), která spočte 
pro zadané přirozené číslo výraz n!=1*2*...*n.
 Příkazy skokuPříkazy skoku slouží pro řešení výjimečných situací v programu, kdy se 
nevyplatí jiné řešení. V jazyce C existuje několik typů skoků. Strukturované 
skoky slouží pro řádné opuštění posloupnosti příkazů ve strukturovaných 
příkazech - jedná se o příkazy break, continue a return . S příkazem 
break sme se již setkali u přepínače. Obecně slouží přerušení nejblíže 
nadřazené konstrukce a jejímu ukončení. Uvedete-li break v některém z již 
zmíněných cyklů, bude tento přerušen a program bude pokračovat příkazem, který 
následuje za cyklem. Příkaz continue také přeruší provádění nejblíže nadřazené 
konstrukce (cyklu) a způsobí přechod na nový cyklus, aniž se dokončil předchozí 
průběh (bude tedy znovu vyhodnocena podmínka cyklu a dle její hodnoty se bude 
dále pokračovat). Posledním skokem, se kterým jsme se již často setkali, je 
příkaz return, který má jednu z následujících podob:
 
 return výraz; return(výraz); return;
 
 Tento příkaz způsobí opuštění těla funkce a pokud obsahuje výraz, stane se 
hodnota tohoto výrazu funkční hodnotou. Pokud je funkce typu void, musí být 
použit příkaz return bez výrazu.
 Kromě strukturovaných skoků existuje v Céčku také nestrukturovaný skok goto. 
Jeho použití je omezeno v rámci jedné funkce (nelze skákat z jedné funkce do 
druhé, ale nemusíme se řídit blokovou strukturou, lze skákat ven z bloku i 
dovnitř bloku. Po skoku do těla bloku je ovšem hodnota všech lokálních 
proměnných tohoto bloku nedefinována! Abychom mohli provést příkaz goto , 
musíme určit, kam se má skočit. Příkaz, na který chceme skočit, musíme označit 
pomocí návěští, což je libovolný identifikátor ukončený dvojtečkou. Tento 
identifikátor se pak stane parametrem goto, jak hned uvidíme. Zpočátku je však 
nejlepší dodržovat zásadu, že goto není vhodné používat.
 Ukažme si realizaci strukturovaných skoků break a continue v cyklu while 
pomocí skoku goto
 
 /* příkaz break */
 while (...)
 {
 /*nějaké příkazy */
 /*zde je goto místo break */
 goto break_navesti;
 /*nějaké příkazy */
 } /*konec cyklu */
 break_navesti:
 /* další příkazy */
 /* příkaz continue */
 while (...)
 {
 /*nějaké příkazy */
 /*zde je goto místo continue */
 goto continue_navesti;
 /* nějaké příkazy */
 continue_navesti: ;
 } /*konec cyklu */
 
 Jak jste si jistě povšimli, návěští musí být před nějakým příkazem. Na konci 
cyklu (při realizaci continue) jsme napsali pouze středník - to je tzv. prázdný 
příkaz, je tvořen samotným znakem ;. Příkazy jsou samozřejmě tvořeny také 
voláním funkcí, jejichž účel může být velice rozmanitý.
 Tím jsme ukončili náš průřez jazykem C, o němž jste snad získali alespoň jakousi 
povrchní představu. Příště (jak jsem zmínil již na začátku) začneme tvořit 
nějakou menší aplikaci (od primitivní verze spouštěné z příkazové řádky až po 
program s mnoha vymoženostmi, uživatelským rozhraním apod.), na níž si ukážeme 
všechny zde popsané vlastnosti jazyka C, podrobně si vše ještě jednou vyložíme 
(tak aby se i naprostý laik nemusel obávat nepochopení) a navíc uvidíme letos z 
toho, co "v manuálu nenajdete". Je to zároveň příležitost pro ty, kteří by 
chtěli začít sledovat náš kurz, nebol právě v příštím pokračování mají možnost 
ještě naskočit do rozjetého vlaku. Jakékoliv dotazy, nápady, návrhy a připomínky 
adresujte redakci Amiga Review.
 
 /* faktoriál pomocí cyklu while */
 unsigned faktorial(unsigned n)
 {
 /* proměnná obsahující výsledek */
 unsigned fact= 1;
 /* dokud nedojdeme až k nule, provádíme tělo cyklu = blok */
 while (n != 0)
 {
 fact *= n;
 /* vynásobení n */
 n--;
 /* snížíme n o 1 */
 }
 /* vrátíme získaný výsledek */
 return(fact);
 }
 /* faktoriál pomocí cyklu do .. while */
 unsigned faktorial(unsigned n)
 {
 /* proměnná obsahující výsledek */
 unsigned fact= 1;
 /* nula se musí ošetřit zvlášť, cyklus alespoň jednou proběhne, což se pro n = 0 
státi nemá */
 if (n == 0) return(fact);
 /* dokud nedojdeme až k nule, provádíme tělo cyklu = blok */
 do
 {
 fact *= n;
 /* vynásobení n */
 n--;
 /* snížíme n o 1 */
 }
 while (n != 0);
 /* vrátíme získaný výsledek */
 return(fact);
 }
 /* faktoriál pomocí cyklu for */
 unsigned faktorial(unsigned n)
 {
 /* proměnná obsahující výsledek */
 unsigned fact;
 /* dokud nedojdeme až k nule, provádíme tělo cyklu = blok; podmínka n != 0 je 
totožná s podmínkou n */
 for(fact = 1; n; n--) fact *= n;
 /* vrátíme získaný výsledek */
 return(fact);
 }
 Vytlačiť článok 
 
 Pozn.: články boli naskenované ako text a preto obsahujú aj zopár chýb. Taktiež neručíme za zdrojové kódy (Asm, C, Arexx, AmigaGuide, Html) a odkazy na web. Dúfame, že napriek tomu vám táto databáza dobre poslúži.
 Žiadna časť nesmie byť reprodukovaná alebo inak šírená bez písomného povolenia vydavatela © ATLANTIDA Publishing
 
 
 
none 
 |