KURZ: Podmíněné příkazy a podmínkové výrazy

  • Vytisknout

I když si to možná neuvědomujeme, denně řešíme celou řadu podmínek na jejichž základě se rozhodujeme. Když např. chceme přejít po přechodu na světelné křižovatce, podíváme se na semafor a zjistíme, zda svítí zelená barva. Pokud svítí červená, čekáme a sledujeme, zda se barva na semaforu nezměnila. Než začneme přecházet na zelenou, určitě se ještě rozhlédneme, jestli i řidiči aut zpozorovali, že mají zastavit. Celý náš den se tak skládá z celé řady podmínek, u kterých se při jejich splnění či nesplnění rozhodujeme, co provést.

V programu nám takovéto základní rozhodování (tentokrát ještě bez možnosti opakování - viz cykly) umožňují podmíněné příkazy. Velmi často se zapisují ve tvaru: "když něco platí, udělej tuto činnost(i)", nebo ve tvaru: "pokud toto platí, vykonej tyto činnosti, ale pokud to neplatí, vykonej tyto jiné činnosti". Př.: Pokud svítí zelená, zahaj přecházení, pokud nesvítí, čekej.

Ve skutečnosti však takovéto rozhodování nemusí být tak jednoduché a i v programu se může skládat z celé řady podmínek. Např. pokud svítí zelená a nic nejede nebo auta po levé ruce i auta po pravé ruce stojí, zahaj přecházení. V programu bychom toto mohli přepsat jako sérii navzájem se doplňujících či vyvracejících podmínek. Takovémuto vyjádření říkáme podmínkový výraz. Výslednou hodnotu (pravda / nepravda) pak získáváme až po jeho vyhodnocení. 

Použití podmíněných příkazů v programovacím prostředí

NXT-G

Blok pro použití podmíněných příkazů

Rozcestník


Umístění bloku podmíněného vykonání (switch)

Po přetažení bloku Blok Switch Switch, který nalezneme v paletě Paleta Complete Complete > FlowControl Flow, do okna programu dojde ke vložení výchozí bloku podmíněného programového vykonání.

V programovacím prostředí NXT-G se poněkud netradičně vyskytují podmíněné příkazy ve dvou variantách.

Blok podmíněného vykonání řízený hodnotou ze senzoru

V první variantě (Control: Sensor) je součástí bloku podmíněného vykonání i senzor, na základě jehož hodnoty a nastavené podmínky se rozhoduje, která část kódu bude vykonána. Při splnění nastavené podmínky se vykoná část označená symbolem Truepřípadně alternativním symbolem vyjadřujícím splnění určité nastavené podmínky (např. Bright,Pressed,intensity100,Temp000,Near, ...), při nesplnění pak část opačná.
NXTG cyklus flat view tlacitko

Nastavení podmínky je odlišné pro každý typ senzoru. Přesto jsou zde 4 základní typy nastavení, které si představíme na příkladech:

  • vznik události se vyskytuje např. u podmínky s dotykovým senzorem (Touch Sensor) Bumper. Zde volíme, ke které akci má dojít (tlačítko stisknuto, tlačítko uvolněno, tlačítko stisknuto a uvolněno), aby byla podmínka splněna.
  • podmínka porovnání je např. u senzoru rotací (Rotation Sensor) RotationSensor, kde se porovnává, zda je počet rotací větší (>) nebo menší (<) než zadaná hodnota.
  • rozsah se využije např. u senzoru barvy (Color Sensor) ColorSensor ve kterém pomocí posuvníku určíme horní a dolní mez načtené hodnoty určenou pro vyhodnocení splnění podmínky. Vybrat si tak můžeme barvy různých odstínů červené, nikoli jen jednu hodnotu.
  • přesně zadaná hodnota je např. u senzoru přijetí zprávy přes bluetooth (Receive Message) MessageRead porovnávána s přijatou zprávou. 

Blok podmíněného vykonání řízený vnější hodnotou

