na obsah klávesové zkratky na hlavní stránku na menu

Podmínky a cykly

Podmínky jsou nesmírně silnou technikou pro ovlivňování chodu programu. Cykly nám usnadní zpracovávání opakujících se událostí bez zbytečné duplikace kódu. V tomto článku se krátce podíváme na obě techniky.

Podmínky

Podmínky jsou v jazyce C dobře podporovány. Obecná plná podmínka má následující strukturu

if (<podmínkový výraz>)
<příkaz>
else
<příkaz>

Všimněme si kulatých závorek kolem podmínkového výrazu. Ty jsou nutné a nelze je vynechat, ukončují totiž výraz. V jazyce Pascal k tomu sloužilo klíčové slovo then, to v jazyce C není. Zpracování probíhá tak, že program nejdříve vyhodnotí podmínkový výraz a je-li výsledek pravda, provede první příkaz. Pokud podmínka splněná není, provede se druhý příkaz za klíčovým slovem else. Větev s else lze vynechat, dostaneme tak neúplnou podmínku. Pokud pak není podmínkový výraz splněn, nic se neprovede a program bude pokračovat prvním příkazem za podmínkou. V těle podmínky samozřejmě můžeme mít víc příkazů, musíme je ale obalit do bloku složených závorek. Na rozdíl od Pascalu se také píše středník před else, protože středník se v jazyce C chová poněkud jinak než v Pascalu.

if (a > 0)
a *= -1; // zde musí být středník
else
a += 2;

Ukázka jednoduché úplné podmínky. Je-li a ostře větší než nula, vynásobí se a mínus jednou, čímž dojde k otočení znaménka. Jinak se do a přičtou dvě.

if (a < 0)
printf("číslo je záporné\n");

V tomto případě se text vypíše jen a pouze, pokud je číslo a ostře menší než nula. V podmínkovém výrazu můžeme využít řadu porovnávacích a logických operátorů. Je třeba dát pozor a neplést si logické a bitové operátory, logické operátory se zapisují zdvojeně!

Vyhodnocování podmínkového výrazu

Jazyk C je velmi benevolentní, pokud jde o vyhodnocování podmínkových výrazů. Podívejme se na následující ukázky:

int a = 1;
if (a) //...

if (a == 1) //..
if (a = 1) //..

V sekci proměnné jsme si říkali o implicitním přetypování. To funguje i v logických výrazem. Jakákoliv nenulová hodnota je vyhodnocena jako pravda. Jakákoliv forma nuly je vyhodnocena jako nepravda. Jazyk C nemá žádný speciální typ bool (až v C99 a C++), vystačit si tak musíme s typy char a int, které se pro uchování logických hodnot nejčastěji používají. První podmínkový výraz se tak vyhodnotí jako pravda a první část podmínky se provede. Ve druhém případě se ptáme, jestli je a rovno jedné. To je pravda, a tak se první část podmínky provede. Co ale znamená poslední podmínkový výraz? Zde totiž ve výrazu přiřazujeme do a hodnotu jedna. Výsledek přiřazení je přiřazovaná hodnota, a tak se podmínka vyhodnotí jako jedna, tedy vždy jako pravda!! Proto si dávejte pozor, jestli při porovnávání používáte správně dvě rovnítka.

Na rozdíl od Pascalu jazyk C provádí v základu tzv. zkrácené vyhodnocování výrazů. V praxi to znamená, že podmínka je vyhodnocována zleva doprava a jakmile je jasné, jaké hodnoty podmínka nabude, vyhodnocování je ukončeno.

if ((a == 1) && longCalculation())
//...

V kódu výše je uveden složený podmínkový výraz. Pokud je hodnota proměnné a jiná než jedna, k zavolání funkce longCalculation() vůbec nedojde. To se může hodit, pokud víme, že taková funkce běží dlouho.

Vícenásobné větvení

Programovací jazyk C umožňuje přehledně zapsat podmínku, která má více možných stavů v závislosti na hodnotě výrazu. Jedná se o příkaz switch s následující syntaxí:

switch (<podmínkový výraz>)
{
  case <hodnota>:<příkaz>
  ...
  <[default:<příkaz>]>
}

