Obsah: Úvod........................................................................................................... 1 1. Algoritmy ............................................................................................ 3 1.1. Základní pojmy ............................................................................. 3 1.2. Způsoby zápisu algoritmu............................................................. 6 1.3. Základní části algoritmu................................................................ 9 1.3.1. Sekvence (posloupnost)...................................................... 9 1.3.2. Selekce (větvení, rozhodování) .......................................... 9 1.3.3. Iterace (cykly, opakování).................................................. 13 1.4. Použití cyklů a podmínek.............................................................. 16 Shrnutí .................................................................................................. 21 Kontrolní otázky................................................................................... 21 Pojmy k zapamatování ......................................................................... 21 Korespondenční úkol ......................................................................... 22 Řešení ................................................................................................... 22 2. Program a programování .................................................................. 23 2.1. Programovací jazyky..................................................................... 23 2.2. Postup programování .................................................................... 25 Shrnutí .................................................................................................. 27 Kontrolní otázky................................................................................... 27 Pojmy k zapamatování ......................................................................... 27 Korespondenční úkol ......................................................................... 28 3. Základy jazyka Pascal ....................................................................... 29 3.1. Struktura programu v Pascalu ....................................................... 29 3.2. Příkazy v Pascalu .......................................................................... 32 3.3. Příkazy vstupu a výstupu .............................................................. 33 Shrnutí .................................................................................................. 36 Kontrolní otázky................................................................................... 36 Pojmy k zapamatování ......................................................................... 36 4. Datové typy v Pascalu ........................................................................ 37 4.1. Základní standardní datové typy ................................................... 39 4.1.1. Integer................................................................................. 39 4.1.2. Real..................................................................................... 41 4.1.3. Boolean............................................................................... 42 4.2. Uživatelem definované datové typy.............................................. 43 4.2.1. Výčet hodnot ...................................................................... 43 4.2.2. Interval ............................................................................... 43 Shrnutí .................................................................................................. 44 Kontrolní otázky................................................................................... 44 Pojmy k zapamatování ......................................................................... 44 Korespondenční úkol ......................................................................... 44 5. Podmínky ............................................................................................ 45 5.1. Neúplná podmínka ........................................................................ 45 5.2. Úplná podmínka............................................................................ 47 5.3. Vnořené podmínky........................................................................ 48 5.4. Vícenásobné větvení ..................................................................... 48
5.5. Výrazy a použití logických operátorů ...........................................51 5.5.1. Použití logických operátorů AND a OR.............................52 5.5.2. Použití logického operátoru NOT.......................................53 Shrnutí ..................................................................................................55 Kontrolní otázky ...................................................................................55 Pojmy k zapamatování..........................................................................55 Korespondenční úkol..........................................................................55 Řešení ...................................................................................................56 6. Cykly ....................................................................................................57 6.1. Cyklus s předem stanoveným počtem opakování .........................57 6.2. Cyklus s podmínkou na začátku ....................................................59 6.3. Cyklus s podmínkou na konci .......................................................61 Shrnutí ..................................................................................................62 Kontrolní otázky ...................................................................................62 Pojmy k zapamatování..........................................................................62 Korespondenční úkol..........................................................................62 7. Práce s textem .....................................................................................63 7.1. Char (znak) ....................................................................................63 7.2. String (řetězec) ..............................................................................66 Shrnutí ..................................................................................................70 Kontrolní otázky ...................................................................................70 Pojmy k zapamatování..........................................................................70 Korespondenční úkol..........................................................................71 Řešení ...................................................................................................71 8. Datový typ Pole (Array) .....................................................................73 8.1. Jednorozměrné pole.......................................................................73 8.2. Dvojrozměrné pole ........................................................................76 8.3. Použití datového typu pole ............................................................80 8.3.1. Řešení I. ..............................................................................81 8.3.2. Řešení II..............................................................................83 8.3.3. Řešení III. ...........................................................................86 Shrnutí .................................................................................................89 Kontrolní otázky ...................................................................................89 Pojmy k zapamatování..........................................................................90 Korespondenční úkol..........................................................................90 Řešení ...................................................................................................90 9. Třídění a vyhledávání.........................................................................93 Shrnutí ..................................................................................................98 Kontrolní otázky ...................................................................................99 Pojmy k zapamatování..........................................................................99 Korespondenční úkol..........................................................................99 Závěr ..........................................................................................................100 Použitá literatura ......................................................................................101 Vysvětlení grafických symbolů................................................................103
Vážení studenti, právě jste otevřeli studijní oporu, jejímž cílem je pootevřít Vám dveře do oblasti zabývající se tvorbou programů. V první kapitole se seznámíte s jazykem vývojových diagramů, který vám pomůže při znázornění postupů řešení problémů (tzv. algoritmů) a také při komunikaci s ostatními programátory. Od druhé kapitoly se začnete seznamovat s řešením základních úloh. K řešení použijete jazyk Pascal (resp. Turbo Pascal nebo Borland Pascal). Proč právě Pascal? Protože je přehledný, proto vhodný pro začátečníky, aby pochopili základy programování. Nebude pak pro Vás problém přejít k jiným programovacím jazykům. Celý učební text zvládnete za 40 hodin. Je vhodnější nestudovat nárazově, ale celé studium si vhodně rozložit. Programování je tvůrčí činností, která, pokud ji věnujete potřebný čas, Vám přinese příjemný pocit uspokojení z vyřešeného problému. Přeji Vám mnoho úspěchů a … pojďme na to. Autor
) po prostudování opory budete znát: 9 značky pro zápis algoritmů pomocí vývojového diagramu 9 základní příkazy jazyka Pascal 9 podmínky a cykly v Pascalu ) budete umět: 9 zpracovat údaje, které uživatel zadá z klávesnice 9 vytvořit jednoduchý program v Pascalu 9 programově zpracovat údaje v jednorozměrném a dvourozměrném poli 9 setřídit zadaná data
1
1. Algoritmy
1.
Algoritmy
Cíl: Po prostudování této kapitoly byste měli umět: definovat pojem algoritmus a vysvětlit vlastnosti algoritmu rozlišit mezi proměnnou a hodnotou uloženou v proměnné popsat způsoby, které můžete použít pro zápis algoritmu použít jednotlivé symboly pro tvorbu vývojového diagramu zapsat jednoduchý algoritmus pomocí vývojového diagramu Čas potřebný k prostudování této kapitoly: 5 hodin O informaticích spousta lidí říká, že jdou poznat podle způsobu, jakým se vyjadřují a jak myslí. Co já na to? Je to pravda. Snažíme se formulovat problém a zjistit, co jej ovlivňuje. A nakonec předložit řešení, pokud to jen jde, tak bez zbytečného "okecávání". Takovému způsobu myšlení se vás pokusím naučit. Nebudu vám jako Churchil optimisticky slibovat krev, pot a slzy, ale slíbím vám jen trochu toho potu ☺. Uvidíte sami, že uspokojení, když se vám podaří rozchodit váš první program, stojí za to. Nejdříve se naučíte pár základních pojmů, kterými se budu v dalším textu ohánět. Hurá na ně. Tuto kapitolu není možné se naučit najednou. Rozložte si učení na jednotlivé podkapitoly.
1.1 Základní pojmy Algoritmus: Postup řešení úlohy prováděný přesně definovaným konečným počtem kroků, který zadané vstupní údaje transformuje na požadované výstupní údaje. Algoritmus je správný vzhledem k vstupní a výstupní podmínce tehdy, když pro všechny vstupní údaje splňující vstupní podmínky, se proces předepsaný algoritmem zastaví a výstupní údaje splňují výstupní podmínky. Vlastnosti algoritmu: determinovanost (určenost): v každém kroku algoritmu je určeno, co bude dále. Musí být jasné, co se bude dít dále. Vy si možná můžete vymyslet, co uděláte, ale počítač je stroj, který si další postup nemůže vymyslet. Nesmí proto nastat situace, kdy nebude vědět jak daný problém vyřešit. hromadnost: znamená, že algoritmus není použitelný jen pro určité vstupní údaj, ale pro libovolné údaje, které splňují vstupní podmínku.
3
Základy Algoritmizace
Příklad 1.1 Popište algoritmus výpočtu plochy zahrady obdélníkového tvaru. Budete pracovat ve dvojici. Váš spolužák umí zacházet s metrem, proto bude měřit. Vám jde matematika, proto vypočítáte plochu zahrady. Podívejte, co děláte automaticky, aniž si to uvědomujete. 1. Nejdříve po spolužákovi chcete, aby strany pozemku změřil a nadiktoval vám délku strany a strany b - délky stran jsou vstupní údaje algoritmu 2. Poté zkontrolujete, zda-li vám spolužák nadiktoval údaje, které nejsou nesmyslné. Například strana a má velikost mínus 8 metrů, nebo jako hodnotu velikosti strany b nadiktoval slovo auto, namísto čísla. - zjišťujete zda vstupní údaje odpovídají vstupní podmínce (v našem případě, že velikost stran je udávána v kladných číslech). 3. Provedete výpočet. Pokud jsou zadaná čísla příliš velká pro výpočet v hlavě, vezmete tužku a papír a pomocí kroků, které jste se učili na 1.stupni základní školy, spočítáte plochu zadaného pozemku tj. konečným počtem kroků provádíte algoritmus 4. Nyní přichází závěrečná fáze, kterou většinou provádíte také automaticky. Zkontrolujete, zda vám nevyšel nesmyslný výsledek např. příliš malé nebo naopak velké číslo apod. tj. zda výstupní údaje algoritmu splňují výstupní podmínky. Hromadnost algoritmu znamená, že stejný postup realizujete pro libovolné pozemky obdélníkového nebo čtvercového tvaru. Postup výpočtu plochy pozemku se skládá z konečného počtu kroků, které při výpočtu provádíte. A protože umíte vypočítat součin dvou čísel pomocí tužky a papíru (ovládáte algoritmus ze základní školy), nemůže nastat situace, že byste nevěděli jak dále. rezultativnost (konečnost): znamená, že pro vstupní údaje, které vyhovují vstupní podmínce, musí být po konečném počtu kroků znám výsledek vyhovující výstupní podmínce. Nejste v pohádce, aby platilo „pokud nezemřeli, žijí dodnes“ nebo „pokud jim neselhal hardware, tak program běží dodnes“. program: algoritmus, který je zapsán určitým programovacím jazykem proměnná: veličina určitého typu, která během realizace algoritmu může nabývat různých hodnot (tj. mění svou hodnotu, nikoli typ) Neděste se, princip práce s proměnnou znáte z matematiky. Šmánkote, použil jsem slovo matematika, při kterém některým trne krev v žilách. Nebojte, je to opravdu, ale opravdu jednoduché.
4
1. Algoritmy
Příklad 1.2 Při výpočtu plochy obdélníka nejdříve pracujete s proměnnými ve vzorci.Teprve později do proměnných dosadíte konkrétní hodnoty. S=a*b (S, a, b jsou proměnné, do kterých budou při každém novém výpočtu vloženy jiné hodnoty) Když a = 5, b = 4 (v proměnných a, b jsou uloženy hodnoty 5 a 4) Provedete výpočet a do proměnné S uložíte hodnotu 20. typ proměnné: říká, jakou hodnotu může počítač očekávat, že bude do proměnné uložena. Když počítači řeknete, že proměnná bude typu celé číslo, tak počítač bude očekávat celé číslo. V případě vložení čísla s desetinnou čárkou nebo textu zahlásí chybu, protože čeká a vyžaduje po uživateli celé číslo. Po dobu běhu programu se může měnit hodnota v proměnné, ale daná hodnota musí být stále definovaného typu, tj. v našem případě celé číslo. Více se o typech proměnných a práci s nimi dozvíte v kapitole č.4 Datové typy. V matematice také pracujete s proměnnými, s konkrétními hodnotami by bylo náročné.
protože
počítat
Prošli jste si pár základních pojmů z nichž nejdůležitější jsou informace, že algoritmus je postup řešení problému a jaký je rozdíl mezi proměnnou a hodnotou uloženou v proměnné. Uf, to chce pauzu. Protáhněte se, projděte se. Prostě odpočiňte si.
5
Základy Algoritmizace
1.2 Způsoby zápisu algoritmu V této časti se dozvíte, jakými způsoby lze zapsat algoritmus a jaké jsou výhody a nevýhody těch zápisů. Samozřejmě, že způsobů je více, ale pro nás jako začátečníky bohatě stačí znát ty, které jsou uvedeny níže. Způsoby zápisu algoritmu: slovně vývojovými diagramy programovacími jazyky různými schématy apod. 1) Slovní zápis algoritmu: Slovně popíšete jak postupovat při řešení problému. Snad nejznámějšími slovními popisy algoritmů jsou kuchařské recepty, které popisují řešení problému – uvaření jídla.
Příklad 1.3 Popište algoritmus čerpání benzínu u pumpy. Možný způsob řešení: Přijíždím k pumě. Zjistím, zda je fronta. Je-li příliš velká podívám se jestli nějakou dobu ještě vydržím s benzínem, který mám, a odjedu. Je-li fronta přijatelná nebo už musím nevyhnutelně tankovat, vyberu řadu, ve které je stojan s typem benzínu, který používám. Čekám ve frontě, až na mě přijde řada (popojíždím, dokud nejsem u stojanu). Je-li na stojanu červená počkám. Čekám-li příliš dlouho zeptám se obsluhy pumpy (zapne zelenou, nebo se stojan zkazil, případně došel benzín). Pokud došlo k některé z těchto nemilých událostí, jdu na začátek a znovu prozkoumám, zda opravdu nevydržím bez benzínu. A celý proces absolvuji ještě jednou. Pokud svítí zelená, otevřu nádrž a začnu tankovat. Kontroluji množství natankovaného benzínu (zda nepřetéká a odpovídá množství peněz, které mám k dispozici). Mám-li natankováno, zavřu nádrž, zaplatím a odjíždím. Podívejte se na popsaný příklad, určitě vás napadne řada vylepšení. Můžete algoritmus doplnit o řadu kroků: např. vypnu motor, vytáhnu klíče, mám-li v autě něco cenného a budu odcházet platit k okénku, zamknu auto apod. Je na vás, do jaké nutné míry podrobnosti algoritmus rozeberete. Nic se nesmí přehánět. Držte se zásady, že problém rozložíte do té míry podrobnosti, abyste dospěli k řešení a neutápěli se v detailech.
6
1. Algoritmy Zkuste se nyní ale zamyslet nad způsobem, jakým je algoritmus popsán. Jaké jsou výhody a nevýhody takového zápisu? Nevýhodou je přílišná obsažnost, čtenář se může kdykoli ztratit a musí se vracet a hledat, kde se zrovna nachází. Špatně zachytí větvení, do kterého se rozpadá řešení problému. Samozřejmě nic není černobílé, takže nevýhoda přílišné obsažnosti může být naopak výhodou. Slovní popis umožňuje zachytit drobné nuance, které jiné způsoby zápisu neumožňují. Nevýhody slovního popisu se pokouší odstranit některé nástroje grafického zápisu algoritmu jako např. vývojové diagramy, které budete dále používat.
2) Vývojové diagramy Vývojové diagramy slouží ke grafickému popisu algoritmů. K zachycení řešení se používají některé specifické grafické symboly, do kterých je zapsán slovní text. Způsob zápisu textu není normou určen, ale doporučuje se využít matematické zápisy a krátký, výstižný popis. Vy se naučíte používat některé zápisy z Pascalu, abyste si usnadnili pozdější přechod od algoritmů k programovému kódu v Pascalu. K zápisu algoritmu se použivájí grafické symboly: zpracování: pro zápis jednoduchých přiřazovacích příkazů
rozhodování: pro zápis podmínky (podmíněného příkazu)
vstup, výstup: pro příkazy čtení nebo tisku.
příprava: pro změnu činnosti, používá se např. pro zápis cyklů se známým počtem opakování
předem definovaná činnost: pro zápis části algoritmu, která je zpracována (popsána) jinde. Používá se pro označení podprogramu.
spojka: pokud musím rozdělit vývojový diagram na několik papírů, tak určí, které části na sebe navazují.
mezní značka: pro zahájení nebo ukončení činnosti (začátek a konec programu)
7
Základy Algoritmizace poznámka: pro zápis komentáře
Symboly spojíte čárami. Šipky u svislých čar nemusíte používat, protože vývojovým diagramem postupujete shora dolů. Pokud čára mění směr, jako např. při použití cyklu, pro zdůraznění šipku nakreslete.
Příklad 1.4 Použití si ukážeme vývojového diagramu na výpočtu plochy pozemku.
Není zbytí, značky se musíte naučit nazpaměť, ať nemusíte pokaždé dohledávat, co znamenají. Taková malá rada, uslyšíte ji ode mne i v jiných souvislostech, je: tužka, papír a guma je na kreslení "vývojáků" nejlepší. Na počítači tvořte vývojové diagramy až v konečné fázi - ušetříte si spoustu časů a nervů.
Cvičení: nakreslete symboly pro: podprogram podmínku cyklus s určitým počtem opakování spojku začátek poznámku načtení proměnné
8
1. Algoritmy
1.3 Základní části algoritmu Algoritmus se skládá ze 3 částí : sekvence (posloupnost příkazů) selekce (větvení, rozhodování) iterace (opakování, cykly)
1.3.1 Sekvence (posloupnost) Posloupnost příkazů, každý příkaz v posloupnosti musí být vykonán (nelze ho přeskočit).
Příkazy se vykonají tak jak jdou za sebou. Pokud byste chtěli, aby se některý z příkazů v posloupnosti nevykonal, musíte jej uzavřít do podmínky. To znamená, že stanovíte, kdy a za jaké podmínky se vykoná a za jaké se nevykoná.
1.3.2 Selekce (větvení, rozhodování) Běžněji se používá označení podmínka. Použijete ji v okamžiku, kdy potřebujete algoritmus rozdělit na větve z nichž se buď provede jedna nebo druhá. Pokud výraz zapsaný v podmínce platí, postupujete po větvi označené plus (označené někdy jako Ano, A). V opačném případě postupujete po větvi - (Ne, N). Existují 3 typy větvení: a) úplné větvení (úplná podmínka) b) neúplné větvení (neúplná podmínka) c) vnořené větvení (vnořené podmínky)
a) úplné větvení (úplná podmínka): Pokud je splněn výraz v podmínce, jsou provedeny příkazy ve větvi plus, v opačném případě příkazy ve větvi mínus.
9
Základy Algoritmizace Úplné větvení používáte naprosto běžně. Například, když dáváte někomu pokyn „Jestli nebude nepršet, běž posekat trávu, jinak vysaj celý byt.“
Příklad 1.5 Jaká bude na konci algoritmu vytištěná hodnota proměnné S, jestliže 1) a = 4, b = 2 2) a = 1, b = 3
Řešení najdete na konci 1.kapitoly.
b) neúplné větvení (neúplná podmínka) Rozdíl oproti úplné podmínce je v tom, že na jedné z větví algoritmu nemusí být žádný příkaz. To znamená, že se nemusí provést žádný příkaz a algoritmus bude pokračovat příkazy za podmínkou.
Tento typ používáte také naprosto běžně, aniž si to uvědomujete. Příkladem je pokyn „Když budeš doma, umyj nádobí a ukliď!“. Všimněte si, že v pokynu není řečeno, co se má dělat, když podmínka není splněna.
10
1. Algoritmy
Příklad 1.6: Jaká bude na konci algoritmu vytištěná hodnota proměnné S, jestliže 1) a = 4, b = 2 2) a = 1, b = 3
-
Řešení najdete na konci 1.kapitoly.
Pozor, zde vás chci upozornit na častou chybu. Pokud přičítáte proměnnou samu k sobě (jako v případě S:= S+1), je důležité ji nastavit počáteční hodnotu. Může se totiž stát, že proměnná má v paměti uloženou nějakou hodnotu z předešlé operace nebo programu.
c) vnořené větvení (vnořené podmínky) Větev pro splněnou nebo nesplněnou podmínku je doplněna o další podmínky.
11
Základy Algoritmizace Sami z vlastní zkušenosti víte, že v tomto případě je situace o něco složitější. Jedná se o pokyny typu „Když skončíš v práci dříve, zajdi do banky. Když skončíš později, udělej nákup a když ani to nestihneš, stav se alespoň na benzín“. Vidíte, že někdy i obyčejné pokyny, které se do sebe vnořují, mohou být složité. Proto je někdy vhodné si u takových pokynů zakreslit, co se má a kdy udělat.
Příklad 1.7: Jaká bude na konci algoritmu vytištěná hodnota proměnné S, jestliže 1) a = 4, b = 2, c = 1 2) a = 1, b = 3, c = 1 3) a = 1, b = 3, c = 4
V tomto případě nastavení počáteční hodnoty by nemělo smysl, protože hodnota proměnné S, ať je jakákoli, se přepíše výsledkem výrazu a + b. Nicméně v rámci celého tohoto algoritmu je nutné nastavit S počáteční hodnotu, protože v příkazu S:= S + c přičítáme S samo k sobě a mohlo by se stát, že budeme pracovat s nesprávnou počáteční hodnotou.
Počáteční hodnota nemusí být 0, může být nastavena libovolně. Záleží na zadání řešeného problému.
S:= 2
+
a >= b
-
S:= a +b
+
b >= c
-
S:= S +3
S:= S + c
S:= S + 1
write(S)
Řešení najdete na konci 1.kapitoly.
12
S:= b + c
1. Algoritmy
1.3.3 Iterace (cykly, opakování) cyklus: činnost, která umožňuje opakování dílčí části algoritmu (programu) tělo cyklu: činnosti (příkazy), které se budou opakovat Rozlišují se 3 typy cyklů: a) cyklus s předem stanoveným počtem opakování (cyklus s řídící proměnnou) b) cyklus s podmínkou na začátku c) cyklus s podmínkou na konci Cykly s podmínkou na začátku a na konci se také označují jako cykly s neznámým počtem opakování.
a) cyklus s předem stanoveným počtem opakování (cyklus s řídící proměnnou) Použijete v případě, kdy dopředu znáte údaj, kolikrát se má tělo cyklu opakovat. Při každém průchodu cyklu se hodnota proměnné zvýší (nebo naopak sníží) o jedničku.
Příklad 1.8 Sečtěte posloupnost čísel, které vám uživatel zadá. Nejdříve od uživatele zjistíte, kolik čísel chce zadat (to uložíte do proměnné pocet). Pak budete načítat čísla a sčítat je v proměnné soucet. Nezapomeňte, že součet budete přičítat sám k sobě, proto musíte nastavit jeho počáteční hodnotu. Vyzkoušejte si algoritmus pro posloupnost pěti čísel (1, 3, -1, 2, 4). Jaká bude vytištěná hodnota proměnné soucet? Řešení najdete na konci kapitoly 1.3.
13
Základy Algoritmizace
b) cyklus s podmínkou na začátku Při provádění cyklu se nejdříve vyhodnotí podmínka. Pokud není splněna, cyklus hned skončí.
Důležité je vědět, že příkazy uvnitř cyklu se nemusí vykonat ani jednou (když není splněna vstupní podmínka).
Příklad 1.9 Sčítejte čísla, která vám uživatel zadá, tak dlouho, dokud nezadá nulu. Pozor, nejdříve musíte načíst jedno číslo ještě před začátkem cyklu, protože musíte mít hodnotu, kterou chcete porovnávat před vstupem do cyklu. Nesmíte také zapomenout toto první číslo přičíst k součtu, proto je načtení dalšího čísla až za součtem. Kdyby to načtení dalšího čísla nebylo až na koni cyklu, tak tu první načtenou hodnotu přepíšete druhou hodnotou v pořadí, aniž byste ji přičetli k součtu. Jaká bude vytištěná hodnota proměnné soucet, pro posloupnost čísel 1, 5, 4, 8, 0 ? Řešení najdete kapitoly 1.3.
14
na
konci
1. Algoritmy
c) cyklus s podmínkou na konci Při provádění cyklu se nejdříve jednou provedou příkazy, které jsou uvnitř cyklu. Teprve na konci cyklu se vyhodnotí, zda je splněna výstupní podmínka. Pokud není, pokračuje provádění cyklu. Je-li splněna výstupní podmínka, cyklus se ukončí.
Důležité je si pamatovat, že příkazy v cyklu se vždy provedou nejméně jednou (protože podmínka se vyhodnocuje až na konci).
Příklad 1.10 Sčítejte čísla, která vám uživatel zadá, tak dlouho, dokud nezadá nulu. Jaká bude vytištěná hodnota proměnné soucet pro posloupnost čísel 2, 3, -1, 2, 1, 0 ? Řešení najdete na konci kapitoly 1.3.
U cyklů je důležité ověřit si, kolikrát se provedou. Vždy si to vyzkoušejte na pokusných datech. To by vám prozatím o podmínkách a cyklech stačilo. Nic se nemá pro začátek přehánět. Ale slibuji vám, že se na ně podíváte podrobněji v dalších kapitolách, kdy začnete tvořit programy a počítač bude vykonávat nějakou činnost.
15
Základy Algoritmizace
1.4 Použití cyklů a podmínek Neoficiálně této části říkám aritmetický průměr na různé způsoby. Podíváte se totiž, jak různě lze vyřešit výpočet aritmetického průměru známek studentů.
Příklad 1.11 Nakreslete vývojový diagram, pomocí něhož spočítáte průměrnou známku studentů ve třídě. K řešení použijte cyklus s předem známým počtem opakování. Z write(‘Zadejte počet studentů ve třídě‘); soucet:= 0; read(pocet);
Ty čárky se nazývají apostrofy a říkají, že chci vytisknout text v apostrofech.
i:= 1,2,…,pocet Write(‘Znamka:‘); Read(Znamka); soucet:= soucet + znamka;
Výpočet průměru proběhne až za cyklem, protože kdybyste ho dali do cyklu, zbytečně by se pocetkrát počítal.
konce cyklu i prumer:=soucet / pocet; write(prumer); K
Výhodou použití cyklu s určitým počtem opakování je jeho jednoduchost. Nevýhodou ale je, že když na začátku zadáte do proměnné počet číslo 30, tak musíte zadat známky 30 studentů. Nemůžete si to uprostřed cyklu rozmyslet a říct, že už zadávat dále nebudete a chcete výsledek z toho, co jste zadali.
16
1. Algoritmy
Příklad 1.12 Nakreslete vývojový diagram, pomocí něhož spočítáte průměrnou známku studentů ve třídě. Zadávání známek bude ukončeno nulou. Řešte pomocí cyklu s podmínkou na začátku Z
Ještě před zahájením cyklu musíte načíst jednu známku, abyste mohli vyhodnotit vstupní podmínku cyklu.
soucet:= 0; pocet:=0; Write(‘Znamka:‘); Read(Znamka);
-
znamka <> 0 +
soucet:= soucet + znamka; prumer:=soucet / pocet; pocet:= pocet + 1; write(prumer); Write(‘Znamka:‘); K
Read(Znamka);
Protože jste načetli jednu hodnotu už před vstupem do cyklu, musíte ji nejdříve zpracovat. Teprve pak můžete načíst další hodnotu.
Nepoužíváte cyklus s řídící proměnnou, proto si musíte počet známek hlídat sami.
Tím, že načtete novou známku až na konci cyklu (za výpočtem součtu a počtu známek) zajistíte: 1) že se nepřepíše první známka, kterou jste zadali před vstupem do cyklu, ještě dříve než ji zvládnete zpracovat. 2) že nová známka se vyhodnotí až před dalším průchodem cyklem. Když známka bude rovná 0, ani do cyklu k zpracování nevstoupí a neovlivní tak proměnnou počet.
17
Základy Algoritmizace
Příklad 1.13a Nakreslete vývojový diagram, pomocí něhož spočítáte průměrnou známku studentů ve třídě. Zadávání známek bude ukončeno nulou. Řešte pomocí cyklu s podmínkou na konci. Z soucet:= 0; pocet:=0; Write(‘Znamka:‘); Read(Znamka); soucet:= soucet + znamka; pocet:= pocet + 1;
znamka =0
Protože přičtete k počtu známek i 0, kterou cyklus ukončíte, musíte ji následně odečíst. Kdybyste ji neodečetli, ovlivnila by průměr známek.
-
Například v posloupnosti známek 1, 2, 3, 2, 4, 0 by počet známek byl 6 a průměrná známka 2. A to není pravda, protože počet známek je 5 a průměrná známka má být 2,4.
+ pocet:= pocet - 1; prumer:=soucet / pocet; write(prumer);
K
Nezapomeňte, že cyklus s podmínkou na konci se vždy provede alespoň jednou. Když se nad problémem s nulou, která je přičtena „navíc“ k počtu známek zamyslíte, můžete najít jiné řešení. Jedno z možných řešení je ukázáno v následujícím příkladu 1.13b.
18
1. Algoritmy
Příklad 1.13b Nakreslete vývojový diagram, pomocí něhož spočítáte průměrnou známku studentů ve třídě. Zadávání známek bude ukončeno nulou. Řešte pomocí cyklu s podmínkou na konci. Z soucet:= 0; pocet:= -1;
Protože víte, že přičtete k počtu známek jednu navíc, připravíte se na to.
Write(‘Znamka:‘); Read(Znamka); soucet:= soucet + znamka; pocet:= pocet + 1;
znamka =0
-
+ prumer:=soucet / pocet; write(prumer);
K
Ehm, taky máte dost té matematiky a všech součtů, počtů a „iksů“? Já tedy jo. Takže ilustrační příklad, který zachycuje situaci, kterou řešíte stále, aniž si to uvědomujete.
19
Základy Algoritmizace
Příklad 1.14 Nakreslete vývojový diagram, pomocí něhož zachytíte chování účastníků silničního provozu na křižovatce řízené semafory.
20
1. Algoritmy
Shrnutí Algoritmus je postup řešení problému konečným počtem kroků. Algoritmy lze popsat slovně, programovacím jazykem apod., ale k nejpřehlednějším způsobům zápisu patří vývojové diagramy. K zakreslení vývojových diagramů se používají stanovené symboly. Algoritmus se skládá ze tří základních částí posloupnosti příkazů, větvení a cyklů. Posloupnost příkazů zachycuje příkazy, které se mají provést v tom pořadí jak jsou zapsány, aniž bude některý vynechán. Větvení slouží k rozhodnutí, po které větvi z možných řešení se vydat. Cyklus opakuje příkazy uvnitř cyklu. Větvení se dělí na úplné, neúplné a vnořené. Při průchodu algoritmem se vyhodnocuje, zda platí nebo neplatí výraz v podmínce. Podle výsledku vyhodnocení se postupuje po určité větvi algoritmu. Existují tři typy cyklů, z nichž každý má své výhody a nevýhody. Nejdůležitější je si vždy uvědomit, kolikrát se příkazy v cyklu provedou a jak to ovlivní požadovaný výsledek algoritmu. Hodnoty, s kterými se v algoritmu pracuje se ukládají do proměnných. Proměnné slouží k uchování hodnoty, která se může v průběhu chodu algoritmu měnit. Nesmí se však měnit typ proměnné.
Kontrolní otázky 1. 2. 3. 4. 5. 6. 7. 8. 9.
Co je to algoritmus ? Jaké vlastnosti má mít správný algoritmus ? Jakými způsoby můžete popsat algoritmus ? Kdy v algoritmu použijete větvení ? Jaký je rozdíl mezi úplným a neúplným větvením ? Co je účelem cyklu ? V kterém z cyklů je přesně stanoveno, kolikrát se má provést ? Který z cyklů se nemusí provést ani jednou ? Který z cyklů se vždy provede alespoň jednou ?
Pojmy k zapamatování algoritmus a jeho vlastnosti proměnná a hodnota uložená v proměnné způsoby zápisu algoritmu typy cyklů typy větvení algoritmu
21
Základy Algoritmizace
Dřina, co?! Ptáte se proč se obtěžovat s vývojovými diagramy, když stejně málokdo z programátorů si je poctivě kreslí? Jednotlivé programovací jazyky se liší a nemůžete se vyznat ve všech. V každém se příkazy zapisují různě. Vývojové diagramy jsou proto takovým programátorským univerzálním jazykem. Vyznají se v nich programátoři ať už se učí v Pascalu, C, Javě či jiných jazycích. Navíc člověk se lépe orientuje v obrázcích a schématech než v čistém textu.
Korespondenční úkol Nakreslete vývojový diagram pro toto zadání: Uživatel bude zadávat čísla. Zadávání skončí, když vloží záporné číslo. Zjistěte kolik zadal kladných čísel a kolik nul. Protože nevíte, kdy uživatel zadá záporné číslo, musíte použít některý z cyklů s neznámým počtem opakování. Dejte si pozor, abyste k výslednému počtu nezapočítali záporné číslo.
Řešení příklad 1.5 (úplné větvení): 1) S = 7 2) S = 0 příklad 1.6 (neúplné větvení): 1) S = 7 2) S = 1 příklad 1.7 (vnořené větvení): 1) S = 10 2) S = 4 3) S = 8 příklad 1.8 soucet = 9 příklad 1.9 soucet = 18 příklad 1.10 soucet = 7
22
2. Program a programování
2.
Program a programování
Cíl: Po prostudování této kapitoly byste měli být schopni: rozdělit programovací jazyky vysvětlit rozdíl mezi algoritmem a programem znát základní pojmy jako program, překladač, syntaxe popsat postup tvorby programu a zásady, které je vhodné v programování dodržovat Čas potřebný k prostudování této kapitoly: 1 hodina Nyní již umíte napsat jednoduchý algoritmus a zapsat jej pomocí vývojového diagramu. Určitě si chcete vyzkoušet zapsat algoritmus v konkrétním programovacím jazyce. Ale vydržte. Nejdříve se musíte seznámit s obecnými pojmy programování a zásadami, kterých se je dobré při tvorbě programu držet. program: algoritmus zapsaný konkrétním programovacím jazykem syntaxe: gramatika programovacího jazyka. Pravidla pro zápis jednotlivých příkazů. sémantika: "stylistická" pravidla programovacího jazyka. Logický význam příkazů. V českém jazyce máte jistou volnost v tom, jaká zvolíte slova, jaké bude jejich pořadí. V programovacích jazycích tomu tak není, musíte striktně dodržovat, jaká slova použijete a v jakém pořadí. Tato pravidla stanovuje syntax. Oproti tomu, jaký bude význam použitých slov a co budou dohromady s ostatními představovat, to je sémantika. V následujících kapitolách se dozvíte, jaká pravidla musíte dodržovat při psaní programu.
2.1 Programovací jazyky Dělení programovacích jazyků: nižší programovací jazyky vyšší programovací jazyky procedurální strukturované objektově orientované neprocedurální
23
Základy Algoritmizace procedurální jazyky: popisují jak problém řešit (tj. algoritmus řešení). neprocedurální jazyky: popisují, co se má řešit (tj. jak mají vypadat výsledná data) strojový kód: instrukce procesoru vyjádřené pomocí čísel ve dvojkové soustavě. Jediné instrukce, které dokáže počítač rovnou provádět (bez překladu). zdrojový kód: text programovacím jazyce.
programu
napsaný
v
konkrétním
vyšším
Pro zájemce Pokud se chcete o jednotlivých programovacích jazycích dozvědět více, nebo si prohlédnout ukázky programovacího jazyka, podívejte se na Internet. Například vám doporučuji otevřenou encyklopedii, kterou najdete na adrese http://cs.wikipedia.org. Zde pak zadejte k vyhledání "programovací jazyk".
Jestli si myslíte, že když napíšete program v Pascalu, C, Javě apod., bude mu počítač rozumět natolik, aby jej rovnou provedl, tak se pletete. Počítač provádí příkazy napsané ve strojovém kódu. Pokud se podíváte na dělení jazyků, zjistíte, že takové jazyky jako Pascal, Java, C, patří mezi vyšší programovací jazyky. A ty se musí do strojového kódu přeložit. Překladače Slouží k převedení zdrojového kódu programu (textu programu) napsaného ve vyšším programovacím jazyce do strojového kódu. 2 druhy překladačů: interpreter: Analyzuje zdrojový text programu řádek po řádku a příkazy ihned provádí. Pro chod programu je nutná přítomnost interpreteru. kompiler (překládač): Čte a překládá zdrojový text programu pouze jednou a jeho výsledkem je soubor se strojovým kódem (tj. spustitelný soubor). Kompiler nejdříve přeloží celý program a pak jej spustí. V dnešní době postupně rozdíly mezi interpreterem a kompilatorem zanikají. Dnes existuje řada vizuálních nástrojů (Visual Age, Delphi, C++ Builder, Visual Basic...), pomocí nichž lze tvořit programy spojováním různých objektů. Ty umožňují vyrobit program téměř bez toho, abyste museli napsat řádky programového kódu. Představte si to jako stavebnici, ve které už máte připravené stavební díly a ty pak lepíte k sobě. Pokud si chcete říkat programátor, musíte se naučit základům - naučit se takové stavební díly tvořit a vědět jak je spojovat.
24
2. Program a programování
2.2
Postup programování
Při tvorbě programu záleží na spoustě faktorů jako např. zkušenosti, znalosti problematiky, kterou řešíte, termínech odevzdání programu. Nemálo záleží na nápadu jak problém řešit. Znáte to, kolikrát přemýšlíte o řešení a nic. Pak v jednu chvíli "cvak" a vás napadne jak problém vyřešit. Tréninkem lze tomu "cvak" pomoci, aby přišlo rychleji. Trénink dělá mistra (každým vyřešeným programem se zlepšujete). Obecně lze postup vytváření programu shrnout do následujících kroků: 1. definice problému 2. sestavení algoritmu (tj. řešení problému) 3. vytvoření programového kódu (zápis konkrétního programovacího jazyka) 4. ověření funkce programu
algoritmu
pomocí
ad 1. definice problému Stanovení požadavků na program, které funkce má plnit. Jaká data do programu vstupují a jaká vystupují, jakou mají mít strukturu (jak mají vypadat). ad 2. sestavení algoritmu V této fázi navrhněte řešení a popište je. Slovně, vývojovými diagramy, schématy, prostě tak, aby se ten, kdo bude algoritmus převádět do zdrojového kódu, v zápise vyznal. Myslete na to, že musíte ošetřit všechny varianty, které mohou nastat. Počítač si nemůže nic domýšlet. ad 3. vytvoření programového kódu Přepište algoritmus pomocí konkrétního programovacího jazyka. Snažte se program psát přehledně. Opatřete program svými komentáři. Těmto třem krokům se budete až habaděj věnovat v následujících kapitolách. Nepodceňujte první část - definování problému. Vždy se přesvědčte, že řešíte správný problém. Nebojte se ptát zadavatele nebo uživatelů, jak si výsledný program představují a co má dělat. ad 4. ověření funkce programu Syntaxi vám pohlídá překladač a zahlásí vám chyby. Neméně důležité je ovšem ověřit logickou funkčnost programu. Zkontrolujte, zda výsledek odpovídá zadání. Zadávejte různá požadovaná data a sledujte, jak se váš program chová. Důležitou částí je vyzkoušet, co se stane, když se uživatel splete, nebo úmyslně zadá jiná data, než vy a váš program očekáváte. Jen tak, mezi námi. Tomu se v "naší hantýrce" říká, že program musí být "omyluvzdorný" a „uživateliodolný“ (slušně řečeno). Ošetřování chyb je mimo rámec tohoto výukového materiálu, ale těm, kteří se rozhodnou programovat, vřele doporučuji dohledat si o tomto tématu informace.
25
Základy Algoritmizace
Pár rad a zásad pro programování: opticky čleňte text programu. Podívejte se na následující ukázky, která je pro vás přehlednější? program prumer; uses crt; var r,S,O:real; begin clrscr; write('Zadejte polomer kruhu: '); readln(r); if r<0 then writeln('polomer musi byt >0') else begin S:=3.14*sqr(r); O:=2*3.14*r; writeln('Obvod kruhu: ',O); writeln('Obsah kruhu je: ',S); readln; end; end.
program prumer; uses crt; var r,S,O:real; begin clrscr; write('Zadejte polomer kruhu: '); readln(r); if r<0 then writeln('polomer musí byt >0') else begin S:=3.14*sqr(r); O:=2*3.14*r; writeln('Obvod kruhu: ',O); writeln('Obsah kruhu je: ',S); readln; end; end.
používejte mnemotechnické pomůcky – z názvu proměnné by mělo být hned jasné, jaké hodnoty jsou v proměnné uchovány. Z názvu proměnné souc_znam vám bude hned jasné, že uchovává součet známek. Bude to na první pohled zřejmé, když se bude proměnná jmenovat sz ? rozlište velkými písmeny víceslovné názvy proměnných. Názvy by ale neměly být příliš dlouhé. např: PrumerZnamek prumer_znamek prum_znam PrumZnam … názvy proměnných, konstant apod. pište zásadně bez diakritiky. Zkrátka pište vše, co je ve zdrojovém kódu programu bez háčků, čárek a ostatních českých znaků (kromě zpráv, které vypisujete uživateli na obrazovku, nebo textových hodnot uložených v proměnných). v době tvorby programu můžete do zdrojového kódu vložit pomocné informace, které vám pomůžou, když ladíte program nebo hledáte chybu. Jen je nezapomeňte po odladění odstranit (výhodnější než vymazání je jejich vložení do komentářů). Myslete na to, co může udělat uživatel dobře a co špatně. Jak to ovlivní váš program. Bude fungovat nebo zhavaruje ?!
26
2. Program a programování Nyní přichází rada, za kterou mě nebudete mít rádi, protože znamená práci navíc. Tady je: TVOŘTE K PROGRAMU KOMENTÁŘE.
DOKUMENTACI
A
PIŠTE
SI
Proč to? Nyní nosíte svůj program v hlavě. Víte, co dělá, jak funguje a co která proměnná znamená. Po 14 dnech si ještě vzpomenete, po dvou měsících už budete mít problém. A pokud budete muset po roce vstoupit do svého programu, tak bez poznámek jej budete pitvat úplně stejně, jako program cizího člověka - nevyznáte se v něm. Nepopisujte každý řádek zdrojového kódu, pouze části programu nebo složité úseky. Ale na to přijdete, až sami sobě několikrát vynadáte.
Shrnutí Každý programovací jazyk má své výhody a nevýhody, hodí se k různým účelům. Programování je nejdříve o způsobu myšlení a řešení problému a teprve pak o znalosti konkrétního programovacího jazyka. Postup tvorby je u většiny programů stejný a lze shrnout do čtyř základních kroků. Během programování je dobré si osvojit některé zásady a dodržovat je. K jedné z nejdůležitějších činností při psaní programu patří vytváření komentářů. Poslouží lidem, kteří musí po vás kód programu číst a také vám, když se budete muset ke svému programu vrátit.
Kontrolní otázky 1. 2. 3. 4.
Jaký je rozdíl mezi programem a algoritmem ? Z kterých čtyř kroků se skládá postup tvorby programu ? Je v programování důležité dbát na správné pořadí příkazů ? Co je to syntaxe a sémantika ?
pojmy k zapamatování program syntaxe a sémantika kroky tvorby programu procedurální a neprocedurální jazyk vyšší a nižší programovací jazyk zdrojový kód strojový kód
27
Základy Algoritmizace
Korespondenční úkol Zkuste se vžít do role rodiče, který má doma pubertální dítě. Dítě má ve svém pokoji přístup k většině vymožeností dnešního světa (televize, počítač, mobil..). Vaším úkolem je navrhnout postup (napsat algoritmus-vývojový diagram), který zajistí, aby dítě spalo. Vžijte se i do role dítěte a přemýšlejte, co vaše dítě podnikne v okamžiku, kdy jej pošlete večer spát a zavřou se dveře pokoje. Jaká bude vaše protiakce. Účelem tohoto úkolu je, abyste se naučili myslet i na to, co dělá „protivník“ . Nyní je to dítě, které se bude snažit obejít vaše nařízení. Později to bude uživatel, který váš program spustí. A vy musíte přemýšlet, co všechno může uživatel udělat, zda jeho činnost nepřivede váš program ke kolapsu. Tento úkol je spíše pro pobavení, takže vaši "rodičovské" fantazii se meze nekladou.
28
3. Základy jazyka Pascal
3.
Základy jazyka Pascal
Cíl: Po přečtení této kapitoly byste měli být schopni vysvětlit základní pojmy používané v programování a jazyce Pascal popsat základní strukturu programu okomentovat program uvnitř zdrojového kódu programu použít přiřazovací a složený příkaz načíst do programu data zadaná uživatelem na klávesnici vypsat na obrazovku zprávu pro uživatele a hodnoty spočítané programem Čas potřebný k prostudování této kapitoly: 3 hodiny Hurá, prokousali jste se k místu, po jehož přečtení byste měli být schopni napsat kratičký program a počítač bude konečně vykonávat nějakou činnost. Zkrátka už uvidíte plody své práce. Vzhůru do tajů Pascalu. Pascal vytvořil jako výukový programovací jazyk Nicolaus Wirth. Později se rozšířil i do komerční sféry, z které je ovšem už dnes vytlačen novými generacemi programovacích jazyků. Nicméně, v oblasti, pro kterou byl navržen – výuku programování, je stále vhodným nástrojem. Dnešní Pascal, který budete používat, se značně liší od původního Wirthova Pascalu. Nejrozšířenější jsou dnes kompilátory Turbo Pascal a Borland Pascal. Dále budete pracovat s Borland Pascalem, ale pro zjednodušení jej budete nazývat pouze Pascal.
3.1
Struktura programu v Pascalu
Program se skládá ze 4 částí : ¨ hlavičky (záhlaví) – obsahuje klíčové slovo program a název programu. V názvu programu nesmí být použito klíčové slovo nebo mezery. ¨ připojení knihoven – slouží k připojení standardních nebo vlastních knihoven. Knihovna (tzv. UNIT) obsahuje části programů, které jsou již zprogramovány a vy je pouze použijete. Typickým příkladem jsou funkce. Např. zavoláte a použijete funkci SQRT a nestaráte se o to, jak funguje. Pouze vás zajímá výsledek, který vám funkce vrátí. Připojení knihovny se provádí pomocí klíčového slova USES a názvu knihovny. ¨ deklarační části – deklarují se konstanty, proměnné, typy proměnných, procedury a funkce, které se budou dále používat v příkazové části programu. Zjednodušeně řečeno deklarace znamená nadefinování, aby počítač věděl s čím bude pracovat. ¨ příkazové části – je tvořena složeným příkazem, který je ukončen tečkou.
29
Základy Algoritmizace program název_programu;
hlavička
uses knihovna;
připojení knihovny
label – deklarace návěští const – deklarace konstant type – deklarace datových typů var – deklarace proměnných procedure – deklarace procedur function – deklarace funkcí begin
deklarační část
příkazová část
příkazy; end. program vypocet_obsahu_obdelnika;
hlavička
uses crt; var a, b, S : integer;
deklarační část
begin write(‘Zadejte velikost strany a, b ‘); read(a,b)` S:= a * b; write(‘Plocha obdelnika je: ‘, S); end.
příkazová část
Toto je jednoduchá ukázka programu v Pascalu. Jednotlivé řádky si později projdete důkladněji. Nyní si všimněte, že příkazy končí středníkem a celý program je ukončen tečkou. Dále si všimněte, že za begin není středník. Počet begin musí být stejný jako počet end. Ještě vás chci upozornit, abyste zdrojový kód opticky členili a tak se v něm vyznali. Při psaní zdrojového kódu programu můžete použít: malá i velká písmena anglické abecedy číslice: 0 až 9 speciální symboly: + - * / . , : ; = < > ( ) [ ] { } # $ @ ^ ‘ dvojice znaků: : = < = > = < > . . ( * * ) identifikátory: názvy, které použijete v programu; tj. názvy proměnných, konstant, datových typů, procedur, funkcí a také název programu. Názvy identifikátorů musí být v programu jedinečné. Pascal nerozlišuje velikost písmen v názvech identifikátorů. Identifikátor nemůže začínat číslicí. Pro identifikátor použijte maximálně 63 znaků. Dávejte si ale pozor, abyste nepojmenovali stejně celý program a některou z proměnných.
30
3. Základy jazyka Pascal klíčová slova: taková slova, která jsou vyhrazena a lze je použít jen přesně definovaným způsobem. Nebo řečeno naopak, jsou to taková slova, která nemůžete použít, jak byste chtěli. Například klíčová slova nelze použít jako název identifikátoru (např. proměnných nebo konstant). and const downto for in library of record string until xor
asm constructor else function inherited mod or repeat then uses
array destructor end goto inline nil packed set to var
begin div exports if interface not procedure shl type while
case do file implementation label object program shr unit with
konstanta: stálá hodnota nadefinovaná na začátku programu, která se v průběhu programu nemění. Klasickým případem je konstanta PI=3.14. řetězce znaků: posloupnost znaků, která je na obou stranách ohraničena apostrofy. Obvykle se používají pro text, kterým komunikujete s uživatelem. funkce: část programu (tzv.podprogram), která vrací jedinou hodnotu. Funkci zadáte vstupní data a nestaráte se o to, co se děje uvnitř funkce. Pouze očekáváte, že vám funkce vrátí výsledek. procedura: část programu (tzv.podprogram), která na rozdíl od funkce nevrací pouze jedinou hodnotu, ale může vrátit více hodnot. Někdy také pouze provede svůj úkol a vůbec nemusí vracet nějakou hodnotu. Typickým příkladem procedury je např. příkaz Writeln.
Pravidla psaní zdrojového kódu v Pascalu: - mezery se mohou psát libovolně (nerozhoduje počet mezer) - nerozlišují se malá a velká písmena - komentáře se uzavírají do složených závorek { } nebo do kulatých závorek s hvězdičkou { Tady je můj komentář } nebo (* Takto take můžu zapsat komentář *)
Příklad 3.1: Ukázka zápisu komentářů. program vypocet_obsahu_obdelnika; uses crt; var a, b, S : integer; begin write(‘Zadejte velikost strany a, b ‘); read(a,b); {do a,b se vloží délky stran} S:= a * b; {výpočet obsahu obdélníka} write(‘Plocha obdelnika je: ‘, S); end.
31
Základy Algoritmizace
3.2 Příkazy v Pascalu Příkaz chápejte jako provedení jednoduché činnosti. Znáte to už odmalička – udělej, proveď, splň apod. V programovacím jazyku mají příkazy svůj přesný význam a zápis. dělení příkazů v Pascalu: jednoduché přiřazovací příkaz příkaz volání procedury příkaz skoku strukturované složený příkaz podmíněné příkazy příkazy cyklu přiřazovací příkaz: zapíše výslednou hodnotu z výrazu na pravé straně do proměnné uvedené na levé straně. zapisuje se jako dvojtečka a rovnítko tj. := x:= a + b; výsledek výrazu a + b se přiřadí do proměnné x.
Příkaz skoku jsem pouze zmínil v dělení příkazů a nebudu jej vysvětlovat. Proč? Protože v strukturovaném programování by se neměl používat, tak proč vás lákat na scestí.
Příklad 3.2: Do proměnné odmocneno, vložte druhou odmocninu ze zadaného čísla. SQRT ( ) je funkce, která vrací druhou odmocninu ze zadaného čísla odmocneno:= sqrt ( x ); Funkce SQRT vrátí a vloží do proměnné odmocneno druhou odmocninu hodnoty, která je uložená v proměnné x. Tj. když x=16, tak po provedení příkazu bude proměnná odmocneno= 4.
složený příkaz: je tvořen více příkazy a je ohraničen klíčovým slovem begin a end zakončeným středníkem. Počítač se na všechny příkazy uvnitř složeného příkazu dívá jako na jeden jediný příkaz. begin příkaz1; příkaz2; příkaz3; end;
Složený příkaz. Pozor, každý příkaz končí středníkem. End se středníkem říká „zde končí složený příkaz“. Začátek složeného příkazu je označen klíčovým slovem Begin. Za Begin není žádné interpunkční znaménko.
32
3. Základy jazyka Pascal
3.3 Příkazy vstupu a výstupu Abyste mohli v programu s daty pracovat, musíte je do programu vložit (načíst). Jedná se o vstupní data. Z kterých vstupních zařízení počítače je získáte, si zopakujte v Úvodu do výpočetní techniky. Nám pro tuto chvíli postačí vědět, že data můžete získat ze souboru, který je již v počítači uložen, nebo z klávesnice. Dále v textu budete uvažovat pouze o vstupech z klávesnice a výstupech na monitor.
1. příkaz vstupu: read a readln read(proměnná); Říká: „Načti to, co ti uživatel „nacvaká“ na klávesnici (do chvíle než stiskne Enter) a ulož to do proměnné.“
např: read(cislo); read(jmeno); read(znak); Můžete použít i tento tvar zápisu: read(promenna1,promenna2, promenna3,…,promennaN) Všimněte si, že proměnné jsou odděleny čárkou, ale za poslední proměnnou čárka nesmí být, jinak program očekává další proměnnou.
Rozdíl mezi read a readln: read: načte zadanou hodnotu z klávesnice (načte jen hodnotu bez Enter) readln: načte zadanou hodnotu z klávesnice a přesune kurzor na další řádek (načte hodnotu i Enter) Poznámka 1. Pozor. Při vstupu se hlídá, zda hodnota, která je vkládána do proměnné z klávesnice, je správného datového typu, který jste pro proměnnou určili. Pokud se například do proměnné typu integer pokusíte vložit text, program se zastaví a nahlásí například tuto chybu: Invalid numeric format 2. Jestliže zadáte jen příkaz readln se středníkem, bude program čekat až zadáte Enter. Toho využijete v okamžiku, kdy chcete program zastavit a počkat dokud uživatel nestiskne Enter (aby vám program hned neskončil a vypsané hodnoty nezmizely).
33
Základy Algoritmizace
2. příkaz výstupu: write a writeln Zde to bude trošku složitější, protože výstup si budete chtít upravit k obrazu svému. Nejlépe se podívejte na příklady. write(promenna); vytiskne se hodnota uložená v proměnné write(‘Tento text se vytiskne‘); vytiskne se text umístěný v apostrofech write(‘Výsledek je: ’, promenna);
Vytiskne se text: „Výsledek je:“ a k němu se pak vytiskne hodnota uložená v proměnné.
Text je oddělen apostrofy a čárkou , teprve pak následuje název proměnné.
Např. když v proměnné promenna bude uložena hodnota 26 pak se vytiskne: Výsledek je: 26
rozdíl mezi write a writeln write: po zobrazení položek uvnitř příkazu zůstane kurzor na stejném řádku writeln: po zobrazení položek uvnitř příkazu se kurzor přesune na další řádek Pokud byste chtěli, aby se vám hodnota uložená v proměnné vytiskla uvnitř věty, je postup následující: write(‘Cena nákupu je: ’, cena,‘Kč ’); text
proměnná text
Na konci není čárka, jinač by překladač očekával další proměnnou nebo text.
Tyto 3 části - text, proměnná, text, musí být od sebe odděleny čárkou. A nezapomeňte text se ohraničuje apostrofy.
Příklad 3.3 Napište program, který vypočítá obsah rovnoramenného trojúhelníka. program obsah_trojuhelnika; uses crt; var a,v,S:real; begin clrscr; {procedura, která vymaže obrazovku} write('Zadejte délku podstavy trojúhelníka: '); readln(a); write('Zadejte vysku trojuhelnika: '); readln(v); S:=(a*v)/2; writeln;writeln; {vloží dva prázdné řádky na obrazovku} writeln('Obsah trojuhelnika je: ',S); readln; {program se zastaví a čeká na stisk klávesy Enter} end.
34
3. Základy jazyka Pascal Protože jste použili reálná čísla, program vypíše výsledek v tomto tvaru: 3.6000000000+01. Vlastně to znamená 3.6 * 101. Člověk na takové zobrazování desetinných čísel není zvyklý. Musíte proto výsledek upravit pomocí formátování výstupu. Výstup si můžete upravit ve tvaru: Write (proměnná : počet znaků: počet desetinných míst); celkem, včetně desetinné čárky
z toho desetinných míst
Příklad 3.3 x = 120
y = 111.387
Toto formátování výstupu lze provádět pro datové typy boolean, char, integer, real a string. Vy se ale určitě spokojíte s tím, že si budete upravovat výsledky typu real, aby „byly pěknější“ ☺
Příklad 3.4 Napište program, který načte z klávesnice desetinné číslo (nejméně s 4 číslicemi za desetinnou čárkou), vymaže obrazovku a poté totéž číslo vytiskne upravené na dvě desetinná místa program vstup; uses crt; {protoze dale v programu pouzivate proceduru ClrScr,musite pocitaci rict, v ktere knihovne ji ma hledat. V tomto pripade je to knihovna Crt} var cislo: real; begin clrscr; read(cislo); clrscr; write(cislo:6:2); {at zde zvolite misto 6 jakoukoli jinou cislici, je dulezite, na kolik desetinnych mist chcete cislo vytisknout} readln; {program se zastavi a ceka na stisknuti Enteru} readln; end. Pomocí příkazu Write nebo Writeln můžete zobrazit i libovolný text zapsaný v apostrofech, ale uvnitř příkazu Read nebo Readln může být pouze proměnná. 35
Základy Algoritmizace Tak a v tuto chvíli mám pro vás pokyn, který vás asi překvapí. Ale věřte mi a pro vaše dobro se jim řiďte. Ve svých programátorských začátcích používejte papír, tužku a gumu. Teprve potom až počítač. Pište své programy na papír, na papíře si je otestujte, zda budou fungovat. Teprve až pak je přepište do počítače. Divné, že?! Nechce se tomu věřit, ale váš mozek je propojen s rukou. V začátcích nezkoušejte přepisovat algoritmus rovnou do počítače. Časem budete schopni jednoduché úlohy řešit v hlavě a rovnou je přepisovat do počítače v konkrétním programovacím jazyce. Ale nyní ještě ten čas nenastal. Tužka, papír a jedem. Žádné odmlouvání, přece po vás nechci kalamář a husí brk ☺.
Shrnutí V této kapitole jste se dozvěděli, jaká je struktura programu a jaké použít příkazy, pokud chcete komunikovat s uživatelem. Program má definovanou strukturu skládající se z hlavičky, deklarační části a příkazové části. Hlavička slouží k základnímu popisu programu. V deklarační části se popisují všechny objekty, které se dále použijí v příkazové části. Pro načtení údajů z klávesnice se používají používá příkaz read a readln. Příkaz read pouze načte hodnotu do proměnné. Příkaz readln načte hodnotu zadanou z klávesnice a přesun kurzor na další řádek. Pro výpis údajů uživateli na obrazovku se používají příkazy write a writeln. Write po vypsání zprávy nebo hodnoty uložené v proměnné ponechá kurzor na stejném řádku, kdežto příkaz writeln navíc přesune kurzor na další řádek. Prázdný příkaz writeln slouží k vložení prázdného řádku na obrazovku. Prázdný příkaz readln se používá k zastavení programu a čekání na to, až uživatel stiskne enter.
Kontrolní otázky 1. 2. 3. 4. 5. 6.
Z kterých částí se skládá program v Pascalu ? K čemu slouží knihovny (unity) ? Jaký je rozdíl mezi funkcí a procedurou ? Čím musí být ohraničen řetězec znaků ? Rozlišuje Pascal v názvech identifikátorů malé a velké znaky ? Kterými klíčovými slovy je ohraničen složený příkaz ?
Pojmy k zapamatování procedura read readln write writeln
proměnná konstanta klíčová slova struktura programu v Pascalu složený příkaz přiřazovací příkaz funkce 36
4. Datové typy v Pascalu
4. Datové typy v Pascalu Cíl: Po prostudování této kapitoly byste měli být schopni vysvětlit účel datových typů vyjmenovat a rozdělit datové typy použít datové typy v programu Čas potřebný k prostudování této kapitoly: 3 hodiny Jak číst tuto kapitolu ? Přečtěte si ji, zapamatujte si jaké existují datové typy, některé základní funkce a procedury. Pozornost věnujte zejména příkladům a způsobu jak jsou v nich použity funkce. V žádném případě se neučte zpaměti přesně rozsahy hodnot, kterých mohou proměnné daného typu nabýt, také se neučte všechny funkce, které lze použít. Mějte o nich povědomí a v případě potřeby si dohledejte potřebné informace. Při programování se pak k těmto informacím vracejte. O datových typech v Pascalu, byly již popsány stohy papíru, takže stačí trochu „zagooglovat“. Druhou možností je najít daný datový typ v nápovědě programového prostředí, které používáte pro psaní programu. My si spolu popíšeme jen základy datových typů a upozorníme, na co si dát pozor. Pro vyhledávání informací na internetu vám navrhuji tato klíčová slova: datové typy v Pascalu, datové typy, Pascal, typy dat, nebo použijte klíčové slovo Pascal a název datového typu, který chcete vyhledat. Datové typy určují, jakých hodnot mohou proměnné nabývat. Jaké operace lze s proměnnými daného typu provádět a jaké předdefinované funkce lze použít. Určují, jestli bude hodnota v proměnné chápana jako text nebo číslo (v případě čísla, zda půjde o celočíselná nebo desetinná /reálná/ čísla) apod. Jinými slovy: jaké hodnoty může program od uživatele očekávat na vstupu a jak má na ně pohlížet.
Příklad 4.1 Rozdíl v chápání čísel a textu Pokud definujete proměnnou x jako celé číslo a uživatel do ní vloží z klávesnice 123, pak po provedení operace y:= x + 53 bude v proměnné y uložená číselná hodnota 176. Pokud definujete proměnnou x jako textovou a uživatel do ní vloží z klávesnice 123, pak u operace y:= x + 53 překladač zahlásí chybu, protože se pokoušíte sečíst číslo a text dohromady. Pokud definujete proměnnou x jako textovou a uživatel do ní vloží z klávesnice 123, pak výsledkem operace y:= x + ‘53‘ bude v proměnné y uložená textová hodnota 12353. Pokud uvedete číslo v apostrofech, nebude chápáno jako číslo, ale jako text
37
Základy Algoritmizace Člověk v obou případech vidí, že jde o číslo, ale pro počítač jde o dvě naprosto odlišné věci - číslo a text. Více se o práci s textem dozvíte v kapitole 7. Práce s textem. Pro deklaraci proměnných se používá klíčové slovo VAR. Název proměnné je od názvu datového typu oddělen dvojtečkou. Proměnné stejného typu lze deklarovat na jednom řádku a oddělit je čárkou.
Příklad 4.2 VAR
x : integer; y : integer; z : real; k : real;
VAR x, y : integer; z, k : real;
Existuje několik dělení datových typů a literatura se v zařazení jednotlivých typů občas mírně liší. Když se na dělení podíváte, tak si asi zprvu řeknete – „K čemu mi to je?“ Dělení slouží pro vaši lepší orientaci, ale to si uvědomíte teprve, až vám jejich používání přejde do krve.
dělení datových typů: 1) datové typy standardní – předdefinované v jazyce Pascal integer (celočíselné) real (reálné) boolean (logické) char (znakové) string (řetězec) jednoduché typy definované uživatelem definované výčtem typ interval set (množina) array (pole) record (záznam) soubor ukazatel 2) datové typy jednoduché – dále nedělitelné real ordinální - integer - boolean - char - výčtový
38
4. Datové typy v Pascalu strukturované – definují určitou strukturu dat, která je dále dělitelná např. typ pole. pole záznam množina soubor string ukazatel
Ordinální datové typy ordinální datový typ: takový typ, kdy můžete prvku určit jeho pořadové číslo, předchůdce a následníka. Pro práci s nimi lze využít funkce SUCC() – vrací následníka zadané ordinální hodnoty PŘED() – vrací předchůdce zadané ordinální hodnoty ORD() – vrací ordinální číslo zadané ordinální hodnoty ordinální datové typy: - integer - char - boolean - výčet - interval
4.1 Základní standardní datové typy Pamatujte si, že je obrovský rozdíl, zda do proměnné ukládáte celé číslo nebo desetinné. Uvedený rozsah hodnot berte orientačně, závisí na typu počítače a verzi překladače Pascalu. Poznámka Výsledkem operací s relačními operátory (= , < , > , <= , >= , <>) je vždy logická hodnota TRUE (pravda) nebo FALSE (nepravada).
4.1.1 Integer celá čísla rozsah hodnot: - 32 768 až 32 767 operace = , < , > , <= , >= , <> +, - , *, / , div, mod div: vrací výsledek po celočíselném dělení mod: vrací zbytek po celočíselném dělení
39
Základy Algoritmizace
Příklad 4.3 použití operátoru DIV a MOD 236 : 2 = 118 výsledek po dělení 36 16 zbytek po dělení 0 y:= 236 mod 2
y:= 236 div 2
vrátí 0, proto v proměnné y bude uložena hodnota 0.
vrátí 118, proto v proměnné y bude uložena hodnota 118.
nejčastěji používané funkce: ABS() – vrací absolutní hodnotu z čísla SQR() – vrací druhou mocninu z čísla SQRT() – vrací druhou odmocninu čísla Celočíselný datový typ integer byl později doplněn o následující celočíselné typy. V tabulce vidíte jejich název, rozsah a nároky na paměť (kolik místa jedno číslo tohoto typu zabere v paměti). Datový typ
Rozsah hodnot
Paměťové nároky
- 32 768 .. 32 768
2 byte
0 .. 255
1 byte
shortint
- 128 .. 127
1 byte
word
0 .. 65 535
2 byte
- 214 748 3648 .. 214 748 3647
4 byte
integer byte
longint comp
63
63
- 2 + 1 .. 2 - 1
8 byte
Příklad 4.4 Napište program, který ze zadaného celého čísla a jeho celočíselného dělitele zjistí výsledek a zbytek po celočíselném dělení. program celociselne_deleni; uses crt; var cislo, delitel: integer; begin clrscr; write('Zadejte cele cislo, ktere se ma vydelit: '); readln(cislo); write('Zadejte cislo, kterym se ma delit (delitele): '); readln(delitel); writeln('Vysledek celociselneho deleni je: ',cislo div delitel); writeln('Zbytek po celociselnem deleni je: ',cislo mod delitel); readln; V případě jednoduchých programů lze zapsat i takto. Výsledek výrazu end. se nemusí zapisovat do žádné proměnné, ale rovnou se vypíše na obrazovku.
40
4. Datové typy v Pascalu
4.1.2 Real reálná (racionální, desetinná) čísla rozsah hodnot: 2.9*10-39 až 1.7*1038 operace: = , < , > , <= , >= , <> +, - , *, / , nejčastěji používané funkce: ABS() – vrací absolutní hodnotu ze zadaného čísla SQR() – vrací druhou mocninu SQRT() – vrací druhou odmocninu SIN() – vrací sinus úhlu zadaného v radiánech COS() - vrací cosinus úhlu zadaného v radiánech ARTAN()- vrací acustangens zadané hodnoty v radiánech LN() – vrací přirozený logaritmus ze zadaného čísla EXP() – vrací hodnotu ex TRUNC() – ořízne hodnotu typu real na hodnotu typu longint (odřízne desetinnou část čísla) ROUND() – zaokrouhlí hodnotu typu real na hodnotu typu integer PI – vrací hodnotu Ludolfova čísla (3.14 …) Pro zájemce Rovněž datový typ real byl rozšířen o další desetinné datové typy. Zde jsou pouze jejich názvy: single, double, extended. Pokud potřebujete o nich zjistit více informací, „vygooglujte“ je nebo se na ně podívejte v nápovědě.
Pozor, nyní vás upozorním na chybu, které se občas nevyhnete. Ale musíte ji umět vyřešit. Často se vám bude stávat, že se pokusíte zapsat desetinné číslo do proměnné, která je typu integer (a očekává tedy celé číslo). Program v tuto chvíli zahlásí chybu. Konverze (převod) datových typů mezi sebou. Hodnotu typu integer (celé číslo) lze zapsat do proměnné typu real. Převod z integeru na real provádí počítač automaticky. Problém ale nastává, pokud chcete zapsat reálné číslo např. 12,85 do proměnné typu integer. Počítač neví, co si má počít s desetinnou částí 0,85. Počítač stojí před dvěmi možnostmi: 1. zaokrouhlit desetinnou část ( v tom případě uloží číslo 13) 2. odříznout desetinnou část (v tom případě uloží číslo 12) Jak sami uznáte, tak čísla 12 a 13 jsou úplně jiná čísla. Proto pokud budete potřebovat převést číslo typu real na integer, musíte počítači říci jak to provést. K tomuto účelu slouží funkce TRUNC() a ROUND().
41
Základy Algoritmizace
Příklad 4.5 Napište program, který spočítá druhou mocninu a druhou odmocninu ze zadaného reálného čísla. Výsledky pak převede na proměnnou typu integer pomocí funkcí trunc() a round(). Program prevod; uses crt; var cislo, mocnina, odmocnina: real; begin clrscr; write('Zadejte desetinne cislo: '); readln(cislo); mocnina:= sqr(cislo); Funkce trunc vrátí celočíselnou odmocnina:= sqrt(cislo); část čísla, které je uloženo writeln;writeln; v proměnné mocnina. writeln('druha mocnina: ',mocnina:4:2); writeln('druha mocnina upravena funkci trunc(): ',trunc(mocnina)); writeln('druha mocnina upravena funkci round(): ',round(mocnina)); writeln;writeln; writeln('druha odmocnina: ',odmocnina:4:2); writeln('druha odmocnina upravena funkci trunc(): ',trunc(odmocnina)); writeln('druha odmocnina upravena funkci round(): ',round(odmocnina)); readln; end.
Když už vás upozorňuji na chyby, tak ještě tři upozornění. Když dělíte dvě čísla mezi sebou, výsledek musíte vždy uložit do proměnné typu real. Výsledek dělení je vždy reálný. Dejte pozor na chybu přetečení. Proměnná bude např. typu byte a vy (nebo uživatel) se do ni pokusíte uložit třeba číslo 1000. A ejhle, chyba je na světě, protože do proměnné typu byte můžete uložit číslo do 255. Pozor na dělení nulou. V případě dělení se vždy přesvědčte, zda náhodou nemůže nastat situace, kdy budete dělit nulou.
4.1.3 Boolean slouží k vyjádření logických hodnot (pravda, nepravda). rozsah hodnot: true, false ( má pouze tyto dvě hodnoty) operace: = , < , > , <= , >= , <> AND, OR, NOT Mezi základní standardní datové typy patří ještě typ Char (znak) a String (řetězec znaků), ale ty jsou probírány až v kapitole 7. Práce s textem.
42
4. Datové typy v Pascalu
4.2 Uživatelem definované datové typy Tyto typy pouze zmíním a zdržíte se u nich velice krátce. Seznámíte se pouze s typem interval a typem výčet hodnot. Věnujte především pozornost, jakým způsobem se deklarují nové datové typy. S datovým typem array (pole), který do této skupiny také patří, se seznámíte v kapitole 8. Datový typ Pole( Array), kde bude také stručně vysvětlen datový typ record. Pascal mimo předdefinovaných datových typů umožňuje nadefinovat vlastní datové typy. K deklaraci se používá klíčové slovo TYPE. TYPE jméno_typu = popis typu; pozor, zde je rovnítko
buď standardní datový typ nebo již existující datový typ (musí být popsán v kódu programu před deklarací nového typu) nebo popis nového typu.
4.2.1 Výčet hodnot Umožňuje definovat výčet hodnot, kterých může proměnná nabývat. TYPE jmeno_typu = (hodnota1, hodnota2,….); TYPE domaci_zvire = (pes, kocka, slepice, krocan, kralik); divoke_zvire = (zajic, jelen, srna); VAR zvire1 : domaci_zvire; zvire2 : divoke_zvire;
4.2.2 Interval Proměnné tohoto typu mohou mít pouze hodnoty z určitého intervalu TYPE jmeno_typu = min_hodnota ..maxim_hodnota; Mohou to být hodnoty již definovaného ordinálního typu.
TYPE
Tznamka = 1..5; Tden = 1..31;
VAR
znamka : Tznamka;
Nelze použít stejné jméno pro typ a proměnno, proto pro název typu použijte např. Tznamka nebo TypZnamka apod.
den : Tden; Tak, mám pro vás potěšující zprávu. Právě jste se prokousali poslední kapitolou, která obsahuje spoustu teorie, kterou musíte pochytit, abyste mohli řádně začít programovat. To chce určitě malou oslavu – skočte si do ledničky, otevřete si mléko a rozšoupněte se ☺
43
Základy Algoritmizace
Shrnutí V této kapitole jste se seznámili s některými datovými typy a jejich rozdělením. Datové typy lze dělit z různých hledisek. Toto dělení pomáhá orientovat se v datových typech. Zvolený datový typ proměnné určuje množinu hodnot, kterých může proměnná nabývat, a množinu operací, které lze s proměnnou provádět. Přiřazení proměnné k datovému typu se provádí v deklarační části programu pomocí klíčového slova VAR. Název proměnné je od názvu datového typu oddělen dvojtečkou. Vysvětlili jsme si některé standardní datové typy, přičemž zvláštní pozornost byla věnována číselným datovým typům integer a real. Při psaní programu byste měli mít neustále na paměti pravidla vzájemného převodu mezi hodnotami typu integer a real. Také byste měli vždy zbystřit, pokud dělíte dvě čísla. Výsledek dělení je vždy typu real. Pro zjištění výsledku a zbytku po celočíselném dělení dvou celých čísel se používají operátory DIV a MOD. S datovými typy char, string, array, record a jejich použitím se seznámíte v dalších kapitolách.
Kontrolní otázky 1. K jakému účelu slouží datové typy ? 2. Je rozdíl, je-li číslo deklarováno jako číselný datový typ nebo textový ? Jaký ? 3. Lze do proměnné typu real vložit hodnotu typu integer ? Platí to naopak ? 4. Jakých hodnot může nabývat výsledek relačních operací ? 5. Které klíčové slovo se používá pro deklaraci proměnných ? 6. Jaké klíčové slovo použijete, chcete-li deklarovat vlastní datový typ ?
Pojmy k zapamatování interval VAR TYPE div mod
datový typ integer real byte boolean typ definovaný výčtem
Korespondenční úkol Napište program, který spočítá obsah a obvod kruhu. Jako vstup do programu zadá uživatel poloměr.
44
5. Podmínky
5. Podmínky Cíl: Po prostudování této kapitoly byste měli být schopni zformulovat podmínky v jazyce Pascal zapsat neúplnou i úplnou podmínku zformulovat a vyhodnotit výraz uvnitř podmínky s použitím logických spojek AND, OR, NOT Čas potřebný k prostudování této kapitoly: 4 hodiny Když jsem vás na konci předchozí kapitoly poslal odpočinout si k ledničce, myslel jsem to s vámi dobře. Protože nyní už začíná opravdové programování. V následujících dvou kapitolách se naučíte používat podmínky a cykly, které jsou jádrem každého programu. Věnujte proto těmto dvěma kapitolám zvýšenou pozornost. Vyplatí se to později. V první kapitole o algoritmech jste se už setkali s podmínkami neboli podmiňovacími příkazy (také ještě označovanými jako příkazy pro rozhodování). Už víte, že existují tři typy: neúplné, úplné, vícenásobné a vnořené podmínky. Nyní se je naučíte používat v programovém kódu. Na konci kapitoly se naučíte sestavovat složitější výrazy, které tvoří jádro rozhodování. V Pascalu se pro podmínku používají klíčová slova IF (jestliže), THEN (pak), ELSE (jinak). Za klíčovými slovy Then a Else se provede vždy jen jeden příkaz. Chcete-li, aby se provedlo více příkazů, musíte použít složený příkaz. Jádrem podmínky je výraz, který se vyhodnocuje (např. cislo > 0). Ať je výraz v podmínce jakkoli složitý, výsledkem vyhodnocení je vždy logická hodnota true (pravda) nebo false (nepravda).
5.1 neúplná podmínka výraz
+ Zapsáno obecně:
-
Přeloženo: JESTLIŽE platí (je splněn) výraz PAK vykonej příkaz;
IF výraz THEN příkaz; příkaz
Neúplná se nazývá, protože neobsahuje část else. Podmínka funguje následovně: výraz se vyhodnotí a pokud je jeho výsledkem logická hodnota true, provede se příkaz uvedený za části then. Pokud je výsledkem logická hodnota false, tak se v případě neúplné podmínky neprovede nic a program pokračuje příkazy následujícími za podmínkou. 45
Základy Algoritmizace Samozřejmě často potřebujete, aby se, pokud je splněn výraz v podmínce (nebo naopak není splněn), vykonal více než jeden příkaz. V tom případě musíte použít složený příkaz. IF výraz THEN BEGIN příkaz1; příkaz2; END;
složený příkaz. Je-li splněna podmínka, provede se příkaz za THEN. Na složený příkaz se pohlíží jako na 1 příkaz.
Pozor, jestliže použijete složený příkaz, nesmí být za klíčovým slovem THEN středník. Pokud byste ho tam dali, tak v případě platnosti podmínky se neprovede nic, protože program chápe středník jako prázdný příkaz a ukončí podmínku. V tom případě se pak bude vždy pokračovat složeným příkazem Begin. Nejlépe tuto chybu vidíte na vývojovém diagramu vpravo.
výraz
+
příkaz
příklad 5.1 Napište program, který načte 2 čísla x, y. V případě, že splňují podmínku x > y, vypíše hlášení „číslo x je větší než y“. begin writeln(‘Zadejte číslo x’);readln(x); writeln(’Zadejte číslo y’);readln(y); IF x >y THEN writeln(’Číslo x je větší než y’); end.
Zde vidíte, že za klíčovým slovem THEN následuje pouze jeden příkaz.
Příklad 5.2 Napište program, který načte 2 čísla x, y. V případě, že splňují podmínku x > y, vypíše hlášení „číslo x je větší než y“ a rozdíl mezi čísly. begin writeln(‘Zadejte číslo x ’);readln(x); writeln(’Zadejte číslo y’);readln(y); IF x >y THEN begin rozdil:= x – y; writeln(’Číslo x je větší než y a rozdíl je: ’, rozdil); end; end. Zde vidíte, že za klíčovým slovem THEN není středník a následuje složený příkaz.
Určitě už vás napadlo, že v životě neplatí jen neúplná podmínka ve tvaru „Když platí to a to pak udělej“, ale většinou ještě vždy dodáváte „v opačném případě dělej to a to.“ Tomu se říká úplná podmínka.
46
5. Podmínky
5.2 Úplná podmínka IF výraz THEN
-
výraz
příkaz2
+
příkaz1
Všimněte si, že za klíčovým slovem End před Else není středník. Pokud jej tam dáte, počítač si myslí, že jste předchozí podmínku ukončili a zahlásí chybu, protože nemůže stát samostatně. ZapsánoElse obecně: Přeloženo: JESTLIŽE platí (je splněn) výraz PAK vykonej příkaz1 IF výraz THEN příkaz1 jinak proveď příkaz2. ELSE příkaz2;
BEGIN příkaz1; příkaz2; END ELSE BEGIN příkaz3; příkaz4; END;
Teprve za tímto End se středníkem končí celá podmínka.
Příklad 5.3 Zadání předchozího příkladu s výrazem x > y trošku poupravte. Pokud výraz platí, vypište, že x je větší než y a velikost rozdílu. V opačném případě vypište, že y je větší než x a velikost rozdílu. begin writeln(‘Zadejte číslo x ’);readln(x); writeln(’Zadejte číslo y’);readln(y); IF x >y THEN begin rozdil:= x – y; writeln(’Číslo x je větší než y a rozdíl je: ’, rozdil); end ELSE begin rozdil:= y – x; writeln(’Číslo y je větší než x a rozdíl je: ’, rozdil); end; end. Upozornění na nejčastější chybu: Vždy si uvědomte, zda chcete za Then nebo Else provést pouze jeden příkaz, nebo se má provést více příkazů. Pokud více příkazů, musíte použít složený příkaz, tj. ohraničit příkazy klíčovými slovy Begin a End. A ještě jedna rada – dejte si pozor, kam v podmínce dáváte středník.
5.3 Vnořené podmínky Podmínky samozřejmě můžete do sebe vnořovat. Jestliže to ale přeženete, budete mít problém se zorientovat ve významech.
47
Základy Algoritmizace
Příklad 5.4 Uživatel na vstupu zadá výšku tří dětí. Zjistěte, které dítě je nejvyšší. program vyska; uses crt; var d1,d2,d3:real; begin clrscr; write('Zadej vyšku 1.dítěte: ');readln(d1); write('Zadej vyšku 2.dítěte: ');readln(d2); write('Zadej vyšku 3.dítěte: ');readln(d3); if d1>=d3 then if d1>=d2 then writeln('vyška nejvyššího dítěte je: ',d1:8:2) else writeln('vyška nejvyššího dítěte je: ',d2:8:2) else if d3>=d2 then writeln('vyška nejvyššího dítěte je: ',d3:8:2) else writeln('vyška nejvyššího dítěte je: ',d2:8:2); readln; end.
5.4 Vícenásobné větvení Výsledkem vyhodnocení výrazu v podmínce je vždy true nebo false. Tedy dvě varianty vývoje algoritmu. Někdy se ale potřebujete rozhodnout mezi více variantami. Můžete to sice vyřešit pomocí vnořených podmínek, ale viděli jste na předchozím příkladě, že člověk se musí hodně zamyslet, jestli podmínky zformuloval dobře. Co když těch variant bude např. 10 ?! Pro tuto situaci existuje v Pascalu příkaz Case. Nelekejte se délky příkladu 5.5. Když se do něj ponoříte, zjistíte, že je docela jednoduchý a délka je pouze z důvodu přehlednosti výpisu pro uživatele. Příkaz Case slouží k zadání vícenásobného větvení a zapisuje se : case vyraz of konstanta1: příkaz1;
48
5. Podmínky konstanta2: příkaz2; …. konstantaN: příkaz N; else příkaz; end; Za zvolenou konstantou se provede vždy jen jeden příkaz. Chcete-li použít více příkazů musíte sáhnout po složené podmínce. Výraz i konstanty musí být stejného datového typu.
příklad 5.5 Uživatel zvolí na začátku programu, zda si přeje vypočítat obvod kruhu, obsah kruhu, objem nebo povrch koule. Program na základě uživatelovy volby spočítá výsledek. program vicenasobne_vetveni; uses crt; var r:real; volba: byte; begin clrscr; writeln('VYBERTE, CO SI PREJETE SPOCITAT'); writeln;writeln; writeln(' 1....obvod kruhu'); writeln(' 2....obsah kruhu'); writeln(' 3....objem koule'); writeln(' 4....povrch koule'); writeln; write(' volba: ');readln(volba); Když uživatel zadá jedničku, provede se výpočet obvodu kruhu
case volba of 1: begin writeln;writeln; write(' zadej polomer kruhu: '); readln(r); writeln;writeln; writeln(' obvod kruhu je: ',2*PI*r:6:2); end; 2: begin writeln;writeln; write(' zadej polomer kruhu: '); readln(r); writeln;writeln; writeln(' obsah kruhu je: ',PI*r*r:6:2); end; 3: begin
49
Základy Algoritmizace writeln;writeln; write(' zadej polomer koule: '); readln(r); writeln;writeln; writeln(' objem koule je: ',4/3*pi*r*r*r:6:2); end; 4: begin writeln;writeln; write(' zadej polomer koule: '); Všimněte si, že v případě Case nevadí za end před else středník. readln(r); writeln;writeln; writeln(' povrch koule je: ',4*PI*r*r:6:2); end; Příkaz za else se provede, pokud else uživatel zvolí jiné číslo než 1, 2, 3 begin nebo 4. writeln;writeln; writeln('zadali jste neplatnou volbu'); end; end; readln; end.
50
5. Podmínky
5.5 Výrazy a použití logických operátorů V této části si zopakujete dovednosti, které již máte z matematiky a procvičíte si je. A jaj, už zase jsem byl donucen použít skoro neslušné slovo matematika, omlouvám se ☺. Neděste se, zkusím vám to vysvětlit jednoduše a názorně. Ovšem chci po vás jedinou věc, čtěte, až budete odpočatí.
Operátory: aritmetické: sčítání +, odčítání - , násobení *, dělení /, div , mod relační: = , < , > , <= , >= , <> logické: NOT, AND, OR, NOT : negace výrazu AND - logické A - do češtiny se nejčastěji překládají jako „a zároveň“ - znamená, že musí platit oba argumenty výrazu současně OR - logické nebo - do češtiny se překládají jako „nebo“ - stačí, když je splněn 1 argument a je vrácena hodnota true. - nezáleží na pořadí v jakém jsou argumenty splněny Nejlépe rozdíl pochopíte na ukázce „ze života“ ☺ IF je den AND neprší THEN můžeš se opalovat IF sněží OR prší THEN zůstaň doma Aby byl v prvním případě výraz pravda (true), musí být splněny oba argumenty. Stačí, když neplatí jeden z argumentů, a už neplatí celý výraz. V dešti se asi opalovat nebudu. Kdybych se chtěl v noci povalovat v plavkách na dece, tak by mě asi brzo strčili pod zámek do ústavu. V druhém případě stačí, když nastane jedna z možností a podmínka je splněna. Pokud tedy budete mít pochybnosti, jak pracovat s OR nebo AND, pomozte si nějakým jednoduchým příkladem.
Priority vyhodnocování výrazů: 1. výraz v závorce, volání funkce 2. not 3. *, /, div, mod, and 4. +, - , or 5. = , < , > , <= , >= , <>
51
Základy Algoritmizace
Tabulky logických operací: Výsledky vyhodnocení argumentů mezi nimiž je logický operátor OR
Výsledek vyhodnocení celého výrazu
False OR False
False
True OR True
True
False OR True
True
True OR False
True
Tabulka 1: Použití operátoru Or Výsledky vyhodnocení argumentů mezi nimiž je logický operátor AND
Výsledek vyhodnocení celého výrazu
False AND False
False
True AND True
True
False AND True
False
True AND False
False
Tabulka 2: Použití operátoru AND
5.5.1 Použití logických operátorů AND a OR Příklad 5.6 Zjistěte, zda zadané číslo a patří do intervalu <0,100>. Protože číslo musí patřit do intervalu, musí být splněny obě části výrazu. Podmínka pak bude vypadat následovně: IF (a >= 0) AND (a <= 100) THEN writeln(‘číslo ‘,a,’ do intervalu 0 až 100 patří’); Uživatel zadá a = 58 IF (a >= 0) AND (a <= 100) THEN writeln(‘číslo ‘,a,’ do intervalu 0 až 100 patří’); 58 >=0
58 <= 100
true AND
true
musí platit zároveň Celý výraz je platný, proto se provede příkaz za THEN
true Uživatel zadá a = 120
IF (a >= 0) AND (a <= 100) THEN writeln(‘číslo ‘,a,’ do intervalu 0 až 100 patří’); 120 >=0
120 <= 100
true AND
false
Celá podmínka neplatí, protože musí platit zároveň oba argumenty
false
52
5. Podmínky
Příklad 5.7 Zjistěte, zda zadané číslo a patří nebo nepatří do intervalu <0,100>. Stačí předchozí řešení doplnit o část Else (No jasně, když neplatí, tak není v tom intervalu 0 až 100 ☺ ) IF (a >= 0) AND (a <= 100) THEN writeln(‘číslo ‘,a,’ do intervalu 0 až 100 patří’) ELSE writeln(‘číslo ‘,a,’ do intervalu 0 až 100 nepatří’);
Ale protože programování je činností tvůrčí, podívejte se na to trošku jinak a podmínku přeformulujte.
Příklad 5.8 Zjistěte, zda zadané číslo a patří nebo nepatří do intervalu <0,100>. Když zadané číslo a nemá patřit do intervalu <0,100>, tak musí naopak patřit do intervalu (∞,0) nebo (0, ∞). A na této podmínce si ukážeme použití logického operátoru OR. Uživatel zadá a = 58 IF (a < 0) OR (a > 100)THEN writeln(‘číslo ‘,a,’ nepatří do intervalu 0 až 100’); 58 < 0 false
58 > 100 OR
false
Protože OR je logické nebo, stačí, když bude platit jeden argument výrazu a bude platit celá podmínka, ale v tomto případě neplatí ani jeden, proto není podmínka splněna.
false
Uživatel zadá a = 120 IF (a < 0) OR (a > 100) THEN writeln(‘číslo ‘,a,’ nepatří do intervalu 0 až 100’); 120< 0 false
120 > 100 OR true
true stačí, když platí jeden argument, pak platí celá podmínka
5.5.2 Použití logického operátoru NOT Jestli se vám zdálo přemýšlení nad vyhodnocování výrazů s OR a AND obtížné, tak zde to bude chtít ještě větší soustředění. Člověk je totiž tvor, který neumí myslet negativně (pomocí negací), ale musíte se to naučit. Zde je to jasné, když podmínka platí, je číslo kladné IF NOT(a > 0) THEN writeln(‘číslo je záporné’); Zde už to asi tak jasné není, podívejte se proto na vyhodnocení detailněji.
IF a > 0 THEN writeln(‘číslo je kladné’);
53
Základy Algoritmizace
Příklad 5.9 Zjistěte, zda je zadané číslo záporné. Uživatel zadá a = 16 IF NOT(a ≥ 0) THEN writeln(‘číslo je záporné’); 16 > 0 NOT(true) false
16 je větší než 0, tak výsledkem je hodnota true Negace neboli opak z hodnoty true je hodnota false. Výsledek vyhodnocení celého výrazu je false, proto není splněna podmínka.
Uživatel zadá a = -5 IF NOT(a ≥ 0) THEN writeln(‘číslo je záporné’); -5 > 0 NOT(false) true
-5 není větší než 0, proto výsledkem je hodnota false Negace neboli opak z hodnoty false je hodnota true. Výsledek vyhodnocení celého výrazu je true, proto je splněna podmínka.
Také vám dělá potíže přinutit mozek myslet obráceně?! Nebojte se, nejste sami. Proto jedna rada – pokud to jen jde, vyhýbejte se negacím. Jeden z případů, kdy patrně použijete operátor NOT, aniž by vám to dělalo potíže, bude až v budoucnu, když budete ověřovat, zda nastal konec souboru či nikoli. Ale to máte ještě před sebou dlouhou cestu.
Cvičení 5.1 Napište program, který zjistí, zda dvě celá čísla zadaná na vstupu splňují nerovnost 4x + 3 < 5y – 2.
Cvičení 5.2 Napište program, který zjistí, zda zadané celé číslo je liché a dělitelné 3. Jak postupovat ? Všimněte si, že v zadání je řečeno liché „a“ dělitelní 3. Z toho vyplývá, že obě tvrzení musí platit současně. Uvědomte si, jak poznáte, že je číslo liché, a jak poznáte číslo dělitelné 3. Pro řešení využijte operátoru MOD, který vrací zbytek po celočíselném dělení.
54
5. Podmínky
Shrnutí Podmínky se v Pascalu zapisují s použitím klíčových slov IF, THEN, ELSE. Za klíčovým slovem THEN se provede vždy jen jeden příkaz. Na konci příkazu, který stojí před klíčovým slovem ELSE, nesmí být středník. Jednotlivé podmínky lze do sebe vnořovat, ale dávejte pozor, abyste se v nich nezamotali. Pokud by se vám to stalo, načrtněte si vývojový diagram pro znázornění, jakým způsobem by se měl program rozhodovat. V případě výběru z většího počtu variant raději použijte vícenásobné větvení – CASE. Pro vyhodnocení výrazů v podmínkách slouží operátory. K tvorbě složitějších výrazů se používají logické operátory AND, OR a NOT. Pořadí vyhodnocování výrazů se určuje podobně jako v matematice pomocí závorek. Pascal stanovuje pořadí vyhodnocování výrazů. Nejdříve NOT poté AND a nakonec OR.
Kontrolní otázky 1. 2. 3. 4. 5.
Zformulujte neúplnou a úplnou podmínku z reálného života. Jak zajistíte, aby program v rámci podmínky provedl více příkazů ? Které můžete použít operátory pro tvorbu výrazu v podmínce? Jaké je pořadí vyhodnocování operátorů? Jaký příkaz použijete v případě, že provádíte výběr z více variant?
Pojmy k zapamatování ELSE CASE AND OR NOT
neúplná podmínka úplná podmínka vnořené podmínky vícenásobné větvení IF THEN
Korespondenční úkol Na vstupu jsou zadána čísla x a y. Napište program, který spočítá hodnotu 3x + 2 2 y − 3 + . výrazu y −1 x+2 Nezapomeňte: výsledek dělení musí být vždy real nelze dělit nulou! Pokud by byly takové hodnoty x a y zadány, vypište zprávu uživateli „pro zadané hodnoty nemá výraz řešení- nelze dělit nulou“.
55
Základy Algoritmizace
Řešení: Cvičení 5.1 program cviceni_5_1; uses crt; var x,y: integer; begin clrscr; write('Zadejte cislo x: ');readln(x); write('Zadejte cislo y: ');readln(y); if (4*x + 3) < (5*y - 2) then writeln('cislo x=',x,' a cislo y=',y,' splnuji nerovnost 4x+3 < 5y-2') else writeln('cislo x=',x,' a cislo y=',y,' nesplnuji nerovnost 4x+3 < 5y-2'); readln; end.
Cvičení 5.2 program cviceni_5_2; uses crt; var cislo:integer; begin clrscr; write('Zadejte cele cislo: ');readln(cislo); if (cislo mod 2 <> 0) and (cislo mod 3 = 0) then writeln('Cislo ',cislo,' je liche a delitelne 3') else begin if (cislo mod 2 = 0) then writeln('Cislo neni liche '); if (cislo mod 3 <> 0) then writeln('Cislo neni delitelne 3'); end; readln; end.
56
6. Cykly
6. Cykly Cíl: Po prostudování této kapitoly byste měli být schopni: vyjmenovat typy cyklů rozpoznat, kdy použijete určitý typ cyklu zapsat cyklus v Pascalu a použít jej v programu Čas potřebný k prostudování této kapitoly: 4 hodiny Z první kapitoly o algoritmech už víte, jaké můžete použít typy cyklů. Nyní se naučíte je zapisovat v Pascalu a použít v některých příkladech. Stejně jako podmínky jsou cykly základem většiny programů. Pokud jste pochopili fungování cyklů už na začátku v algoritmech, neměla by vám tato kapitola činit potíže. Takové doporučení – naučte se nazpaměť český překlad ukončovacích podmínek cyklů. Při programování pak budete méně tápat v pochopení, kdy cyklus skončí.
6.1 Cyklus s předem stanoveným počtem opakování Použijete v případě, kdy znáte údaj, kolikrát se má tělo cyklu opakovat. Tento údaj musíte získat od uživatele ještě před začátkem cyklu. Při každém průchodu cyklu se hodnota řídící proměnné zvýší (nebo naopak sníží) o jedničku. Řídící proměnná vlastně říká, po kolikáté se už cyklus provádí. pozor, přiřazovací příkaz
i:= 1,2,…,n příkaz1;
FOR řídící proměnná:= počátek TO konec DO příkaz;
příkaz2; konec cyklu i
Před prvním průchodem cyklu se hodnota řídící proměnné nastaví na hodnotu uloženou v proměnné počátek. Cyklus se bude vykonávat tak dlouho, až hodnota řídící proměnné se bude rovnat hodnotě uložené v proměnné konec. Po každém průchodu se hodnota proměnné zvýší o jedničku. Místo proměnných počátek a konec lze v kódu programu zapsat konstanty.
Důležité je si pamatovat, že za příkazem DO se provede vždy jen jeden jediný příkaz. Proto v případě, že je nutné opakovat uvnitř cyklu více příkazů, musíte použít složený příkaz. FOR i:= 1 TO 10 DO...
FOR k:= 4 TO 15 DO…
Cyklus se provede 10krát. Při prvním průchodu bude mít proměnná i hodnotu 1, při druhém hodnotu 2 a tak dále až do posledního průchodu, kdy bude mít hodnotu 10 a cyklus skončí V tomto případě bude mít při prvním průchodu proměnná k hodnotu 4, potom 5 a tak dále až do 15. To znamená, že cyklus se provede 12krát!
57
Základy Algoritmizace Příkaz FOR lze použít i ve variantě, kdy se řídící proměnná snižuje o jedničku. Cyklus se pak zapisuje ve tvaru : FOR řídící proměnná:= počátek DOWNTO konec DO příkaz; FOR i:= 5 DOWNTO 1 DO…
při prvním průchodu cyklu bude mít i hodnotu 5, při druhém 4 a tak dále až při posledním průchodu bude mít hodnotu 1.
Příklad 6.1 Vytvořte program, který spočítá průměr známek 30 studentů třídy program prumer; uses crt; var soucet,znamka :integer; prumer : real; begin Tělo cyklu, protože chceme za soucet:=0; příkazem DO provést více příkazů, for i:=1 to 30 do musíme použít složený příkaz. begin write(‘Zadejte známku studenta: ’);readln(znamka); soucet:= soucet + znamka; end; prumer:=soucet/30; writeln(‘Prumer znamek je: ’,prumer); readln; end. Všimněte si, že přičítáte proměnnou soucet „samu k sobě“, proto nastavujete její počáteční hodnotu. Průměr spočítáte až po skončení cyklu, protože vám stačí jeho výsledná hodnota a uvnitř cyklu by se zbytečně 30krát počítal.
Vypadá ten algoritmus v pořádku? Funkčně ano, ale představte si situaci, že takový program vytvoříte a předáte sekretářce ve škole. Do třídy se přistěhuje nový 31. student a už vám sekretářka bude volat, ať s tím něco uděláte. A vy budete muset udělat zásah přímo do kódu programu. Lepší řešení vidíte v příkladu 6.2.
Příklad 6.2
Cyklus se provede n-krát. Uživatel sice musí zadat na začátku počet studentů, ale algoritmus bude fungovat pro třídu ve které je 15 studentů i pro třídu ve které je 32 studentů.
program prumer;
uses crt; var soucet,znamka:integer; prumer : real; begin soucet:=0; write(‘Zadejte počet studentů ve třídě: ’);readln(n); for i:=1 to n do begin write(‘Zadejte známku studenta: ’);readln(znamka); soucet:= soucet + znamka; end; prumer:=soucet/n; writeln(‘Prumer znamek je: ’,prumer); readln; end.
58
6. Cykly Proto pokud si nejste jisti, nedávejte do kódu programu konkrétní počet opakování (v našem případě 30 studentů). Raději použijte proměnnou, do které uložíte počet opakování získaný od uživatele. Na co si dát pozor? za DO se provede pouze 1 příkaz (chci-li více – použít složený příkaz) na použití konkrétních hodnot v programovém kódu v příkaze FOR je za řídící proměnnou přiřazovací příkaz
6.2 Cyklus s podmínkou na začátku WHILE výraz DO příkaz; +
Pomozte si překladem: Dokud platí výraz dělej (tj. když platí výraz proveď tělo cyklu, když neplatí přeskoč na příkaz za cyklem).
Při provádění cyklu se nejdříve vyhodnotí výraz, pokud není splněn, cyklus hned skončí. Pozor, všimněte si, že pokud není splněn výraz, nemusí se tělo cyklu provést ani jednou.
příklad 6.3 Vytvořte program, který spočítá aritmetický průměr známek studentů třídy. Zadávání známek je ukončeno, když je zadána známka 0. V případě cyklu s FOR jste nemuseli kontrolovat, kolik je studentů. Zde to dopředu nevíte, proto si zavedete proměnnou pocet, do které budete postupně ukládat počet studentů, jejichž známky už máte sečteny. Pozor. Protože budete vyhodnocovat
program prumer;
na začátku cyklu výraz, tak musíte mít uses crt; co vyhodnocovat. Je nutné známku var soucet, znamka,pocet :integer; prvního studenta načíst ještě před prumer : real; cyklem. begin soucet:= 0; pocet:=0; write(‘Zadejte známku studenta: ’);readln(znamka); WHILE znamka <> 0 DO V prvním kroku se započte Begin známka studenta, kterého soucet:= soucet + znamka; jsme načetli před začátkem pocet:= pocet + 1; cyklu write(‘Zadejte známku studenta: ’); Načte se další známka. Program se readln(znamka); vrátí na začátek cyklu a ptá se, zda End; známka splňuje podmínku, pokud ano, prumer:= soucet / pocet; je známka započítána. Pokud ne, writeln(‘Prumer znamek je: ’,prumer); cyklus se ukončí a tím není ani readln; známka s hodnotou 0 přičtena k počtu. end.
59
Základy Algoritmizace Předchozí příklad je v pořádku, promyslete si dobře pořadí přičítání součtu a počtu známek. Podívejte se nyní na špatná řešení :
Příklad 6.4 – špatné řešení … soucet:= 0; pocet:=0; write(‘Zadejte známku studenta: ’);readln(znamka); WHILE znamka <> 0 DO Begin write(‘Zadejte známku studenta: ’);readln(znamka); soucet:= soucet + znamka; pocet:= pocet + 1; End; prumer:= soucet / pocet;
… Co je špatně ? Hodnota známky prvního studenta (načtená ještě před začátkem cyklu) se nikde nezapočítá a hned se přepíše novou známkou (načtenou na začátku těla cyklu). Tuto chybu byste mohli vyřešit takto :
Příklad 6.5 – špatné řešení … write(‘Zadejte známku studenta: ’);readln(znamka); soucet:= znamka; pocet:=1; WHILE znamka <> 0 DO Begin write(‘Zadejte známku studenta: ’);readln(znamka); soucet:= soucet + znamka; pocet:= pocet + 1; End; prumer:= soucet / pocet;
… Ale stále zůstává druhá závažná chyba. Zamyslete se na nad poslední zadanou známkou (tou, která je 0 , jejímž úkolem je ukončení cyklu). Pomozte si tím, že si projdete poslední opakování cyklu: je načtena 0 k součtu je přičtena 0 – to nám nevadí, nula součet nezmění k počtu je přičtena 1 – a tady je problém, protože máte navíc neexistující známku studenta, která je započítána do celkového počtu známek. Dobře si proto rozmyslete pořadí příkazů uvnitř cyklu, není to jedno. Podívali jste na chybná řešení? Vraťte se ještě jednou ke správnému řešení!
60
6. Cykly
6.3 Cyklus s podmínkou na konci
+
Repeat příkaz; příkaz; Until výraz;
Pomozte si překladem: Opakuj tak dlouho dokud není splněna podmínka. Tj. je-li splněna podmínka opusť cyklus, není-li vrať se na začátek cyklu a zopakuj tělo cyklu.
V případě tohoto cyklu se tělo cyklu provede minimálně jednou (ať je nebo není splněna podmínka, protože ta se vyhodnotí až na konci).
Příklad 6.6 Vytvořte program, který spočítá aritmetický průměr známek studentů třídy. Zadávání známek je ukončeno, když je zadána známka 0. program znamky; uses crt; var soucet, pocet, znamka: integer; prumer: real; begin soucet:= 0; pocet:=0; repeat write('Zadejte znamku studenta: ');readln(znamka); soucet:= soucet + znamka; Známky se budou načítat tak pocet:= pocet + 1; dlouho, dokud nebude zadána 0. until znamka = 0; pocet:= pocet -1; Protože se načetla do počtu i nula, je nutné ji odstranit, prumer:= soucet / pocet; writeln('Prumer znamek je: ',prumer:6:2); aby nezkreslovala počet známek. readln; end. Existuje řada možných postupů jak problém vyřešit. Například někomu může vadit pokyn pocet := pocet -1. Protože při tvorbě programu už předem víte, že nula bude započítána do počtu, můžete se na to připravit a místo příkazu pocet:=0 použijete pocet:= -1.
61
Základy Algoritmizace
Shrnutí V této kapitole jste se naučili používat 3 typy cyklů v Pascalu. Cyklus For, While a Repeat. Cyklus For použijete, pokud už dopředu víte, kolikrát se činnost v cyklu bude opakovat. Snažte se, jak jen to půjde, vyhnout zapsání konkrétního počtu opakování přímo do kódu programu. V případě, že předem nevíte, kolikrát se tělo cyklu bude opakovat, použijte cyklus Repat nebo While. Měli byste ovšem znát za jakých podmínek se tělo cyklu bude opakovat a za jakých podmínek cyklus skončí. Při použití cyklu Repeat se tělo cyklu provede vždy alespoň jednou, kdežto při použití While se tělo cyklu nemusí provést vůbec. V okamžiku, kdy použijete některý z cyklů, ověřte si, kolikrát cyklus opravdu proběhne. Zda se neprovádí o krok více nebo naopak méně. To by vám mohlo změnit hodnoty proměnných uvnitř cyklu a v důsledku toho byste mohli obdržet nežádoucí výsledky.
Kontrolní otázky 1. 2. 3. 4. 5. 6.
Jak zapíšete cyklus s podmínkou na konci? Jak zapíšete cyklus s podmínkou na začátku? Jaký je tvar cyklu s řídící proměnnou? Který z cyklů se provede alespoň jednou? Který z cyklů se nemusí provést vůbec? Na co je dobré si dávat pozor při použití cyklů?
Pojmy k zapamatování: cyklus For…To … Do cyklus Repeat …Until řídící proměnná tělo cyklu cyklus While … Do
Korespondenčí úkol Jsou zadávány výše platů zaměstnanců firmy. Jako poslení je zadán plat ředitele, který převyšuje částku 25 000 Kč. Zjistěte: počet zaměstnanců firmy průměrný plat všech zaměstnanců kolik plat ředitele převyšuje průměrný plat ve firmě Uvědomte si, že předem neznáte kolik platů budete zadávat. Zadávání skončí v okamžiku vložení platu ředitele.
62
7. Práce s textem
7. Práce s textem Cíl: Prostudování této kapitoly vám umožní objasnit rozdíl mezi datovým typem Char a String reagovat v programu na stisk kláves uživatelem zpracovat text zadaný uživatelem z klávesnice Čas potřebný k prostudování této kapitoly: 6 hodin Prozatím jste pracovali s proměnnými, do kterých jste ukládali čísla. Text jste používali jen jako zprávu pro uživatele. Velice často ovšem potřebujete pracovat se znaky a textem uloženými v proměnné (načítáte jméno, příjmení, ulici, město…). K definování takových proměnných budete potřebovat datový typ Char (znak) a String (řetězec znaků). Uvědomte si, že znaky netvoří pouze písmena, ale také číslice a všechny ostatní znaky ASCII tabulky.
7.1 Char (znak) Zahrnuje všechny znaky ASCII kódu. Používá se, pokud do proměnné chcete ukládat 1 znak (pouze jeden znak). paměťové nároky: 1 byte operace: = , < , > , <= , >= , <> nečastěji používané funkce: CHR() – vrací odpovídající znak zadanému ordinálnímu číslu ORD() – vrací ordinální hodnotu zadaného znaku PRED() – vrací předchůdce zadaného ordinální hodnoty SUCC() - vrací následníka zadaného ordinální hodnoty
Úkol k zamyšlení Najděte na internetu znaky ASCII kódu. Taky se někdy označuje jako ASCII tabulka. Podívejte se, které znaky obsahuje. Všimněte si, že každý znak má přiřazeno pořadové číslo (ordinální hodnotu) v desítkové a šestnáctkové soustavě. Ordinální hodnota znaku je tedy číslo, které má znak přiřazeno v ASCII tabulce. Jakou hodnotu má znak A ?
A = 65.
Všimněte si také, že malá a velká písmena mají odlišná pořadová čísla. Počítači proto není jedno, jestli zadáte malé nebo velké písmeno Jen tak mimochodem, podívejte se na znak s pořadovým číslem 64, je to zavináč. A tím se vysvětluje to, co někteří z vás provádí automaticky – stisknou pravé tlačítko Alt a na numerické klávesnici namačkají 64. Říkají tím vlastně počítači, že má zobrazit znak s pořadovým číslem 64 a to je náš @. 63
Základy Algoritmizace Znak lze proto v Pascalu vyjádřit 2 způsoby 1) zapsáním znaku ‘A’ (znak musíte zapsat do apostrofů) znak:= ‘A’; (do proměnné znak, vkládáte velké A) 2) zapsáním ordinální hodnoty čísla. Ta se musí zapsat pomocí znaku # znak:= #65 ( 65 je ordinální hodnota velkého A)
Příklad 7.1 Napište program, který vypíše ordinální hodnotu (pořadové číslo v ASCII tabulce) znaku zadaného z klávesnice. program vypis_kodu_ascii; uses crt; var znak:char; begin Funkce ord() vrátí hodnotu clrscr; zadaného znaku v ASCII tabulce Write('Zadejte znak: '); readln(znak); write('Znak ',znak,' ma v ASCII tabulce hodnotu: ',ord(znak)); readln; end.
Příklad 7.2 Napište program, který vypíše ordinální hodnotu (pořadové číslo v ASCII tabulce) znaku zadaného z klávesnice. Poté se uživatele dotáže, zda si přeje pokračovat nebo ukončit program. program vypisy_hodnot_Znaku; uses crt; var znak,ukonceni:char; begin repeat clrscr; Write('Zadejte znak: '); readln(znak); writeln;writeln; writeln('Znak ',znak,' ma v ASCII tabulce hodnotu: ',ord(znak)); writeln;writeln; writeln('Chcete-li pokracovat, zadejte libovolny znak.'); writeln; write('Prejete-li si skoncit, zadejte znak K. Vase volba: '); readln(ukonceni); Cyklus se bude opakovat tak dlouho, dokud uživatel nezadá until (ukonceni='k') or (ukonceni='K'); malé nebo velké písmeno K. end.
Vždy byste se měli snažit ošetřit pokud možno všechny varianty, které uživatel může zadat. Proto ukončení malým i velkým písmenem K.
64
7. Práce s textem
Příklad 7.1 můžete řešit i jiným způsobem – použitím procedury readkey. Procedura readkey načte stisknutou klávesu a vloží ji do proměnné. znak:= readkey; Rozdíl mezi readln a readkey je následující. Při použití readln se stisknutý znak vloží do proměnné až v okamžiku, kdy stisknete Enter. V případě readkey se hodnota klávesy vloží do proměnné už v okamžiku stisknutí klávesy.
Příklad 7.3 Napište program, který vypíše ordinální hodnotu (pořadové číslo v ASCII tabulce) znaku zadaného z klávesnice. program priklad_7_3; uses crt; var znak:char; begin clrscr; Write('Zadejte znak: '); znak:=readkey; write('Znak ',znak,' ma v ASCII tabulce hodnotu: ',ord(znak)); readln; end.
Tento jednoduchý program můžete použít ke zjištění, jakou hodnotu v ASCII tabulce má klávesa Enter, Esc apod. Pokud jste zjistili, že Enter má hodnotu 13 a Esc 27, můžete toho využít při psaní dalších programů.
Přiklad 7.4 Napište program, který vypisuje ordinální hodnotu znaků stisknutých na klávesnici tak dlouho, dokud není stisknuta klávesa Esc. program priklad_7_4; uses crt; var znak:char; begin clrscr; writeln('Zadavejte znaky. Pro ukonceni stisknete Esc'); writeln;writeln; repeat znak:=readkey; Cyklus se opakuje, dokud writeln(znak,' : ', ord(znak)); není stisknuta klávesa Esc. until znak=#27; end.
65
Základy Algoritmizace
7.2 String (řetězec) Slouží k vyjádření řetězce znaků o maximální délce 255 znaků. Řetězec je v programovém kódu zapsán v apostrofech. den:= ‘pondělí ’ paměťové nároky: tolik bajtů, kolik obsahuje řetězec znaků operace: = , < , > , <= , >= , <> + (používá se k slučování několika řetězců dohromady) nejčastěji používané funkce: DELETE() – smaže část ze zadaného řetězce INSERT() – vloží další řetězec do řetězce na zadanou pozici STR() – převede číselný tvar čísla na řetězec znaků VAL() – převede číslo v řetězci do číselného tvaru COPY() – vrací podřetězec ze zadaného řetězce CONCAT() – Spojí posloupnost řetězců (výsledek se samozřejmě musí vejít do rozsahu datového typu string - tj. 255 znaků). LENGTH() – vrací počet znaků zadaného řetězce POS() – vyhledá pozici začátku podřetězce v řetězci znaků deklarace VAR rezetec1: string; retezec2: string[10]; retezec3: string[25]; Pokud uvedete v hranatých závorkách rozsah, tak říkáte, kolik znaků může být maximálně uloženo do proměnné. Takže v proměnné retezec2 může být maximálně 10 znaků a v proměnné retezec3 nejvíce 25 znaků. Jestliže rozsah neuvedete, jako v případě proměnné retezec1, vyhradí se pro proměnnou maximální velikost, tedy 255 znaků. Jak už víte, řetězec napsaný přímo v programovém kódu se zapisuje v apostrofech. retezec2:= ‘Ahoj ‘; retezec3:= ‘Františku, jak se vede?‘ Jaká pak bude v následujících případech hodnota řetězce uloženého v proměnné retezec1? a) retezec1:= retezec2 + retezec3; b) retezec1:= retezec3 + retezec2;
66
7. Práce s textem Řešení je docela snadné. Jen musíte dávat pozor na pořadí slučování řetězců. a) retezec1 = ‘Ahoj Františku, jak se vede?‘ b) retezec2 = ‘Františku,jak se vede?Ahoj ‘ Každý znak v řetězci má svou pozici (tzv. index), která se zapisuje do hranatých závorek. První znak má pozici 1. retezec2[1] = ‘A‘ retezec2[2] = ‘h‘ retezec2[3] = ‘o‘ retezec2[4] = ‘j‘ retezec2[5] = ‘ ‘ Například je-li řetězec uložen v proměnné jmeno:=‘ František Vomáčka‘; pak znaky na pozicích 1,5,8 jsou tyto: jmeno[1] = ‘F‘ jmeno[5] = ‘t‘ jmeno[8] = ‘e‘
Příklad 7.5: Uživatel zadá větu. Vypište znaky na sudých pozicích. Protože má každý znak ve větě svou pozici (index), stačí zjistit zda je pozice sudá nebo lichá. program sude_znaky; uses crt; var veta:string; Funkce length vrátí délku věty. Cyklus i:byte; se bude opakovat do posledního znaku Begin věty. clrscr; writeln('Zadejte vetu: '); Je-li zbytek po dělení 0, je číslo sudé a readln(veta); pak se vypíše sudý znak. writeln;writeln; for i:=1 to length(veta) do if (i mod 2) = 0 then write(veta[i],' '); readln; end.
K zamyšlení Napadá vás jiné řešení jak vypsat znaky na sudých pozicích ? Co tohle: for i:=2 to length(veta) do begin write(veta[i], ' '); i:= i + 1; end;
67
Základy Algoritmizace
Přiklad 7.6: Vypište zadanou větu obráceně ( např. Karel → leraK). program veta_obracene; uses crt; var veta:string; i:byte; Begin clrscr; writeln('Zadejte vetu: '); readln(veta); writeln;writeln; for i:=length(veta) downto 1 do write(veta[i]); readln; End.
Při použití downto klesá hodnota řídící proměnné i. To znamená, že vypisuje od posledního znaku k prvnímu.
Příklad 7.7: Zjistěte, zda se zadané slovo v větě opakuje. Stačí procházet větu od prvního znaku k poslednímu a vždy si „vyříznout“ řetězec o stejné délce jaké má hledané slovo. A pak porovnat jestli je „vyříznutý“ řetězec stejný jako hledané slovo. Program se pak přesune na další znak věty a znovu „vyřízne“ další řetězec. program opakující_slovo; uses crt; var veta,HledaneSlovo,PorovnavaneSlovo:string; i,DelkaSlova:byte; pocet:byte; Begin clrscr; writeln('Zadejte vetu: '); readln(veta); writeln('Zadejte slovo,pro ktere chcete vetu prohledat,zda se v ni slovo opakuje: '); Funkce Copy vrátí z věty řetězec znaků, readln(HledaneSlovo); který začíná na pozici i a má délku writeln;writeln; hledaného slova. pocet:=0; for i:=1 to length(veta) do Begin PorovnavaneSlovo:= Copy(veta,i,length(HledaneSlovo)); if HledaneSlovo = PorovnavaneSlovo then pocet:=pocet +1; End; writeln('Slovo "',HledaneSlovo,'" se ve vete opakuje ',pocet,'krat'); readln; End.
68
7. Práce s textem
Příklad 7.8 Uživatel zadá větu, v níž jsou jednotlivá slova oddělena jednou nebo více mezerami. Vypište jednotlivá slova věty pod sebe. program Vety; uses crt; var i: byte; veta: string; Slovo: string; vypsat: boolean; delka:byte; begin clrscr; vypsat:=false; write ('Zadejte vetu: '); readln (veta); delka:=length(veta); for i:=1 to delka do if (veta[i]<>' ') and (veta[i]<>'.') and(veta[i]<>'?') and (veta[i]<>',') and (veta[i]<>'!') then begin Když se skládá slovo, tj. znaky jsou různé Slovo:=Slovo+(veta[i]); od mezery, čárky , ?,! a tečky, program si vypsat:=true; poznačí, že má slovo vypsat. end else V okamžiku, kdy skončí skládání slova, protože if vypsat then program narazil na jiný znak , se slovo vypíše. Do begin proměnné vypsat se poznačí, že slovo už bylo Writeln (Slovo); vypsáno. Slovo:=''; vypsat:=false; end; readln; end.
Nad čím si asi budete trošku lámat hlavu, je použití logické proměnné vypsat. Schválně, zkuste ji nepoužít a ověřte, jak se program bude chovat, pokud uživatel zadá za slovy více mezer. Jak by to vypadalo po odstranění proměnné vypsat vidíte na druhém obrázku.
Obr. 7. 2: Výsledek nesprávného řešení
Obr. 7. 1: Výsledek správného řešení
69
Základy Algoritmizace
Cvičení 7.1 Uživatel zadává znaky z klávesnice tak dlouho, dokud nestiskne klávesu Enter. Spočítejte, kolik ze zadaných znaků bylo malých a kolik velkých písmen anglické abecedy.
Cvičení 7.2 Uživatel zadá své jméno a příjmení. Zajistěte, aby ve jméně a příjmení bylo první písmeno vždy velké. Když se podíváte do ASCII tabulky, zjistíte, že se ordinální hodnota velkého písmene liší od ordinální hodnoty malého písmene vždy o konstantní hodnotu 32. Druhou možností jak zadání vyřešit je použití funkce UpCase (viz. nápověda ☺)
Shrnutí V této kapitole jste se naučili pracovat s textem v Pascalu a použít datový typ Char (znak) a typ String (řetězec znaků). Do proměnné typu Char můžete vložit vždy jen jeden znak, kdežto proměnnou typu String můžete naplnit až 256 znaky. Každý znak v řetězci je identifikován svou přesnou pozicí. Nezapomeňte, že nadefinujete-li některou proměnnou jako znak nebo řetězec znaků, pak i čísla jsou chápána jako text. A tudíž s nimi nelze provádět aritmetické operace. Každý znak má přiřazenu odpovídající hodnotu (číslo) v ASCII tabulce. Při psaní programu můžete využít znalostí toho, že klávesa Enter má přiřazeno číslo 13 a klávesa Esc číslo 27. Pro načítání znaků z klávesnice můžete použít procedury read a readln nebo využít procedury readkey. Při použití readln se znak do proměnné vloží až po stisknutí klávesy Enter, kdežto v případě readkey se znak do proměnné vloží okamžitě.
Kontrolní otázky 7. Vysvětlete, kdy použijete proměnnou typu Char a kdy typu String 8. Jakým způsobem můžete v programovém kódu Pascalu zapsat znak ? 9. Jakým způsobem určíte konkrétní znak v řetězci znaků ? 10. Kterou funkci použijete pro zjištění hodnoty znaků v ASCII tabulce? 11. Jakou funkcí zjistíte délku zadaného řetězce znaků? 12. Objasněte rozdíl v použití read či readln, oproti použití readkey.
Pojmy k zapamatování ASCII tabulka Char funkce Chr( ) funkce Length( ) ordinální hodnota znaku
readkey řetězec znaků String znak
70
7. Práce s textem
Korespondenční úkol Uživatel zadá z klávesnice text. Zadávání textu je ukončeno stiskem klávesy Enter. Při zadávání musí mít uživatel možnost kdykoli psaní textu opustit stiskem klávesy ESC ( v tom případě se program ukončí bez výpočtu). zajistěte, že v případě, kdy se uživatel pokusí zadat více než 256 znaků textu, ukončí program sám přijímání textu a vypíše uživateli zprávu: „Nelze zadat text delší než 256 znaků“. spočítejte, kolik je v zadaném textu slov spočítejte, kolik je v zadaném textu velkých písmen
Řešení Cvičení 7.1 program cviceni_7_1; uses crt; var znak: char; velka, mala: integer; begin clrscr; velka:=0; mala:=0; writeln('Zadejte text. Zadavani ukoncite stiskem klavesy Enter'); writeln; repeat znak:=readkey; write(znak); if (ord(znak)>=65) and (ord(znak)<=90) then velka:=velka +1; if (ord(znak)>=97) and (ord(znak)<=122) then mala:=mala +1; until znak =#13; writeln;writeln; writeln('Pocet velkych pismen je: ',velka); writeln('Pocet malych pismen je: ',mala); readln; end.
Cvičení 7.2 program cviceni_7_2; uses crt; var jmeno: string[20]; prijmeni:string[30]; begin clrscr; writeln('Zadejte jmeno: '); readln(jmeno); writeln('Zadejte prijmeni: '); readln(prijmeni); if (ord(jmeno[1])>=97) and (ord(jmeno[1])<=122) then jmeno[1]:= chr( ord(jmeno[1])-32); if (ord(prijmeni[1])>=97) and (ord(prijmeni[1])<=122) then prijmeni[1]:= chr( ord(prijmeni[1])-32); writeln;writeln; writeln(jmeno); writeln(prijmeni); readln; end.
71
Základy Algoritmizace
72
7. Práce s textem
8. Datový typ Pole (Array) Cíl: Po prostudování kapitoly byste měli být schopni deklarovat jednorozměrné a vícerozměrné pole napsat program s použitím datového typu pole Čas potřebný k prostudování kapitoly: 10 hodin Říkáte si proč další datový typ? Zatím jste v programu nebyli schopni zapamatovat si více hodnot uvnitř jedné proměnné. Tj. uchovat více hodnot v jedné proměnné. Dejme tomu, že jste měli v proměnné jméno uloženu hodnotu Pepa. Při načtení jména dalšího člověka do proměnné jméno, se přepsala původní hodnota Pepa novou hodnotou např. Franta → nemohli jste uchovat v proměnné obě hodnoty, ale pouze jednu hodnotu – tu poslední načtenou. Proto nový datový typ, který vám umožní uchovat více hodnot v rámci jedné proměnné. strukturovaný datový typ (strukturovaný typ je dále dělitelný) umožňuje uchovávat seznam více hodnot stejného typu v jedné proměnné prvky jsou indexovány (tzn. každý prvek pole má své pořadové číslo a tím je jednoznačně v poli určen) rozlišují se pole: jednorozměrná, dvojrozměrná a vícerozměrná. Jednorozměrné pole si představte jako tabulku s jedním sloupcem. Dvojrozměrné jako tabulku s více sloupci.
8.1 Jednorozměrné pole Jak tedy bude vypadat deklarované pole? Představte si jej například jako seznam: index 1 2 3 … 99 100
Pracovnici Krupička Vomáčka Šilhálek Přítulná Kropáček
deklarace: VAR jméno proměnné : array [min..max] of datový typ; velikost (rozsah) pole. Stanovuje maximální rozsah pole. To neznamená, že pole musí být v tom maximálním rozsahu naplněno hodnotami.
říkáte, jakého datového typu budou hodnoty uložené v proměnné typu pole. Musí být použit již deklarovaný datový typ.
73
Základy Algoritmizace
VAR pracovnici : array [1..100] of string[30]; velikost pole bude v intervalu od 1 do 100. Tj. V poli můžete mít údaje od 1 do 100 pracovníků.
hodnoty uložené v proměnné pracovnici budou typu string o maximální velikosti 30 znaků. Tzn. Budete-li v poli uchovávat jména pracovníků, tak délka jména nesmí přesáhnout 30 znaků.
práce s konkrétním prvkem pole: Pokud chcete pracovat s konkrétním prvkem v poli, pak to zapíšete následovně: Proměnná[index]; Např. budete chtít pracovat s údaji pana Šilhálka a Kropáčka. Pak to zapíšete: Pracovnici[3]; Pracovnici[100]; Když se tedy zeptám, kdo je 99.pracovník v seznamu, tak vaše odpověď bude znít? Přítulná.
Naplnění pole hodnotami Hodnoty do jednotlivých prvků pole můžete zadat tímto způsobem: Writeln(‘Zadejte jméno pracovníka’); Readln(pracovnici[1]); Writeln(‘Zadejte jméno pracovníka’); Readln(pracovnici[2]); Writeln(‘Zadejte jméno pracovníka’); Readln(pracovnici[3]); Jaká je nevýhoda tohoto způsobu? V případě, že budete zadávat 1000 pracovníků, tudy cesta asi nepovede. Když se na předchozí naplnění prvků pole podíváte, co se zde mění ? Mění se pozice hodnoty v poli, tedy index pole. Proto je výhodnější použít cyklus. uživatel před cyklem zadá, kolik chce vložit pracovníků
FOR i:=1 to n DO Begin Writeln(‘Zadejte jméno pracovníka’); Readln(pracovnici[i]); Protože se mění řídící proměnná i, End; zapíše se při každém průchodu cyklu nová hodnota na novou pozici v poli.
Pro načítání můžete použít i cyklus While a Repeat, ale nesmíte zapomenout sami měnit hodnotu indexu (proměnné i).
Výpis hodnot pole:
74
8. Datový typ Pole Provede se stejně jako při načítání pole, pouze příkaz Readln nahradíte příkazem Writeln.
Příklad 8.1: Napište program, který načte n čísel z klávesnice a vypíše je v opačném pořadí než byla zdána. program opacne_poradi; uses crt; var i:byte; {ridici promenna cyklu} n:byte; {pocet cisel,ktery se bude nacitat} cislo: array [1..200] of integer; Begin Write('Zadejte pocet cisel, ktere budete zadavat (z intervalu 1 az 200)'); Readln(n); FOR i:=1 to n DO Begin Načtení prvků do pole Write('Zadejte cele cislo'); Readln(cislo[i]); Výpis prvků pole od End; posledního k prvnímu. FOR i:=n downto 1 do Writeln(cislo[i]); readln; end.
Příklad 8.2 Načtěte posloupnost N celých kladných čísel. Zadávání čísel posloupnosti bude ukončeno 0, která už součásti posloupnosti nebude. Vypište čísla na lichých pozicích (tj. s indexem 1,3,5 …). program posloupnost_licha; uses crt; var i:byte; {index pole} delka:byte; {poznamenam si delku pole} pom:integer; cislo: array [1..200] of integer; Begin i:=1; Repeat Write('Zadejte cele cislo: '); Readln(pom);{ nactu cislo, ktere nejdrive overim zda neni nula} IF pom <> 0 THEN cislo[i]:=pom; {protoze nula nesmi byt zahrnuta} i:=i+1; {musim se posunout na dalsi pozici v poli} Until pom=0; delka:=i-1; {pred ukoncenim cyklu jsem se posunul navic o jednu pozici v poli} FOR i:=1 to delka do IF (i MOD 2)=1 THEN Writeln(cislo[i]); {je-li cislo na liche pozici v poli, tak jej vypisu}
readln; end.
75
Základy Algoritmizace Nyní už budete vědět, že v programování se pod pojmem pole nemyslí sousedovo pole řepy, ale seznam prvků stejného typu.
8.2 Dvojrozměrné pole Prozatím jste pracovali s tzv. jednorozměrným polem, které si můžete představit jako tabulku pouze s jedním sloupcem. Dvojrozměrné pole si představte jako tabulku s více sloupci. Pole pracovnici index i
1 2 3 .. m
index j 1
2
3
Vomáčka Vopička Oříšek … Simonová
Karel Josef František … Helena
…
Ing. … Mgr. … … … … Ing. …
n
Orlová Havířov Karviná Bohumín
Deklarace dvojrozměrného pole: VAR jméno proměnné : array [min..max, min..max] of datový typ; počet řádků
počet sloupců
Řádky i sloupce musí být stejného datového typu
Určení konkrétního místa v poli: Postupuje se podobně, jako když jste byli malí a hráli hru „Lodě“, kde jste určili konkrétní políčko, na které jste stříleli např. A5 a soupeř zahlásil vodu nebo zásah. Pozice v poli se určí : Jméno proměnné [index řádku, index sloupce] např. pracovnici[2,3]
obsahuje hodnotu : Mgr.
pracovnici[3,1]
obsahuje hodnotu : Oříšek
Jaká je hodnota například políček pracovnici[2,2], pracovnici[1,3] v poli pracovnici? ( Josef, Ing.)
76
8. Datový typ Pole
Naplnění pole hodnotami: Postupuje se následovně. Nejdříve se naplní celý řádek (budou se měnit sloupce, do kterých zadáváte hodnoty). Teprve pak se přejde na další řádek a postup zopakujete. Program vstoupí do vnějšího cyklu (i=1), hned nato vstoupí do vnitřního cyklu j. Vnitřní cyklus se provede n-krát (proměnná i je stále rovna 1). Takto pomocí vnitřního cyklu projde všemi sloupci prvního řádku. Opustí vnitřní cyklus a pokračuje ve vnějším cyklu tj. i=2 a znovu vstoupí do vnitřního cyklu. Takto se pokračuje až do doby, kdy i=m.
i:= 1..m j:= 1..n r ead ln (pra covn ic i[ i,j ]) ;
průchod sloupci jednoho řádku
průchod mezi řádky
konec j konec i
Zapsáno v kódu programu vypadá naplnění dvojrozměrného pole hodnotami následovně: FOR i:=1 TO m DO {průchod mezi řádky} FOR j:=1 TO n DO {průchod všemi sloupci jednoho řádku} Readln(pracovnici[i,j]); Toto zadávání bude fungovat, ale na obrazovce bude pouze blikat kurzor a uživatel nebude vědět, co má dělat. Proto je dobré zadávání dat uživateli zpřehlednit. Podívejte se na následující tabulku a naplňte ji daty od uživatele. Příjmení 1 2 3 .. m
Jméno
Kropáček Kouzelná Prasátko … Kropenatá
Pavel Petra Emil … Jana
Titul
Město
Ing. Karviná Mgr. Orlová Karviná … Ing. Bohumín
Pozor, v samotném poli nebudou uloženy názvy sloupců. Sloupce budou popsány pouze indexem, ale vy víte, jaký význam daný sloupec má.
77
Základy Algoritmizace
Příklad 8.3: Načtěte seznam pracovníků. Následně vypište údaje pouze o těch pracovnících, kteří jsou inženýry. program vypis_inzenyru; uses crt; var i,j:byte; {index pole} n:byte; {počet zadávaných pracovníků} pracovnik: array [1..50,1..4] of string; Begin Write('Zadejte počet zadavaných praconíků: '); readln(n); for i:=1 to n do Begin clrscr; writeln('Zadejte údaje o pracovníku');writeln;writeln; (*nebudete používat vnitřní cyklus pro přechod mezi sloupci*) (*přechod zajistíte sami v kódu programu zadáním čísla sloupce*) write('Příjmení: ');readln(pracovnik[i,1]); Protože jména se write('Jméno: ');readln(pracovnik[i,2]); budou zadávat do write('Titul: ');readln(pracovnik[i,3]); stejného sloupce, write('Město: ');readln(pracovnik[i,4]); můžete napsat kód programu tak, že End; jméno se vždy do (*Výpis těch pracovníků, kteří jsou inženýry*) sloupce 1. clrscr; writeln('Seznam inženýrů');writeln;writeln; Pole se projde od for i:=1 to n do prvního do posledního Begin řádku. if pracovnik[i,3]= 'Ing.' then Jestliže má pracovník titul Ing., for j:=1 to 4 do pak se vypíšou všechny jeho údaje (projdou se a vypíšou write(pracovnik[i,j],' '); hodnoty ve všech čtyřech writeln; sloupcích řádku). End; readln; End.
Deklarace pole jako uživatelem definovaného datového typu Type pracovnici = array [1..50,1..4] of string; Var pracovnik: pracovnici; Nezapomeňte, že pokud deklarujete datový typ, tak se za názvem typu používá rovnítko.
78
8. Datový typ Pole
Cvičení 8.1 Je dána posloupnost 20 čísel. Zjistěte, kolik z nich se rovná prvnímu a poslednímu zadanému číslu. Vaším úkolem je zjistit, kolik čísel je stejných jako první zadané číslo a kolik čísel je stejných jako poslední zadané číslo. Ale jaké to poslední číslo je, se dozvíte až naposled. Musíte si proto někde uložit předchozí zadaná čísla, abyste je mohli dodatečně porovnat s posledním zadaným číslem. Využijete proto datového typu pole.
Cvičení 8.2 Je dána posloupnost 15 celých čísel. Zjistěte počet kladných a počet záporných čísel. Vypište nejdříve seznam dvojnásobků všech kladných čísel a pak seznam absolutních hodnot záporných čísel. Oba seznamy budou vypsány v opačném pořadí než byla čísla zadána. K převodu čísla na absolutní hodnotu můžete využít funkci ABS ()
79
Základy Algoritmizace
8.3 Použití datového typu pole Pokud jste se nad tím zamysleli, tak datový typ pole má jedno omezení – všechny hodnoty uložené v poli musí být stejného datového typu. Nemůžete nadefinovat, že hodnoty v jednom sloupci jsou např. integer, v dalším sloupci jsou hodnoty typu string a v dalším typu byte. Toto omezení můžete obejít následujícími způsoby: I. načíst vše (i čísla) jako typu string a pokud budete potřebovat matematické operace, tak tyto hodnoty převést na čísla II. použít více polí (tabulek) z nichž každé bude jiného datového typu III. použít datový typ record (záznam) Každé z navržených řešení má své výhody a svá úskalí. Podíváte se na ně proto blíže. Proč se tím zabývat? Příklady na dalších stranách vám ukáží, že problém lze řešit různými způsoby. Navíc aplikujete mnoho z toho, co už umíte. Berte to jako takové komplexnější příklady k procvičení.
Zadání příkladu: Zpracujte seznam studentů jedné třídy (jméno, příjmení, město) a jejich známky z matematiky, českého jazyka, informatiky a účetnictví. Příjmení 1 2 3 .. m
Jméno
Město
M
CJ
Inf
Kocourek Franta Lžička Josef Myšpulín Albrecht
Orlová Havířov Orlová
1 1 1
3 2 3
2 1 2
Slzavá
Bohumín
1
1
2
Cecilie
Zjistěte: průměr známek celé třídy průměr známek studenta průměr známek daného předmětu Program řešte uživatelsky přívětivě – program se vždy uživatele zeptá, zda chce zadávat dalšího studenta (tj. nebude uživatele nutit k zadání např. všech 30 studentů třídy). Takže zadání máme, tak hrr na řešení. Doporučuji, abyste byli odpočatí a mohli se plně soustředit.
80
8. Datový typ Pole
8.3.1 Řešení I. Načtení všech hodnot jako řetězce znaků a v případě výpočtu jejich převedení na čísla. Všechny hodnoty včetně známek se uloží do pole jako řetězec znaků. Teprve v okamžiku, kdy je nutné počítat průměr, se známky převedou na čísla pomocí procedury VAL(). program reseni1; uses crt; var i,j:byte; {index pole} poc_studentu:byte; {pocet zadanych studentu} student: array [1..30,1..6] of string; znak:char; souc_mat, souc_cj, souc_inf: integer; {soucty znamek vsech studentu predmetu} poc_mat, poc_cj, poc_inf: byte; {pocet znamek udelenych v predmetu} souc_stud: byte; {soucet znamek 1 studenta} poc_stud: byte; {pocet znamek 1 studenta} znamka:integer; chyba:integer; {zde se ulozi index znaku, u ktereho doslo pri prevodu na cislo k chybe} Begin Protože je použít cyklus repeat until, musíte i:=0; sami určit, na kterém řádku v poli se program repeat nachází. clrscr; i:=i+1; writeln('*** Budete zadavat udaje o studentovi ***'); writeln;writeln; Načtení údajů studentů. write('Prijmeni: ');readln(student[i,1]); Nepoužijete druhý cyklus pro přechod mezi sloupci, write('Jmeno: ');readln(student[i,2]); protože chceme vypisovat write('Mesto: ');readln(student[i,3]); u každého sloupce jeho popis. tj. Příjmení:, Jméno: write('Matematika: ');readln(student[i,4]); atd. write('Cesky jazyk: ');readln(student[i,5]); write('Informatika: ');readln(student[i,6]); writeln;writeln; write('Prejete si zadat dalsiho studenta ? A/N: '); readln(znak);writeln;writeln; Načítání studenta se opakuje tak dlouho, dokud until (znak='N') or (znak='n'); uživatel nezadá N. Když se nad ukončením cyklu zamyslíte, zjistíte, že ať uživatel zadá poc_studentu:=i; jakékoli písmeno bude pokračovat v zadávání studentů. Teda dokud nezadá N. ☺ Musíte si poznamenat, kolik máme studentů v poli
81
Základy Algoritmizace (*zjištění prumeru*) souc_mat:=0; poc_mat:=0; souc_cj:=0; poc_cj:=0; souc_inf:=0; poc_inf:=0; for i:=1 to poc_studentu do begin souc_stud:=0; poc_stud:=0; for j:=4 to 6 do begin
Budete procházet pole po jednotlivých řádcích. Převádět známky ze stringu na integer a počítat průměr studenta.
Při přechodu na nového studenta (řádek pole) musíte vyčistit součet a počet známek každého studenta. Budete procházet známky jednoho studenta (od 4 do 6 sloupce v poli)
val(student[i,j],znamka,chyba);
Procedura VAL převede známku uloženou jako string na číslo a uloží ji do proměnné znamka.
if (j=4) and ((znamka>=1) and (znamka<=5)) then Je-li j=4, pak pracujete begin s matematikou. Zbytek podmínky souc_stud:= souc_stud + znamka; zajistí, že budeme počítat se poc_stud:=poc_stud + 1; známkami od 1 do 5. Navíc ošetří, souc_mat:=souc_mat + znamka; situaci, kdy uživatel nezadal poc_mat:= poc_mat + 1; známku nebo zadal jiné než povolené známky nebo zadal nějaký end; znak. Tyto chyby neovlivní ani součet ani počet známek.
if (j=5) and ((znamka>=1) and (znamka<=5)) then počítáte součet a počet známek begin daného studenta souc_stud:= souc_stud + znamka; poc_stud:=poc_stud + 1; Tato část poslouží později pro výpočet souc_cj:=souc_cj + znamka; průměrné známky z předmětu za všechny studenty. poc_cj:= poc_cj + 1; Známku studenta z ČJ si přičtete end; k součtu všech známek z ČJ a zvýšíme počet známek z ČJ o 1.
if (j=6) and ((znamka>=1) and (znamka<=5)) then begin souc_stud:= souc_stud + znamka; poc_stud:=poc_stud + 1; souc_inf:=souc_inf + znamka; poc_inf:= poc_inf + 1; Příjmení Jméno end; end; write('Prumerna znamka studenta ',student[i,1],' ',student[i,2],' je: '); writeln(souc_stud/poc_stud:4:2); Vypíše se průměrná známka sstudenta ze všech jeho předmětů end; Zde končí cyklus FOR a přejde se na dalšího studenta (posune se na další řádek pole).
82
8. Datový typ Pole (* Vypocet a vypis prumernych znamek za predmet a prumerne znamky cele tridy *) writeln;writeln;
Může nastat situace, kdy uživatel nezadá žádnou známku z matematiky (nebo ji zadá špatně). Pak by v proměnné poc_mat byla uložena hodnota 0. A nulou nemůžete dělit.
if poc_mat > 0 then writeln('Prumerna znamka z matematiky je: ',souc_mat/poc_mat:4:2) else writeln('Nebyla zadana zadna znamka z matematiky'); if poc_cj > 0 then writeln('Prumerna znamka z ceskeho jazyka je: ',souc_cj/poc_cj:4:2) else writeln('Nebyla zadana zadna znamka z ceskeho jazyka'); if poc_inf > 0 then writeln('Prumerna znamka z informatiky je: ',souc_inf/poc_inf:4:2) else writeln('Nebyla zadana zadna znamka z informatiky');
writeln;writeln; writeln('Prumerna znamka tridy: ', (souc_mat+souc_cj+souc_inf) / (poc_mat+poc_cj+poc_inf):4:2); readln; Průměrná známka třídy vypočítaná jako součet všech známek z matematiky, českého jazyka a informatiky. End. Doufám, vás toto řešení nevyděsilo. Je dobré se nad ním zamyslet a párkrát si je projít. Problém můžete určitě vyřešit jiným způsobem a elegantněji. Právě proto je programování tvůrčí činností chráněnou Autorským zákonem. Všimněte si, že program při zadávání vůbec neřeší to, jestli náhodou někdo nezadá jinou hodnotu než regulérní známku. Tuto kontrolu provádí až při výpočtu průměrů. Proč? Musíte se rozhodnout, zda budete uživatele nutit zadat známky od 1 do 5, nebo mu umožníte poznačit případy, kdy je student nehodnocen (pak vloží třeba 0) apod. Než se podíváte na druhý způsob jak vyřešit zadaný příklad, odpočiňte si ať jste čerství.
83
Základy Algoritmizace
8.3.2 Řešení II. Použití více polí (tabulek) z nichž každé bude jiného datového typu Údaje o studentech rozdělte do dvou tabulek (tj. dvou dvojrozměrných polí) Student a Známky takto: Student: Příjmení 1 2 3 .. m
Známky: Jméno
Město
Kocourek Franta Lžička Josef Myšpulín Albrecht
Orlová Havířov Orlová
Slzavá
Bohumín
Cecilie
1 2 3 .. m
M
CJ
Inf
1 1 1
3 2 3
2 1 2
1
1
2
Jedna osoba má stejný index v obou tabulkách
Tabulky „propojíte“ pomocí indexu řádku. Na stejném řádku v obou tabulkách budou data stejného člověka. program reseni2; uses crt; var i,j:byte; {index pole} poc_studentu:byte; {pocet zadanych studentu} student:array [1..30,1..3] of string; V jednom poli budou uloženy údaje znamky:array [1..30,1..3] of byte; o studentech, v druhém známky. znak:char; souc_mat, souc_cj, souc_inf: integer; {soucty znamek studentu za predmet} poc_mat, poc_cj, poc_inf: byte; {pocet znamek udelenych v predmetu} souc_stud: byte; {soucet znamek 1 studenta} poc_stud: byte; {pocet znamek 1 studenta} Begin i:=0; repeat {nacteni studentu} clrscr; i:=i+1; writeln('*** Budete zadavat udaje o studentovi ***'); writeln;writeln; write('Prijmeni: ');readln(student[i,1]); Všimněte si, že se write('Jmeno: ');readln(student[i,2]); zadávají údaje do dvou write('Mesto: ');readln(student[i,3]); různých polí, ale na write('Matematika: ');readln(znamky[i,1]); stejný řádek. write('Cesky jazyk: ');readln(znamky[i,2]); write('Informatika: ');readln(znamky[i,3]); writeln;writeln; write('Prejete si zadat dalsiho studenta ? A/N: '); readln(znak);writeln;writeln; until (znak='N') or (znak='n'); poc_studentu:=i;
84
8. Datový typ Pole (*zjištění průmerů*) souc_mat:=0; poc_mat:=0; souc_cj:=0; poc_cj:=0; souc_inf:=0; poc_inf:=0; for i:=1 to poc_studentu do begin souc_stud:=0; poc_stud:=0; if ((znamky[i,1]>=1) and (znamky[i,1]<=5)) then begin Ověření, zda čísla v poli souc_stud:= souc_stud + znamky[i,1]; známky, ve sloupci poc_stud:=poc_stud + 1; matematika odpovídají souc_mat:=souc_mat + znamky[i,1]; rozmezí 1 až 5. poc_mat:= poc_mat + 1; end; if ((znamky[i,2]>=1) and (znamky[i,2]<=5))then begin souc_stud:= souc_stud + znamky[i,2]; poc_stud:=poc_stud + 1; souc_cj:=souc_cj + znamky[i,2]; poc_cj:= poc_cj + 1; end; if ((znamky[i,3]>=1) and (znamky[i,3]<=5)) then begin souc_stud:= souc_stud + znamky[i,3]; poc_stud:=poc_stud + 1; souc_inf:=souc_inf + znamky[i,3]; poc_inf:= poc_inf + 1; end; write('Prumerna znamka studenta ',student[i,1],' ',student[i,2],' je: '); writeln(souc_stud/poc_stud:4:2); end; writeln;writeln; if poc_mat > 0 then writeln('Prumerna znamka z matematiky je: ',souc_mat/poc_mat:4:2) else writeln('Nebyla zadana zadna znamka z matematiky'); if poc_cj > 0 then writeln('Prumerna znamka z ceskeho jazyka je: ',souc_cj/poc_cj:4:2) else writeln('Nebyla zadana zadna znamka z ceskeho jazyka'); if poc_inf > 0 then writeln('Prumerna znamka z informatiky je: ',souc_inf/poc_inf:4:2) else writeln('Nebyla zadana zadna znamka z informatiky'); writeln;writeln; writeln('Prumerna znamka tridy: ', (souc_mat+souc_cj+souc_inf) / (poc_mat+poc_cj+poc_inf):4:2); readln; End.
85
Základy Algoritmizace
8.3.3 Řešení III. – použití datového typu record Už víte, že všechny hodnoty uložené v proměnné typu pole musí být stejného datového typu. V předchozích dvou příkladech jste se naučili toto omezení obejít. Určitě vás už napadlo, že ta řešení jsou trochu komplikovaná. Proto existuje další datový typ – record (záznam). O tomto datovém typu se pouze zmíním jako o možnosti řešení. Jeho podrobný popis a použití není náplní tohoto výukového materiálu a více se o něm dozvíte v Základech programování.
Datový typ Record (záznam) strukturovaný datový typ Občas potřebujete uchovávat záznamy např. o člověku. Tyto záznamy se skládají z více položek, které jsou různých datových typů (například jméno a příjmení jsou řetězce znaků, věk a výplata je typu číslo apod.). Deklarace: TYPE
Deklarace vlastního typu člověk,
clovek = record který obsahuje položky jméno, příjmení a počet dětí. Dejte si jmeno:string[20]; pozor, za klíčovým slovem primeni:string[20]; record není středník. poc_deti:byte; Definice typu končí end se středníkem.
end;
Definujete, že proměnná zaměstnanec je datového typu člověk.
VAR zamestnanec: clovek;
K položkám proměnné, přistupovat následovně:
v našem
případě
zaměstnanec,
můžete
Přiřazení řetězce ‘Petr‘ do proměnné jmeno daného zaměstnance Načtení hodnoty do proměnné jmeno ze vstupního zařízení
zamestnanec.jmeno:= ‘Petr’; raedln(zamestnanec.jmeno);
Tolik velice stručně k datovému typu record. Nyní už je čas vrátit se k našemu problému. Pokud k jeho řešení použijete record, pak si údaje o studentech a jejich známkách můžete klidně představit jako níže uvedenou tabulku. V programu Řešení 3 si ukážeme jak zkombinovat datové typy record a array. Řádek tabulky chápejte jako jeden záznam a celou tabulku jako pole záznamů. Příjmení 1 2 3 .. m
Jméno
Město
M
CJ
Inf
Kocourek Franta Lžička Josef Myšpulín Albrecht
Orlová Havířov Orlová
1 1 1
3 2 3
2 1 2
Slzavá
Bohumín
1
1
2
Cecilie
86
8. Datový typ Pole program Reseni3; uses crt; type student_skoly = record jmeno:string[20]; prijmeni:string[30]; mesto:string; mat:byte; cj:byte; inf:byte; end; var student:array [1..30] of student_skoly; i:byte; poc_studentu:byte; znak:char; souc_mat,souc_cj,souc_inf:integer; poc_mat,poc_cj,poc_inf:byte; souc_stud:byte; poc_stud:byte; begin i:=0; repeat {nacteni studentu} clrscr; i:=i+1; writeln('*** Budete zadavat udaje o studentovi ***'); writeln;writeln; write('Prijmeni: ');readln(student[i].prijmeni); write('Jmeno: ');readln(student[i].jmeno); write('Mesto: ');readln(student[i].mesto); write('Matematika: ');readln(student[i].mat); write('Cesky jazyk: ');readln(student[i].cj); write('Informatika: ');readln(student[i].inf); writeln;writeln; write('Prejete si zadat dalsiho studenta ? A/N: '); readln(znak);writeln;writeln; until (znak='N') or (znak='n'); poc_studentu:=i; (*zjištění průmerů*) souc_mat:=0; poc_mat:=0; souc_cj:=0; poc_cj:=0; souc_inf:=0; poc_inf:=0; for i:=1 to poc_studentu do
87
Základy Algoritmizace begin souc_stud:=0; poc_stud:=0; if ((student[i].mat>=1) and (student[i].mat<=5)) then begin souc_stud:= souc_stud + student[i].mat; poc_stud:=poc_stud + 1; souc_mat:=souc_mat + student[i].mat; poc_mat:= poc_mat + 1; end; if ((student[i].cj>=1) and (student[i].cj<=5))then begin souc_stud:= souc_stud + student[i].cj; poc_stud:=poc_stud + 1; souc_cj:=souc_cj + student[i].cj; poc_cj:= poc_cj + 1; end; if ((student[i].inf>=1) and (student[i].inf<=5)) then begin souc_stud:= souc_stud + student[i].inf; poc_stud:=poc_stud + 1; souc_inf:=souc_inf + student[i].inf; poc_inf:= poc_inf + 1; end; write('Prumerna znamka studenta ',student[i].prijmeni,' ',student[i].jmeno,' je: ');
writeln(souc_stud/poc_stud:4:2); end; writeln;writeln; if poc_mat > 0 then writeln('Prumerna znamka z matematiky je: ',souc_mat/poc_mat:4:2) else writeln('Nebyla zadana zadna znamka z matematiky'); if poc_cj > 0 then writeln('Prumerna znamka z ceskeho jazyka je: ',souc_cj/poc_cj:4:2) else writeln('Nebyla zadana zadna znamka z ceskeho jazyka'); if poc_inf > 0 then writeln('Prumerna znamka z informatiky je: ',souc_inf/poc_inf:4:2) else writeln('Nebyla zadana zadna znamka z informatiky'); writeln;writeln; writeln('Prumerna znamka tridy: ', (souc_mat+souc_cj+souc_inf) / (poc_mat+poc_cj+poc_inf):4:2); readln; End.
88
8. Datový typ Pole
Nyní se mě asi budete chtít zeptat, proč jsem vás obtěžoval řešením I, II a III, když stačilo ukázat pouze jedno. Nestačilo, protože vás chci naučit myslet trochu odlišně. Ukázat vám, že problém lze řešit více způsoby. Nejde-li v informatice něco zleva, tak to zkuste zprava ☺. Kdysi jsem vás posílal vydechnout si k ledničce a dát si mléko. Myslím si ale, že po této kapitole si zasloužíte něco lepšího – dejte si, na co máte chuť. ☺
Shrnutí V této kapitole jste se naučili používat proměnnou typu pole. Po proměnné tohoto datového typu sáhnete vždy, když budete potřebovat uchovat více hodnot v rámci jediné proměnné. Seznámili jste s jednorozměrným a dvourozměrným polem. Příkladem jednorozměrného pole může být jakákoli tabulka hodnot s více řádky tvořená jedním sloupcem. Dvourozměrné pole si můžete představit jako tabulku s více sloupci. Pole je vždy tvořeno prvky stejného datového typu. Každý prvek má své pořadové číslo (tzv. index), které jednoznačně určuje jeho pozici v poli. V případě dvourozměrného pole je prvek určen indexem pro pozici v řádku a indexem pro pozici ve sloupci. K naplnění, výpisu a práci s polem se používají cykly. Pro práci s dvourozměrným polem se používají dva cykly. Pomocí jednoho cyklu (vnějšího) se prochází řádky a pomocí druhého (vnitřního) se pohybuje po sloupcích v daném řádku pole. Nevýhodou datového typu pole je omezení, že každý prvek pole musí být stejného datového typu. To může být problémem při použití v reálném životě, kde pracujete s údaji různého datového typu (např. jméno, příjmení, věk…). Toto omezení můžete obejít několika způsoby. Načíst všechny hodnoty prvků pole jako jednoho datového typu a v případě potřeby je převádět na jiný datový typ (ze stringu na číslo apod.). Nebo můžete pracovat s více tabulkami, z nichž každá bude obsahovat hodnoty jiného typu, a tabulky propojíte pomocí indexu. Jako další řešení můžete použít kombinaci pole a datového typu záznam.
Kontrolní otázky 1. 2. 3. 4.
Kdy použijete proměnnou typu pole ? Vysvětlete, jaký je rozdíl mezi jednorozměrným a dvourozměrným polem. Popište, jak deklarujete jednorozměrné a dvourozměrné pole. Jakým způsobem načtete hodnoty prvků jednorozměrného a dvourozměrného pole? 5. Který datový typ použijete pro deklaraci proměnné indexu pole? 6. Jaké je omezení datového typu pole a jakými způsoby můžete toto omezení obejít?
89
Základy Algoritmizace
Pojmy k zapamatování: pole hodnot jednorozměrné pole dvourozměrné pole řádek pole sloupce pole prvek pole index
Korespondenční úkol Vytvořte program, který průběžně načítá výsledky školních závodů ve skoku do dálky. Po skončení závodu program vypiše jména studentů na prvních třech místech a hodnotu toho výsledku, který jim zajistil vítězství. Skáče se ve třech soutěžních kolech.
Řešení Cvičení 8.1 program cviceni_8_1; uses crt; type Tpole=array[1..20] of integer; var cislo:Tpole; i,n:byte; poc_prvnich,poc_poslednich:byte; {pocet cisel stejnych jako prvni a posledni cislo} begin clrscr; poc_prvnich:=0; poc_poslednich:=0; write('Kolik cisel chcete zadavat? : '); readln(n); for i:=1 to n do begin write('Zadejte ',i,'. cislo: '); readln(cislo[i]); end; for i:=1 to n do begin if cislo[i]= cislo[1] then poc_prvnich:=poc_prvnich + 1; if cislo[i]= cislo[n] then poc_poslednich:=poc_poslednich + 1; end; writeln; writeln; writeln('prvni cislo ',cislo[1],' se v posloupnosti vyskytuje ',poc_prvnich,' krat'); writeln('posledni cislo ',cislo[n],' se v posloupnosti vyskytuje ',poc_poslednich,' krat'); readln; end.
90
8. Datový typ Pole Cvičení 8.2 program priklad_8_2; uses crt; var cislo:array [1..15] of integer; i:byte; kladnych, zapornych:byte; begin clrscr; kladnych:=0; zapornych:=0; for i:=1 to 5 do begin writeln('Zadejte cele cislo'); readln(cislo[i]); if cislo[i] > 0 then kladnych:= kladnych + 1; if cislo[i] < 0 then zapornych:= zapornych + 1; end; writeln;writeln; writeln('*** Vypis dvojnasobku kladnych cisel ***');writeln; for i:= 5 downto 1 do if cislo[i] > 0 then writeln('cislo: ',cislo[i],' dvojnasobek: ',2*cislo[i]); writeln; writeln; writeln('*** Vypis absolutni hodnoty zapornych cisel ***');writeln; for i:= 5 downto 1 do if cislo[i] < 0 then writeln('cislo: ',cislo[i],' absolutni hodnota: ',abs(cislo[i])); writeln;writeln; writeln('pocet zadanych kladnych cisel: ',kladnych); writeln('pocet zadanych zapornych cisel: ',zapornych); readln; end.
91
Základy Algoritmizace
92
9. Třídění a vyhledávání
9. Třídění a vyhledávání Cíl: Po prostudování této kapitoly byste měli být schopni objasnit rozdíl ve vyhledávání dat v setříděném a nesetříděném poli dat vysvětlit důvod pro použití třídících algoritmů uvést příklady třídících algoritmů setřídit pole čísel pomocí bublinkového třídění a třídění metodou minima Čas potřebný k prostudování této kapitoly: 4 hodiny
Příklad 9.1 Podívejte se na následující data a určete, v kterém případě najdete všechny výskyty jména Karel. Zjistěte, kolikrát se jméno Karel opakuje. Nesetříděná data Adam Karel Petr Alfons Karel Lumír Cecílie Karel Tomáš Žaneta Veronika Karel Brunhilda Lumír Petr
Setříděná data Adam Alfons Brunhilda Cecílie Karel Karel Karel Karel Lumír Lumír Petr Petr Tomáš Veronika Žaneta
Jestli jste si odpověděli 4x, pak je to správně ☺. Určitě jste si všimli, že nalezení všech záznamů se jménem Karel vám trvalo v méně času v setříděných datech.
V této kapitole se seznámíte se základními vyhledávacími a třídícími algoritmy. Seznámení to bude zběžné.
Vyhledávání Při vyhledávání si vždy musíte uvědomit, jestli vyhledáváte v setříděných nebo nesetříděných datech. Vyhledání v nesetříděných datech: procházíte data od začátku do konce (nebo naopak od konce k začátku). Ptáte se, jestli položka, na které stojíte, je ta hledaná. Tento postup je zdlouhavý, protože musíte projít data od začátku do konce.
93
Základy Algoritmizace
Příklad 9.2 - vyhledání v nesetříděných datech Je dán nesetříděný seznam se jmény studentů. Seznam je ukončen prázdným řetězcem. Napište program, který zjisti, kolikrát se jméno zadané uživatelem vyskytuje v seznamu studentů. Program priklad_9_2; uses crt; var student: array [1..20] of string[35]; i,pocet: byte; jmeno: string[35]; begin clrscr; pocet:=0; i:=0; Prochází se postupně writeln('Zadejte jmeno, ktere chcete nalezt'); celý seznam do konce. readln(jmeno); Konec nastane, když je v poli místo jména repeat prázdný řetězec. nalezen i:=i+1; if student[i]=jmeno then pocet:=pocet+1; until student[i]=''; if pocet <>0 then writeln('Hledane jmeno se v seznamu vyskytuje ',pocet,' krat') else writeln('Hledane jmeno se v seznamu nevyskytuje'); readln; end. Předpokládá se, že jména jsou v poli už zadaná. Budete-li si chtít kód vyzkoušet, doprogramujte si vytvoření seznamu studentů a naplňte si jej daty. Pro snazší pochopení vyhledávacího algoritmu program neřeší rozdíl mezi malými a velkými písmeny.
Vyhledání v setříděných datech: Najdete první výskyt hledané položky. Pak postupujete postupně po dalších položkách, které odpovídají tomu, co hledáte. V okamžiku když narazíte na položku, která už neodpovídá, víte, že jste našli všechny výskyty. Zdá se vám to vysvětlení kostrbaté?! Asi jako každý obecný postup . Jednoduše si to přečtěte a použijte na příklad 9.1. Zkráceně řečeno. Při vyhledávání v nesetříděných datech musím projít všechno. Při hledání v setříděných datech najdu první položku, kterou hledám. Pak už si vypisuji jen to, co odpovídá podmínce. A když narazím na něco jiného můžu skončit. V případě vyhledávání v setříděných datech není uvedeno, jak najdete první výskyt hledané položky. Existuje totiž řada algoritmů pro nejrychlejší nalezení prvního výskytu hledané položky.
94
9. Třídění a vyhledávání Algoritmy vyhledávání: sekvenční vyhledávání (postupné, lineární): procházíte od začátku postupně všechny položky tak dlouho, až narazíte na položku, kterou hledáte. Vypíšete všechny odpovídající položky a vyhledávání můžete ukončit. blokové vyhledávání: Rozdělíte si data na bloky např. po 10 položkách. Nepostupujete po jedné položce, ale postupujete po blocích. Vždy se podíváte se na první položku bloku. Je-li její hodnota větší než hodnota hledané položky, vrátíte se k předchozímu bloku, který už projdete sekvenčně (protože někde v něm je hledaná položka). Je-li hodnota první položky menší než hodnota hledané položky, přejdete k dalšímu bloku. binární vyhledávání (půlení intervalů): jde o nejrychlejší vyhledávací metodu. Nejdříve porovnáte hledanou hodnotu s hodnotou položky uprostřed pole dat. Je-li menší, rozdělíte první polovinu dat (v ní se někde bude nacházet hledaná hodnota) znovu na půlku. Postup opakujete, až naleznete hledanou položku. Příklad 9.3 ukazuje sekvenční vyhledání v setříděných datech. Nejdříve naleznete první výskyt hledaného jména. Pak už jen počítáte kolik jmen odpovídá hledanému jménu. Program je napsán tak, abyste zbytečně neprochazeli i zbytek dat, když už jste našli vše, co jste hledali.
Příklad 9.3 – vyhledání v setříděných datech Je dán setříděný seznam se jmény studentů. Seznam je ukončen prázdným řetězcem. Napište program, který zjisti, kolikrát se jméno zadané uživatelem vyskytuje v seznamu studentů. Program priklad_9_3; uses crt; var student: array [1..20] of string[35]; i,pocet: byte; jmeno: string[35]; nalezeno:boolean; begin clrscr; pocet:=0; i:=0; nalezeno:=false; writeln('Zadejte jmeno, ktere chcete nalezt'); readln(jmeno); repeat i:=i+1; Program prochází postupně seznam if student[i]=jmeno then od začátku až do okamžiku, kdy begin najde hledané jméno nebo narazí na pocet:=pocet+1; prázdný řetězec. nalezeno:=true; end; until ((student[i]<>jmeno) and nalezeno) or(student[i]=''); if pocet <>0 then writeln('Hledane jmeno se v seznamu vyskytuje ',pocet,' krat') else writeln('Hledane jmeno se v seznamu nevyskytuje'); readln; end. Pozor. Tento program funguje s setříděnými daty, budete-li jej zkoušet, musíte vložit už setříděný seznam dat. Pro práci s nesetříděnými daty není algoritmus účinný.
95
Základy Algoritmizace Nyní už víte, že rychleji lze vyhledávat v setříděných datech. Umíte použít sekvenční (postupné, lineární) vyhledávání v setříděném souboru a víte, že existují i jiné vyhledávací algoritmy. Nyní proto nastal čas, abyste se naučili takový nesetříděný soubor setřídit.
Třídění Třídící algoritmy slouží k setřídění dat podle různých kritérií (např. velikosti, pořadí, abecedy…). Existuje řada třídících algoritmů (třídění metodou minima, bublinkové třídění, třídění vsouváním, Quick Sort apod.). Každý algoritmus se hodí k jiným účelům. Některé jsou rychlé, některé méně nebo více náročné na výpočetní techniku a jiné naopak jednodušší na pochopení. Příklady některých třídících algoritmů: třídění metodou minima nebo maxima Bublinkové třídění (Bubble sort) Třídění metodou minima. Vyberete první prvek, který považujete za minimum, a porovnáváte jej s ostatními prvky. Je-li porovnávaný prvek menší než minimum, tak je mezi sebou zaměníte. Pak vezmete druhý prvek a postup opakujete.
Příklad_9.5 – třídění metodou minima Setřiďte zadanou posloupnost čísel. program priklad_9_5; uses crt; var cislo: array[1..100] of byte; pom,i,j,n: byte; begin clrscr; writeln('Zadejte pocet zadavanych cisel'); readln(n);writeln; Nemusíte procházet až do konce, protože for i:=1 to n do vždycky porovnáváte s tím dalším prvkem. begin Ten poslední byste neměli s kým porovnat. write('Zadejte cislo: '); readln(cislo[i]); S proměnnou cislo[i] budete porovnávat end; další prvky a ptáte se, jestli nejsou menší for i:=1 to n-1 do než cislo[i]. for j:= i+1 to n do if cislo[j]< cislo[i] then begin Narazíte-li na menší číslo, tak je mezi pom:=cislo[i]; sebou vyměníte. cislo[i]:=cislo[j]; cislo[j]:=pom; end; writeln;writeln('Setridena cisla:'); for i:=1 to n do writeln(cislo[i]); readln; end;.
96
9. Třídění a vyhledávání Zde vidíte jak probíhá třídění metodou minima v jednotlivých krocích:
j=2 j=3 j=4 j=5 j=3 j=4 j=5 j=4 j=5 j=5
Před začátkem: 4 2 6 1 i=1 4 2 6 1 2 4 6 1 2 4 6 1 1 4 6 2 i=2 1 4 6 2 4 6 2 1 1 2 6 4 i=3 1 2 6 4 1 2 4 6 i=4 1 2 3 6 Po dokončení: 1 2 3 4
3 3 3 3 3 3 3 3 3 3 4 6
Bublinkové třídění Porovnáváte dva sousední prvky. Když větší prvek je před menším prvkem, prohodíte je mezi sebou. Takto se největší prvek posunuje až na konec. Projdete celé pole a sledujete, zda jste byli nuceni měnit pořadí prvků. Pokud ano, opakujete porovnání znovu od začátku a to tak dlouho, dokud neprojdete pole bez jediné změny (viz proměnná zmena v příkladu 9.6).
Příklad 9.6 – bublinkové třídění program priklad_9_6; uses crt; var cislo: array[1..100] of byte; i,n,pom:byte; Načtení nesetříděné zmena:boolean; posloupnosti dat. begin clrscr; writeln('Zadejte nesetridenou posloupnost cisel. Kolik chcete zadat cisel? : '); readln(n); for i:=1 to n do Abyste nemuseli pokračovat v třídění až begin do konce, použijete pomocnou writeln(i,' cislo: '); readln(cislo[i]); proměnnou zmena. Jestli nedojde, k žádnému prohození prvků mezi sebou, end; je už posloupnost setříděná a můžete repeat třídění ukončit. zmena:=false; Pokaždé, před průchodem polem for i:=1 to n-1 do nastavite proměnnou zmena na false. if cislo[i]>cislo[i+1] then begin Prohození prvků mezi pom:=cislo[i]; sebou, vždy realizujete přes cislo[i]:=cislo[i+1]; třetí pomocnou proměnnou. cislo[i+1]:=pom; zmena:=true; Dojde-li k prohození dvou prvků mezi end; sebou, došlo ke změně a musíte until zmena=false; pokračovat v třídění … Nyní už stačí jen vypsat setříděné pole
97
Základy Algoritmizace Před začátkem vnitřního cyklu se pokaždé nastaví proměnná zmena na false. V případě, že byly prvky mezi sebou prohozeny, změní se hodnota proměnné zmena na true. Před začátkem třídění 4 2 6 1 3 i=1 4 2 6 1 3 2 4 6 1 3 i=2 i=3 2 4 6 1 3 2 4 1 6 3 i=4 Vysledek po skončení 2 4 1 3 6 vnitřního cyklu 2.průchod: proměnná zmena se nastaví na false i=1 2 4 1 3 6 i=2 2 4 1 3 6 2 1 4 3 6 i=3 i=4 2 1 3 4 6 Vysledek po skončení 2 1 3 4 6 vnitřního cyklu 3.průchod: proměnná zmena se nastaví na false i=1 2 1 3 4 6 1 2 3 4 6 i=2 i=3 1 2 3 4 6 1 2 3 4 6 i=4 Vysledek po skončení 1 2 3 4 6 vnitřního cyklu 4.průchod: proměnná zmena se nastaví na false i=1 1 2 3 4 6 i=2 1 2 3 4 6 1 2 3 4 6 i=3 1 2 3 4 6 i=4 Vysledek po skončení 1 2 3 4 6 vnitřního cyklu
F T T T T T T T T T
Protože je proměnná zmena=true (tj. došlo k prohození prvků), pokračuje se v třídění
T T T T T T F F F F
Proměnná zmena je false – nedošlo k žádné změně. Proto se třídění ukončí.
F
Existuje řada různých řešení třídících algoritmů. Proto se nedivte, že když vyhledáte třídící algoritmy na Internetu, mohou být trochu odlišné. Princip daného algoritmu je stejný, liší se v provedení. Například tak jako třídíte metodou minima, můžete použít metodu maxima a postupujete obdobně.
Shrnutí V této kapitole jste se seznámili se základy vyhledávání a třídění dat. Uvědomili jste si, že vyhledávat lze jak v setříděných tak také nesetříděných datech. Ovšem rychlejší je hledání v již setříděných datech. Při hledání v nesetříděných datech musíte postupně projít všechny položky a zjišťovat, která položka vyhovuje zadaným požadavkům. Tento postup bývá zdlouhavý, protože postupujete od začátku až do konce. Naproti tomu hledání v setříděných datech je rychlejší a můžete použít řadu vyhledávacích algoritmů. Mezi základní vyhledávací algoritmy patří hledání metodou sekvenční, blokovou a binární (metoda půlení intervalů). Abyste mohli použít některou z uvedených vyhledávacích metod, musíte data nejdříve setřídit. K tomuto účelu slouží řada různých třídících algoritmů. Některé z těchto algoritmů více nebo méně zatěžují počítač, jiné jsou naopak jednodušší na pochopení. Mezi základní třídící algoritmy patří třídění metodou minima (maxima) a bublinkové třídění.
98
9. Třídění a vyhledávání
Kontrolní otázky 1. Jaký je rozdíl ve vyhledání v setříděných a nesetříděných datech? 2. Popište princip fungování vyhledávacích algoritmů. 3. Můžete v nesetříděných datech vyhledávat pomocí metody blokového vyhledávání nebo metody půlení intervalů? 4. Které třídící algoritmy znáte? 5. Popište postup třídění dat metodou minima a bublinkovým tříděním.
Pojmy k zapamatování nesetříděná data setřídaná data rychlost vyhledávání sekvenční vyhledávání blokové vyhledávání binární vyhledávání (půlení intervalů) bublinkové třídění (bubble sort) třídění metodou minima (maxima)
Korespondenční úkol Na vstupu uživatel zadává informace o pacientech – jméno, příjmení a věk. Napište program, který vypíše seznam pacientů setříděný podle věku od nejstaršího k nejmladšímu.
99
Závěr Uf, a jste v závěru. Dospěli-li jste až sem, máte můj obdiv. Prokousat se samostudiem začátky programování bez možnosti se hned zeptat učitele a dostat hned odpověď, je velmi obtížné. V opoře jsme pouze nahlédli do problematiky algoritmizace a programování. Ti z vás, kteří se ji budou chtít věnovat podrobněji, mohou použít nepřeberné množství informací v různých knihách, časopisech a na Internetu. To nejdůležitější, co jste si měli po prostudování a procvičení úkolů odnést, je trošku změněný pohled na řešení problémů. Od formulování složitějších podmínek až po uvědomění si, kolikrát se má určitý činnost vykonat, aby bylo dosaženo výsledku. A nezapomeňte, programovací jazyk (vlastně i počítač) je nástroj, nikoli cíl. Cílem je vyřešený problém. Doufám proto, že vám tento učební text ukázal, po jakých cestách se můžete vydat, abyste k vyřešenému problému došli. Autor
100
Seznam použité literatury DRÓZD, J., KRYL, R., Začínáme s programováním. 1.vyd.. Praha: Grada, 1992. 306 s. ISBN 80-85424-41-X HRUŠKA, T., Pascal pro začátečníky. 1.vyd.. Praha : Státní nakladatelství technické literatury, 1989. 366 s. ISBN 80-03-00345-8 TÖPFLER, P., TÖPFLEROVÁ, D., Sbírka úloh z programování. 1.vyd. Praha: Grada, 1992. 98 s. ISBN 80-85424-99-1 RUBEŠ, J., Nebojte se programovat. 1.vyd.. Bedihošť: Computer Media, c2001. 287 s. ISBN 80-902815-4-0
101
102
Vysvětlení grafických symbolů Průvodce studiem Příklad Pojmy k zapamatování Shrnutí Kontrolní otázky, K zamyšlení Upozornění Cvičení, úkol Poznámka Pro zájemce Řešení Korespondenční úkol Cíl
103