Blok podmíněného vykonání řízený vnější hodnotou je univerzálnějším typem podmínky. Hodnotu typu pravda Truenepravda False (true / false) lze na vstup bloku přivést z libovolného senzoru či z dalších rozšiřujících programových bloků a proměnných. Díky tomu lze kombinovat i podmínky z výstupů několika senzorů či proměnných či případně používat možnost kontroly rozsahu i u senzorů jenž to v předchozí variantě nepodporují.

NXTG cyklus flat view hodnota

Při pravdivosti (splnění) vstupu se vykoná část označená symbolem True(zaškrtnutí - správně), při nesplnění pak část označená symbolem False (křížek).

Volba flat view

Podobu bloku lze velmi výrazně změnit a v případě rozsáhlejšího programu i zpřehlednit vhodným využitím volby Flat view.

Při jejím zaškrtnutí jsou vykreslovány všechny části bloku podmíněného vykonání a to jak bloky při splnění, tak i bloky při nesplnění podmínky. Na první pohled je tak zřejmé, jaká část kódu se bude kdy vykonávat. Nevýhodou však je množství zabraného místa a to i u bloků, jenž v jedné větvi nic nevykonávají.

Odškrtnutím políčka Flat view se části kódu zobrazí jako záložky, nezi nimiž lze přepínat. Bloky tak sice nelze vidět najednou, ale u rozsáhlejších programů toto může být i výhoda.

NXTG cyklus noflat view hodnota

Výběr z více položek

Dosud jsme při rozhodování vybírali ze dvou hodnot pravda / nepravda (splněno / nesplněno). V některých případech by se nám ale mohlo hodit rozlišovat více variant. Pro tuto možnost je ale nejprve nutno zrušit režim Flat view.


Jeho typ je nutno zvolit v parametrech bloku.

Parametry bloku

NXT-G Panel cyklu LOOP

Volba typu cyklus se provádí v sekci Control a to z těchto možností:

  • Forever – nekonečný cyklus ukončitelný pouze koncem celého programu.
  • Time – časově omezený cyklus s podmínkou na konci, který testuje uplynutí času zadaného v parametru Seconds: v sekci Until:. Pro cyklus trvající půl vteřiny zde nastavíme Seconds: 0.5.
  • Logic – cyklus s podmínkou na konci, který o svém pokračování rozhoduje na základě logické hodnoty přivedené na rozhodovací vstup (obrázek ano/ne).
  • Sensor – je kombinací předchozího cyklu s výstupem senzoru. Senzor pak poskytuje informaci, zda z něj získaná hodnota splňuje námi nastavenou podmínku. Díky tomuto cyklu pak nemusíme vkládat blok senzoru a následné propojení s cyklem Logic.
  • Count – cyklus s pevným počtem průchodů. Počet průchodů se nastavuje v parametru Minimální počet průchodů a je stanoven na 1.
U všech cyklů lze pomocí parametru Show: Counter aktivovat výstup počítadla průchodů. To můžeme použít i pro zpracování ve vnitřní části cyklu (např. pro třídičku vykonávající odlišné operace pro sudá a lichá čísla).

Ukázka použití cyklů



RobotC

Příkazy a metody

Na rozdíl od grafického prostředí NXT-G máme v jazyce RobotC k dispozici všechny tři základní typy cyklů. Pojďme si je přiblížit.
Rozcestník


Cyklus s podmínkou na začátku

Cyklus s podmínkou na začátku nejprve zkoumá, zda došlo ke splnění podmínky či podmínkového výrazu. Pokud je její výsledek pravda (true), vykoná vnořený kód (blok mezi složenými závorkami). Po jeho dokončení se cyklus vrací opět k podmínce a cyklus tak probíhá neustále dokola, dokud nedojde k nesplnění podmínky - nepravda (false).

Základní zápis cyklu

Cyklus se skládá z klíčového slova while za kterým následuje podmínka uzavřená do kulatých závorek (). Za nimi se nachází blok kódu vykonávaný při jejím splnění. Blok kódu je umístěn do složených závorek {}.

 //CYKLUS S PODMINKOU NA ZACATKU 
