Řídící struktury - cykly

03-Cykly

Typy a charakteristika cyklů

Cykly jsou strukturované příkazy, součástí každého z nich je příkaz, jehož opakované provádění cyklus předepisuje. Tento příkaz nazýváme tělo cyklu. Opakování těla cyklu závisí na hodnotě výrazu, o kterém budeme také hovořit jako o podmínce opakování. Jednotlivé průchody tělem cyklu označujeme jako iterace.
Někdy potřebujeme provádění cyklu ukončit předčasně. K tomu můžeme použít příkaz break. Jestliže potřebujeme předčasně ukončit jednotlivou iteraci (vynechat při průchodu zbytek těla cyklu), můžeme použit příkaz continue.

Příkaz while

Příkaz while představuje cyklus s podmínkou na počátku.

while ( podmínka ) příkaz

Kde příkaz je tělo cyklu. Podmínka je výraz, který lze implicitně převést na typ bool. Podmínka může obsahovat deklaraci proměnné (jen v C++) a tato proměnná bude lokální v těle cyklu.

Význam příkazu while:
Nejprve se vyhodnotí podmínka, což je výše zmíněná podmínka opakování. Je-li nepravdivá, tělo cyklu se neprovede a provádění příkazu while skončí.
Je-li podmínka splněna, provede se příkaz tvořící tělo cyklu. Poté se opět vyhodnotí podmínka.
Je-li nyní nepravdivá, tělo cyklu se již neprovede a příkaz while skončí. Je-li opět splněna, znovu se provede tělo cyklu, vyhodnotí se podmínka atd. Podmínka opakování se tedy vyhodnocuje před každou iterací. Není-li podmínka před prvním průchodem splněna, neprovede se tělo cyklu while ani jednou.

Příkaz do-while

Zkráceně označovaný jako příkaz do. Je to cyklus s podmínkou na konci.

do příkaz while ( výraz );

Výraz v příkazu do musí mít hodnotu číselného typu, typu ukazatel nebo objektového typu, pro který existuje možnost přetypování na typ bool. Syntaktická pravidla nyní charakterizují podmínku opakování jako výraz; jediný rozdíl se srovnání s podmínkou v příkazu while je v tom, že výraz zde nemůže obsahovat deklaraci.

Význam příkazu do:
Nejprve proběhne tělo cyklu, tedy příkaz. Pak se vyhodnotí výraz. Pokud je roven false, znamená to, že podmínka opakování není splněna a provádění příkazu do skončí. V opačném případě se opět provede tělo cyklu a znovu se testuje podmínka opakování atd. To znamená, že tělo cyklu se provede vždy alespoň jednou.

Příkaz for

Příkaz for je asi nejsložitější z cyklů v jazyce C++

for ( inicializační_příkaz; podmínka ; krok ) příkaz;

Inicializační_příkaz je příkaz, který chceme provést před vstupem do cyklu. Končí středníkem, může obsahovat deklaraci (C++) a může být prázdný (tj. může obsahovat pouze středník).
Podmínka představuje podmínku opakování a má stejný význam jak u ostatních cyklů; může obsahovat deklaraci a také zde můžeme zapsat prázdný výraz. Krok je vlastně výrazový příkaz (bez středníku), který chceme provést po každém průchodu tělem cyklu; zpravidla předepisuje změny proměnných, které je třeba po průchodu tělem cyklu udělat. I tento výraz může být prázdný.
Proměnné, deklarované v inicializačním_příkazu a v podmínce, jsou lokální v těle cyklu. Přesněji: Proměnné, deklarované v inicializačním_příkazu, můžeme použít v podmínce, v kroku a v těle cyklu. Proměnné, deklarované v podmínce, můžeme použít v kroku a v těle cyklu.

Příklad: Příkaz for se často používá při zpracování polí. Chceme-li např. vynulovat všechny prvky pole A o 100 prvcích, napíšeme:

const N = 100; int A [N] ;
// ...
for(int i = 0; i < N; i++) A[i] = 0;

