Podmínky jsou nesmírně silnou technikou pro ovlivňování chodu programu, umožňují nám větvit program na základě vyhodnocení podmínky. 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.

Příkazy

V jazyce C jsou jednoduché a složené příkazy. Každý jednoduchý příkaz je ukončen středníkem.

Několik jednoduchých příkazů lze pomocí složených závorek proměnit ve složený příkaz.

int a = 1;
int b = 2;
int t = 0;

a = a + b;	// jednoduchý příkaz

// složený příkaz, prohození hodnot proměnných a, b
{
	t = a;
	a = b;
	b = t;
} // konec složeného příkazu

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_1>
else
	<příkaz_2>

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. 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.

I když je příkaz jenom jeden, je velmi vhodné psát okolo něj složené závorky.

Podmínka se složeným příkazem
if (<podmínkový výraz>) {
	<příkaz_1_1>
	<příkaz_1_2>
	// ...
    }
else {
	<příkaz_2_1>
	<příkaz_2_2>
	// ...
    }

Odsazování příkazů je jenom z důvodů čitelnosti programu, není to jako v Pythonu, kde odsazování určuje příkaz.

Jednoduchá úplná podmínka
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ě.

Jednoduchá neúplná podmínka
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; (1)
if (a) //... (2)

if (a == 1) //.. (3)
if (a = 1) //.. (4)
1 Definice a inicializace proměnné a, hodnota uložená v proměnné a je odteď 1.
2 Prasácky napsaný podmínkový výraz, který je vyhodnocen jako pravdivý pokud \(a\ne 0\). Je-li \(a=0\) je výraz vyhodnocen jako nepravidvý. V našem případě je výraz vyhodnocen jako pravdivý. Mnohem lépe je napsat if( a != 0 ).
3 Výraz je vyhodnocen jako pravdivý
4 Velmi častá a těžko odhalitelná sémantická chyba. Do proměnné a se přiřazuje jednička a výraz je vyhodnocen jako pravdivý. Správně má být: if( a == 1 ), potom skutečně testujeme zda proměnná a je rovna jedné.

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() ) (1)
//...
1 Toto je jedna z osobitostí jazyka C. V rámci výrazu se kliedně může volat funkce a hodnota vrácená z funkce se potom ve výrazu vyhodnocuje.

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>?<výraz>:<výraz>

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

int abs(int x)
{
return (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.

cyklus while
while (<podmínkový výraz>)
<příkaz>
cyklus do — while
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 do — while se vždy provede aspoň jednou.

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++.

Cyklus for v C99
for ( int i = 0; i < 10; i++) (1)
{
  //...
}
1 Výhodou tohoto zápisu je to, že indexová proměnná i existuje jenom po dobu provádění cyklu. Po opuštění cyklu proměnná i zaniká.

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.

Příkazy 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).