Podmínkový výraz se musí vyhodnotit jako celočíselná hodnota (tedy i znak). Porovnávání jiných typů není možné. Příkaz funguje tak, že se nejprve vyhodnotí výraz a jeho výsledek se pak hledá odshora v hodnotách jednotlivých case větví. Jakmile se najde první shoda, vykoná se příkaz za dvojtečkou. Na rozdíl od Pascalu se pak pokračuje ve vykonávání následujících větví, interně se totiž při shodě hodnot pouze skočí na dané místo v kódu a vše od tohoto místa se vykoná. Pokud chceme vykonat právě jednu větev (což je obvyklé), je nutné příkaz na konci větve ukončit příkazem break. Nenajde-li se shoda s žádnou hodnotou, provede se nepovinná větev default.

int i = 1;
switch (i)
{
  case 2:
  i = 4;
  break; // ukončení větve
  case 3:
  i = 6;
  // zde má být break, jinak pokaždé provedeme část default
  default:
  i = 0;
}

V tomto příkazu switch se rozhodujeme na základě hodnoty proměnné i. Je-li hodnota dvě, nastavíme proměnnou na hodnotu čtyři a příkaz ukončíme. Je-li hodnota tři, nastavíme proměnnou na hodnotu šest a dále znovu nastavíme hodnotu na nulu, protože jsme neukončili příkaz a ten tak bude pokračovat ve vykonávání zbylého kódu.

Ternární výraz

V jazyce C existuje právě jeden ternární výraz. Hodí se pro zkrácené zapsání jednodušší podmínky.

<podmínka>?<příkaz>:<příkaz>

Při zpracování příkazu se nejprve vyhodnotí podmínka a je-li výsledek pravda, vykoná se první příkaz před dvojtečkou. Je-li výsledek nepravda, vykoná se příkaz za dvojtečkou. Klasickou ukázkou je implementace funkce abs().

(x >= 0) ? x : -x;

Cykly

V jazyce C máme celkem tři typy cyklů. Je to for, while a do-while.

Cykly while a do-while

Cykly while a do-while jsou si velmi podobné a liší se jen prvním průběhem. U while se podmínkový výraz vyhodnotí před prvním provedením těla cyklu, zatímco u do-while se tělo provede vždy alespoň jednou.

while (<podmínkový výraz>)
<příkaz>
do
<příkaz>
while (<podmínkový výraz>)

Jako u podmínky i zde můžeme do cyklu vložit více příkazů, které ovšem musíme umístit do bloku. U obou variant se cyklus provádí do té doby, dokud je výraz vyhodnocen jako pravda (pomůcka: while jako zatímco platí).

Cyklus For

Cyklus for je z celé skupiny nejkomplikovanější a na rozdíl od svého ekvivalentu v Pascalu je daleko mocnější. Příkaz má následující strukturu:

for (<[inicializace]>;<[podmínkový výraz]>;<[iterace]>)
<příkaz>

Všechny části uvnitř kulatých závorek jsou nepovinné. První část se provede před prvním provedením cyklu a hodí se pro prvotní nastavení hodnot proměnných. Druhá část je podmínkový výraz, který jako u ostatních typů cyklů řídí ukončení cyklu. Pokud ho vynecháme, poběží cyklus donekonečna. Poslední část se provádí při každém průběhu cyklu. Lze použít pro zvýšení hodnoty nebo jakékoliv nastavení, které je nutné provést při každém průběhu. Klasická forma cyklu for vypadá takto.

int i;
for (i = 0; i < 10; i++)
{
  //...
}

Tento cyklus provede celkem deset iterací. Řídící proměnná musí existovat před voláním cyklu, její definici v těle cyklu lze provést až v C99 nebo v C++. Cyklem for lze ale také simulovat chování cyklu while pouhým vynecháním první a poslední části:

int i;
// ...
for (;i != 10;)
{
  //...
}

kde cyklus poběží, dokud bude proměnná i různá od deseti.

Break a Continue

V jazyce C existují dva příkazy pro ovlivnění vykonávání cyklů. Je to break a continue. Příkaz break ukončí okamžitě vykonávání cyklu a program následuje prvním příkazem za cyklem. continue okamžitě ukončí aktuální iteraci a započne novou. Oba příkazy lze volat pouze uvnitř těla cyklu (příkaz break lze umístit i do příkazu switch).