while (true) //na misto true umistnete podminku ci podminkovy vyraz 
{ 
//zde umistnete kod, ktery se ma opakovane vykonavat 
}
Z důvodu přehlednosti programu a odstraňování potencionálních chyb Vám doporučujeme se držet výše uvedeného formátování.
Příklad možné programové konstrukce 

V následující ukázce kódu vidíte řešení přiblížení robota na vzdálenost cca. 20 cm od překážky. V případě, že se překážka nachází příliš blízko, motory se nerozjedou a robot zůstane stát.

 

 //UKAZKA - PRIBLIZENI ROBOTA K PREKAZCE (ZDI) NA 20 CM
//Robot otestuje, zda se pred nim nenachazi prekazka
while (SensorValue[Ultrazvuk1]>20)
{
//pokud ma pred sebou volno, prekazka je dale nez 20 cm, rozjede se
//motor B a C se nastavi na 75% vykon
motor[motorB] = 75;
motor[motorC] = 75;
 
//protoze nehrozi kolize (prekazka je daleko) a neni tak potreba prilis
//casteho testovani, nechame robota jet a dalsi test udelame za 100ms
wait1Msec(100);
}
 
//Cyklus skoncil, jsme na miste, vypiname motory
motor[motorB] = 0;
motor[motorC] = 0;
 
//Tento kod je mozno opakovat dle libosti a na rozdil od podminky na konci
//nebude dochazet k neustalemu nepatrnemu priblizovani robota k prekazce
 

 


Cyklus s podmínkou na konci 

Cyklus s podmínkou na konci nejprve provede příkazy umístěné v jeho těle a až následně zkoumá, zda má opětovně vykonat tento blok. Je-li podmínka či podmínkový výraz cyklu splněna (výsledná hodnota pravda (true)) bude cyklus vykonáván. Při hodnotě nepravda (false) se cyklus přeruší a pokračuje se v dalším běhu programu. 

Základní zápis cyklu

Cyklus se skládá z klíčového slova do za kterým se nachází blok kódu, který je v případě splnění podmínky opakovaně vykonáván. Blok je uzavřený do složených závorek {}. Po nich následuje klíčové slovo while a podmínka či podmínkový výraz uzavřená do kulatých závorek (). Cyklus je zakončen středníkem ;.

 

 //CYKLUS S PODMINKOU NA KONCI
do
{
//zde umistnete kod, ktery se ma opakovane vykonavat
}
while (true); //na misto true umistnete podminku ci podminkovy vyraz
 
 
Příklad možné programové konstrukce 

V následující ukázce kódu vidíte řešení měřiče vzdálenosti, který počítá ujetou vzdálenost podle otáček motoru jež koeficientem přepočítává na ujetou vzdálenost. Pro snazší měření je začátek i konec měření spuštěn stiskem tlačítka.

 //UKAZKA MERIC VZDALENOSTI
//Meric vzdalenosti pocita pocet stupnu otoceni motoru,
//ktere pak prepocita na vzdalenost a zobrazi na displeji
//Ke spusteni i zastaveni mereni bude vyuzito tlacitko.
 
//MERENI ZACNE STISKEM TLACITKA
do
{
//specialitou je, ze v teto sekci nebude zadny kod
//opakovane se tedy bude vykonavat "nic"
//jen se bude testovat, zda muzeme pokracovat
}
while (SensorValue(dotykovySenzor) == 0); //tlacitko nestisknuto
 
//VYMAZEME POCITADLO MOTORU
nMotorEncoder[MotorA] = 0;
wait1Msec(1000); //nyni musi uzivatel do vteriny pustit tlacitko
 
//A OPET TESTUJEME TLACITKO
do
{
}
while (SensorValue(dotykovySenzor) == 0); //tlacitko nestisknuto
 
//VYPOCET VZDALENOSTI - obvod kola 12 cm
float vzdalenost = nMotorEncoder[MotorA] / 360 * 12;
 
 
nxtDisplayTextLine(4, "%f", vzdalenost); //zobrazeni vzdalenosti na displ.
wait1Msec(5000); //cekam, jinak by se displej smazal

 

