![](img/tr.png)
V tomto díle zakončíme cykly s podmínkou na začátku a s podmínkou na konci složitějšími úlohami. Budeme v nich kombinovat různé typy cyklů.
Asi nikoho po přečtení přechozích dílů nepřekvapí, že i cykly s podmínkou lze používat ve vývojových diagramech vícekrát. Už jenom z toho důvodu, že jsme si ukázali řešení jedné úlohy všemi typy cyklů a měli jsme tu příklady, ve kterých jsme měli 2 cykly s daným počtem opakování, takže by se stejná úloha dala řešit např. 2 cykly s podmínkou na začátku.
I z tohoto důvodu si v tomto díle ukážeme řešení úloh, ve kterých využijeme kombinace různých typů cyklů. Nejprve budeme počítat průměr známek předmětu pro jednotlivé žáky ve třídě. Dále si vytvoříme algoritmus na nalezení Armstrongových čísel. A jako poslední si vytvoříme algoritmus pro spočítání počtu daného znaku v souboru. Pusťme se do práce.
Průměry známek
Zadání úlohy by znělo následovně: vytvořte algoritmus na výpočet průměru známek jedné třídy. Je znám počet žáků ve třídě (20), ale každý žák má různý počet známek. Jejich zadávání u každého žáka bude ukončeno zadáním 0.
Na vstupu od uživatele budou známky vždy pro jednoho žáka. Hodnotou 0 ukončíme zadávání a můžeme spočítat průměr a přejít na dalšího žáka. Procházení žáků, protože známé jejich počet, provedeme v cyklu s daným počtem opakování. Zadávání známek provedeme v cyklu s podmínkou na konci. Ukážeme si jak ošetřit vstup od uživatele i možné výsledky.
Vnější cyklus bude tedy s daným počtem opakování. V jeho těle bude vše důležité. Vzhledem k tomu, že pro každého žáka musíme zadat alespoň jedno číslo - minimálně ukončovací 0 - takže bychom mohli použít na zadávání cyklus s podmínkou na konci. Samozřejmě můžeme použít i cyklus s podmínkou na začátku, a to taky uděláme.
Pro výpočet průměru potřebujeme znát součet a počet známek. Nesmíme zapomenout, že poslední zadaný údaj bude 0, takže nejprve zjisttíme, jak by to v případě použití cyklu s podmínkou na konci ovlivnilo tyto dvě proměnné - zadávání a zpracování se děje před podmínkou. Přičtením 0 do součtu ho nijak nezměníme, což znamená, že to nemusíme nijak ošetřovat (inicializace pro součet by byla 0). U počtu by to tak bezpracné nebylo, poslední zadaná 0 by se nám bez dalšího ošetření také přidala do výsledného počtu, takže bychom měli o jednu známku navíc. Z tohoto důvodu bychom museli tento stav ošetřit.
První z možností, která se nabízí, je ošetřit zvětšování počtu jen pro platné známky, tj. 0 vyloučit. Další z možností je před výpočtem průměru zmenšit počet o 1, takže dostaneme platný počet známek. My bychom asi využili v podstatě podobnou možnost, a to "schovat" korekci výsledného počtu do inicializace. Počáteční hodnotu proměnné pro počet bychom nastavili na -1, takže pokud bychom zadali 5 známek a ukončovací 0, tak bychom dostali výsledný počet 5 (-1 + 6 = 5
) apod.
My ovšem použijeme cyklus s podmínkou na začátku, takže inicializace proměnné pro počet i součet bude na 0. Jediné, co musíme "ošetřit" je umožnost zadání známky před vstupem do cyklu a v těle cyklu. Ve vývojovém diagramu musíme dále ošetřit, aby uživatel zadával pouze platné známky (1 až 5), další hodnoty do součtu a počtu nezahrnovat. A dále nesmíme zapomenout na situaci, kdy žák nedostal ani jednu známku, tj. výsledný počet je 0. V tomto případě by při výpočtu průměru došlo k dělení 0, a to je nepřípustná operace. Výsledný vývojový diagram si můžete prohlédnout na obrázku.
Armstrongova čísla
Armstrongova čísla jsou taková čísla, jejichž hodnota se rovná 3. mocnině jejich jednotlivých číslic. Naším úkolem je, pro nalezení takových čísel na zadaném intervalu od 1, vytvořit algoritmus. Na vstupu od uživatele dostaneme číslo, do kterého budeme Armstrongova čísla hledat. Výstupem algoritmu budou všechna nalezená čísla.
Rozmezí pro hledání je dané, takže s výhodou použijeme cyklus s daným počtem opakování. V jeho těle musíme z číslic daného čísla spočítat součet 3. mocnin a výsledek porovnat s aktuálně testovaným číslem. V případě rovnosti se jedná o Armstrongovo číslo, v opačném případě nikoliv.
Jak spočítáme součet cifer? Číslo musíme na jednotlivé číslice "rozsekat", vypočítat 3. mocninu a provést součet. Rozdělení čísla provedeme postupným cyklickým výpočtem zbytku po dělení 10 a následným dělením 10. Problém je v tom, že nevíme kolik bude mít dané číslo cifer. V tom případě musíme použít jeden z cyklů s podmínkou a čekat až nebude co "sekat". Vzhledem k tomu, že začínáme číslem 1, takže vždy provedeme alespoň jeden průchod cyklem a tudíž můžeme použít cyklus s podmínkou na konci (použití cyklu s podmínkou na začátku by bylo v tomto případě stejně výhodné).
Pro ty, kteří ještě netuší, jak probíhá takové programové "rozsekání" čísla na jeho číslice, uděláme malý příklad. Mějme číslo 159. Výsledkem by měly být číslice 1, 5 a 9. Jak již bylo naznačeno, začneme zbytkem po dělení 10: 159 % 10 = 9
, tj. dostáváme první číslici. Teď potřebuje získat další, ale přes zbytek po dělení 100 to nepůjde (ten je 59), takže musíme číslo celočíselně vydělit 10 (159 / 10 = 15
) a z výsledku opět vypočítat zbytek po dělení 10 (15 % 10 = 5
). Pokračujeme dále stejným postupem, tj vydělíme 10 (15 / 10 = 1
) a vypočítáme zbytek po dělení (1 % 10 = 1
). Při dalším dělení dostáváme 0 a to je konečná pro cyklus.
Stejným postupem bude pracovat i naše část algoritmu. Testované číslo (A) si nejprve uložíme do pomocné proměnné (T), abychom si původní hodnotu uchovali pro porovnání. Nastavíme počáteční hodnotu proměnné pro součet číslic (S) na 0 a začneme provádět tělo cyklu. V něm nejprve spočítáme zbytek po dělení 10. Výsledek umocníme (na 3) a přičteme k celkovému součtu. Jako poslední krok těla cyklu provedeme celočíselné dělení pomocné proměnné T (a výsledek uložíme do této pomocné proměnné). Cyklus končí v případě, že je pomocná proměnná nulová.
Po ukončení vnořeného cyklu porovnáme spočtený výsledek s hodnotou testovaného čísla, pokud jsou stejné, tak jsme našli Armstrongovo číslo a můžeme ho vypsat. V případě, že se čísla liší, tak se o Armstrongovo číslo nejedná a nebudeme provádět žádnou akci. Následně přecházíme vnějším cyklem (s daným počtem opakování) na další testované číslo a vše počítáme znovu od začátku. Výsledný vývojový diagram si můžete prohlédnout na obrázku.
Počet znaků v souboru
Poslední úlohou tohoto dílu bude spočtení vybraného znaku v souboru. Zadání by bylo následující: vytvořte algoritmus pro spočtení počtu vybraného znaku v souboru. Na vstupu od uživatele bude znak, jehož četnost chceme spočítat. Na výstupu budu počet znaků, které soubor obsahuje.
Řešení je opět přes 2 vnořené cykly. Vnější bude načítat jednotlivé řádky souboru - řekněme, že to umíme. Samozřejmě nevím kolik těch řádků je, takže to vede na cyklus s podmínkou. Soubor může být i prázdný, takže tělo se nemusí vykonat ani jednou, a proto použijeme cyklus s podmínkou na začátku. Obsahem testu podmínky bude zjištění, jestli už jsme nebo nejsme na konci souboru. Pokud ještě nebudeme na konci, tak můžeme načítat další řádek.
Po načtení řádku potřebujeme projít jeho jednotlivá písmenka - znaky - ze kterých je složen. Máme v podstatě 2 možnosti, projít řádek dokud nenarazíme na znak, kterým je řádek ukončen (odřádkování) nebo si necháme zjistit délku řádku, tj. počet znaků, ze kterých je složen. Vybral jsem druhou možnost, takže k jednotlivým znakům budeme přistupovat v těle cyklus s daným počtem opakování.
Po získání každého jednotlivého znaku z řádku provedeme test, je-li to námi hledaný znak. V případě, že ano, tak zvýšíme hodnotu celkového počtu znaků proměnné P (provedeme inkrementaci). V opačném případě neprovedeme nic. Po skončení vnějšího cyklu máme v P počet znaků Z v souboru. Výsledek vypíšeme a program ukončíme.
Jaká každá úloha, tak i tato se dá řešit různými způsoby. Mohli bychom například načítat obsah souboru po jednom znaku a ten testovat, takže by celý program tvořil jeden cyklus. Problém takového řešení je například v tom, že obecně jsou přístupy do souboru pomalé (pomalejší než do paměti), takže je snahou omezit počet přístupů a nenačítat obsah po jednom znaku, ale více najednou.
Nám se zvolené řešení hodilo z ukázkových důvodů pro další kombinaci vnořených cyklů. A také proto, že se v další pokračování seriálu dostaneme k podprogramům. Ve vývojové diagramu máme použité příkazy typu: "Otevři soubor", "Načti řádek" atd., což by mohly být knihovní funkce nebo-li podprogramy. V příštím díle si ukážeme, co to takový podprogram je a k čemu se vůbec hodí.