Co je to cyklus
Jak již samotný název napovídá, jedná se o něco, co se bude opakovat. V programování tedy cykly používáme, chceme-li nějakou sekvenci příkazů několikrát zopakovat. Můžeme mít tedy nějaký příkaz, u kterého budeme chtít, aby se provedl desetkrát, tudíž použijeme cyklus. Existují dvě možnosti, jak říct, kolikrát se příkaz zopakuje. První možostí je, že přesně víme, kolikrát chceme něco opakovat, čili např. desetkrát. Druhá možnost je taková, že chceme, aby se sekvence příkazů opakovala tak dlouho, dokud platí nějaká podmínka (popř. dokud neplatí nějaká podmínka). Proto si cykly v programování můžeme rozdělit do dvou skupin - cyklus for a cyklus while.
Cyklus for
U tohoto cyklu známe předem počet opakování. Jinak řečeno víme, že daný příkaz chceme zopakovat právě n-krát. Uvedeme si krátký, v praxi zcela zbytečný příklad. Chceme desetkrát za sebou vypsat na obrazovku text "Umim pouzivat cyklus". Pokud byste cykly neznali, asi byste napsali desetkrát příkaz cout. Jednodušší řešení je však toto:
for (int i = 0; i < 10; i++)
{
cout << "Umim pouzivat cyklus\n";
}
Tento kód Vám na obrazovku skutečně vypíše text desetkrát. Otázkou zůstává, jak to celé funguje. Není v tom skryta žádná složitost. Klíčovým slovem for uvozujeme, že se jedná o cyklus. V kulatých závorkách máme proměnnou i typu int, kterou inicializujeme na nulu. Této proměnné se říká iterační. Za nastavením proměnné na hodnotu 0 následuje středník a podmínka, že cyklus se bude opakovat tak dlouho, dokud bude proměnná i menší než hodnota deset. V poslední části se v závorkách nachází inkrementace proměnné i. To, co se vyskytuje ve složených závorkách jsou příkazy (v našem případě jeden příkaz), které se budou opakovat. Na obrazovku se tedy vypíše text "Umim pouzivat cyklus" a hodnota proměnné i se zvýši o jedna. Zkontroluje se, jestli hodnota i je menší než deset a poté se celý příkaz provede znovu. Tak se to celé bude opakovat do doby, než hodnota i bude rovna deseti. Pak cyklus skončí. S iterační proměnnou (proměnná i) je možné pracovat i v těle cyklu, jako s každou jinou proměnnou. Zkuste uhádnout, co na obrazovku vypíše následující fragment kódu:
for (int i = 0; i < 5; i++)
{
cout << i + 1 << "\n";
}
Pokud si myslíte, že se na výstupu objeví čísla od jedné do pěti, máte pravdu. Proměnná i se každým průchodem zvyšuje o jedničku, její původní hodnota je nula a vypisuje se vždy hodnota o jedničku vyšší, než i (i + 1). V prvním průchodu je tedy hodnota proměnné i rovna 0, vypisujeme ale 0 + 1, tedy jedna. V dalším průchodu už hodnota i je jedna, vypíše se tedy 1 + 1, čili dva. Celé to pokračuje do doby, než bude mít i hodnotu 5 - v tu chvíli cyklus končí.
V tuto chvíli možná ještě nevidíte obrovský přínos, kterými cykly v programování jsou. Vězte ale, že postupem času to zjistíte, možná už i u příkladu, který si uvedeme na konci tohoto článku. Nevýhodou cyklů je, že si musíte dát pozor, abyste náhodou nenapsali tzv. "nekonečný cyklus", který Vám nikdy neskončí. Uvedu směšný příklad, abyste viděli co myslím.
for (int i = 0; i > -5; i++)
{
cout << "Nekonecny cyklus";
}
Cyklus nám poběžím tak dlouho, dokud hodnota proměnné i bude větší než číslo -5. Problém je v tom, že původní hodnota proměnné i je 0 a s každým dalším průchodem se zvyšuje, čili bude pořád větší než -5. Cyklus proto nikdy neskončí a na kód, který se vyskytuje v programu pod cyklem, se nikdy nedostane. Toto byl velmi primitivní příklad nekonečného cyklu, asi si říkáte, že to se Vám nemůže nikdy stát. Pokud ale budete programovat, stane se Vám to. Nebude se ale samozřejmě jednat o takovýto banální příklad.
Co se týče iterační proměnné i, je čistě na Vás, jak si ji pojmenujete. Nikde není psáno, že musíte používat zrovna i, nicméně je to jakýmsi zvykem. Ani hodnota, na kterou proměnnou i nastavíte, nemusí být nula. A také nemusíte při každém průchodu zvyšovat hodnotu o jedničku, můžete si ji třeba násobit pětkou, exponenciálně zvětšovat, dělit, odečítat, zkrátka co Vás napadne. Vemte však v potaz, že poté je mnohem složitější poznat, k čemu onen cyklus vlastně slouží.
Vnořené cykly, anebo cykly v cyklech
Aby to celé bylo ještě trochu zajímavější, řekneme si o vnořených cyklech. V těle cyklu se vyskytuje nějaké sekvence příkazů, které se budou opakovaně provádět. Co když ale do těla cyklu umístíme další cyklus? Pokud toto uděláme, máme vnořený cyklus. Jednoduchý příklad:
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 2; j++)
{
cout << i << "." << j << "\n";
}
}
Tělo vnějšího cyklu (ten s iterační proměnnou i) se bude opakovat celkem dvakrát. V těle cyklu se však vyskytuje další cyklus, jehož tělo se bude opakovat také dvakrát. Příkaz cout se tedy provede celkem čtyřikrát (2 x 2 = 4), pokaždé však proměnné i a j mají jinou hodnotu. Uvědomte si, že na jeden průchod vnějšího cyklu je nutné provést všechny průchody vnitřího cyklu. Tímto způsobem do sebe můžete vnořit tereticky nekonečný počet cyklů, nicméně mít sto vnořených cyklů není zrovna "to pravé ořechové".
Program - průměr známek ve škole
V minulém díle jsme na závěr počítali průměr z pěti známek. K uložení známek jsme využili pole. V dnešním díle si celý program napíšeme znovu, nicméně trochu jinak, lépe. Umíme totiž používat cykly, proto bude program o hodně snažší. Uvědomte si, že uživatel zadává pět známek, což by Vám mělo napovědět, že příkaz, kterým uživatele vybídneme k zadání známky, se bude vyskytovat v těle cyklu. Dále dojde k uložení známky na patřičné místo v poli. Vzhledem k tomu, že v našem případě počítáme průměr z pěti známek, cyklus proběhne právě pětkrát. Nějak takto by mohl vypadat kód:
#include <iostream>
using namespace std;
int main()
{
int soucet, znamky[5];
double prumer;
soucet = 0;
for (int i = 0; i < 5; i++)
{
cout << "Zadej " << i + 1 << ". znamku: ";
cin >> znamky[i];
soucet += znamky[i];
}
prumer = soucet / 5;
cout << "Tvuj prumer je " << prumer << ".\n";
return 0;
}
Určitě se mnou budete souhlasit, když řeknu, že tento kód je mnohem "hezčí" než ten v předchozím díle. Dále je zde výhoda v tom, že kdybychom chtěli počítat průměr třeba ze sta známek, kód by zůstal stále stejně dlouhý. Jedinné, co by se změnilo, je číslo 5, které bychom nahradili číslem 100.
Pro tento díl je to vše, v díle příštím budeme s cykly pokračovat, podíváme se však na cykly while. Pokud si myslíte, že jste cykly pochopili, můžete se zkusit podívat na následující úkoly:
Máme následující fragmenty kódů:
for (int i = 5; i < 10; i += 2)
{
cout << i + 3 << "\n";
}
int vysledek = 0;
for (int i = 0; i < 5; i++)
{
for (int j = 5; j > 0; j++)
{
vysledek = i + j;
}
}
cout << vysledek;
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 5; j++)
{
int soucet = 0;
soucet = soucet + i + j;
}
}
cout << soucet;
Co se objeví na výstupu u jednotlivých kódů? Je v kódu něco špatně? Předpokládejte, že v programu máme řádně napsanou funkci main a další potřebné náležitosti.
Pokud by něco nebylo jasné, napište do diskuze, není problém cokoliv lépe vysvětlit.