Jste zde

Domů

Chybová zpráva

  • Notice: Undefined offset: 8 ve funkci user_node_load() (řádek: 3697 v souboru /export/www/tplov.cz/drupal7/modules/user/user.module).
  • Notice: Trying to get property 'name' of non-object ve funkci user_node_load() (řádek: 3697 v souboru /export/www/tplov.cz/drupal7/modules/user/user.module).
  • Notice: Undefined offset: 8 ve funkci user_node_load() (řádek: 3698 v souboru /export/www/tplov.cz/drupal7/modules/user/user.module).
  • Notice: Trying to get property 'picture' of non-object ve funkci user_node_load() (řádek: 3698 v souboru /export/www/tplov.cz/drupal7/modules/user/user.module).
  • Notice: Undefined offset: 8 ve funkci user_node_load() (řádek: 3699 v souboru /export/www/tplov.cz/drupal7/modules/user/user.module).
  • Notice: Trying to get property 'data' of non-object ve funkci user_node_load() (řádek: 3699 v souboru /export/www/tplov.cz/drupal7/modules/user/user.module).
  • Deprecated function: The each() function is deprecated. This message will be suppressed on further calls ve funkci menu_set_active_trail() (řádek: 2405 v souboru /export/www/tplov.cz/drupal7/includes/menu.inc).

Cyklus for

Verze pro tiskVerze pro tisk

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:

  • cyklus používá tzv. řídící proměnnou,
  • cyklus je konečný, tj. v některém okamžiku skončí,

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:

  • řídící proměnná je nastavena/modifikována,
  • řídící proměnná je používána.

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ář

CAPTCHA
Tato otázka je pro ověření, zda jste opravdový návštěvník a ne automatizovaný spamový robot.
Fill in the blank.