Jak jednoduše pochopit používání cyklů v programech? Právě toto se dozvíte v dnešním článku, který je zaměřen zejména pro začátečníky nebo těm, kteří stále tápou.
Znám pár lidí, kteří nemůžou pochopit, jak cykly pracují nebo jak je používat. To jim pak nedovoluje napsat složitější programy tak, jak by si přáli. Také jsou tady studenti, kteří mají programování v C jako jeden z předmětů ve škole a právě těm se může podobný článek hodit. Nevím jak jinde, ale na mé škole, respektive od učitele, který má naší třídu na programování, se prostého vysvětlení cyklů nedočkáte. A i kdyby měl být tento článek pro těch pár jedinců z mojí třídy – proč ne.
Cykly jsou jednou ze základních řídících struktur programů, a to nejen v jazyce C/C++, ale obecně. Pochopení cyklů vás posouvá k možnostem psát téměř dokonalé programy, které jsou uživatelsky přívětivé. A můžete v klidu programovat až do okamžiku, kdy se k vám dostane okruh programování zvaný pointery (ukazatele). Ale to je už jiná kapitola…
V tomto článku se budu zabývat cykly, které jsou použitelné jak v programovacím jazyku C, tak v C++. V článku je používána syntaxe z jakyka C. Princip použití v C++ je ovšem naprosto stejný, pouze používáte jiné příkazy. Stavby cyklů jsou jinak stejné.
O co tady vlastně jde
Představte si jednoduchý příklad, kdy máte vypsat věk určitého počtu osob. Bez existence cyklů bychom museli napsat něco takového:
výpis věk osoby 1
výpis věk osoby 2
.
.
atd
Z tohoto můžeme jasně vyvodit, že kód programu by byl jednak velice dlouhý a jednak poměrně nepřehledný. Pokud bychom měli tuto úlohu zrealizovat pomocí cyklů, napsali bychom posloupnost příkazů:
Což by se dalo znázornit i takto:
přiřazení hodnoty počítadla
{
příkaz(y) – tělo cyklu, tedy to co se má vykonat, je-li splněna určitá podmínka
}
podmínka – pokud je splněna, tělo cyklu se provede znova
Hovořím tady o nějaké podmínce, která zde má obdobné využití jako u klasického větvení. Pokud je splněna určitá podmínka (v našem příkladě to znamená, že počítadlo nedosáhlo hodnoty počtu osob, jejichž věk chceme vypsat), tělo cyklu proběhne znova. V opačném případě se cyklus ukončí a pokračuje se následujícím příkazem za cyklem (hodnota počítadla dosáhla počtu osob – není již tedy třeba dále vypisovat věk). Právě v podmínkách může nastat občas problém. Nechtěně totiž můžete vytvořit podmínku, která bude platit vždy a cyklus tak bude probíhat neustále. Funkčnost programu tak může být značně, v horším případě zcela, omezena. Příklad cyklu, který nikdy neskončí:
počítadlo = 5
{
tělo cyklu
navýšení počítadla o 1
}
podmínka: počítadlo < 5
Tady se bude cyklus neustále opakovat, protože výchozí hodnota počítadla je 5, přičemž se bude při každém opakování cyklu navyšovat.
Cyklus je tedy jakási ohraničená smyčka obsahující příkazy. Ty se provádějí, pokud je splněna nějaká podmínka. Její definice má určitá pravidla a stejně tak stavba cyklu má několik základních prvků. Ještě před tím, než si ukážeme jednotlivé cykly, které jazyk C/C++ umožňuje, podíváme se na dva příkazy, které mohou být v některých případech velice užitečné. Oba se můžou použít ve všech typech cyklů a oba nějakým způsobem mění jejich provádění.
break - okamžitě ukončuje provádění cyklu a opouští jej
continue – udělá skok na konec cyklu a vynutí jeho opakování, cyklus se tedy neukončuje
Cyklus while
Nyní se již podíváme na jednotlivé cykly podrobně. Každý cyklus má určitou strukturu a slova, která ho definují. První z cyklů je z pohledu kódu nejjednodušší a nazývá se while - cyklus s podmínkou na začátku. Tento cyklus testuje podmínku před samotným provedením těla. Z toho vyplývá, že cyklus nemusí proběhnout ani jednou. Pokud není před prvním průchodem splněna podmínka, cyklus se jakoby přeskočí a pokračuje se následujícím příkazem. Cyklus se používá v případě, pokud nevíme, kolikrát v programu proběhne. Ukončovací podmínka tedy závisí na nějaké akci (příkazu) uvnitř těla cyklu.
Obecná syntaxe:
while (výraz) {
tělo cyklu
}
Příklad:
while (i < 10) { /* Výraz musí být uveden v závorkách */
printf("Ahoj"); /* Vypíše text */
i++; /* Navýšení proměnné i o 1 */
}
Pokud za podmínkou následuje pouze jeden příkaz, nemusí se složené závorky psát, podobně jako je tomu u klasického větvení if-else. Následující příklad potvrdí nejen toto, ale také ukáže využití tohoto cyklu v praxi. Program načítá znaky a počítá, kolik jich bylo zadáno před první zadanou číslicí:
#include <stdio.h>
int main()
{
int i = 0;
int znak;
while ((znak = getchar()) < '0' || znak > '9')
i++;
printf("Bylo zadano %d neciselnych znaku.", i);
return 0;
}
Pokud není načtený znak číslo, cyklus se opakuje. Příklad navíc demonstruje, že podmínky mohou být i složitější, v této se nejprve načtě znak a potom provede vyhodnocení podmínky.
Cyklus do-while
Jinými slovy, je to cyklus s podmínkou na konci. Používá se v přípdadech, kdy víme, že cyklus musí být proveden alespoň jednou, příčemž nemusíme znát kolik opakování přesně bude. Pokud program dospěje k cyklu, provede bez okolků všechny příkazy v jeho těle a potom narazí na podmínku. Pokud je tato podmínka splněna, program se vrací na začátek těla cyklu a ten se opakuje. V opačném případě je cyklus ukončen.
Obecná syntaxe:
do {
tělo cyklu
} while (výraz);
Příklad:
do {
printf("Ahoj");
i++;
} while (i > 10);
Na rozdíl od předchozího cyklu, tento provede o jedno vypsání více, protože ještě než dojde k testování podmínky, tělo cyklu je jednou provedeno. Jinak není v podstatě na tomto cyklu jiný významný rozdíl. Nyní si ještě ukážeme praktický příklad využití. Program načte od uživatele celé číslo a vypíše jeho cifry v opačném pořadí. Pokud je zadáno záporné číslo, převede ho na kladné.
#include <stdio.h>
int main()
{
int cislo, cifra;
scanf("%d", &cislo); /* Načtení čísla */
if (cislo < 0)
cislo = cislo*(-1);
do {
cifra = cislo %10; /* Zbytek po dělení 10 */
printf("%d", cifra); /* Výpis zbytku */
cislo = cislo / 10; /* Celočíselné dělení 10 */
} while (cislo > 0);
return 0;
}
Podmínka na konci cyklu testuje, jestli není číslo 0, protože další dělení už by nemělo smysl. Použití tohoto cyklu v tomto příkladu je více než vhodné, protože víme, že cyklus musí proběhnou alespoň jednou – číslo má alespoň jednu cifru. Šlo by to samozřejmě realizovat i pomocí cyklu while. Sami už musíte zjistit, který cyklus vám více vyhovuje.
Cyklus for
Tento cyklus se používá v případech, kdy předem víme, kolikrát proběhne. Velice často se používá při práci s poli, kdy hodnota iteračního výrazu určuje, se kterou hodnotou v poli se bude v tomto okamžiku pracovat.
Obecná syntaxe:
for (počáteční výraz; podmínka; iterační výraz) {
tělo cyklu
}
Příklad:
for (i = 0; i < 10; i++) {
printf("Ahoj");
}
První výraz v závorce nastaví počáteční hodnotu proměnné, která se používá ke kontrole, zda má již cyklus skončit. Další výraz je podmínka a poslední je příkaz k navýšení nebo zmenšení hodnoty proměnné, kterou jsme nastavili v první části. Po každém průchodu se navýší hodnota iteračního výrazu. V příkladu výše proběhne cyklus 10× a tolikrát se také vytiskne text. Počátečním výrazem je přiřazení, které vynuluje naši řídící proměnnou. Poté dojde k testování, jestli platí podmínka – toto je předpokladem k dalšímu provedení cyklu. Nakonec se tedy řídící proměnná navýší o 1. Vše takto pracuje, dokud hodnota i není 9, pak cyklus končí.
Ještě jednou ve stručnosti:
Následující program vytvoří pole o 10 celých číslech a do každé pozice uloží náhodně vygenerované číslo od 1 do 99 a vytiskne je.
#include <stdio.h>
#include <time.h>
int main()
{
srand((unsigned)time(NULL)); /* Inicializace generátoru */
int pole[10];
int i;
for (i=0; i<10; i++) { /* Deset průběhů */
pole[i] = rand() % 100; /* Přířazení náhodného čísla do pozice v poli */
printf("%d\n", pole[i]); /* Tisk pozice s číslem */
}
return 0;
}
Tento program zároveň ukazuje běžnou práci s poli. Řídící proměnná se používá pro určení pozice v poli, do kterého se ukládá náhodně vygenerované číslo. Obdobně je tatáž pozice o řádek níže vytištěna na obrazovku. Pole začíná od 0, proto je tak nastavená i řídící proměnná před začátkem cyklu.
Zásady dobré práce s cykly:
Na závěr
Tento přehled cyklů a použití byl opravdu pro začínající programátory nebo pro ty, kteří stále tápali. Doufám, že tomu tak již není. Alespoň jsem se tedy pokusil o maximálně zjednodušené vysvětlení.