Poznámka: V rámci zjednodušení řešení úlohy se předpokládá, že uživatel vždy stisknuté tlačítko do jedné vteřiny pustí. Pro přesnější realizaci by bylo vhodné reagovat spíše na uvolnění tlačítka.


Cyklus s pevným počtem průchodů

Cyklus s pevným počtem průchodů funguje ve třech režimech. V prvním inicializačním režimu, který nastává pouze při novém vstupu do cyklu nastaví výchozí hodnotu proměnné. Tu pak bude využívat pro řízení cyklu. V druhé části dochází k porovnání zadané podmínky. Není-li podmínka splněna, cyklus svou činnost ukončuje. V opačném případě (splnění podmínky) dojde k vykonání příkazů umístěných v programovém bloku cyklu {}. Po dokončení jejich provádění dochází ke změně proměnné podle uživatelem zadaného vzorce (nejčastěji její zvýšení o 1). Poté se celý proces (vyjma úvodního nastavení) opakuje a dochází k opětovnému vyhondocení splnění podmínky.

Cyklus se skládá z klíčového slova for za kterým následují kulaté závorky () obsahující tři časti oddělené středníky: 

  1. inicializace proměnné (příklad: int pruchod=0; nebo i=1;)
    V této první části dochází k definici proměnné použité pro řízení programového cyklu a k nastavení její vychozí hodnoty. Proměnná musí být celočíselného datového typu Pokud je proměnná použita jen v rámci tohoto cyklu a nepožadujeme zachování její hodnoty pro zpracování mimo cyklus, je výhodné ji zadeklarovat jako místní proměnnou (int i=1;). Velmi častým názvem proměnné pro tento typ cyklů je i, jenž je zkratkou slova index. Při vnořování cyklů do sebe je pak též využívána proměnná j. Velmi vám proto doporučujeme, abyste proměnné tohoto jména používali výhradně pro cykly.
  2. kontrola splnění podmínky (příklad: pruchod<5; nebo i<=128;)
    Ve druhé sekci se definuje podmínka obsahující proměnnou deklarovanou v předchozí části. Při splnění podmínky dojde k vykonání programového kódu umístěného v bloku cyklu. V případě že podmínka není splněna, je cyklus ukončen a je vykonán další příkaz následující za cyklem. Protože podmínka je testována před samotným provedením bloku cyklu, může se stát, že cyklus neproběhne ani jednou (příklad: v zásobníku balícího stroje není dostatečný počet zboží (žvýkaček), takže nelze balení po deseti kusech zkompletovat - čeká se na doplnění zboží).
  3. krok - provedení změny proměnné (příklad: pruchod++; nebo i=i*2;)
    Po vykonání příkazů vnořených do cyklu je volán tento blok. Ten obsahuje vzorec pro změnu (zvýšení, snížení) obsahu proměnné. Přesto, že nejčastějším případem je zvýšení proměnné o jedna, je možné obsah proměnné změnit podle předem zadaného vzorce - např. výpočet mocnin čísla 2: i=i*2;.

Za touto sekcí se nachází blok kódu vykonávaný při jejím splnění. Blok kódu je umístěn do složených závorek {}. V tomto bloku je možno využít obsah proměnné určující průběh cyklu.

 //CYKLUS S PEVNYM POCTEM PRUCHODU - DEKLARACE
for (inicializace_promenne; kontrola_splneni_podminky; krok_provedeni_zmeny_promenne)
{
//opakovane vykonavany programovy kod
}

 

Příklad možné programové konstrukce 

V následující ukázce vidíte použití cyklu pro postupné vypsání čísel 0 až 5 na displeji jendotky.

  //CYKLUS S PEVNYM POCTEM PRUCHODU - PRIKLAD
for (int i = 0; i<5; i++)
{
//opakovane vykonavany programovy kod
//vypisujici na displeji postupne cisla od 0 do 
nxtDisplayTextLine(4, "%d", i);
wait1Msec(500);
}
 

Vnoření cyklů

