Lekce 13 - Cykly v C# .NET podruhé - do-while, break a continue
V minulé lekci, Podmínky v C# podruhé - Ternární výraz a propadávací switch, jsme se věnovali další syntaxi podmínek.
Na úvod by bylo dobré podotknout, že dnešní lekce obsahuje méně používané praktiky a slouží hlavně k tomu, aby nás tyto praktiky nepřekvapily v cizím kódu. Není příliš důležité, abychom je sami uměli používat.
do
-while
Cyklus while
již dobře známe. Méně používaný
do
-while
se liší pouze tím, že se vždy vykoná
nejméně jednou. Podmínka tohoto cyklu je totiž umístěna až za
jeho tělem. Vypadá tedy takto:
do { // kód... } while (podmínka);
I k zapsání tohoto cyklu můžeme využít snippet ve
Visual Studiu: Napíšeme do
a dvakrát stiskneme
Tabulátor. Zbytek cyklu se sám dopíše.
Příklad
Použití do
-while
cyklu si ukažme na naší
kalkulačce z lekce o
cyklech. Pro zkrácení příkladu nebudeme používat verzi s ověřením
uživatelských vstupů.
Varianta s cyklem while
V kalkulačce jsme použili cyklus while
, který umožnil celý
program opakovat, a tak zadávat další a další příklady. Kód vypadal
takto (jedná se o verzi s konstrukcí switch
):
Console.WriteLine("Vítejte v kalkulačce"); string pokracovat = "ano"; while (pokracovat == "ano") { Console.WriteLine("Zadejte první číslo:"); float a = float.Parse(Console.ReadLine()); Console.WriteLine("Zadejte druhé číslo:"); float b = float.Parse(Console.ReadLine()); Console.WriteLine("Zvolte si operaci:"); Console.WriteLine("1 - sčítání"); Console.WriteLine("2 - odčítání"); Console.WriteLine("3 - násobení"); Console.WriteLine("4 - dělení"); int volba = int.Parse(Console.ReadLine()); float vysledek = 0; switch (volba) { case 1: vysledek = a + b; break; case 2: vysledek = a - b; break; case 3: vysledek = a * b; break; case 4: vysledek = a / b; break; } if ((volba > 0) && (volba < 5)) Console.WriteLine("Výsledek: {0}", vysledek); else Console.WriteLine("Neplatná volba"); Console.WriteLine("Přejete si zadat další příklad? [ano/ne]"); pokracovat = Console.ReadLine(); } Console.WriteLine("Děkuji za použití kalkulačky, aplikaci ukončíte libovolnou klávesou."); Console.ReadKey();
Všimněme si, že jsme se u této varianty s while
museli
zamyslet nad výchozí hodnotou proměnné pokracovat
. Té jsme
nastavili hodnotu "ano"
, aby podmínka byla splněna pro první
průchod cyklem. Vymyslet výchozí hodnotu ale může být poměrně složité
a někdy je třeba použít i pomocnou proměnnou.
Varianta s cyklem
do
-while
Když použijeme cyklus do
-while
, výchozí hodnotu
dané proměnné už nemusíme řešit:
Console.WriteLine("Vítejte v kalkulačce"); string pokracovat; do { Console.WriteLine("Zadejte první číslo:"); float a = float.Parse(Console.ReadLine()); Console.WriteLine("Zadejte druhé číslo:"); float b = float.Parse(Console.ReadLine()); Console.WriteLine("Zvolte si operaci:"); Console.WriteLine("1 - sčítání"); Console.WriteLine("2 - odčítání"); Console.WriteLine("3 - násobení"); Console.WriteLine("4 - dělení"); int volba = int.Parse(Console.ReadLine()); float vysledek = 0; switch (volba) { case 1: vysledek = a + b; break; case 2: vysledek = a - b; break; case 3: vysledek = a * b; break; case 4: vysledek = a / b; break; } if ((volba > 0) && (volba < 5)) Console.WriteLine("Výsledek: {0}", vysledek); else Console.WriteLine("Neplatná volba"); Console.WriteLine("Přejete si zadat další příklad? [ano/ne]"); pokracovat = Console.ReadLine(); } while (pokracovat == "ano"); Console.WriteLine("Děkuji za použití kalkulačky, aplikaci ukončíte libovolnou klávesou."); Console.ReadKey();
break
a continue
Někdy je potřeba běh cyklu přerušit. K tomu nám slouží následující dvě klíčová slova.
break
Příkaz break
ukončuje aktuální cyklus. Používá
se nejčastěji tehdy, když pomocí cyklu nalezneme nějakou položku v kolekci
a dále již v jejím procházení nechceme pokračovat. Nebudeme tak
dále zbytečně prohledávat zbytek kolekce, neboť již máme to, co jsme
hledali.
Příklad
Představme si, že máme pole položek a chceme v nich nějakou najít.
Nabízí se použít metodu IndexOf()
nebo Contains()
.
Pokud půjde o pole, bude použití těchto metod vhodné, ale některé kolekce
je nemají nebo například chceme hledat pomocí jiné vlastnosti, než kterou
tyto metody zohledňují. Vyhledávání pak tedy musíme buď napsat hezky
ručně cyklem, nebo k němu použít výrazně pokročilejší konstrukce, než
nyní ovládáme.
Představme si, že máme velké a malé štítky na sklenice. Na všechny sklenice chceme použít buď jedny, nebo druhé štítky. Zajímá nás tedy, zda se text všech popisků vejde na malé štítky. Napíšeme program, který zjistí, zda se v poli nachází slovo delší než 6 znaků. Pokud ano, musíme použít větší štítky.
Cyklem začneme procházet jednotlivá slova, a jakmile najdeme slovo delší
než 6 znaků, uložíme si jeho index. Zatím stále nic nového pod sluncem.
V téže chvíli však cyklus pomocí příkazu break
ukončíme.
Ukázka použití příkazu break
:
string[] seznamOvoce = {"Jablka", "Hrušky", "Švestky", "Meruňky", "Jahody", "Třešně"}; int hledanyIndex = -1; for (int i = 0; i < seznamOvoce.Length; i++) { if (seznamOvoce[i].Length > 6) { hledanyIndex = i; break; } } if (hledanyIndex >= 0) Console.WriteLine("První slovo delší než 6 znaků: " + seznamOvoce[hledanyIndex]);
Výstup:
Konzolová aplikace
První slovo delší než 6 znaků: Švestky
Příkaz break
se v praxi často nahrazuje
příkazem return
za předpokladu, že je kód v naší vlastní
metodě. Vlastní metody se ale naučíme deklarovat až v navazujícím kurzu
Základy objektově orientovaného programování v C#.
Příkaz break
poté doporučujeme spíše nepoužívat,
správnější varianta je kód pro práci s kolekcí vyčlenit do samostatné
funkce.
continue
Příkaz continue
je podobný jako break
.
Používá se však k ukončení pouze aktuální iterace (průběhu) cyklu, a
ne celého cyklu. Cyklus poté rovnou přechází na další
iteraci. Na použití příkazu continue
můžeme narazit např.
při validování položek při procházení nějaké
kolekce.
Příklad
Představme si, že máme od uživatele zadaná čísla a tato čísla chceme sečíst. Uživatel tato čísla zadá jako jeden řetězec, v němž je každé číslo oddělené čárkou. Bohužel musíme počítat i s tím, že uživatel místo čísla zadá nějaký nesmysl. Řešení by mohlo vypadat následovně:
string cislaRetezec = "10,50,abcd,30,9"; // rozložení řetězce do pole string[] cislaPole = cislaRetezec.Split(','); int soucet = 0; foreach (string cislo in cislaPole) { // převedení řetězce na celé číslo int celeCislo; if(!int.TryParse(cislo, out celeCislo)) continue; soucet += celeCislo; } Console.WriteLine("Součet je: " + soucet);
Výstup:
Konzolová aplikace
Součet je: 99
Program sečte všechny správně zadané hodnoty, tedy ty, u kterých metoda
TryParse()
vrátila hodnotu true
. U nesprávně
zadaných hodnot je aktuální iterace ukončena. Místo continue
bychom samozřejmě mohli použít i příkaz if
, kód bychom tím
však zbytečně vnořili.
Zkrácený zápis cyklu for
Následující konstrukce zde uvádíme pouze pro ukázku, s čím vším je možné se setkat v cizích kódech, a není dobrý nápad je používat!
Cyklus for
je možné zapsat takto zkráceně, bez těla
cyklu:
for (int i = 0; i < 10; Console.Write(i++));
Výstup:
Konzolová aplikace
0123456789
Psát logiku průběhu běhu cyklu i logiku v cyklu na jeden řádek ale není intuitivní. Navíc se tak může snadno zapomenout na inkrementaci proměnné, případně ji můžeme inkrementovat vícekrát.
V hlavičce cyklu for
dokonce není nutné uvádět jakýkoliv
příkaz:
for (;;) { // nekonečný cyklus }
Tento zápis je stejný jako:
while (true) { // nekonečný cyklus }
Oba výše deklarované cykly běží donekonečna a můžete se s nimi
setkat ve špatně napsaných zdrojových kódech spolu s příkazy
break
, které z nich potom za nějakých podmínek vyskakují.
Jakmile podmínka není přímo v deklaraci cyklu, je poměrně obtížné zjistit, kdy cyklus vůbec skončí. Z takového cyklu je pak snadné vytvořit nechtěně nekonečný. To platí zvláště tehdy, když z cyklu vyskakujeme vícero podmínkami a nepokryjeme všechny možné případy.
Ač dnešní lekce obsahovala standardní gramatiku C# .NET pro
cykly, z nových konstrukcí používejte pouze
do
-while
a continue
. Přechodně ještě
můžete používat break
, než se dostaneme k objektům
V následujícím kvízu, Kvíz - Pokročilé podmínky a cykly v C# .NET, si vyzkoušíme nabyté zkušenosti z předchozích lekcí.