Tento příkaz znamená: Na počátku uložíme do proměnné i hodnotu 0. Pak vyhodnotíme podmínku opakování; protože je i < 100, je tato podmínka splněna, takže proběhne tělo cyklu — do A[0] se uloží 0. Pak se vyhodnotí výraz i++, tj. v i bude nyní 1. Opět se vyhodnotí podmínka opakování, a protože je stále i < 100, znovu proběhne tělo cyklu — do A[l] se uloží 0. Vyhodnotí se výraz i++, takže v i bude 2, atd. Při posledním průchodu tělem cyklu bude i == 99 a do A [99] se uloží 0. Po vyhodnocení reinicializačního výrazu (kroku) bude i == 100, podmínka opakování nebude splněna a provádění příkazu for skončí.

for (;;) { //nekonečný cyklus; }

Poznámky k cyklům

  • Používat pouze jednu řídící proměnnou
  • Řídící proměnná ovlivňována pouze v řídící části cyklu a ne v těle cyklu.
  • Pokud má cyklus prázdné tělo, jeho ukončující středník je na nové řádce.
  • Continue lépe nahradit čitelnějším konstrukcí if-else.
  • Break by se měl vyskytovat jen v nejnutnějším případě a na jednom místě.
  • Přednost while a for před do-while, kvůli přehlednosti.

Grafický zápis

Příkazy break, continue

Podobně jako ve většině jiných programovacích jazyků se i v C++ příkazy za normálních okolností vyhodnocují sekvenčně, tj. v pořadí, v jakém jsou zapsány. Některé příkazy ovšem mohou tuto přirozenou posloupnost přerušit a přenést řízení na jiné místo programu.

Příkaz break

Tento příkaz smíme použít jen v těle cyklu (for, while, do) nebo v těle příkazu switch; vvskytne-li se jinde, ohlásí překladač chybu.
Význam příkazu break:
Ukončuje nejvnitřnější neuzavřenou smyčku a hned opouští cyklus. A také obsáhleji:
Příkaz break způsobí ukončení příkazu cyklu nebo přepínače (switch), v jehož těle se vyskytl. Při několika do sebe vnořených příkazech do, while, for nebo switch způsobí ukončení nejvnitmějšího z nich, který tento příkaz break obklopuje.

Příkaz continue

Příkaz umožňuje předčasně ukončit daný průchod tělem cyklu (iteraci). Smí se vyskytnout pouze v těle cyklu (v příkazech for, do a while). Jeho použití kdekoliv jinde způsobí chybu.
Význam příkazu continue:
Skáče na konec nejvnitřnější neuzavřené smyčky a tím vynutídalší iteraci smyčky, cyklus neopouští. Také:
Příkaz continue přenese řízení na pokračovací část nej vnitřnějšího příkazu while, do nebo for, v jehož těle se vyskytl. To znamená, že ukončí právě probíhající iteraci a způsobí vyhodnocení podmínky pro pokračování (a v cyklu for ještě reinicializaci, tedy vyhodnocení výrazu).

Příkaz return

Význam příkazu return:
Příkaz return ukončí provádění těla funkce, v níž se nachází, a vrátí řízení funkci volající.
První varianta, ve které není uveden výraz, se používá ve funkcích typu void (které nevracejí žádnou hodnotu, tedy v procedurách). Uvedeme-li výraz, vrátí funkce hodnotu tohoto výrazu. Typ výrazu musí být možné implicitně převést na typ vracené hodnoty uvedený v deklaraci funkce, podobně jako např. při přiřazení.

Funkce typu void nemusí příkaz return obsahovat. Dojde-li řízení v těle funkce až ke složené závorce „}“ ukončující její tělo, je to stejné, jako kdyby zde byl zapsán příkaz return; (bez výrazu).

Z funkcí jiného typu (tj. z funkcí, které vracejí nějakou hodnotu) se musíme vždy vrátit pomocí příkazu return s výrazem odpovídajícího typu.