Minulý týden jsme se seznámili s cykly, přesněji řečeno s cyklem for. Cyklus obecně slouží k opakování určité sekvence příkazů. Sekvence příkazů (někdy též nazývané tělo cyklu) je ohraničena levou a pravou složenou závorkou, avšak pokud má tělo cyklu jen jeden příkaz, je možné blok vypustit a nahradit jej právě tímto jedním příkazem. Předpokladem každého běžného cyklu v programu je, že:
Tyto předpoklady budou vysvětleny v následujícím textu.
Na minulém setkání jsme si ukázali, jak je možné z Arduina zaslat čísla od 1 do 100. Za použití našich běžných znalostí bez cyklů bychom pravděpodobně museli napsat program jako 100 řádků, kde bychom na každém řádku zasílali postupně se zvyšující číslo, tj. nejdříve 1, pak 2 atd. Tento způsob je nevhodný nejen proto, že je mimořádně pracný, ale také proto, že pokud bychom chtěli pozměnit zadání a namísto čísel od 1 do 100 zaslat čísla od 20 do 200, museli bychom velkou část programu přepsat.
Namísto tohoto nevhodného zápisu je možné využít právě cyklus. Již tušíme, co bude v těle cyklu - zasílání určitého čísla. Jak však zabezpečit, že se nám nejdříve pošle právě číslo 1, pak číslo 2 atd? Klíčem k řešení problému je řídící proměnná cyklu.
S řídící proměnnou bývá nakládáno dvojím způsobem:
Mějme řídící proměnnou cyklu s názvem i. V tomto okamžiku pro nás není podstatné, jak je zabezpečeno, že se hodnota proměnné i postupně mění. Každopádně vězme, že proměnná i má při prvním průchodu těla cyklu hodnotu 1, pak 2, 3 ... až 100. To jsou přesně hodnoty, které potřebujeme poslat. V tom případě bude v těle cyklu pouze následující příkaz
for (...) // prozatim nenastaveno { Serial.writeln(i); }
Jak však zařídit, aby řídící proměnná nabývala postupně hodnot 1, 2, … 100? K tomu slouží parametry příkazu for.
for (počáteční_hodnota_proměnné; podmínka_vykonávání_cyklu; změna_hodnoty_řídící_proměnné)
Na počátku nastavíme hodnotu řídící proměnné i na hodnotu 1, neboť víme, že první zaslané číslo má mít právě hodnotu 1. V dalším průběhu cyklu má byt hodnota proměnné i = 2. Jakým způsobem musíme změnit hodnotu proměnné i, aby se její hodnota změnila z hodnoty 1 na hodnotu 2, či z hodnoty 2 na hodnotu 3? Ano, správně, musíme přičíst jedničku. Proto je jako poslední parametr uveden příkaz i = i + 1, který nám právě toto zabezpečí. Kdy však cyklus končí? Cyklus končí tím, že se pošle číslo 100. V parametrech cyklu for se však neuvádí podmínka, kdy cyklus skončí, avšak kdy se má cyklus provádět. Je třeba také počítat s tím, že se tato podmínka ověřuje před každým vykonáním těla cyklu.
Pokud bychom napsali naši podmínku takto, kolikrát by se cyklus provedl?
for (int i = 1; i == 100; i = i + 1) { Serial.writeln(i); }
Odpověď je snadná - ani jednou,.Nejprve by se sice nastavila hodnota i na hodnotu 1, avšak po té by se zjištovalo, zda i má hodnotu 100. Jelikož i nemá hodnotu 100, ale 1, tak by cyklus skončil.
Ještě hůře je odhalitelná následující chyba:
for (int i = 1; i = 100; i = i + 1) { Serial.writeln(i); }
V takovém případě by vznikl nekonečný cyklus, neboť i = 100 není podmínka, ale přiřazení. Přiřazení je zároveň výraz a ten má v tomto případě hodnotu 100, což je Arduinem chápáno jako hodnota true. Ať už je tedy hodnota i jakákoliv, tento zápis bude vždy nabývat hodnoty true, tj. je pravdivý a tělo cyklu se bude vykonávat vždy, tj. nekonečně dlouho.
A co zápis:
for (int i = 1; i < 100; i=i+1)
Tento zápis má také drobné mouchy. Po spuštění programu byste zjistili, že posledním vypsaným číslem je hodnota 99 namísto 100. Proč? Je to z toho důvodu, že poté, co dojde ke zvýšení hodnoty řídící proměnné z hodnoty 99 na100, probíhá ověření podmínky cyklu. No a jelikož 100 není menší než 100, cyklus se ukončí. Poslední vypsané číslo je tedy číslo 99.
Jak upravit parametry cyklu, aby se vypsalo i číslo 100? Tak např. takto:
for (int i = 1; i <= 100; i = i + 1)
Nebo takto
for (int i = 1; i < 101; i = i + 1)
V prvním, pravděpodobně nejlepším řešení, se tělo cyklu vykonává vždy, když je hodnota řídicí proměnné menší nebo rovno 100. Tato podmínka platí již od počátku cyklu, tj. 1 je menší nebo rovna 100, 2 je menší nebo rovno 100 a 100 je menší nebo rovno 100. Po té, co se zvýší hodnota proměnné i na hodnotu 101 se podmínka vyhodnotí naposledy. Jelikož podmínka 101 <= 100 splněna není, tak se cyklus ukončí. Poslednim poslaným číslem je tedy podle očekávání hodnota 100. Řešení číslo 2 je obdobné.
Jelikož náš programovací jazyk obsahuje tzv. inkrementační příkaz, je možné použít i následující zápis, který je v běžné praxi nejčastější:
for (int i = 1; i <= 100; i ++)
Zápisy i=i+1 a i++ jsou pro naše účely shodné.
Pro vyřešení našeho problému by bylo možné použít i následující podmínku:
for (int i = 1; i != 101; i++)
Tento zápis podmínky cyklu by také vedl k očekávaným výsledkům, jen se příliš často nepoužívá (!= je operátor nerovnosti).
Přidat komentář