Na následujícím programu můžete vidět využití vnoření cyklů v praxi. Program slouží k plnění blistru na tabletky složeného ze dvou řad. Pro umístění tabletek je využíváno vnoření cyklů s pevným počtem průchodů. Detailní popis programu je obsažen v komentářích.

 
task main() 
{ 
  //VNORENI CYKLU - PROGRAM BALICKA 
  //Program slouzi k plneni blistru na tabletky paralenu 
  //Blistr vzdy obsahuje dve rady tabletek po 5 kusech 
  //Jamky na tabletky jsou od sebe vzdy ve stejne vzdalenosti 
 
  //ZACATEK - jsem ve vychozi pozici nad prvni tabletkou 
  //potrebuji v kazde ze dvou rad 5x po sobe umistit tabletku 
  //a posunout se na dalsi pozici
 
  //nejprve vlozim cyklus pro vyber rady 
  //protoze je pocet rad znamy, zvolim cyklus s pevnym poctem pruchodu 
  for(int rada=1; rada<=2; rada++) 
  { 
   //do kazde rady umistim 5 tabletek 
   //i zvolim cyklus s pevnym poctem pruchodu 
    for (int tabletka=1; tabletka<=5; tabletka++) 
    { 
      //na displeji si vypisu, jakou tabletku plnim 
      nxtDisplayTextLine(4, "r: %d, t: %d", rada, tabletka); 
 
      //umistim tabletku - ovladano motorem C 
      motor[motorC] = 60; 
      wait1Msec(200); 
      motor[motorC] = -60; 
      wait1Msec(200); 
 
      //premistim se na dalsi pozici, ktera presne odpovida otoceni 126 stupnu 
      nMotorEncoder[motorA] = 0; 
      nMotorEncoderTarget[motorA] = 126; 
 
      //rozjedu motor na 45% vykon 
      motor[motorA] = 45; 
 
      //a necham ho otacet do doby, nez dosahnu ciloveho natoceni 
      //zvolil jsem cyklus while, ktery okamzite testoval, zda nejsem uz spravne 
      while (nMotorRunState[motorA] != runStateIdle) 
      { 
       //motor stale neni na spravne pozici, tak cekam, nez tam dojede 
       //krome neustaleho testovani nedelam nic 
      } 
 
      //vypnu motor 
      motor[motorA] = 0; 
      //jdu na dalsi tabletku 
     } 
 
     //zaplnil jsme celou radu tabletek, nyni se vratim na puvodni misto 
     nMotorEncoder[motorA] = 5 * 126; 
     nMotorEncoderTarget[motorA] = 0; 
     motor[motorA] = -45; 
 
     while (nMotorRunState[motorA] != runStateIdle) 
     { 
 
     } 
 
     //vypnu motor posuvu plnicky 
     motor[motorA] = 0; 
 
     //a posunu platicko na druhou radu 
     nMotorEncoder[motorB] = 0; 
     nMotorEncoderTarget[motorB] = 253; 
     motor[motorB] = 45; 
 
     while (nMotorRunState[motorB] != runStateIdle) 
     { 
 
     } 
 
     //vypnu motor posuvu platicka 
     motor[motorB] = 0; 
 
     //opakuji plneni rady ... 
     } 
 
     //nyni mam jiz naplnene platicko a vracim se do vychozi polohy 
     nMotorEncoder[motorB] = 253; 
     nMotorEncoderTarget[motorB] = 0; 
     motor[motorB] = -45; 
 
     while (nMotorRunState[motorB] != runStateIdle) 
     {
 
     } 
 
    //vypnu motor posuvu platicka 
    motor[motorB] = 0; 
 
  //cely tento kod mohu umistit do dalsiho cyklu, ktery bude provadet napr. baleni do krabicky 
}
 

 


Import z knihovny funkcí

Pokud si nepamatujeme názvy klíčových slov vykonávajících matematické funkce, můžeme je nalézt v knihovně funkcí (Function Library) sekci _C Constructs.

Po přetažení položek v sekcích Control Structures do programového okna dojde ke vložení námi zvoleného cyklu. 



1 1 1 1 1 1 1 1 1 1 Hodnocení 1.00 (1 hodnocení)