8. Příkazy řídící běh programu III
  1. Vytvořte konzolovou aplikaci, která zjistí, zda zadané přirozené číslo je prvočíslo.
  2. Vytvořte konzolovou aplikaci, která čte z klávesnice větu ukončenou tečkou a která spočítá počet znaků písmen (anglické abecedy), počet znaků číslic a celkový počet znaků.
  3. Mimo již popsaného příkazu cyklu while můžeme používat další dva příkazy cyklů. Jedná se o cykly for a do-while. Cyklus for používáme, když známe omezení cyklu (jeho inicializační instrukci, ukončující kritérium a inkrementační instrukci). Např. cyklus for je často používán k procházení prvky pole nebo znaky řetězce.

  4. for (i = 0; i < delka; i++) {
        // nějaká činnost s i-tým prvkem
    }
    Když zapisujeme program, víme že např. chceme začít od začátku pole, skončit na konci pole a použít každý prvek pole. V tomto případě je vhodný příkaz for. Obecný popis příkazu for je tento:
    for (inicializace; ukončení; inkrementace)
      příkaz
    Inicializace je příkaz, který inicializuje cyklus; je proveden pouze jednou a to na začátku cyklu. Ukončení je výraz, který určuje kdy bude cyklus ukončen. Když je výraz pravdivý, cyklus pokračuje, není-li pravdivý, cyklus skončí. Inkrementace je výraz, který je vyvolán po každém průchodu cyklem. Každá z těchto částí může být prázdným příkazem (samotný středník). Inicializace a inkrementace může být tvořena i více příkazy (oddělujeme je čárkou).
  5. Použití příkazu for si ukážeme v následující konzolové aplikaci. V této aplikaci jsou použity dva příkazy cyklů, jeden probíhá vzestupně a druhý sestupně.

  6. cout << endl << "Začátek programu ... " << endl << endl;
    int i;
    for (i = 0; i < 10; i++) {
      cout << "Iterace číslo " << i << endl;
    }
    cout << endl;
    for (i = 10; i > 0; i--) {
      cout << "Iterace číslo " << i << endl;
    }
    Podmínka ukončení může být libovolný výraz C++. Hodnota v testovacím výrazu může být číselná konstanta (jak je použito v předchozím příkladě), proměnná nebo hodnota vrácená voláním funkce. Následují příklady přípustných cyklů:
    for (int i = 0; i < 100; i++) {...}
    for (int i = 0; i < pocetPrvku; i++) {...}
    for (int i = 0; i < ZiskejPocetPrvku(); i+=2) {...}
    V posledním příkladě je řídící proměnná cyklu zvětšována po 2. Inkremntace může být o libovolnou hodnotu. Např. o 10:
    for (int i = 0; i < 100; i+=10) {...}
  7. Posledním příkazem cyklu je cyklus do-while, který se podobá cyklu while, s tím rozdílem, že podmínka opakování cyklu je uvedena na konci cyklu.

  8. do {
      příkazy
    } while (výraz)
    Tento příkaz je málo používaným příkazem, ale má své opodstatnění. Příkaz je užitečný v případech, kdy cyklus musí proběhnout alespoň jednou (když např. čteme informace ze souboru a víme, že musíme přečíst alespoň jeden znak).
  9. V příkazu cyklu je možné také používat příkaz break a to ve stejném významu jako v příkazu switch. Použití příkazu break způsobí přechod na příkaz, který je uveden bezprostředně za cyklem. V cyklu lze použít také příkaz continue. Použití tohoto příkazu způsobí přechod na podmínku ukončující cyklus a tato podmínka rozhodne, zda cyklus bude ještě pokračovat. Je to vlastně přechod na nový průchod cyklu bez dokončení předchozího průchodu.

  10. Např. můžeme mít jistou část cyklu, kterou chceme provést pouze v případě splnění jisté podmínky.
    bool done = false;
    while (!done) {
      bool chyba = NejakaFunkce();
      if (chyba) continue;            // skok na konec cyklu
      // další příkazy, které se mají provést pouze když chyba nevznikne
    }
    Příkaz break lze např. použít při hledání nějaké hodnoty v poli hodnot (potřebujeme zjistit index hledaného prvku).
    int index = -1;
    int hledanaHodnota = 50;
    for (int i = 0; i < pocetPrvku; i++) {
      if (mojePole[i] == hledanaHodnota) {
        index = i;
        break;
      }
    }
    if (index != -1) cout << "Číslo nalezeno na indexu " << index << endl;
    else cout << "Číslo se v poli nevyskytuje." << endl;
    S poli hodnot se podrobněji seznámíme později.
  11. Posledním ukončujícím příkazem je příkaz return. Tento příkaz je možno použít k ukončení funkce a k přechodu na následující příkaz za voláním funkce. Tento příkaz má dva tvary: s hodnotou a bez ní. Tvar s hodnotou používáme k návratu hodnoty funkce. V tomto případě za return zapíšeme výraz určující vrácenou hodnotu. Např.

  12. return ++pocet;
    Tato vrácená hodnota musí být stejného typu jako je typ opouštěné funkce. Jestliže funkci deklarujeme jako funkci typu void, pak používáme druhý tvar příkazu return, který neobsahuje výraz s vracenou hodnotou:
    return;
  13. Následující konzolová aplikace vypisuje hodnoty funkcí sinus a kosinus pro úhly 0 až 90 stupňů s krokem 10 stupňů:

  14. cout << "Úhel     Sinus        Cosinus" << endl;
    cout << "-----------------------------" << endl;
    char pom[50];
    for (int i = 0; i <= 90; i += 10) {
      sprintf(pom, "%3d   %10.6f   %10.6f",
              i, sin(i*3.14159/180), cos(i*3.14159/180));
      cout << pom << endl;
    }
    Povšimněte si, že deklarace proměnné i je uvedena v příkazu for (toto je možné v C++, ale nelze to použít v C). Matematické funkce (sinus, kosinus, atd.) jsou deklarovány v hlavičkovém souboru math.h (musíme jej vložit direktivou include na začátku zdrojového textu programu). Při použití funkcí sinus a kosinus je nutno úhel zadávat v radiánech.
    Funkce sprintf vytváří ve svém prvním parametru řetězec podle formátovacího řetězce určeného druhým parametrem. Na místa označená %d a %f ve formátovacím řetězci jsou uloženy hodnoty dalších parametrů. Čísla v %d a %f určují počet znaků použitých pro výstup. %nd slouží k výstupu celočíselné hodnoty na n míst a %n.mf slouží k výstupu reálné hodnoty pomocí n znaků s m místy za desetinnou tečkou. Vytvořený výstupní řetězec znaků je v našem příkladu vložen do proměnné pom (musí umožňovat vložení potřebného počtu znaků).
    Vyzkoušejte tuto aplikaci.
  15. Napište konzolovou aplikaci, která vypíše tabulku funkčních hodnot funkce f(x) = 3x2 + 7x v intervalu <1,10> s krokem 2. Vypisujte x a f(x). Tabulku opatřete hlavičkou.
  16. Vrátíme se opět k aplikacím GUI. Vytvoříme nový prázdný projekt a umístíme na formulář seznam řetězců (ListBox zvětšíme jeho velikost a změníme v něm typ pí zvětší ? Courier New) a dvě tlačítka (s texty For a While). Obsluha stisku prvního tlačítka bude tvořena příkazy:

  17. char pom[30];
    ListBox1->Items->Clear();
    for (int i = 1; i <= 20; i++){
      sprintf(pom, "Řetězec %3d", i);
      ListBox1->Items->Add(pom);
    }
    Pro druhé tlačítko vytvoříme tuto obsluhu:
    char pom[30];
    ListBox1->Items->Clear();
    randomize();
    int i = 0;
    while (i < 1000) {
      i = i + random(100);
      sprintf(pom, "Náhodné číslo:%5d", i);
      ListBox1->Items->Add(pom);
    }
    Tato aplikace ukazuje použití cyklů a generování náhodných čísel. V našem programu funkce sprintf ukládá vytvořený výstup do proměnné pom. Proměnná pom je deklarována jako pole o 30 prvcích typu char (do této proměnné můžeme uložit řetezec o délce až 29 znaků). Funkce randomize inicializuje generátor náhodných čísel. Funkci random potom můžeme použít pro generování náhodných čísel z intervalu <0, n), kde n je parametr funkce. Aplikaci vyzkoušejte.
  18. Vytvořte aplikaci, ve které budete zobrazovat tabulku funkčních hodnot funkcí sinus a cosinus od 0 do 90 stupňů s krokem 10. Na formulář umístěte komponentu ListBox a zvětšíme ji. Tabulku vypisujte ve dvou sloupcích; první sloupec nadepište ?Úhel a druhý ?Sinus, resp. ?Cosinus. Na formulář ještě vložíme tlačítka ?Sinus a ?Cosinus. Vytvořte obsluhy stisku tlačítek tak, aby vždy při stisknutí jednoho z tlačítek byly zobrazeny funkční hodnoty příslušné hel?

Kontrolní otázky:

  1. Kolik úrovní vnoření může být u příkazu if?
  2. Bude cyklus automaticky ukončen v případě nekonečného cyklu?
  3. Musí příkaz switch obsahovat část default?
  4. Které příkazy jsou provedeny, když podmínka příkazu if je pravdivá?
  5. Co reprezentují tři parametry příkazu for?
  6. Čím se liší cykly while a do-while?
  7. Co dělají příkazy break a continue?
Řešení


8. Příkazy řídící běh programu III