Programování I.
Mgr. Jarmila Halšková
Zlepšování podmínek pro využívání ICT ve výuce a rozvoj výuky angličtiny na SPŠei Ostrava OP VK CZ.1.07/1.1.07/03.0089
Ostrava 2011
Obor: Informační technologie Předmět: Programování Ročník: 2. Autor: Mgr. Jarmila Halšková
Doporučená literatura a další zdroje: Herout, P. Učebnice jazyka C, Kopp, České Budějovice, 1996, ISBN 80-9013421-1 Herout, P. Učebnice jazyka C - 2.díl, Kopp, České Budějovice, 1995, ISBN 8085828-50-2 Fikar, Z.,Frimlová, I., Kukal, J., Letoš, R. Programátorský babylón, Grada, Praha 1992, ISBN 80-85424-77-0 Schildt, H. Nauč se sám C. Třetí vydání, SoftPress, Praha 2001. Autorizovaný překlad z originálního anglického vydání„Teach Yourself C“.ISBN 80-86497-16-X Šaloun, P. Programování v jazyce C, [online]. 1996. Dostupné na www
Kračmar, S., Vogel, J. Programovací jazyk C, [online]. 1995. Dostupné na www:
© Mgr. Jarmila Halšková © Střední průmyslová škola elektrotechniky a informatiky, Ostrava, příspěvková organizace
OBSAH Úvod ............................................................................................................................... 9 1
Algoritmizace – základní pojmy.......................................................................... 10 1.1 1.2 1.3
2
Vlastnosti algoritmu ............................................................................................ 16 2.1 2.2 2.3 2.4 2.5 2.6
3
Historie programovacích jazyků .................................................................................33 Standardizace ...........................................................................................................34 Obecné charakteristiky jazyka C................................................................................34
Stavba programu a způsob jeho zpracování ..................................................... 37 6.1 6.2
7
Formulace problému..................................................................................................28 Analýza úlohy ............................................................................................................29 Vytvoření algoritmu úlohy ..........................................................................................29 Sestavení vývojového diagramu ................................................................................29 Sestavení programu ..................................................................................................29
Historie a charakteristika jazyka C ..................................................................... 33 5.1 5.2 5.3
6
Značky vývojového diagramu ....................................................................................20 Konstrukce vývojového diagramu ..............................................................................22
Etapy řešení algoritmické úlohy ......................................................................... 28 4.1 4.2 4.3 4.4 4.5
5
Elementárnost ...........................................................................................................17 Determinovanost .......................................................................................................17 Konečnost .................................................................................................................18 Rezultativnost ............................................................................................................18 Hromadnost ...............................................................................................................18 Efektivnost .................................................................................................................19
Grafické vyjádření algoritmu .............................................................................. 20 3.1 3.2
4
Problém .....................................................................................................................10 Algoritmus .................................................................................................................11 Možnost zápisu algoritmu ..........................................................................................12
Způsob zpracování programu ....................................................................................37 Stavba programu .......................................................................................................38
Elementy jazyka ................................................................................................... 43 7.1.Klíčová slova ...................................................................................................................43 7.2.Identifikátory....................................................................................................................44 7.4.Konstanty ........................................................................................................................45
8
Datové typy .......................................................................................................... 48 8.1 8.2 8.3 8.4 8.5 8.6
Rozdělení datových typů ...........................................................................................49 Celočíselné typy ........................................................................................................49 Reálné typy ...............................................................................................................51 Typ void .....................................................................................................................52 Logický datový typ .....................................................................................................53 Typová konverze .......................................................................................................53
9
Použití datových typů v programech ................................................................. 56
10 10.1 10.2 10.3
11 11.1
12 12.1 12.2 12.3
13 13.1 13.2 13.3 13.4 13.5 13.6 13.7 13.8
14 14.1
15 15.1 15.2
16 16.1 16.2 16.3 16.4 16.5
Proměnná ......................................................................................................... 59 Deklarace a definice proměnných ..............................................................................60 Statická proměnná.....................................................................................................61 Lokální a globální proměnné .....................................................................................62
Výraz, přiřazení a příkaz .................................................................................. 64 Vícenásobné přiřazení ...............................................................................................67
Operandy, operátory a jejich dělení podle počtu operandů ......................... 69 Unární operátory........................................................................................................70 Binární operátory .......................................................................................................73 Ternární operátor.......................................................................................................74
Dělení operátorů podle jejich funkčnosti ....................................................... 77 Aritmetické operátory .................................................................................................77 Logické operátory ......................................................................................................78 Relační operátory ......................................................................................................80 Přiřazovací operátory ................................................................................................81 Bitové operátory ........................................................................................................83 Operátory bitového posuvu ........................................................................................84 Přístupové operátory .................................................................................................85 Oddělovací operator ..................................................................................................85
Priorita a pořadí vyhodnocování .................................................................... 86 Postranní efekty.........................................................................................................88
Použití operátorů v programech ..................................................................... 91 Tvorba matematických výrazů ...................................................................................91 Matematické funkce...................................................................................................93
Vstup a výstup.................................................................................................. 99 Formátovaný vstup a výstup ......................................................................................99 Formátová specifikace .............................................................................................101 Používané řídící znaky ............................................................................................102 Vstup a výstup znaku ..............................................................................................104 Bloky .......................................................................................................................105
17
Založení projektu konzolové aplikace .......................................................... 108
18
Sekvence a řídící struktury ........................................................................... 114
18.1 18.2
19 19.1
20
Řídící struktury ........................................................................................................114 Sekvence - posloupnost ..........................................................................................114
Typy větvení, větvení úplné........................................................................... 121 Úplné větvení se sekvencí příkazů ..........................................................................128
Větvení - ternární operátor ............................................................................ 132
20.1
21 21.1
22 22.1
Generátor náhodných čísel......................................................................................135
Větvení - ošetření nežádoucích důsledků .................................................... 138 Ošetření nežádoucích důsledků ..............................................................................138
Větvení neúplné.............................................................................................. 149 Neúplné větvení se sekvencí příkazů ......................................................................153
23
Větvení vnořené ............................................................................................. 155
24
Větvení vícenásobné...................................................................................... 162
25
Větvení – procvičování .................................................................................. 168
26
Typy cyklů, cyklus s podmínkou na začátku ............................................... 173
26.1 26.2
Typy cyklů ...............................................................................................................173 Cyklus s podmínkou na začátku ..............................................................................174
27
Cyklus s podmínkou na konci....................................................................... 178
28
Cykly řízené podmínkou - procvičování ....................................................... 184
29
Cyklus s řídící proměnnou ............................................................................ 186
29.1
30 30.1 30.2 30.3
31 31.1 31.2
32 32.1 32.2 32.3 32.4 32.5
33 33.1 33.2 33.3
Řídící proměnná - parametr .....................................................................................187
Skoky, přerušení a ukončení cyklu ............................................................. 191 Break .......................................................................................................................191 Continue ..................................................................................................................193 Goto a návěští .........................................................................................................194
Cykly – vnořené a procvičování cyklů ......................................................... 196 Vnořené cykly ..........................................................................................................196 Procvičování cyklů ...................................................................................................199
Ladění programu ............................................................................................ 203 Činnost programu krok za krokem ...........................................................................205 Sledování proměnných ............................................................................................206 Změna hodnoty proměnné za běhu programu .........................................................207 Činnost programu krok za krokem ...........................................................................208 Sledování proměnných ............................................................................................208
Faktoriál .......................................................................................................... 209 Faktoriál řešený cyklem for ......................................................................................210 Faktoriál řešený cyklem while ..................................................................................211 Faktoriál řešený cyklem do - while ...........................................................................212
34
Sumy a řady .................................................................................................... 214
35
Opakování probrané látky ............................................................................. 218
Vysvětlivky k používaným symbolům
Obsah hodiny – popisuje náplň hodiny
Cíl hodiny – specifikace dovedností a znalostí, které si studující osvojí během hodiny
Klíčová slova – nové pojmy, specifické termíny či cizí slova, jejichž význam je v textu vysvětlen
Definice – definování a vysvětlení nového pojmu či jevu
Příklad – objasnění nebo konkretizování problematiky na příkladu ze života, z praxe, ze společenské reality apod.
Shrnutí – shrnutí probrané látky, shrnutí kapitoly
Kontrolní otázky a úkoly – prověřují, do jaké míry studující text a problematiku pochopil, zapamatoval si podstatné a důležité informace a zda je dokáže aplikovat při řešení problémů Otázky k zamyšlení - úkoly rozšiřující úroveň základních znalostí
Literatura – literatura a zdroje pro doplnění a rozšíření poznatků kapitoly
9
Úvod Studijní text, který máte před sebou, je adresován žákům 2. ročníků oboru Informační technologie a zájemcům o studium předmětu Programování. Cílem tohoto studijního textu je seznámit vás s problematikou tvorby algoritmů a základů programování a to aplikací na konkrétní, komerčně velmi rozšířený a využívaný programovací jazyk C. Studium tohoto modulu nepředpokládá žádné vstupní znalosti, ať už z všeobecného programování, algoritmizace nebo teoretické informatiky. Po absolvování modulu budete umět vytvářet programy a jednoduché aplikace v tomto jazyce. Získané znalosti využijete v návazných modulech Programování II a Programování III. Dovednosti a znalosti z jazyka C uplatníte v programovacích jazycích C++ a Java.
10
1 Algoritmizace – základní pojmy Obsah hodiny Seznámíme se s pojmem problém, algoritmus a program.
Cíl hodiny Po této hodině budete schopni: • • • •
pojmenovat problém nalézt postup řešení definovat pojem algoritmus vyjádřit algoritmus slovně a písemně
Klíčová slova Problém, algoritmus, postup řešení.
1.1 Problém Základem změn v našem životě jsou určité překážky, které se snažíme překonat. Právě překážky nás „ ženou“ dopředu. O takových překážkách hovoříme, že jsou problémem. Problém – stav, ve kterém je rozdíl mezi tím, co v daném čase máme ( známe), a tím co potřebujeme ( chceme). Pojem problém musíme brát subjektivně. To znamená, že pokud je něco pro někoho problémem, pro druhého to problém nemusí být. Našim subjektem při řešení problému bude počítač a pro ten je většina věcí problémem. Pro něj musíme najít řešení problému. Tuto činnost si můžeme rozdělit do dvou částí: •
nalezení postupu řešení,
•
vykonání postupu řešení.
Nalezení postupu řešení – je činnost, při které tvoříme sled událostí, které máme vykonat, abychom dospěli k požadovanému výsledku. Je to tvořivá činnost, a proto ji musí vykonávat člověk, neboť zatím neexistuje takové zařízení, které by mělo vlastní tvořivou mysl. Na každý problém může existovat mnoho různých řešení. Nejlepší je ten nejjednodušší.
11 Vykonání postupu řešení – je to činnost, při které realizujeme nalezený postup řešení. Na to již nepotřebujeme tvořivou činnost, a proto tím můžeme pověřit kohokoliv, kdo je schopen tuto činnost vykonat. Může to být člověk i stroj – v našem případě počítač. Snažte se počítači vysvětlit, co má dělat, stejně vás nebude poslouchat. Počítač vůbec netuší, co vykonává, ani co má být výsledkem jeho činnosti. On totiž není žádná myslící bytost, a proto nebudeme hovořit o postupu řešení, ale o algoritmu.
1.2 Algoritmus Tento pojem patří mezi základní pojmy informatiky a setkáváme se s množstvím jeho definic. Z mnoha vybírám: Algoritmus – postup, jehož realizací získáme ze zadaných vstupních údajů po konečném počtu činností, v konečném čase správný výsledek.
Důležitou součástí tvorby algoritmu je přizpůsobení algoritmu znalostem a schopnostem potenciálního uživatele. Algoritmus práce s počítačem bude jiný pro člověka, který k počítači usedá poprvé, než pro člověka, který už má určité zkušenosti.
Příklad Uveďme si nějaký algoritmus, se kterým jste se možná již setkali: 1. Vynes smetí 2. Napiš si domácí úkol 3. Ohřej si a sněz večeři, která je v lednici Přijdeme kolem 20.00
Tento vzkaz napsali rodiče své ratolesti. Sestavili postup, podle kterého má vykonávat dané činnosti.
12
1.3 Možnost zápisu algoritmu •
slovní vyjádření
•
matematické vyjádření
•
graficky vyjádření
•
počítačový program
Slovní vyjádření Používá se pro skupinu lidí, která nemá programátorské vzdělání - návody k obsluze, recepty, postup práce. Výhodou je, že se lze domluvit i s laikem. Nevýhodou je malá přehlednost a absence nástrojů k dodržení vlastností algoritmu.
Příklad Algoritmus přípravy polévky ze sáčku. Formulace problému: Uvař polévku ze sáčku. Analýza úlohy Vstupní údaje: polévka, voda, hrnec, lžíce, vařič Výstupní údaje: uvařená polévka Analýza: Polévku nesmíme převařit ani vyvařit Sestavení algoritmu Slovní popis: 1. Vyber požadovanou polévku. 2. Napusť do hrnce studenou vodu. 3. Rozmíchej polévku ve studené vodě lžící. 4. Zapni vařič. 5. Vař polévku 10 minut. 6. Vypni vařič. V algoritmech velmi často nastává situace, kdy se musíme na základě podmínky rozhodnout k vykonání určité činnosti, nebo některé činnosti musíme zopakovat. Buď přesně známe, kolikrát se má činnost opakovat, nebo opakování závisí na vzniku určité situace.
13
Příklad Algoritmus přechodu křižovatky, která je řízena semaforem. Formulace problému: Přejdi na druhou stranu ulice. Analýza úlohy Vstupní údaje: přechod, semafor Výstupní údaje: pozice na druhé straně ulice Analýza: Přes přechod se nechodí na červenou Sestavení algoritmu Slovní popis: 1. Dojdi až k semaforu. 2. Svítí na semaforu červená? •
ANO - čekej, vrať se na bod 2.
•
NE - pokračuj bodem 3.
3. Přejdi přes přechod.
Příklad Algoritmus zatloukání hřebíků. Formulace problému: Zatluč hřebík do desky. Analýza úlohy Vstupní údaje: kladivo, hřebík, deska Výstupní údaje: hřebík zatlučen do desky Analýza: Tlouct tak dlouho, dokud není hřebík zatlučen až po hlavičku Sestavení algoritmu Slovní popis: 1. Vezmi kladivo a hřebík. 2. Přilož hřebík k desce. 3. Uhoď kladivem na hlavičku. 4. Je hřebík zatlučen? •
ANO - Pokračuj bodem 5.
•
NE - Vrať se na bod 3.
5. Ukonči činnost a odlož kladivo.
14 Matematické vyjádření Používá se tam, kde je možné daný problém popsat matematickými vztahy. Výhodou je, že jednoznačný. Nevýhodou může být, že při neošetření vstupních podmínek nemusí být věcně správný
Grafické vyjádření Vývojové diagramy a strukturogramy. Jedna z nejdokonalejších forem zápisu algoritmu. Jsou to symbolické, algoritmické jazyky, které se používají pro názorné zobrazení algoritmu. Používají se jako komunikační prostředek, při týmové spolupráci analytiků s programátory. Jsou přehledné a mají nástroje k dodržení vlastností algoritmu. Výborně se hodí k dokumentačním účelům, kde jsou přehlednější než výpis programu. Nevýhodou může být, že jim laik nemusí rozumět. Jedná se o značky ( ovály, obdélníky, kosočtverce…), jejichž význam je stručně popsán v kapitole Vývojové diagramy a strukturogramy. Počítačovým programem Je to algoritmus zapsaný v jazyce, kterému počítač rozumí a umí z něho vytvořit strojový kód. Tomuto vyjádření rozumí pouze programátor, který umí konkrétní programovací jazyk. Program není napsán přímo v „jazyce počítače“, tím je strojový kód. Ale je napsaný v jazyce, se kterým si počítač poradí, pokud je vybaven příslušným překladačem. Překladač je program, který umí přeložit program napsaný v programovacím jazyce do strojového kódu. V dnešní době bývá překladač součástí integrovaného vývojového programátorského prostředí.
Důležitou součástí tvorby algoritmu je přizpůsobení algoritmu znalostem a schopnostem potenciálního uživatele. Algoritmus práce s počítačem bude jiný pro člověka, který k počítači usedá poprvé, než pro člověka, který už má určité zkušenosti.
Kontrolní otázky a úkoly Sestavte algoritmus: 1) Nákupu kávy ve školním automatu. 2) Přípravy čaje. 3) Ranního stávání (od zvonění budíku až k odchodu z domova).
15
Literatura Samotné slovo algoritmus pochází ze jména perského matematika Abú Abd Alláh Muhammada ibn Músá al-Chwárezmího, který kolem roku 825 napsal knihu, v níž položil základy algebry. V latinském překladu začínala tato kniha větou:„ Algorithmi dici…“, což znamená: „ Al-Chvarezmi hovoří…“
Shrnutí kapitoly Algoritmus je postup řešení, které vede k dosažení stanoveného cíle. Algoritmy nejčastěji znázorňujeme v grafické podobě ve formě vývojových diagramů, protože tím zajistíme srozumitelnost a názornost řešení pro potenciální uživatele. Při kreslení vývojových diagramů používáme předem domluvené značky. Do algoritmu zařazujeme posloupnosti příkazů, rozhodovací bloky a bloky pro cyklické opakování některých činností – ty jsou obsahem další kapitoly.
16
2 Vlastnosti algoritmu Obsah hodiny Seznámíme se s vlastnostmi algoritmu
Cíl hodiny Po této hodině budete schopni: • •
pojmenovat jednotlivé vlastnosti algoritmu popsat vlastnosti algoritmu
Klíčová slova Elementárnost, determinovanost, rezultativnost, hromadnost, konečnost, efektivnost
Algoritmus můžeme definovat jako instrukci či přesný návod, kterým lze vyřešit daný typ úlohy. Je ale každý postup algoritmem? Každý postup opravdu nelze považovat za algoritmus. Jaký je tedy rozdíl mezi algoritmem a běžným souborem pokynů nezbytných k provedení nějakého úkolu? Algoritmem se rozumí pouze takové postupy, které splňují přesně stanovené požadavky tzv. vlastnosti algoritmu. Vlastnosti správného algoritmu •
Elementárnost - algoritmus se skládá z konečného počtu jednoduchých kroků, které jsou pro realizátora srozumitelné.
•
Determinovanost – v každé fázi zpracování musí být určen další postu.
•
Konečnost – činnost algoritmu skončí v reálném čase.
•
Rezultativnost – algoritmus dává pro stejné vstupní údaje vždy stejné výsledky.
•
Hromadnost – algoritmus musí být použitelný pro všechny úlohy stejného typu.
•
Efektivnost – algoritmus se uskuteční v co nejkratším čase a při nejmenším počtu činnosti.
17 Věnujme se nyní podrobnějšímu popisu jednotlivých vlastností s uvedením příkladů ze života.
2.1 Elementárnost Ve slovníku cizích slov bychom pod pojmem element našli, že je to základní, prvopočáteční článek. Tedy něco, co realizátor algoritmu – postupu, umí zpracovat. Opět si musíme uvědomit, pro koho je daný algoritmus určený. Pokud se jedná o počítač, musí být algoritmus napsaný abecedou jazyka, kterému bude rozumět. Pokud se jedná o člověka, je nutné si ujasnit, komu je algoritmus určený. To co může být elementární pro jednoho, nemusí být pro druhého.
Příklad Děti ve třetí třídě na ZŠ dostali od paní učitelky dva následující příklady: V prvním příkladu měli vypočítat kolik je 23. V druhém příkladu měli vypočítat kolik je 2 x 2 x 2. S prvým příkladem si neuměli poradit, ale druhý příklad vypočítali bez problémů. Proč ? Protože počítat s mocninami se ještě neučili. Násobit čísla už umí, je to pro ně elementární.
2.2 Determinovanost Ve slovníku cizích slov bychom pod pojmem determinovaný našli, že to znamená vymezený, určený, stanovený, předurčený. Jednoduše řečeno přesně určený pořadím činností. V každé situaci musí být zřejmé, co a jak se má provést a jak má provádění algoritmu pokračovat. Proč je tato vlastnost tak důležitá ? Nejdříve uvedu příklad a potom vysvětlím.
Příklad Našim úkolem je sestavit algoritmus pro telefonování z veřejného mincového telefonního automatu. Předpokládejme, že chceme místní volání. Návod by mohl vypadat následovně: 1. Zvedni telefonní sluchátko. 2. Vhoď minimální hodnotu pro zvolené telefonní spojení. 3. Vyťukej správně volané číslo. 4. Pokud uslyšíš tón vyzvánění, čekej. 5. Po navázání spojení hovoř. 6. Po ukončení hovoru odlož sluchátko opět do vidlice.
18 Proč je tedy důležitá determinovanost? Člověk už na základě intuice ví, jak má pokračovat. Teda, že nemůže vhodit minci pokud ještě nemá zvednuté sluchátko, že minimální cena hovoru je např. 5 Kč apod. Avšak nemyslící zařízení to neví. Proto je přesný postup vykonávání činností velmi důležitý.
Kontrolní otázky a úkoly Sestavte návod na obsluhu: 1) parkovacího automatu 2) jízdenkového automatu
2.3 Konečnost Člověk jako myslící tvor má výhodu proti strojům. Pokud vykonává určitou činnost, která nevede k žádnému cíli, jednoduše ji ukončí. Opraví postup a může vylepšenou činnost opakovat. To však stroj nedokáže, a proto musíme vytvářet takové algoritmy, které určitě končí. Existuje i jiný druh nekonečnosti. Některé postupy se zdají být konečné a algoritmicky správné, mohou však trvat tak dlouho, že jsou nerealizovatelné. Takové postupy se dají sestavit například na zjištění počtu zrnek soli v zakoupeném sáčku. Aby bylo řešení problému konečné je výhodné zjednodušit jej a řešit ho přibližně. V takových případech je třeba zadat velikost chyby, kterou jsme ochotni tolerovat.
2.4 Rezultativnost Tento pojem je odvozený ze slova result – výsledek. Měli bychom přemýšlet nad tím, že algoritmus může dávat různé výsledky při stejných vstupních datech. Vysvětleme si tuto skutečnost na příkladu.
Příklad Tři sourozenci dostali od rodičů úkol, koupit si něco k večeři. Každý z nich přinesl jiný nákup. Proč ? Protože každý z nich má jiné chutě. Proto nezapomínejte! „ Když dva dělají totéž, není to totéž.“
2.5 Hromadnost Algoritmus slouží k řešení celé třídy ( skupiny) navzájem si podobných úloh. Úlohy jsou si podobné, ale liší se vstupními daty. Abychom tuto vlastnost dodrželi, musí být algoritmus napsaný všeobecně ( univerzálně).
19 Z matematiky víme, že zevšeobecnit zápis umožňují proměnné. Ukažme si to na následujícím příkladě.
Příklad Již na základní škole nás učili výpočet obsahu obdélníka S = a.b, kde a, b jsou strany obdélníka. V žádném případě jsme se neučili S = 3.5. Na první pohled je patrné, že první může být příkazem algoritmu, avšak druhý ne. Zajímavé je, že algoritmus musí být napsaný všeobecně, ale jeho realizace nabývá konkrétních hodnot v závislosti na vstupních údajích bývá s konkrétními hodnotami.
2.6 Efektivnost Ve slovníku cizích slov bychom pod pojmem efektivnost našli, že je to nějaký přínos, zisk z činnosti vzhledem k vynaloženému úsilí. Tato vlastnost je důležitá především tehdy, když zpracováváme velké množství údajů. Tehdy hledáme postup, který bude trvat nejkratší dobu a bude při něm vykonávat co nejméně instrukcí (činností).
Příklad Žáci byli s paní učitelkou na Velké Pardubické. V cíli dostihu měli spočítat kolik koní doběhlo. Pepíčkovi to trvalo déle než ostatním. Tak se paní učitelka zeptala, jakým způsobem to počítal. Pepíček odpověděl: „Spočítal jsem všechna kopyta a vydělil čtyřmi.“ Co můžeme usoudit z Pepíčkovy odpovědi ? Podle mého názoru, Pepíček zvolil nejméně efektivní metodu. Více efektivnější by bylo, kdyby spočítal koňské hlavy.
Otázky k zamyšlení Pokud danou úlohu řeší více algoritmů, podle jakých kriterií vybíráme ten nejefektivnější ?
20
3 Grafické vyjádření algoritmu Obsah hodiny Seznámíme se s možnostmi grafického vyjádření algoritmu pomicí vývojových diagramů.
Cíl hodiny Po této hodině budete schopni: • • •
vyjádřit algoritmus graficky použít předdefinované prvky pro sestavení vývojových diagramů zakreslit jednoduchý problém ve vývojovém diagramu
Klíčová slova Vývojový diagram, značky vývojového diagramu
Vývojový diagram je symbolický algoritmický jazyk, který se používá pro názorné zobrazení algoritmu. Ke kreslení vývojových diagramů používáme standardní grafické symboly.
3.1 Značky vývojového diagramu Vývojové diagramy mohou obsahovat mnoho různých grafických symbolů a značek. Z mnoha vybíráme ty nejpoužívanější: Začátek - start nebo konec - cíl programu
Vstup. Znázorňuje načtení dat potřebných pro činnost programu.Uvnitř značky je Čti:
Výstup. Znázorňuje zobrazení výstupu na zobrazovacím zařízení. Uvnitř značky je Tisk:
21 Zpracování. Znázorňuje nějakou činnost programu. V bloku může být zapsána jedna nebo více instrukcí.
Rozhodovací blok. Slouží k rozvětvení programu na základě podmínky, která je uvedena uvnitř.
Značka podprogramu (funkce). Znázorňuje samostatnou část programu, která může obsahovat větší množství kroků.
Cyklus. Cyklus o známém počtu opakování. Podrobnější vysvětlení naleznete v kapitole cykly.
Spojka. Umožňuje spojit dvě části vývojového diagramu, které nebylo možné nakreslit souvisle. Spojky na konci přerušení a na začátku pokračování musí být označeny stejnými čísly.
Vývojové diagramy se skládají z jednotlivých symbolů, jež jsou mezi sebou spojeny orientovanými čárami, které jsou označeny šipkou vyjadřující směr postupu algoritmu. Obecně vžitý postup psaní značek je od shora dolů a zleva doprava. V některých případech tento postup nemůže být dodržen (například v cyklech se čára vrací o několik kroků zpět). V těchto případech je šipka nezbytně nutná.
22
3.2 Konstrukce vývojového diagramu V dnešním světě objektového programování se často nesetkáváme se strukturovaným programováním. To však nijak neubírá vývojovým diagramům na užitečnosti. Zejména pro začátečníky a nováčky v oboru algoritmizace jsou vývojové diagramy velmi komfortními pomocníky, s nimiž je pochopení struktury programu daleko jednodušší. Největší výhodou vývojových diagramů je jejich vizualizace algoritmu. Jak je známo, člověk lépe a efektivněji pracuje s obrázkovými informacemi než s pouhou množinou alfanumerických znaků. Nyní se seznámíme s již hotovými vývojovými diagramy, které „oblékají algoritmus do grafického kabátku“. První vývojový diagram zobrazuje algoritmus známé písničky „ Pes jitrničku sežral“.
23
Kontrolní otázky a úkoly Proveďte analýzu ukázkového vývojového diagramu. a) sledujte, z jakých symbolů se skládá. b) všimněte si podmínky v závěru vývojového diagramu, která umožňuje ukončit opakování písničky. c) zaměňte textová návěští „ ANO“ a „NE“ u spojnic rozhodovacího bloku identickými matematickými symboly + a - .
Příklad Sestavte algoritmus a následně vývojový diagram, podle kterého se dá zjistit, zda je tělesná hmotnost osoby adekvátní ve vztahu k její výšce. Vypočtěte si svůj vlastní BMI. Řešení: Vědci odvodili pro index BMI ( Body Mass Index) vzoreček: index BMI = m / v 2 Kde m je hmotnost osoby v kilogramech a v představuje výšku osoby v metrech. Algoritmus pro výpočet indexu BMI může vypadat takto: 1. Zjistíme hmotnost a výšku zkoumané osoby 2. Zjištěné údaje doplníme do vzorce, jehož výpočtem získáme výsledek 3. Pokud hodnota výsledku bude z intervalu <19;25>, můžeme prohlásit, že hmotnost osoby se pohybuje v normálních mezích ( není ani hubená. Ani obtloustlá). 4. Pokud je hodnota BMI menší než 19, pak je hmotnost ve vztahu k výšce nízká. 5. Naopak, je-li vypočtená hodnota větší než 25, hmotnost osoby vykazuje nadváhu. Výše uvedený vzorec můžete aplikovat na osobu, která : měří 1,68 m a váží 55 kg její Index BMI získáme po dosazení do vzorce : 55 / 1,68 2 = 19,49 Hodnota Indexu BMI u této osoby je v normálu.
24
Jste s výsledkem svého BMI spokojen/ a ?
25
Příklad Častou operací, kterou využijete jako součást dalších algoritmů, je záměna obsahu dvou proměnných. Popište pomocí vývojového diagramu algoritmus záměny obsahu dvou proměnných. Formulace problému: Výměna dvou proměnných. Analýza úlohy: Vstupní údaje: dvě proměnné A = 3, B = 5 Výstupní údaje: dvě proměnné A = 5, B =3 Řešení: Záměna dvou proměnných pomocí třetí proměnné - POM: Představte si, že máte sklenici označenou písmenem A, kde je mléko, a sklenici B, ve které je káva. Chcete-li dostat do sklenice A kávu a do sklenice B mléko, pak musíte použít další pomocnou nádobu, která bude zpočátku prázdná a bude označena POM. 1. krok: Vezměte sklenici A a její obsah ( mléko) nalijete do prázdné sklenice POM. Nyní máte mléko v pomocné sklenici POM a sklenici A jste vyprázdnili. Vztah bude mít formu zápisu: POM = A
(Obsah A si schovám do pomocné proměnné POM)
2. krok: Vezměte sklenici B a její obsah ( kávu) nalijete do vyprázdněné sklenice A. Nyní je káva ve sklenici A a sklenice B je volná. Vztah bude mít formu zápisu: A=B
(Do A přesunu to, co je v B)
3. krok: Sklenice B je prázdná. Vezměte sklenici POM a její obsah (mléko) nalijete do vyprázdněné sklenice B. Nyní je mléko ve sklenici B a sklenice POM je opět prázdná, tak jako byla na začátku. Vztah bude mít formu zápisu: B = POM
( Do B přesunu to, co mám schováno v POM)
26 Vývojový diagram výměny, který přehledně zobrazuje výše uvedený postup.
27
Otázky k zamyšlení Proveďte záměnu obsahu dvou proměnných bez použití pomocné proměnné. (Malá nápověda – použijte sčítání a odčítání.)
Shrnutí kapitoly Vývojový diagram je symbolický algoritmický jazyk, který se používá pro názorné zobrazení algoritmu. K jeho kreslení používáme standardní grafické symboly. Jednotlivé symboly spojujeme čárami a spojkami. Ve vývojovém diagramu dodržujeme směr shora dolů, proto není nutné svislé čáry kreslit se šipkou. Čáru zakončujeme šipkou v případě, kdy se směr mění, např. při naznačení cyklu. Spojky použijeme v případě, že se vývojový diagram nevejde na jednu stránku a pokračuje na straně další. Pak je vhodné pomocí spojek označit návaznosti.
28
4 Etapy řešení algoritmické úlohy Obsah hodiny Seznámíme se s jednotlivými etapami řešení algoritmické úlohy.
Cíl hodiny Po této hodině budete schopni: ● ● ●
formulovat problém analyzovat úlohu sestavit a vytvořit vývojový diagram jednoduchých příkladů
Klíčová slova Etapy řešení problému, formulace problému, analýza úlohy, vytvoření algoritmu, sestavení vývojového diagramu, sestavení programu.
Algoritmizace je postup při tvorbě programu pro počítač, kterým lze prostřednictvím algoritmu řešit nějaký problém. Algoritmizaci lze rozdělit do několika etap: •
formulace problému,
•
analýza úlohy,
•
vytvoření algoritmu,
•
sestavení vývojového diagramu.
Po zvládnutí programovacího jazyka v dalších kapitolách, pak můžeme přidat další dvě etapy a to: •
sestavení programu a jeho následné odladění.
4.1 Formulace problému V této etapě je třeba přesně formulovat požadavky, určit výchozí hodnoty, vytýčit požadované výsledky, jejich formu a přesnost řešení.
29
4.2 Analýza úlohy Při analýze úlohy si ověříme, zda je úloha řešitelná a uděláme si první představu o jejím řešení. Dále zjistíme, zda výchozí hodnoty jsou k řešení postačující a zda má úloha více řešení. Podle charakteru úlohy vybereme nejvhodnější řešení.
4.3 Vytvoření algoritmu úlohy Sestavíme jednoznačný sled jednotlivých operací, které je třeba provést, aby byla úloha správně vyřešena. Algoritmus přesně popisuje postup zpracování daného úkolu, nedává však odpověď na daný problém, ale pouze postup, jak ji získat.
4.4 Sestavení vývojového diagramu Zakreslíme algoritmus v přehledné a srozumitelné podobě, tedy ve formě vývojových diagramů. Ve vývojových diagramech již budeme používat zápis v souladu s programovacím jazykem, který v další etapě zajistí zpracování algoritmu ve formě programu. My budeme používat programovací jazyk C.
4.5 Sestavení programu Na základě algoritmu řešené úlohy sestavíme program (zdrojový text) v konkrétním programovacím jazyce. Ze zdrojového textu se pomocí překladače do strojového kódu vytvoří spustitelný program. Dá se tedy říci, že dobře provedená analýza úlohy a algoritmizace daného problému je základním předpokladem sestavení programu pro počítač.
Příklad Sestavte pomocí vývojového diagramu algoritmus výpočtu obvodu a obsahu čtverce. Formulace problému: Výpočet obvodu a obsahu čtverce Analýza úlohy a řešení: Použijeme známé vzorce pro výpočet : O = 4. a
S=a.a
Sestavíme algoritmus řešení ve formě vývojového diagramu.
30
V bloku může být zapsána jedna nebo více instrukcí.
Příklad Sestavte vývojový diagram dělení dvou čísel. Jsou dána čísla A a B, o nichž není známo nic bližšího. Sestavte vývojový diagram pro výpočet jejich podílu: C = A / B. Formulace problému: Podíl dvou čísel. Analýza úlohy a řešení: Mohou nastat dvě možnosti:
31
•
B !=0, pak můžeme čísla bez obav vydělit
•
B = 0, pak čísla dělit nemůžeme a zobrazíme upozornění
Pokud bychom hodnotu jmenovatele neošetřili, program zhotovený podle takto nesprávného algoritmu by právě při B = 0 zhavaroval.
32
Shrnutí kapitoly Dá se tedy říci, že dobře provedená analýza úlohy a algoritmizace daného problému je základním předpokladem sestavení vývojového diagramu a po zvládnutí programovacího jazyka i programu pro počítač. Při analýze úlohy si ověříme, zda je úloha řešitelná a uděláme si první představu o jejím řešení. Dále zjistíme, zda výchozí hodnoty jsou k řešení postačující a zda má úloha více řešení. Podle charakteru úlohy vybereme nejvhodnější řešení. Vytvořením algoritmu sestavíme jednoznačný sled jednotlivých operací, které je třeba provést, aby byla úloha správně vyřešena. Na základě algoritmu řešené úlohy sestavíme vývojový diagram, v němž budeme používat zápis v konkrétním programovacím jazyce.
Kontrolní otázky a úkoly Proveďte analýzu, sestavte postup řešení a zakreslete vývojový diagram následujících příkladů: 1) Je dán plánovaný počet výrobků a počet výrobků, které podnik opravdu vyrobil. Na základě těchto dvou hodnot určete, na kolik procent podnik splnil svůj plán výroby. 2) Na základě zadané výše vkladu ( v Kč) a roční úrokové míry (v procentech) spočítejte, jaký bude zůstatek na účtu na konci roku. 3) Je dán poloměr koule. Spočítejte její objem a povrch podle známých 4 matematických vzorců. V = πr 3 , S = 4πr 2 3 4) Spočítejte výšku rotačního kužele, je-li zadán jeho objem a poloměr podstavy. 5) Je dán poloměr podstavy a výška nádoby tvaru válce (v centimetrech). Vypočítejte objem vody (v litrech), která se vejde do nádoby. 6) Jsou zadány hodnoty dvou odporů v ohmech. Určete hodnotu celkového odporu při jejich sériovém a paralelním zapojení. 7) Nádrž má čtvercové dno o straně velikosti A. Přitéká do mí voda rychlostí N litrů za sekundu. Na základě vstupních údajů A (v metrech) a N (litry za sekundu) spočítejte, jak dlouho musí voda přitékat, aby hladina stoupla o dva metry.
33
5 Historie a charakteristika jazyka C Obsah hodiny Seznámíme se základními informacemi o historii, vývoji a stručnou charakteristikou programovacího jazyka C.
Cíl hodiny Po této hodině budete schopni: ● ● ● ●
orientovat se v historii jazyka popsat etapy vývoje jazyka vyjmenovat předchůdce i následníky programovacího jazyka C charakterizovat základní vlastnosti programovacího jazyka C
Klíčová slova Fortran, Algol, jazyk B, jazyk C, typovost jazyka, case senzitivnost.
5.1 Historie programovacích jazyků Jazyk C navazoval na jazyk FORTRAN (FORmula TRANslation – jazyk pro vědeckotechnické výpočty), který v roce 1957 vytvořila firma IBM. Dalším jeho významným předchůdcem byl ALGOL (r.1960, ALGOrithmic Language – jazyk pro zápis algoritmů. Stal se základem pro návrh dalších jazyků – SIMULA 67 (první jazyk s prvky objektově orientovaného programování), ALGOL 68, CPL (Combined Programing Language) a z něho navržený BCPL (Basic CPL). V roce 1970 na Cambridgi odvodil Ken Thomson z jazyka BCPL jazyk “B” pro OS UNIX. V roce1972 vytvořili Brian W. Kerninghan a Dennis M. Ritchie u firmy AT&T nový jazyk, který úzce navazoval na jazyk „B“ (jazyk C se od jazyka B liší především existencí datových typů). Jazyk „C“ byl navržen pro lepší práci pod OS UNIX. Původní verze B.W. Kerninghana a D.M. Ritchieho se někdy značí zkratkou K&R nebo „klasické C“. K popularitě jazyka „C“ přispěla jeho možnost snadné a elegantní práce s ukazateli (adresami v paměti). Na jazyk „C“ úzce navazuje jeho rozšíření tj. jazyk „C++“, který navrhl Bjarne Stroustrup z Bellových laboratoří AT&T. Ten pro svou práci na
34 simulaci modelu pro distribuované systémy zjistil, že se mu velmi dobře hodí objektový přístup. Nejprve použil jazyk SIMULA, ale ten se příliš neosvědčil, a proto se zaměřil na návrh nového jazyka, který by nejen podporoval objektový přístup, ale byl i dostatečně rychlý. Jako základ použil existující jazyk „C“, nový jazyk dostal nejprve název „C with Classes“ (C s třídami). Později se prosadil název C++ („následník C“).
5.2 Standardizace Jazyk C se stal, po krátké době, velmi populární. Začaly vznikat překladače nového jazyka pro různé hardware. To s sebou však neslo problémy. Jazyk C nebyl nijak standardizován a mnoho překladačů si při jeho implementaci přidalo další různé specifické vlastnosti. Tím ale vznikaly potíže s přenositelností kódu, jednou z velkých předností „ Céčka“. V roce 1978 D. M. Ritchie a B. W. Kerninghan vydali první vydání knihy „The C Programming Language“. Tato kniha, mezi programátory známá jako „K&R C”. Jazyk C byl kodifikován normou ANSI Americký národní úřad pro normalizaci) - dostal označení ANSI C. Tato norma definuje jazyka C jako moderní vyšší programovací jazyk všeobecného použití. Shodný standard definuje ISO. Proto se někdy uvádí spojení jako norma ANSI/ISO norma. ANSI jazyk je bezpečnější, navíc umožňuje převzetí zdrojových kódů vytvořených ve stylu K&R. Standardizační komise přidala několik vlastností jako funkční prototypy a schopnější processor. ANSI C je podporováno všemi rozšířenými překladači. Většina kódů psaného v současné době v C je založena na ANSI C („ American National Standard for Information systéme – Programming language C“). Norma C99 vznikla v roce 1999. Následně byla přijata jako ANSI standard. Přináší několik nových vlastností jako inline funkce a deklarace proměnných kdekoliv.
5.3 Obecné charakteristiky jazyka C Jazyk C je velmi rozšířený univerzální programovací jazyk, který není vázán k určitému OS nebo určitému počítači. Jsou v něm napsány OS, ovladače, i běžné aplikace. Je to obecně použitelný programovací jazyk – nespecializuje se jen na jednu oblast používání. Má velmi úsporné vyjadřování a je důsledně strukturovaný. Umožňuje definovat funkce a proměnné, vykonávat na nich jednoduché operace, pracovat s pamětí a řídit tok programu. Jazyk C nepodporuje práci se složitějšími datovými typy, jako jsou textové řetězce nebo pokročilejší správa paměti. Dokonce nepodporuje na své úrovni vstupy či výstupy nebo práci se soubory. To však neznamená, že nemůžeme
35 se všemi těmito prvky běžných programovacích jazyků pracovat. Můžeme, avšak musíme používat funkce, které nám všechny tyto vysokoúrovňové vlastnosti poskytují. Proto je součástí každé implementace jazyka C velké množství funkcí, které jsou umístěny do tzv. knihoven funkcí, nebo jednoduše do knihoven. Tento návrh pomáhá oddělit vlastnosti jazyka od vlastností spojených s konkrétním procesorem či architekturou. Velkou předností je, že uživateli poskytuje možnosti jeho rozšiřování vytvářením vlastních knihoven. Mezi jeho další nepřehlédnutelnou vlastnost patří jeho typovost. Znamená to, že všem proměnným je na počátku určen typ, nebo-li rozsah hodnot, které mohou uchovávat a tento typ už později nelze měnit. Při každé operaci se také kontroluje, zda je vykonávána na proměnných odpovídajících typů. Podobná striktní pravidla jsou aplikována i na parametry a návratové hodnoty funkcí a na jejich použití. Důsledně rozlišuje malé a velké písmena, je tedy „case senzitivní“. Proto Muj, muj a MUJ jsou jednoznačně různé identifikátory. Jazyk C má ještě mnoho dalších charakteristických rysů, které si postupně představíme. Neodpustím si však ještě zmínit jeden z často vyvyšovaných a jindy zase proklínaných rysů. Je jim silná podpora práce s ukazateli. Jazyk C je důležitý i z jiného důvodu. Je bránou k dalším celosvětovým profesionálním programovacím jazykům: C++, C#, Java. Jazyk C je tak základem veškerého moderního programování a znalost C je základem pro úspěšné vytvoření vysoce výkonného a kvalitního softwaru. Jednoduše řečeno, být dnes profesionálním programátorem znamená, že ovládáte C.
36
Shrnutí kapitoly Programovací jazyk C patří dnes mezi velmi populární jazyk, zvlášť mezi profesionály. Za autory jazyka jsou považování Dennis Ritchie a Ken Thompson, kteří jej sestavili na počátku sedmdesátých let. Byl vytvořen jazyk s bohatými datovými typy, přičemž byla zachována jednoduchost a přímý přístup k hardware. Programy vytvořené pomocí jazyka C mají poměrně krátkou dobu provádění, nízké nároky na paměť a dají se lehce přenášet na jiné počítače( portabilita). Neobsahuje funkce pro provádění vstupu a výstupu, alokaci paměti, práci s obrazovkou a řízení procesů. Tyto funkce jsou v systémových knihovnách. Popis jazyka je realizován podle normy ANSI C.
Kontrolní otázky a úkoly 1) Ve které roce byla vydána kniha „The C Programming Language“.? 2) Ve kterých letech vznikl jazyk C a jaký jeho standard je nejvíce používaný? 3) Jaké jsou výhody a nevýhody programovacího jazyka C ?
37
6 Stavba programu a způsob jeho zpracování Obsah hodiny Popíšeme hlavní části programu v jazyce C. Seznámíme se s průběhem zpracování programu od zapsaného kódu v editoru po spustitelný exe soubor. Jednotlivé části zpracování podrobně popíšeme. Sestavíme jednoduchý program, v němž vysvětlíme jednotlivé části zdrojového kódu.
Cíl hodiny Po této hodině budete schopni: ● ● ● ● ● ●
rozlišit a popsat jednotlivé fáze zpracování programu vysvětlit účel jednotlivých části zpracování programu popsat hlavní části programu zapsat hlavní funkci nadeklarovat proměnné zapsat komentář
Klíčová slova Editor, preprocesor, compiler, linker, debugger, stavba programu, hlavička, globální a lokální deklarace, hlavní funkce, komentář, case sensitivní.
6.1 Způsob zpracování programu
Zpracování programu probíhá v několika fázích. Nejprve je potřeba v editoru napsat zdrojový soubor, který má většinou příponu c. Dále přichází
38 na řadu preprocesor, který bývá součástí překladače a který dále zpracovává zdrojový text. Například vkládá hlavičkové soubory, rozvíjí makra, atd. V další fázi compiler (překladač, kompilátor) provádí překlad upraveného zdrojového textu do relativního kódu (někdy kódu relativních adres) a vytvoří soubor s příponou obj. V této fázi nejsou ještě známy adresy proměnných a funkcí. Následuje spojování (sestavování) programu pomoci linkeru, který zajišťuje nahrazení relativních adres adresami absolutními a provede odkazy na příslušné knihovní funkce. Výsledkem této činnosti je již spustitelný soubor s příponou exe (případně com). Debugger („odvšivovač“) je ladící program, který běží zároveň se spuštěným programem a hledá chyby, které nastanou při běhu programu. Je také určený pro krokování programu a hledání chyb. Umožňuje sledovat běh programu řádek po řádku a sledovat při tom hodnoty proměnných, registrů nebo dokonce vybraných míst v paměti. Během kompilace programu je potřeba nejprve soubor uložit. Některá vývojová prostředí totiž obsahují kompilátory jazyka C i C++ (což jsou do značné míry rozdílné programovací jazyky). Nástroje většinou implicitně připojují ke zdrojovému souboru koncovku cpp a spouští kompilátor C++. Nehledě k tomu, že spouštět neuložený program, je hazardování s textem, který programátor v potu tváře vytvořil! Po napsání a uložení zdrojového souboru se nesnažte program okamžitě spustit. Ale nejprve soubor překompilujte a zkontrolujte si errors i warnings. Warnings (upozornění) nemusí ještě stoprocentně znamenat chybu, ale upozorňují na podezřelou nebo neobvyklou konstrukci. Pozor! Nikdy nekompilujte a nespouštějte neuložený zdrojový soubor. Mohli by jste přijít o svou práci.
6.2 Stavba programu Pojďme se podívat, z jakých částí je složen zdrojový kód programu. V úvodu programu se pro lepší orientaci tvůrce uvádí základní charakteristika programu: jméno souboru, stručný popis programu a jeho verze, jméno autora a datum vytvoření programu. Na dalším řádku se nachází direktiva preprocesoru #include, která určuje hlavičkový soubor stdio.h, jenž je důležitý pro správné provádění vstupně výstupních datových operací. Hlavičkové soubory obsahují definice konstant
39 a deklarace funkcí. Snadno je poznáte podle přípony *.h. Direktiva #include říká preprocesoru, aby provedl tyto operace. •
Našel a otevřel hlavičkový soubor stdio.h
•
Vybral do bloku veškerý zdrojový kód, jenž je v uvedeném hlavičkovém souboru uložen, zkopíroval jej a umístil do zdrojového souboru program.c přesně na ten řádek na němž se nachází direktiva #include.
Deklarace proměnných se v jazyce C provádí následujícím způsobem: int a; float x, y1, soucet; Deklarace proměnných může být spojená s její inicializací na počáteční hodnotu: int a = 5, b = 21; I ten nejjednodušší program v jazyce C musí mít hlavní funkci main( ). Mějte na paměti, že název funkce je zapsán malými písmeny. Program touto funkcí zavolá operační systém pokaždé, když dojde ke spuštění programu. Tělo hlavní funkce je ohraničeno levou a pravou složenou závorkou. Složené závorky nám podávají informaci o tom, kde začíná a kde končí tělo hlavní funkce main. V těle se nacházejí příkazy, které se budou provádět po každém spuštění programu a budeme se jim blíže věnovat v následujících kapitolách. Poslední příkaz vrací nulu, která působí jako návratová hodnota funkce main( ). Kam je tato hodnota posílána? Jejím přijímatelem je operační systém, který dokáže určit, zda program skončil normálně, nebo byl jeho běh nečekaným způsobem přerušen.
40 // Hlavička /* Zdrojovy text, v C v.1.0
jméno souboru a verze
* Stavba programu v jazyce C
stručný popis programu
* Albert Znaly 20.10. 2020
autor a datum vytvoření
*/ // Příklady preprocesoru #include <stdio.h>
//vloženi hlavičkového souboru
#define CISLO 13
// symbolická konstanta
// Globální deklarace – globální proměnné jsou automaticky nulovány int soucet ;
// deklarace celočíselné proměnné
int x = 50 ;
// deklarace s inicializací
// Hlavní program – vždy začíná hlavní funkcí main int main() {
// začátek
// Lokální deklarace - lokální proměnné nejsou automaticky nulovány. soucet = x + CISLO; printf(" Soucet je %d ",soucet); return (0); }
//konec
Naučit se programovat v libovolném jazyce je nejlepší na praktických příkladech. Proto se budeme této osvědčené zkušenosti držet i v dalších kapitolách.
Příklad Pro ilustraci toho jak vypadá program v C si uvedeme jednoduchý program, který vypisuje text: „ Hurá, můj první program v C!“. Řešení: /* První.c * Můj první program * Jan Sova 1.1. 2011 */
41 #include < stdio.h> #include
// pro funkčnost getch()
int main()
// Hlavni funkce
{ printf (“ Hura, muj prvni program v C!”); getch(); return(0); } V prvním řádku se vyskytuje komentář. V jazyce C jsou víceřádkové komentáře ohraničeny mezi znaky /* a */. Jednořádkový komentář a poznámky jsou za dvojznakem //. Pozor na vložené komentáře, neboť poznámka je vždy ukončena první dvojicí znaků */. /* Mezi těmito znaky je nějaký komentář /* zde je nějaký vložený komentář */ Tato část již není považována za komentář */ Dále se vyskytuje direktiva (příkaz preprocesoru) #include <stdio.h>, která zajišťuje připojení knihovny funkcí. V tomto případě stdio.h pro standardní formátovaný vstup a výstup. Hlavní program je zapsán do funkce main(), kterou musí obsahovat každý program. Začátek a konec programu zapisujeme pomocí bloku {…}.Definice funkcí i hlavní funkce main() většinou obsahují nepovinný příkaz return. V těle programu je funkce pro tisk na standardní výstup printf() a po ní funkce getch(), která je zde jen proto, aby se okno programu nezavřelo hned po spuštění. V tomto programu se jednalo o pouhé nastínění toho, jak má program v C vypadat. V dalších kapitolách se dozvíte vše podrobněji.
42
Shrnutí kapitoly V Editoru vytvořený zdrojový kód programu uložený s příponou *.c zpracovává nejprve Preprocesor, který zdrojový kód jen upraví. Compiler provede syntaktickou kontrolu kódu, převede jej od relativního kódu a uloží do objektového souboru *.obj. Následuje spojování (sestavování) programu pomoci Linkeru, který zajišťuje nahrazení relativních adres adresami absolutními a provede odkazy na příslušné knihovní funkce. Výsledkem této činnosti je již spustitelný soubor s příponou *.exe (případně com). Ladící program Debugger hledá chyby, které nastanou za běhu programu. Sestavený algoritmus přepíšeme prostřednictvím programovacího jazyka do programu, který má přesně danou strukturu. Programovací jazyk C je „case senzitivní“ - důsledně rozlišuje velká a malá písmena.
Kontrolní otázky a úkoly
1) Co se zdrojovým kódem provádějí jednotlivé části zpracování programu? 2) Jakou příponu má zdrojový soubor po zápisu v editoru ? 3) V které části zpracování se provádí překlad upraveného zdrojového textu do relativního kódu? 4) Proč vkládáme do kódu programu komentáře ? 5) Kolik musí mít každý program, vytvořený v jazyce C, nejméně funkcí? 6) Čím je ohraničeno tělo hlavní funkce?
Literatura Herout, P. Učebnice jazyka C, Kopp, České Budějovice, 1996, ISBN 80-901342-1-1
43
7 Elementy jazyka Obsah hodiny Seznámíme se se základními prvky jazyka C a jejich vlastnostmi, které jsou nezbytné pro tvorbu programu.
Cíl hodiny Po této hodině budete schopni: ● ● ● ●
rozlišit klíčová slova účelně vytvářet identifikátor zapsat definici konstanty rozlišit jednotlivé druhy konstant a vysvětlit jejich účel
Klíčová slova Identifikátor, konstanta, globální, lokální, ASCII tabulka.
V této kapitole se budeme zabývat základními prvky programovacího jazyka. Každý program, tak jak jsme měli možnost vidět v předchozí kapitole, se skládá z několika prvků. Jsou jimi různá klíčová slova jako je např. for, return, int, která tvoří množinu slov, jimž překladač jazyka C rozumí a má je ve své „slovní zásobě“.
7.1.Klíčová slova V jazyce C jsou následující klíčová slova, tj. jména, která mají pro překladač speciální význam a nesmí být použita jako identifikátory.
Příklad Následující řádky kódu způsobí chybu při překladu programu: int MojeJmeno; for; float case; Proměnná MojeJmeno má správně vytvořený název, avšak proměnná for nebo case způsobí chybu, protože jsou to klíčová slova jazyka C.
44 Programátor sice může použít identifikátory se stejným názvem, ale musí být napsány jinou výškou písma. Například slovo for nesmí být použito jako identifikátor, zatí co For, fOR a FOR jsou již v pořádku. Následující tabulka shrnuje klíčová slova definovaná normou ANSI:
auto
double
int
struct
break
Else
long
switch
case
Enum
register
typedef
char
Extern
return
union
const
Float
short
unsigned
continue For
signed
void
default
Goto
sizeof
volatile
do
If
static
while
Tato slova jsou vyhrazenými identifikátory, žádný jiný identifikátor nemůže mít ve fázi překladu stejné znění jako klíčové slovo daného jazyka.
7.2.Identifikátory V jazyce pojmenováváme – identifikujeme nejen proměnné, konstanty ale i funkce. Pro tvorbu identifikátorů jsou přesně stanovená pravidla, která jsou velmi jednoduchá. Pro vytvoření jména můžeme použít: •
písmena a..z, A..Z
•
číslice 0..9
•
znak podtržítka (_)
•
prvním znakem nesmí být číslice
•
maximální délka je 31 znaků
Jména proměnných, konstant a funkcí volíme podle toho co představují, např.:Suma, Sum, Soucet – volíme pro identifikátor součtu. Pro lepší orientaci nepoužíváme podobné identifikátory, např.: sum, suma. V žádném případě nepožíváme dva stejné identifikátory rozlišené jen typem písma, např.: prom, Prom, PROM.
45
7.4.Konstanty Konstanta je datový prvek, jehož hodnota je neměnná. Překladač přiřadí konstantě typ, který této hodnotě odpovídá. Uvozuje se klíčovým slovem const. Dělíme je na:
7.4.1.Číselné konstanty Číselné konstanty mohou být v desítkové, osmičkové nebo šestnáctkové soustavě. Desítkové celé číslo je vyjádřeno posloupnosti číslic, z niž první nesmí být nula. Např. 165, 12, 1. V osmičkové (oktálové) začíná posloupnost číslic nulou následována posloupností osmičkových číslic (0 - 7): 061, 07. Číslo zapsáno v šestnáctkové (hexadecimální) soustavě je vytvořené posloupnosti nuly, malého či velkého znaku x a hexadecimálními znaky (0 9, A – F, a - f). U záporných čísel se píše znaménko mínus.
Příklad Různých zápisů celočíselných hodnot: •
desítkové
12, 0, 3
•
oktálové
065, 015, 0,
•
hexadecimální
0x12, E1, FF, ac, 0X3A, 0Xcd, 0xa
7.4.2.Reálné konstanty Reálné konstanty se zapisují s desetinou tečkou. Například: 3.14 , 0.65 , 12. ,.65 . Můžeme je psát také v semilogaritmickém tvaru, kde mantisa a exponent jsou odděleny znakem E (resp. e). Například: 5e12, 1E-5, 2.32e5, 5.52 e -10.
7.4.3.Znakové konstanty Znakové konstanty jsou ohraničeny apostrofy: 'a' , 'B', '+', '7'. Hodnota znakových konstant je odvozena z odpovídající kódové tabulky – nejčastěji ASCII. Velikost znakové konstanty je kupodivu int a ne char. Některé obvykle používané znaky mají své znakové vyjádření a využívají se zejména ve výstupních funkcích jako printf( ). O těchto znakových konstantách se dozvíte více v další kapitole.
46 Jazykem počítačů jsou čísla. Aby počítač mohl komunikovat s aplikacemi a dalšími počítači, převádí znaky a symboly na jejich číselná vyjádření. V 60.letech 20. století v důsledku nutnosti standardizace vznikl standard ASCII (American Standard Code for Information Interchange). Tabulka znaků ASCII obsahuje 256 čísel, která jsou přiřazena odpovídajícím znakům. Standard ASCII umožňuje počítači ukládání a výměnu dat s dalšími počítači a aplikacemi.
Příklad Prostřednictvím internetu nalezněte kódovou tabulku ASCII. Následně zjistěte, jaký znak se v této tabulce nachází na pořadovém místě: 46, 65, 91, 97,123 ? Zjistěte jejich hexadecimální případně oktálové vyjádření.
7.4.4.Řetězcové konstanty Konstantní řetězce – literály jsou na rozdíl od znakových konstant tvořeny více než jedním znakem, zpravidla slovem či větou. Řetězcové konstanty jsou ohraničeny uvozovkami. Příklad: "Nejaky text". Řetězcová konstanta "a" je tvořena písmenem a, tedy řetězec délky jeden znak. Nesmíme ji zaměňovat se znakovou konstantou. Znaková konstanta, bez ohledu na její zápis představuje jeden znak, zatímco řetězová konstanta může mít i značnou délku. Konstanty definujeme po klíčovém slovu const následovaném typem konstanty, jejím identifikátorem a po rovnítku její hodnotou ukončenou středníkem.
Příklad const int kon = 123; cnst zapor = - 65; const float x = 5.52 e -10; const char male_a = ‘a’;
47
Shrnutí kapitoly Většina objektů, označených identifikátorem, musí být deklarována dříve, než je použita. Konstanty k takovým objektům patří. Konstanty jsou symboly, reprezentující neměnnou číselnou nebo jinou hodnotu. Konstanty definujeme po klíčovém slově const následovaném typem konstanty, jejím identifikátorem a po rovnítku její hodnotou ukončenou středníkem.
Kontrolní otázky a úkoly 1) Jak se definuje znaková konstanta z na hodnotu ‘A’? 2) Jaký znak se nachází v ASCII tabulce na 42. místě? 3) Na kterém místě v ASCII tabulce se nachází znak ‘Z’, ‘m’, ‘!’, ‘)’ ?
48
8
Datové typy
Obsah hodiny Seznámíme se s dělením datových typů. Zorientujeme se v jednoduchých datových typech. Objasníme používání jednotlivých datových typů a konverzi mezi nimi.
Cíl hodiny Po této hodině budete schopni: ● ● ● ●
nadeklarovat celočíselnou i reálnou proměnnou pracovat s jednotlivými podtypy zjistit velikost jednotlivých datových typů provádět konverzi mezi jednotlivými typy
Klíčová slova Jednoduché a strukturované datové typy, sada operací, typ ukazatel, int, char, void, short, long, float, double, signet, unsignet, implicitní a explicitní konverze
Jazyk C je striktně typový jazyk, kde musíme vždy každé proměnné určit nejen její název ale i typ. Pokud bychom někdy opomněli typ určit, překladač tento fakt bere jako hrubou chybu a nikdy nedojde k překladu. Překladač se tak jistí, že se nesnažíme přiřadit např. dvě nekompatibilní proměnné. Datové typy zavádí sadu operací, které můžeme na danou proměnnou aplikovat. Pokud použijeme celočíselný datový typ int, pak můžeme prohlásit, že s hodnotami tohoto typu smí provádět všechny základní aritmetické operace. Data, s kterými budeme v programech jazyka C pracovat, mohou mít různou povahu. Někdy půjde o celá čísla nebo o čísla s desetinnou částí, jindy budeme pracovat se znaky nebo řetězci. V této knize budeme pracovat jen s některými jednoduchými datovými typy, které v další knize rozšíříme o strukturované datové typy a typ ukazatel.
49
8.1 Rozdělení datových typů Datové typy jazyka C rozdělujeme na: a) Jednoduché •
Celočíselný
•
Reálný
•
Typ bez hodnoty – void
•
Výčtový – enum (budeme probírat v další knize)
b) Strukturované (budeme probírat v další knize) •
Soubor – FILE
•
Unie – union
•
Struktura – struct
•
Pole a řetězec – nemají klíčové slovo a jsou složeny se základních datových typů
c) Zvláštní datový typ – ukazatel (budeme probírat v další knize)
8.2 Celočíselné typy V jazyce C existuje několik celočíselných typů lišících se rozsahem hodnot, které v nich lze uchovat. To odráží i počet bajtů resp. bitů, které proměnné jednotlivých typů zabírají v paměti. Jednotlivé rozsahy jsou určeny příslušnými překladači a dají se zjistit aplikací operátoru sizeof. Výsledek je v bajtech. Například sizeof (int). Následující tabulka shrnuje všechny celočíselné typy, společně s jejich velikostí a maximálními hodnotami, které mohou uchovat. typ unsigned char char, signed char unsigned int int, signed int unsigned short int signed short int, short int long int unsigned long int signed long int
dolni mez horni mez 0 255 -128 127 0 65 535 -32 768 32 767 0 65 535 -32 768 32 767 -2 147 483 647 2 147 483 647 0 4 294 967 295 -2 147 483 647 2 147 483 647
velikost [bit] 8 8 16/32/64 16/32/64 16 16 32 32 32
50 Jak je z tabulky patrné, celočíselné neznaménkové typy jsou deklarovány klíčovým slovem unsigned, zatímco znaménkové signed. Použití klíčového slova signed je však u většiny kompilátorů zbytečné, protože automaticky považují všechna celá čísla za znaménková. Tato implicitní volba se však dá často vypnout. Obdobně jde vypustit i klíčové slovo int u deklarace short int nebo unsigned short int , kde stačí pouze slovo short.
Příklad Příklad dvojího zápisu deklarace celočíselné proměnné unsigned int. unsigned a; unsigned int b;
Stejné zkrácení deklarace si můžeme dovolit i u nejdelšího celočíselného typu, kdy stačí použít pouze klíčové slovo long na místě long int. Zajímavá je i velikost celočíselných typů int a unsigned int. V tabulce jsou uvedeny tři hodnoty 16, 32 nebo 64 bitů. Velikost u tohoto typu je závislá na implementaci překladače v prostředí operačního systému.
Příklad Následující část programu ukazuje, jak číst a vypisovat hodnoty typu short a long. int main( ) { unsigned int u; long l; printf( “ Zadej unsigned: “); scanf(“ %u”, &u); printf( “ Zadej long: “); scanf(“ %ld”, &l); printf( “ %u %ld “, u, l); ………… }
51
Příklad Na základě ukázkového příkladu výpisu celého čísla si samostatně procvičujte různé formáty výpisů vámi zvolených celých čísel. int poc= -123; printf("Znamenkovy decimalni: %d,\n Neznamenkovy: %u",poc, poc); printf("\n Hexa: %X, \n Oktalove: %o", poc, poc); Nejmenším typem, kterým je možno reprezentovat celá čísla je typ char, který zabere v paměti jeden byte a jak je již z jeho názvu patrné, používá se často k ukládání znaků. Ty jsou pak v proměnných uloženy jako ascii kódy znaků, a proto s nimi lze i nadále pracovat jako s čísly.
Příklad Příklad výpisu celočíselné proměnné char ve formě znaku a celého čísla, které představuje pořadí v ASCII tabulce. char znak = 'h'; printf("Zobrazeni znaku: %10c %10d", znak, znak);
Jazyk C nemá datový typ odpovídající logické hodnotě (pravda nebo nepravda, TRUE nebo FALSE), místo něj je možné použít některý z celočíselných datových typů, přičemž hodnota 0 je brána jako nepravda a jakákoli jiná hodnota jako pravda.
8.3 Reálné typy Reálná čísla, neboli čísla v pohyblivé (plovoucí) řádové čárce (tečce) jsou v jazyce C reprezentována třemi typy. Nejúspornější z nich, co se paměti týče, je typ float, který ale neposkytuje dostatečnou přesnost. Tu by měl ve většině případů zajistit typ double. Stejně jako by se měl mezi celočíselnými typy preferovat int, mezi reálnými by to měl být typ double. Pokud budeme potřebovat ještě větší přesnost, poskytuje nám jazyk C ještě typ long double. Následující tabulka ukazuje rozsahy, přesnost v počtu desetinných míst a alokovanou paměť jednotlivých reálných typů.
52
typ
maximum float 3.40282 . 1038 double 1.79769313486232 . 10308 long double 1.18973149535723176 . 104932
přesnost 6 15 18
velikost [bit] 32 64 80
Příklad Na základě ukázkového příkladu výpisu reálného čísla si samostatně procvičujte různé formáty výpisů vámi zvolených reálných čísel. double cis= 123.4567; printf("Vypis realneho cisla:\n %f \n %.2f \n %e \n %E",cis, cis,cis,cis);
Příklad Napište program, který vypočítá počet sekund v nepřestupném roce. Na základě ukázkového příkladu výpisu reálného čísla si samostatně procvičuj. #include <stdio.h> #include int main(void) { printf("Pocet sekund v roce: "); printf("%.2f ", 60.0 * 60.0 * 24.0 * 365.0); getch(); return (0); }
8.4 Typ void Nemá definovaný rozsah. S použitím klíčového slova se blíže seznámíme v další knize. Jen pro vaši ilustraci. Případy použití klíčového slova void jsou následující: •
Návratová hodnota funkce – funkce nemá návratovou hodnotu
void main( ) •
Typ formálního parametru funkce – funkce nemá žádné formální parametry.
int main(void)
53
8.5 Logický datový typ V jazyce C neexistuje datový typ boolean. Pokud potřebujeme někde získat nebo uchovat hodnotu pravda/ nepravda ( true/ false), můžeme k tomu využít např. typ int. V jazyce C je totiž vše nenulové považováno za true a ostatní za false. Nula je tedy false ( logická nepravda) a jiné číslo (nejčastěji se používá jednička) je true.
8.6 Typová konverze Jazyk C umožňuje implicitní (automatickou) a explicitní (požadovanou) typovou konverzi (převod mezi datovými typy). a) K implicitní konverzi dochází: •
V přiřazovacích výrazech je typ na pravé straně konvertován na typ na levé straně výrazu.
•
Jsou-li dva operandy ve výrazu různých typů, pak se operand s nižší prioritou konvertuje na typ s prioritou vyšší. Podle schématu int => unsigned int => long => unsigned long => float=> double => long double
•
Typ char a short int se konvertují automaticky na int
b) Explicitní konverzi využíváme v případě, kdy chceme změnit určitý datový typ (přetypovat) a nenastane samovolná konverze. Provádí se tak, že do kulatých závorek umístěných před konvertovanou proměnnou či výrazem uvedeme nový datový typ. (int) char_vyraz
Převede char výraz na int
(float) int_vyraz
Převede int výraz na float
(int) float_vyraz
Převede float výraz na int, odřízne desetin. část.
Příklad Jaký výstup bude mít následující program, který demonstruje explicitní typovou konverzi?
54 int main() { float a=3.21; int x; char zn='A'; x = (int) a;
// Explicitni typova konverze
printf("Promenna x ma hodnotu: %d \n",x); x = (int) zn; printf("Promenna x ma hodnotu: %d \n",x); return(0); }
Shrnutí kapitoly Datové typy určují rozsah hodnot, velikost alokované paměti a množinu přípustných operací. Velikost proměnné a rozsah jejich hodnot závisí na implementaci překladače v operačním systému. Pro zjištění velikosti datového typu se používá operátor sizeof( datový typ). Typy float, double a long se používají pro reálná čísla. Typ int a z něj odvozené typy short int a long int pracují s celými čísly. Poněkud překvapivě patří k celočíselným typům i char. Je sice určen pro uložení jednoho znaku, ten je však v jazyce C reprezentován jako číslo. Všechny celočíselné typy mohou být klíčovým slovem unsigned deklarovány pro čísla bez znaménka. Implicitně jsou deklarovány jako signed. V jazyce C neexistuje logický datový typ - boolean. Pokud potřebujeme někde získat nebo uchovat hodnotu pravda/ nepravda (True/ False), můžeme k tomu využít např. typ int. Nula je logická nepravda – False, vše ostatní (většinou jednička) je považováno za logickou pravdu – True.
55
Kontrolní otázky a úkoly 1) Co udává datový typ pro proměnnou. 2) Načtěte od uživatele reálné číslo. Vypočtěte a vypište zaokrouhlené výsledky: celou část zadaného čísla a jeho část za desetinnou čárkou (příklad: pro 523,1254 vypíše celou část 523 a část za desetinnou čárkou 0,1254) 3) Zjistěte, jaký rozsah mají datové typy: char, int, long, float, double a long double ve vašem kompilátoru jazyka C. 4) Vyberte mezi uvedenými (long, unsigned int, int,char) datový typ s největším požadavkem na paměť.
56
9 Použití datových typů v programech Obsah hodiny Procvičíme použití datového typu integer a real na konkrétních příkladech.
Cíl hodiny Po této hodině budete schopni: • • •
vhodně použít typ integer, char a float přetypovat danou proměnnou správně zapsat jednoduchý program
Každý, z níže uvedených programů, můžeme různě modifikovat, používat různé datové typy. Zjistíme, že variant řešení určitého problému může být hodně a že není snadné najít vždy hned nejoptimálnější řešení s optimálními vstupními i výstupními daty.
Příklad Zadejte stranu, výšku pravoúhlého trojúhelníka a vypočtěte jeho obsah. Řešení: #include <stdio.h> #include main() { int zak,vys; float obs; printf("Zadej zakladnu a výšku trojuhelnika"); scanf("%d %d",&zak, &vys); obs=(float)(zak*vys)/2; // Použití přetypování čitatele printf("\n Obsah je %4.2f",obs); getch(); return(0); }
57
Příklad Zadejte tři celá čísla a vypočtěte jejich aritmetický průměr, který vypíšete na tři desetinná místa. Řešení: #include<stdio.h> #include int main() { int a,b,c; float vysledek; printf("Zadej tri cela cisla"); scanf("%d %d %d",&a,&b,&c); vysledek=(a+b+c)/3.0; // Přetypování jmenovatele na typ float printf("Aritmeticky prumer je %.3f",vysledek); //Výpočet průměru můžeme provést bez použití proměnné vysledek // printf("Aritmeticky prumer cisel %d;%d;%d%.3f\n",a,b,c,(float)(a+b+c)/3); getch(); return(0); }
Příklad Zadejte malé písmeno a převeďte jej na velké. Vyhledejte na internetu ASCII tabulku a zjistěte rozdíl pořadí umístění malého a odpovídajícího velkého písmene (např.: malého 'm' a velkého 'M'). Řešení: #include <stdio.h> #include int main() { char z; printf("Zadej male pismeno: "); z=z - ('m'-'M');
// Převod malého písmena na velké také: z=z – 32;
printf("Velke pismeno: %c", z); getch(); return(0); }
scanf(" %c",&z);
58
Kontrolní otázky a úkoly 1) Načtěte velké písmeno, převeďte jej na malé a vypište jeho pořadí v ASCII tabulce – jeho desítkovou, oktávovou a hexadecimální hodnotu. 2) Vytvořte program, který načte znak od uživatele a vypíše jej v jeho znakové podobě, jeho desítkovou a hexadecimální hodnotu v ASCII tabulce. Vypište jeho předchůdce a následovníka v ASCII tabulce. 3) Jsou zadány hodnoty dvou odporů v ohmech. Určete hodnotu celkového odporu při jejich sériovém a paralelním zapojení. Zakreslete přesně vývojový diagram vašeho funkčního programu. 4) Je dán plánovaný počet výrobků a počet výrobků, které podnik opravdu vyrobil. Na základě těchto dvou hodnot určete, na kolik procent podnik splnil svůj plán výroby.
59
10 Proměnná Obsah hodiny Seznámíme se s deklarací, inicializací a způsobem používání proměnné. Naučíme se účelně používat lokální i globální proměnné.
Cíl hodiny Po této hodině budete schopni: ● ● ● ● ●
účelně pojmenovat proměnnou nadeklarovat proměnné inicializovat proměnné využít deklarace lokální proměnné orientovat se ve způsobu alokace paměti proměnných
Klíčová slova Proměnná, deklarace a definice proměnných, deklarace s inicializací, globální a lokální proměnné, statická proměnná, zásobník - LIFO.
Proměnné jsou pojmenovaná místa v paměti, která jsou přístupná prostřednictvím identifikátorů. Hodnotu proměnných můžeme během programu měnit. Proměnné deklarujeme uvedením datového typu, ten je následován identifikátorem nebo seznamem identifikátorů navzájem oddělených čárkami. Deklarace končí středníkem. Pro deklaraci proměnné používáme tento obecný formát: datový typ identifikátor; Pro deklaraci více proměnných stejného typu se používá tento zápis: datový typ identifikátor_1, identifikátor_2;
60
Příklad int a, b, cis; // deklarace tří proměnných typu integer float x;
// deklarace jedné reálné proměnné x
10.1 Deklarace a definice proměnných Deklarace proměnných je příkaz, který pouze udává typ proměnné a její jméno. Deklarace nepřiděluje žádnou paměť! Naopak pod pojmem definice proměnných se míní příkaz, který přidělí proměnné určitého typu jméno a paměť. Adresu proměnné v paměti získáme pomocí & - adresního operátoru. Programovací jazyk C nám umožňuje spojit deklaraci a explicitní inicializaci proměnné do jednoho příkazu. Proměnné tak přiřadíme počáteční hodnotu a tím i adresu v paměti, kde je proměnná uložena. definiční deklaraci: datový typ identifikátor_promenne = hodnota;
Příklad int a = 3, sum = 0; // deklarace dvou proměnných typu integer s jejich následnou inicializací Datový typ proměnné určuje její alokační kapacitu. Alokační kapacita je prostor, který proměnná zabírá v operační paměti počítače. Například datový typ int má rozsah 32 bitů. Aby mohla být vytvořena proměnná tohoto typu, musíme v paměti vyhradit prostor dlouhý 4 bajtů ( 32/8 = 4). Alokační kapacity proměnných jsou dány použitými datovými typy. Zatímco proměnná typu char si vystačí s jedním bajtem, proměnná double potřebuje osm bajtů. Definice proměnných je spojena s alokací paměti: int a=5;
// definiční deklarace
61
10.2 Statická proměnná Proměnné můžeme rozdělit do dvou základních skupin: statické a dynamické. S dynamickými se setkáme v další knize. Každá statická proměnná má své jméno - identifikátor, velikost v paměti určenou datovým typem proměnné a adresu místa, které je vyhraženo alokováno v paměti. Pro všechny definované statické proměnné překladač sám určí požadavky na paměť a alokuje tuto paměť na začátku spuštění programu. Existence staticky alokovaných proměnných je od začátku programu do jeho konce, čili od odevzdání řízení zpět operačnímu systému, který všechny alokace, provedené před spuštěním programu najednou zruší. Názorně vše popisuje následující obrázek.
Příklad int x =5, y=2 , z ; // definiční deklarace proměnných x,y // deklarace proměnné z a její následné přidělení paměti scanf("%d", &z); Lokální proměnné jsou alokovány ve speciální paměťové sekci, které se říká zásobník ( LIFO: Last-In-First-Out – jako věž z kostek). Zde jsou jednotlivé proměnné ukládány v pořadí svého vzniku. Odebrána je vždy ta proměnná, která byla vložena jako poslední.
62
10.3 Lokální a globální proměnné Proměnné deklarované mimo všechny funkce (tzn. i mimo funkci main) jsou globální. Můžeme je použít kdekoliv v programu a jsou implicitně nulové. Proměnné deklarované ve funkcích nebo uvnitř bloku se nazývají lokální proměnné. Můžeme je použít v dané funkci či bloku a jsou implicitně nenulové. Pokud ji programátor pouze deklaruje a neinicializuje, pak její obsah může být jakýkoliv. Bloky příkazů jsou ohraničeny složenými závorkami { a }. V programovacím jazyku C je možné na začátku každého bloku definovat lokální proměnné. V jazyce C musí být všechny lokální proměnné deklarovány (nebo definovány) na začátku těla funkce, k níž patří. Toto omezení je platné pouze pro jazyk C, ovšem nikoliv pro další jazyky, jako jsou C++ nebo C#.
63
Příklad int x; // globální proměnná int main() { int a ;
// lokální proměnná – uvnitř funkce main( ) {int b; // lokální proměnná. Její působení je omezeno jen na blok. }
// zde již proměnná b nelze použít }
Shrnutí kapitoly Proměnné jsou paměťová místa přístupná prostřednictvím identifikátoru. Hodnotu proměnných můžeme během výpočtu měnit. Tím se proměnné zásadně odlišují od konstant, které mají po celou dobu chodu programu hodnotu neměnnou – konstantní. Proměnné deklarujeme uvedením datového typu, jež je následován identifikátorem, nebo seznamem identifikátorů, navzájem oddělených čárkami. Deklarace končí středníkem. Datový typ proměnné určuje její alokační kapacitu.
Kontrolní otázky a úkoly 1) Jak se zapíše deklarace celočíselné proměnné x ? 2) Jak se zapíše deklarace lokální reálné proměnné y ? 3) Jak se inicializuje celočíselná proměnná a na hodnotu 10 a reálná proměnná b na hodnotu 5,2 ? 4) Co je chybné v těchto jménech proměnných ? a) 1krat b) black+white c) $suma
64
11 Výraz, přiřazení a příkaz Obsah hodiny Objasníme si smysl výrazů a způsob zpracování přiřazovacích příkazů. Nastíníme techniku vícenásobného přiřazení.
Cíl hodiny Po této hodině budete schopni: ● ● ● ● ●
rozlišit výraz od příkazu vyhodnotit jednotlivé příkazy s jednoduchými výrazy přiřadit hodnoty výrazům jednotlivých typů použít vícenásobné přiřazení aplikovat teoretické znalosti na příkladech
Klíčová slova Výraz, proměnná, hodnota, příkaz, výraz s přiřazením, prázdný příkaz, vícenásobné přiřazení, L – hodnota.
V předcházejících kapitolách jsme se naučili, jak deklarovat proměnnou určitého typu. Na co nám však bude proměnná, která nemá konkrétní hodnotu? Jak tuto konkrétní hodnotu proměnné přiřadíme? K tomu nám slouží výraz s přiřazením. Jeho zápis je: proměnná = hodnota Výraz se stává příkazem, když jej ukončíme středníkem ; a=2
výraz s přiřazením
a=2;
příkaz s přířazením
Pouhý středník představuje často používaný prázdný příkaz (null statement), který se používá v cyklech, s nimiž se seznámíme v následujících kapitolách. Následující obrázek demonstruje přiřazovací příkaz aritmetického výrazu (b + c).
65
Smysl přiřazovacího příkazu si snadněji zapamatujeme, když si uvědomíme, že se tento příkaz skládá ze tří částí: levé strany, přiřazovacího operátoru (=) a pravé strany tvořené většinou výrazem ukončené středníkem. Na levé straně od operátoru přiřazení se nachází proměnná neboli datový objekt, který je schopen uchovat hodnotu datového typu. Hodnota, která bude do proměnné uložena, je na pravé straně přiřazovacího příkazu.
Příklad Inspirujte se následujícími příklady přiřazení a vytvořte své vlastní příklady. int x,a; float k; char znak; x = 1;
// proměnné x se přiřadí hodnota 1
k = 3.2 ;
// proměnné k se přiřadí hodnota 3,2
znak = ‘G’;
// proměnné znak se přiřadí znak G
a=2+x;
// proměnné a se přiřadí součet 2 a x, tedy 3
Z výše uvedeného příkladu vyplývá, že na pravé straně přiřazovacího příkazu se mohou nacházet nejen čísla, znaky, ale i matematické operace či jiné proměnné, které mají před použitím konkrétní hodnoty. Takže například, pokud chceme do proměnné a uložit číslo 5, napíšeme: int a; // deklarace proměnné a = 5; // v a je nyní 5
66 Důležité ovšem je, aby na levé straně příkazu byla vždy L – hodnota, která představuje adresu. Proměnná je L - hodnota, ale konstanta 5 není L hodnotou.
Příklad Příklady správných a chybných přiřazení: int u = 3; // definiční deklarace = deklarace s inicializací proměnné u i = u; // proměnná může být vlevo i vpravo, i = 3 i = 2 + u;
// i = 5
i = u * 5 + 10; i + 1 = u;
// i = 25, výraz může být jen na pravé straně
// Chyba! Matematická operace je na levé straně příkazu.
Překladač naštěstí tyto chyby odhalí již při překladu. 1 = u;
// Chyba! Konkrétní hodnota je na levé straně příkazu.
Příklad Jaký bude výstup následujícího programu ? #include <stdio.h> #include int x; // deklarace float z; int main( ) { int x; // deklarace 1. lokální proměnné float a = 1.3; x = 10;
// definiční deklarace 2. lokální proměnné
// přiřazení konkrétní hodnoty do x
printf("%4d", x + 5); // zobrazení proměnné x po přičtení 5 a=a+x; printf("\n Hodnota a+x = %4.2f", a); getch(); return(0); }
// zobrazení hodnoty výrazu a + x
67 Můžeme používat i příkaz přiřazení, kde se na pravé i levé straně nachází stejná proměnná? x = x+ 1 ; Odpověď zní ano. Proměnná na levé straně může být i na straně pravé. V tomto případě nejde o rovnost. Nejdříve se vyhodnotí pravá strana a ta se pak přiřadí proměnné na levé straně. Aby se toto mohlo realizovat, musí mít proměnná x nejprve přiřazenou nějakou hodnotu. K této hodnotě se připočte 1 a tato nová hodnota se přiřadí proměnné x. Posloupnost vyhodnocování je uvedena na následujícím obrázku.
Příklad Které z uvedených přířazení je správně pro následující deklaraci? int i,j ; float a,b ; a = 4. 32;
// správně
i = 12.34 ;
// nesprávně
Proměnná na levé straně může nabývat jen hodnoty podle typu své deklarace, a proto se na pravou stranu kladou určitá omezení. Musí platit, že hodnota výrazu na pravé straně musí patřit do množiny hodnot levé strany. Nebo na pravé straně je podtyp ( typ s nižším rozsahem) strany levé. Například: na pravé straně je typ integer a na levé straně typ float. i = 12.34 ; // Nesprávně! Levá strana je typu int, ale pravá strana je typu float.
11.1 Vícenásobné přiřazení Programovací jazyk C umožňuje i vícenásobné přiřazení. Přiřazujeme jednu hodnotu do více proměnných, a to vše v jednom příkazu. Postupuje se přitom následovně: proměnná_3 = proměnná_2 = proměnná_1 = hodnota;
68 Přiřazení probíhá zprava doleva. Nejdřív je hodnota přiřazena do proměnné_1, čímž je tato proměnná inicializována. Posléze je hodnota proměnné_1 přiřazena do proměnné_2. Stejný proces se opakuje i pro proměnnou_3. V okamžiku, kdy se inicializuje proměnná_3, je proces vícenásobného přiřazení u konce a všechny proměnné obsahují stejnou hodnotu. Příkaz: a = b = c = 5 ;
vyhodnotíme následovně: a = ( b = ( c=5))) ;
Shrnutí kapitoly Nejzákladnější operací je přiřazení, jako např.: s = 2, a = x. V jazyku C je přiřazení reprezentováno jediným rovnítkem. Hodnota vpravo od rovnítka se přiřadí vlevo. Přiřazení může na pravé straně obsahovat kromě hodnoty i výraz, jako např.: s = a+b. Pokud je výraz na pravé straně ukončen středníkem, stává se z něho příkaz: s = a+b ; Jazyk C umožňuje použít i vícenásobné přiřazení, např. s = a = b. V takovém případě se vyhodnocování provádí zprava doleva, takže hodnota b se přiřadí proměnné a, jejíž nová hodnota se přiřadí proměnné s. Všechny tři proměnné budou mít tutéž hodnotu. Konkrétně tu, kterou měla původně jen proměnná b.
Kontrolní otázky a úkoly 1) Pro deklaraci : char k; float a; posuďte, zda jsou následující přiřazení přípustná. V kladném případě je vyhodnoťte: a) a = 1; b) k = ‘ m’; c) a = ‘ 1’; d) a= 5.32; e) k = 4; 2) Pro definiční deklaraci: int a = 4; vyhodnoťte následující příkazy: a) a = a - 2; b) a = (5 + a) * 2; c) a = (2 + a) / 3; d) a = (a + 4) / 3.0 ;
69
12 Operandy, operátory a jejich dělení podle počtu operandů Obsah hodiny Seznámíme se s dělením operátorů. Objasníme si dělení operátorů podle počtu operandů. Zorientujeme se, a na příkladech vyjasníme, prefixové a postfixové operátory.
Cíl hodiny Po této hodině budete schopni: ● ● ●
rozčlenit příkaz přiřazení na jednotlivé segmenty rozdělit operátory podle počtu operandů vyhodnotit jednoduché výrazy a přiřazení
Klíčová slova Operand, operátor, výraz, unární, binární, ternární, inkrementace, dekrementace, negace, reference, dereference, prefix, postfix, modulo, logické operátory
S příkazem přiřazení jsme se seznámili v předcházející kapitole. Nyní se zaměříme na výraz. Ten je v jazyce C tvořen posloupností operandů a operátorů, které určují, jak se má výraz vyčíslit.
Operand je hodnota, se kterou počítáme ( konstanta, proměnná, výsledek funkce).
70 Operátor určuje operaci, kterou hodláme provést s operandem nebo operandy. Dělení operátorů: a) podle funkčnosti operátorů - aritmetické, logické, relační, přiřazovací, bitové, operátory bitového posuvu, přístupové, oddělovací b) podle počtu operandů - unární, binární, ternární Arita operátoru udává počet jeho operandů, čili počet výrazů, se kterými se daná operace provádí. V jazyku C máme k dispozici operátory unární (tj.s aritou 1), binární (tj. s aritou 2) a jeden operátor ternární (tj. s aritou 3).
12.1 Unární operátory Vztahují se pouze k jednomu operandu. Patří sem:
12.1.1
+
unární plus
+5
-
unární mínus
-5
++
inkrementace
a++
--
dekrementace
a--
!
logická negace
!a
~
bitová negace
~a
&
operátor reference
&a
*
operátor dereference
*a
Unární mínus
c = - b; operátor mínus v této variantě vytvoří zápornou hodnotu čísla b a pracuje tak pouze s jedním operandem
12.1.2
Operátory pro inkrementaci a dekrementaci
Tyto operátory zvětšují (případně zmenšují) výraz o jedničku. Podle toho zda tyto operátory leží před ( prefix) nebo za operandem ( postfix) se buď nejprve operand upraví o jedničku a pak se tato hodnota použije ve výrazu nebo naopak. ++a;
inkrementace před použitím ( prefixový zápis)
Proměnná je nejprve zvětšena o jedničku a pak je tato nová hodnota vrácena jako hodnota výrazu.
71 a++; `
inkrementace po použití ( postfixový zápis)
Nejprve je vrácena původní hodnota proměnné a ta je pak zvětšena o jedničku. Analogicky dekrementační operátor: --a;
dekrementace před použitím ( prefixový zápis)
a--; `
dekrementace po použití ( postfixový zápis)
Věnujme se nyní rozdílům, které plynou z užití prefixové a postfixové verze operátoru ++ nebo --. Uvažujme následující příklad:
Příklad #include <stdio.h> #include int main( ) { // definiční deklarace (deklarace s inicializací) celočíselné proměnné a int a = 2; int b,c; // prefixová inkrementace lokální proměnné a v přiřazovacím příkazu b = ++a;
// a má hodnotu 3, b má hodnotu 3
// postfixová inkrementace lokální proměnné a v přiřazovacím příkazu c = a++;
// a má hodnotu 4, c má hodnotu 3
// výpis hodnot jednotlivých proměnných: a = 4, b = 3, c = 3 prinf( “ a = %d, b = %d, c = %d “, a,b,c); getch( ); return(0); } Jak bude překladač postupovat, při zpracovávání jednotlivých příkazů? b = ++a; Jelikož na pravé straně od přiřazovacího příkazu (=) je zapsán výraz ++a, víme, že jde o prefixovou inkrementaci proměnné a. Nejdříve se provede inkrementace ( zvýšení o 1) proměnné a, poté je výsledek inkrementace přiřazen proměnné b.
72 c = a++; Zde je použita postfixová verze operátoru ++. Překladač nejprve vezme aktuální hodnotu proměnné a ( což je 3) a přiřadí ji do proměnné c. Hned, jak bude přiřazovací operace hotová, překladač zabezpečí inkrementaci proměnné a. To znamená, že po provedení přiřazovacího příkazu bude v proměnné c uložena hodnota 3 a v proměnné a se bude nacházet hodnota 4.
Příklad Jaké hodnoty budou uloženy v jednotlivých proměnných ve fragmentu (části) zdrojového kódu? int a = 5, b = 2 , c; b++;
// b má hodnotu 3
c = a + b++;
// c bude 8, a bude 5, b bude 4
c = ++a + b;
// c bude 10, a bude 6, b bude 4
12.1.3
Logická negace
Výsledkem logické negace ! je True nebo False, což jazyk C vyhodnocuje jako 1 nebo 0. Například !3 je 0.
12.1.4
Bitová negace
Bitová negace ( doplněk, inverze) ~ obrací jednotlivé bity ve výrazu. Takže například: ~00000101 je 11111010.
12.1.5
Operátor reference a dereference
S operátorem reference & a dereference * se blíže seznámíme v příštím ročníku. Operátor * vrací hodnotu objektu, na který ukazuje ukazatel, který před ním stojí. Operátor & vrací adresu proměnné, před kterou stojí.
Příklad Takto můžeme přečíst hodnoty dvou proměnných jedinou funkci pro formátový vstup: int x; float y; scanf( “ %d %f”, &x, &y);
73
12.2 Binární operátory Spolupracují se dvěma operandy, operátor se píše mezi ně. +
Sčítání
-
Odečítání
*
Násobení
/
dělení – reálné nebo celočíselné
%
modulo - zbytek po celočíselném dělení
S trojicí operátorů +, -, a * jsme se již setkali, takže víme, jak pracují. Operátor / je trochu specifický. O tom, zda dělení bude celočíselné nebo reálné rozhoduje typ operandů. Je-li alespoň jeden z nich typu float, double nebo long double bude dělení realné. Budou-li oba operandy celá čísla, jedná se o dělení celočíselné. int / int
celočíselné
int / float
reálné ( float)
float / int
reálné ( float)
float / float
reálné ( float)
Příklad Která odpověď je správně? Operátor / má význam: a)
dělení dvou celých čísel?
b)
zbytek po dělení dvou celých čísel?
c)
dělení dvou jakýchkoliv čísel?
d)
dělení celého čísla dvěma?
Operátor % je tzv. modulo operátor nebo také operátor pro zjištění zbytku po celočíselném dělení. Jak tento operátor pracuje? Na základě hodnoty podílu vypočítá operátor % zbytek po celočíselném dělení a ten poskytne jako svou návratovou hodnotu. Více nám o funkci tohoto aritmetického operátoru poví další výpis zdrojového kódu.
74
Příklad #include <stdio.h> #include int main( ) { int a = 10, b = 3; prinf( “%d\n “, a % b); getch( ); return(0); } Jistě nebude žádným překvapením, když prohlásíme, že po spuštění programu se vypíše na obrazovku 1 jako hodnota zbytku po celočíselném dělení 10 a 3 ( 10 / 3 = 3, zb. 1).
Příklad Vyhodnoťte výsledek a jeho typ u uvedených příkazů pro následující deklaraci. (Počítejte stále jen s počátečními hodnotami z definiční deklarace) int a = 5, b = 13 ; float c; a = a / 4;
// celočíselné dělení, a bude 1
b = a % (- 3);
// dělení modulo, b bude 1
a = b / 2;
// celočíselné dělení, a bude 6
c = (float)b / 2;
// reálné dělení, c bude 6,5
c = b / 2.0;
// reálné dělení, c bude 6,5
12.3 Ternární operátor V určitých případech si potřebujeme vybrat hodnotu jednoho ze dvou výrazů v závislosti na určité podmínce. Obecná syntaxe je následující: v1 ? v2 : v3 v1 je výraz, jehož hodnota je po vyhodnocení považována za logickou. Pokud je tato hodnota logická pravda – true, operátor vyhodnotí výraz v2 a vrátí jeho hodnotu, zatímco v případě logické nepravdy – false výrazu v1 je vyhodnocen výraz v3 a je vrácena jeho hodnota.
75 V některých příkladech můžeme s ternárním operátorem pracovat i podle zjednodušeného předpisu: (podmínka) ? pravda : nepravda
Příklad Ukázka použití ternárního operátoru ve fragmentu programu: int main( ) { int a, c, b = 2; // Pokud je b rovno 2, pak a bude 1, v opačném případě a bude rovno 3 a = ( b ==2)? 1 : 3; // Pokud je b různé od 0, pak a = 5, v opačném případě bude a = 10 a = (b != 0) ? 5 : 10; // c bude maximum z a, b c = (a > b)? a : b; // Inkrementuje se buď a nebo b (a == 1) ? a++ : b++; // Co se vypíše ? ( b ==2)? printf(“ Mam rad PRG !”) : printf(“ Nemam rad PRG !”); // Co se vypíše ? printf("%s ", (a > b) ? "a je vetsi nez b" : "b je vetsi nez a"); return(0); } S tímto operátorem se ještě setkáme v kapitolách věnovaných alternativě – větvení.
76
Shrnutí kapitoly Operátory lze rozdělit několika způsoby. V této kapitole jsme je rozdělili podle počtu operandů na unární, binární, ternární, neboli na operátory s jedním, dvěma nebo třemi operandy. Operandy jsou data (většinou čísla), se kterými operátory (např. plus) pracují. S většinou operátorů jsme se již setkávali v matematice. Operátor / je trochu specifický. O tom, zda dělení bude celočíselné nebo reálné rozhoduje typ operandů. Podmíněný operátor ? : je ternárním operátorem (má 3 operandy). Prvním operandem je výraz, který se vyhodnotí jako logický výraz (True nebo False). Pokud se vyhodnotí jako True, výsledkem bude druhý operand.
Kontrolní otázky a úkoly Napište jaké hodnoty budou uloženy v proměnných a, b, c. Počítejte stále jen s počátečními hodnotami: int a=1, b=3, c=4! Pro kontrolu správnosti vašeho výpočtu sestavte program s výpisem jednotlivých proměnných. 1)
b=--c;
2)
c=2+a++;
3)
a=--b*10;
4)
c=a*b--;
5)
b= a-- +c/2;
6)
a++;
7)
c=a + b++;
8)
c= --a + b;
9)
c= a++ +b;
10)
++a--;
77
13 Dělení operátorů podle jejich funkčnosti Obsah hodiny Seznámíme se s tříděním operátorů podle jejich funkčnosti. Podrobněji se podíváme na to, jak jsou výrazy s těmito operátory vyhodnocovány.
Cíl hodiny Po této hodině budete schopni: ● ● ●
rozčlenit operátory podle jejich funkčnosti vyhodnotit jednoduché výrazy a přiřazení objasnit použití operátorů
Klíčová slova Operand, operátor, výraz, kategorie operátorů, modulo, relace, bit, konjunkce, disjunkce, negace, nonekvivalence, booleova algebra,
Již víme, že operátory jsou symboly, které předepisují provedení různých programovacích operací. Tak například operátor + sčítá hodnoty, zatímco operátor * je násobí. Rovněž jsme si již řekli, že hodnoty, s nimiž operátory pracují, se nazývají operandy. Výraz jsme definovali jako smysluplnou posloupnost operandů a operátorů, která produkuje hodnoty určitého datového typu. Jazyk C disponuje celou řadou operátorů. V předcházející kapitole jsme si operátory klasifikovali podle počtu operandů, s nimiž pracují. V této kapitole budeme operátory třídit podle jejich funkce, tedy podle druhu programovacích operací, které uskutečňují. Z funkčního hlediska jsou v jazyce C k dispozici následující kategorie operátorů:
13.1 Aritmetické operátory + * / %
sčítání odečítání násobení dělení celočíselné nebo reálné zbytek po celočíselném dělení
78 Operátory +, -, *, / lze použít s jakýmkoliv základním datovým typem. Operátor % lze použít jen s celočíselným typem. Jak již bylo uvedeno v předcházející kapitole, operátor modulo dává jako výsledek zbytek po celočíselném dělení. Pokud chceme celočíselně dělit float musíme jej nejdříve přetypovat: x = (int) 123.456 % 3;
Příklad Výpočet celočíselného, reálného dělení a zbytku po celočíselném dělení: #include <stdio.h> int main( ) { printf( “ %f”, 5.0 / 2);
// reálné dělení – vypíše 2,5
printf( “ %f”, (float)5 / 2);
// reálné dělení – vypíše 2,5
printf( “ %d”, 5 / 2);
// celočíselné dělení – vypíše 2
printf( “ %d”, 5 % 2);
// modulo dělení – vypíše 1
return(0); }
13.2 Logické operátory Programovací jazyk C definuje tři základní logické operátory: || && !
logická disjunkce - logický součet - OR logická konjunkce - logický součin - AND logická negace - NOT
Operátory logické konjunkce a disjunkce jsou binární, avšak operátor logické negace je unární. Logické operátory vracejí vždy jednu ze dvou hodnot: buď logickou pravdu – true (je reprezentována většinou nenulovou hodnotou – 1), nebo logickou nepravdou – false (je reprezentována 0). Následující tabulka uvádí použití logických operátorů: X 0 0 1 1
y 0 1 0 1
x && y 0 0 0 1
x || y 0 1 1 1
!x 1 1 0 0
!y 1 0 1 0
79 Pravidla pro určeni výsledku známe z Booleovy algebry. Výsledek logických výrazů je tedy vždy 1 (true) nebo 0 (false). Při použití logických operátorů || a && překladač zajišťuje, že druhý operand se vyčísluje pouze tehdy, jestliže první operand ještě neurčuje jednoznačně výsledek. Nehrozí tedy nebezpečí, že by ve výrazu: x>0 && y / x > 0 mohlo dojít k dělení nulou.
Příklad Program na výpis vyhodnocení logických operátorů: #include <stdio.h> int main( ) { int x,y; printf( “ Zadej x a y ( 0 nebo 1)” ); scanf(“ %d %d”, &x, &y); printf( “ x AND y = %d”, x && y ); printf( “ x OR y = %d”, x || y ); printf( “ NOT x = %d”, !x ); return(0); }
Příklad Vyjádřete v jazyce C podmínku, že bod o souřadnicích [x, y] leží v 1. kvadrantu. Řešení: ( x >=0) && ( y>=0)
Příklad Vyjádřete v jazyce C podmínku, že bod o souřadnicích [x, y] leží: a) uvnitř čtverce o souřadnicích [2;3], [9;3]; [2;6] a [9;6] b) vně čtverce Řešení: a) (x>2) && (x<9) && (y>3) && (y<6) b) (x<2) || (x>9) || (y<3) || (y>6)
80
13.3 Relační operátory Slouží k porovnávání operandů, tedy zjišťují, zda jsou jejich hodnoty shodné nebo odlišné. Všechny relační operátory jsou binární. Výsledkem výrazu s relačním operátorem je logická hodnota potvrzující nebo zamítající uvedené srovnání (logická pravda – true-logická 1, logická nepravda – false – logická 0). V jazyce C jsou tyto relační operátory: Operátor
Charakteristika operátoru
Ukázka použití
==
rovnost
x == y
!=
nerovnost
x != y
>
větší než
x>y
<
menší než
x
>=
větší nebo rovno
x >=y
<=
menší nebo rovno
x <= y
Začínající programátoři si velmi často pletou přiřazovací operátor (=) s relačním operátorem rovnosti (==). Abychom věci uvedli na pravou míru. Operátor (=) uskutečňuje přiřazení, tedy operaci uložení hodnoty do cílového datového objektu. Naproti tomu operátor (==) testuje, zda existuje relace rovnosti mezi dvěma datovými objekty. Proč by jste se měli starat o to, zda je něco pravdivého nebo ne? Důvod použití pochopíte na následujícím příkladu
Příklad Zadejte dvě celá čísla a půjde-li to, proveďte jejich dělení. Co se stane, když jako druhou hodnotu (b – jmenovatele) vložíte 0? int main() { int a,b; printf("Zadej dve cela cisla:\n"); scanf("%d %d",&a, &b); (b == 0 )?: printf("Nulou nelze delit\n"): printf("Podíl je: %6.2f\n",(float)a/b); …} Relační operátory si více procvičíme v kapitolách věnujících se větvení.
81
13.4 Přiřazovací operátory Se standardním přiřazovacím operátorem(=) jsme se již setkali. Jazyk C nám ovšem umožňuje pracovat i se složenými přiřazovacími operátory. S největší frekvencí se používají složené přiřazovací operátory, které sdružují dovednosti přiřazovacího operátoru a aritmetických operátorů. =
x=y
+=
x=x+y
-=
x=x–y
*=
x=x*y
/=
x=x/y
%=
x=x%y
&=
x=x&y
|=
x=x|y
^=
x=x^y
v1 operátor = v2; Operátor přiřazení je binární, přičemž jeho levý operand (v1) musí být tzv. l - hodnota, čili výraz, který má adresu, na níž uložená hodnota může být změněna (typicky identifikátor proměnné). Pravý operand (v2) je pak libovolný výraz, jehož hodnota se při vyhodnocování operátoru (z uvedené tabulky) uloží do levého operandu. Výsledná hodnota operátoru je tato přiřazovaná hodnota. Zkrácený zápis
Normální zápis
l-hodnota += výraz
l-hodnota = l-hodnota + výraz
l-hodnota -= výraz
l-hodnota = l-hodnota - výraz
l-hodnota *= výraz
l-hodnota = l-hodnota * výraz
l-hodnota /= výraz
l-hodnota = l-hodnota / výraz
l-hodnota %= výraz
l-hodnota = l-hodnota % výraz
l-hodnota &= výraz
l-hodnota = l-hodnota & výraz
l-hodnota |= výraz
l-hodnota = l-hodnota | výraz
82 Mezi operátorem a znakem rovnítka nesmí být žádná mezera. Důvod proč by jste měli tento zkrácený zápis používat, nespočívá jen v tom, že si ušetříte trochu psaní, ale protože překladač jazyka C může vytvořit efektivnější programový kód. Podívejme se na některé příklady zpracování přiřazovacích příkazů: a += b;
// a = a+b;
a *= b + c;
// a = a * (b+c); nikoliv a = a * b + c;
a /= b - 2;
// a = a / (b -2); nikoliv a = a / b - 2;
a %= b+2
// a = a % ( b + 2); nikoliv a = a % b + 2;
Příklad Jak se zapíše následující příkazy pomocí složeného přiřazovacího operátoru? x = x &y;
// x &= y;
x = x + 8;
// x += 8;
y = y/(x + 3);
// y /= x + 3;
Příklad Napište jaké hodnoty budou uloženy v proměnných i, j pro každý příklad (počítejte stále jen s počátečními inicializovanými hodnotami (viz. níže)!) Pro kontrolu správnosti vašeho výpočtu sestavte program s výpisem jednotlivých proměnných. 1) j+=i;
// i = 4, j = 7
2) j/=--i;
// i = 3, j = 1
3) j *= i -2;
// i = 4, j = 6
4) i %= -- j;
// i = 0, j = 2
5) j *= ++i – 3; // i = 5, j = 6 int main() { int i=4, j=3; j+=i; printf("Hodnoty: i=%d , j=%d \n",i, j); ….}
83
13.5 Bitové operátory Bitové operátory se zabývají zpracováním bitových operací na jednotlivých bitech binárních hodnot svých operandů. Operátory bitové disjunkce, konjunkce a nonekvivalence jsou binární operátory. Operátor bitového doplňku je unární operator a seznámili jsme se s ním již v minulé kapitole. Operátor | & ^ ~
Charakteristika operátoru bitová disjunkce (bitová operace OR) bitová konjunkce (bitová operace AND) bitová nonekvivalence (bitová operace XOR) bitový doplněk (bitová operace NOT)
Zápis x|y x&y x^y ~x, ~y
Zopakujme si pravdivostní tabulku logických operací z minulé kapitoly, která má navíc exkluzivní OR ( XOR). x 0 0 1 1
y 0 1 0 1
x&y 0 0 0 1
x|y 0 1 1 1
x^y 0 1 0 1
~x 1 1 0 0
~y 1 0 1 0
Příklad Napište jaké hodnoty budou nabývat následující příkazy (počítejte stále jen s počátečními inicializovanými hodnotami: a=3, b=2 !) Pro vaši kontrolu sestavte program s výpisem jednotlivých proměnných. c= a & b;
// Výsledkem je: 3 & 2 = 2;
c= a | b;
// Výsledkem je: 3 | 2 = 3;
c= a ^ b;
// Výsledkem je: 3 ^ 2 = 1;
Řešení: Nejprve jsou oba operandy (proměnné a, b) převedeny do své binární podoby. Tedy : (3)10 = (11)2 a (2)10 = (10)2 Operátor & začne porovnávat bity obou operandů, které stojí na stejných pozicích. Mají-li oba testované bity hodnotu 1 (jednotkový bit) , operátor & vrací hodnotu 1 (jednotkový bit). Pokud mají testované bity rozdílné hodnoty, operátor & vrací hodnotu 0 (nulový bit). 00000011 &
00000010 00000010 = (10)2 = (2)10
84 Finální hodnota bitového výrazu bude mít podobu bitové posloupnosti 00000010, což odpovídá hodnotě 2 v desítkové soustavě Prostřednictvím programu provedeme kontrolu správnosti našich výpočtů u prvního příkladu: #include<stdio.h> #include int main() { int a=3; int b=2, c; c= a & b; printf("%d & %d = %d \n", a, b, c); getch(); return(0); }
13.6 Operátory bitového posuvu V jazyce C máme ještě dva bitové operátory, které umožňují pracovat s celými čísly na bitové úrovni. Pomocí těchto operátorů můžeme všemi bity , tvořícími číslo, posunout směrem doprava nebo doleva. Operátor
Charakteristika
<<
bitový posun doleva, posun všech bitů o 1 pozici doleva
>>
bitový posun doprava, posun všech bitů o 1 pozici doprava
Pro zapsání operátoru posuvu slouží dvojice znaků: << nebo >> s počtem posunutí. x << 2;
// x posune o 2 bity doleva
y >> k;
// y posune o k – bitů doprava
Co se však stane s bity, které “přetečou” mimo rozsah čísla a čím je číslo doplněno zprava nebo zleva? Bity, které se při posunu dostanou mimo rozsah, jsou zapomenuty a chybějící bity jsou doplněny nulami. číslo x před posuvem
1100 0011
posun o 1 bit doleva
x << 1
1000 0110
posun o 2 bity doprava
x >> 2
0011 0000
85
13.7 Přístupové operátory ( .) a ( ->) slouží k přístupu k položkám struktury nebo unionu. Více si o nich řekneme v příštím roce.
13.8 Oddělovací operátor Operátor sekvenčního vyhodnocování – operator čárka se používá k vytváření sekvenčních výrazů. Operátor se vyhodnocuje tak, že se vyhodnotí první operand (výsledek vyhodnocení je "zapomenut"), vyhodnotí se druhý operand a jeho hodnota je rovněž výsledkem vyhodnocení celého sekvenčního výrazu. Praktické využití tohoto operátoru je především v řídících řádcích cyklů, o kterých budeme hovořit v kapitolách věnovaných cyklům.
Shrnutí kapitoly Jazyk C obsahuje bohatou sadu operátorů, které můžeme rozčlenit nejen podle počtu operandů, ale také podle jejich funkce. Tedy podle druhu programovacích operací, které je uskutečňují.
Kontrolní otázky a úkoly Napište jaké hodnoty budou uloženy v proměnných a,b,c pro každý příklad (počítejte stále jen s počátečními hodnotami!) Pro kontrolu správnosti vašeho výpočtu vypište hodnoty proměnných v programu. int a=1, b=3, c=4; 1) c*=b-2; 2) c -=2+a++; 3) a +=--b*10; 4) c +=a*b--; 5) a+=b; 6) b-=a++; 7) a+=--b; 8) c+=5 - a++; 9) c %= b; 10) c %= ++b + 4;
86
14 Priorita a pořadí vyhodnocování Obsah hodiny Seznámíme se s realizací programových operací, které jsou předepsány jednotlivým operátorům.
Cíl hodiny Po této hodině budete schopni: ● ● ● ● ●
kategorizovat operátory podle priorit použít prioritní pravidla vyhodnotit jednoduché výrazy a přiřazení aplikovat uzávorkování u problémových výrazů vyhodnotit jednoduché výrazy
Klíčová slova Operand, operátor, asociativita, priorita, prioritní pravidla, hierarchie operátorů, preference, výraz, podvýraz, postranní efekty,
Při popisu některých operátorů jsme si uváděli jejich prioritu, která stanovuje, která část výrazu se vyhodnotí dříve a která později. Pro každý typ operátoru je přesně určeno, v jakém pořadí se budou vyhodnocovat jeho operandy. Díky znalosti způsobu vyhodnocování výrazů můžeme případně zasáhnout použitím kulatých závorek tak, aby výsledek operace odpovídal našemu očekávání. Moje rada tedy zní v případě nejistoty používejte závorky! Komplikovaný výraz lze v naprosté většině případů rozepsat do několika méně komplikovaných, byť za cenu částečné ztráty efektivnosti programu. Je to někdy rychlejší cesta k doladění programu než přemítání nad prioritami operátorů. Následující tabulka - tabulka preferencí udává jednak prioritu jednotlivých operátorů – hierarchii operátorů (od nejvyšší po nejnižší) a dále jejich asociativitu (v jakém pořadí se budou vyhodnocovat). Pokud se v tabulce nachází několik operátorů na jednom řádku, znamená to, že mají stejnou prioritu vyhodnocování.
87
Pr. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15.
Operátory Typ operátoru ( ) [ ] -> . Postfixové ! ~ ++ -- + - (typ) * & sizeof Unární * / % multiplikativní + Aditivní << >> bitového posuvu < > <= >= Relační == != rovnosti & bitový AND ^ bitový XOR | bitový OR && logický AND || logický OR ?: ternární operátor = *= /= += -= %= >>= <<= &= |= ^= Přiřazení , operátor čárky
Asociativa zleva doprava zprava doleva zleva doprava zleva doprava zleva doprava zleva doprava zleva doprava zleva doprava zleva doprava zleva doprava zleva doprava zleva doprava zprava doleva zprava doleva zleva doprava
Příklad Vyhodnoťte následující výraz, kterému předchází definiční deklarace: signed int x = 7; y = 9; x++ - y / 4; Řešení: Nejdříve výraz: x++
priorita 2.
výsledek 8
pak výraz: y / 4
priorita 3.
výsledek 2
a nakonec výraz: 8 – 2
Příklad Dávají tyto dva výrazy stejný výsledek ? a) 0 && 1||1 b) 0 && (1||1) Řešení: Ne, první je pravdivý, druhý je nepravdivý. Pokud se na jedné úrovni výrazu vyskytuje více operátorů téže priority, jsou příslušné operace vyhodnocovány podle jejich asociativity zleva doprava nebo zprava doleva. Asociativita je vlastnost operátorů, podle níž dokáže překladač určit, zda se operátor váže (čili asociuje) s levým nebo pravým operandem. Pořadí dané asociativitou bude vždy dáno dvěma směry: buď zleva doprava, nebo zprava doleva. Také asociativita může být zastíněna použitím závorek.
88
Příklad Vyhodnoťte následující výraz, kterému předchází definiční deklarace: int x = 50; y = 2, z= 4 ; x * y % z; Řešení: Vzhledem k tomu, že operátory * a % mají stejnou prioritu, musí si překladač pomoci jejich asociativitou. Ta má orientaci zleva doprava, což znamená, že výraz bude vyhodnocen jako ( x * y) % z. Pro uvedenou deklaraci s inicializací pak hodnota výrazu bude 0: ( 50 * 2) % 4.
14.1 Postranní efekty Ovšem pozor! Pořadí vyhodnocení inkrementace (dekrementace) ve výrazu není normou jazyka C nijak dáno. Tudíž není zaručeno, že každý překladač pořadí výpočtu vyhodnotí stejně. Vlastně i jeden překladač se na různých místech může v zájmu optimalizace programu rozhodnout k různému pořadí vyhodnocování výrazu. Následující konstrukci výrazu by jste se měli vyhýbat. Odhalit proč se program nechová, jak má, kvůli jinému vyhodnocování různými překladači, bývá zdlouhavé.
Příklad Vyhodnoťte následující výraz, kterému předchází definiční deklarace: int x = 2; x + ++x; Problémové řešení: Příklad demonstruje nebezpečnost podobných zápisů. Před vyhodnocením celého výrazu má proměnná x hodnotu 2. Bohužel ale nevíme, který z operandů operátoru + bude vyhodnocen dříve. Bude-li to levý operand, bude mít celý výraz hodnotu 5. Pokud však bude jako první vyhodnocen pravý operand, bude hodnotou výrazu číslo 6. Proto je dobré takovéto výrazy nepoužívat a radši je rozepsat do více kroků tak, aby na jednu proměnnou byl aplikován vždy maximálně jeden operátor s postranním efektem.
89
Příklad Vyhodnoťte následující výraz, kterému předchází definiční deklarace: int x, y = 5; x = y+++++y; Problémové řešení: Po této operaci bude y rovno sedmi (dvakrát se inkrementuje). Ale co x? Může se to vyhodnotit jako 5+6, nebo jako 5+7? V tomto případě by vám ani závorky nepomohli. Překladač si totiž řekne: „První y se má zvýšit až po použití ve výrazu, tj první y bude 5“. A teď si může říct 2 věci: „ y už jsem použil, můžu ho inkrementovat“, nebo si to neřekne a přejde na vyhodnocování druhého y, které inkrementuje (na 6), obě čísla sečte (5+6) a až teď teprve se rozhodne, že provede postfixovou inkrementaci y a zvýší jej na 7.
Příklad Vyhodnoťte následující výraz, kterému předchází definiční deklarace: int x = 5; int y = (--x) * (--x); Problémové řešení: Kritické místo je ve vyhodnocení výrazu (--x) * (--x). Podle překladače můžeme získat výsledek hodnoty 9. Hodnota x je dvakrát dekrementována předtím, než je vynásobena. Jiný překladač hlásí výstup 12, čímž dává najevo, že průběh vyhodnocení je jiný.
90
Shrnutí kapitoly Priorita operátoru určuje, jak jsou operátory spojovány, kdy jeden operátor uzavírá jiný. Například * má větší prioritu než +. Takže výraz a + b * c znamená b krát c a pak se k výsledku přičte a, tedy: (a + (b * c)). Pokud jsou operátory sobě rovny a jsou užity zároveň, začínají se seskupovat podle jejich asociativity buď zleva doprava, nebo zprava doleva. Takže výraz a - b + c je seskupen jako (a - b)+c, ale výraz a=b=c je seskupen jako a = (b = c), nebo se jedná o několikanásobné přiřazení. Pokud si nejsme jisti, jakou prioritu a asociativitu mají operátory v zapsaném výrazu, můžeme si pomoci uzávorkováním části výrazu (čili podvýrazu), které mají být provedeny před ostatními. Vložíme-li podvýraz do závorek, zvyšujeme preferenci jeho zpracování.
Kontrolní otázky a úkoly Pro následující deklarace s inicializací vyhodnoťte následující výrazy a určete správný výsledek. 1) Proměnné int a=3, b=2, c=1; jsou po přiřazení : c - = - b + a ++; a) a=2, b=2, c=1 b) a=4, b=2, c=0 c) a=4, b=2, c=2 d) a=3, b=2, c=1 2) Proměnné int a=1, b=3, c=4; jsou po přiřazení : c+= 5 – a++; a) a=2, b=2, c=8 b) a=4, b=2, c=7 c) a=2, b=3, c=8 d) a=3, b=2, c=8 3) Proměnné int a=2, b=2, c=1; jsou po přiřazení : --b * c++ - a; a) a=2, b=2, c=1 b) a=2, b=1, c=2 c) a=2, b=1, c=3 d) a=3, b=2, c=1
91
15 Použití operátorů v programech Obsah hodiny Zopakujeme si probranou látku z předcházejících kapitol. Na konkrétních příkladech si procvičíme tvorbu jednoduchých matematických výrazů a na základě aplikace probrané teorie sestavíme programy.
Cíl hodiny Po této hodině budete schopni: ● ● ●
vytvořit matematické výrazy použít matematické funkce ve výrazech vytvářet programy jednoduchých úloh
Klíčová slova Ludolfovo číslo, přetypování
15.1 Tvorba matematických výrazů Výpočty se v jazyce C zapisují obdobně jako v matematice. Operátory + a – jsou stejné, násobení se zapisuje hvězdičkou *, dělení lomítkem /. Hvězdičku je nutno psát vždy, není možno ji vynechávat podobně, jako symbol násobení v matematice. Násobení a dělení má přednost před sčítáním a odčítáním, stejně jako v matematice. Pokud chceme výraz vyhodnotit v jiném pořadí, je nutné použít závorky. Jak zapisovat některé jednoduché matematické výrazy si ukážeme v následujících příkladech.
Příklad Zapište v jazyce C následující matematické výrazy: 1)
2x + 3 převedeme na ( 2*x +3)/ 3*y 3y
2) y =
2 x − 10 převedeme na y = ( 2 *x – 10) / ( 5 * x + 3) 5x + 3
3) y = 2 x −
12 + 3 převedeme na y = 2 * x – 12 / ( 5 * x) + 3 5x
92
Příklad Sestavte program na výpočet hodnoty matematického
2x + 3 , kde x a y 3y
zadáte v programu jako celá čísla. Řešení: #include <stdio.h> #include int x,y; // deklarace dvou celych cisel float z; int main() { printf("Zadej cele cislo x:"); scanf(" %d",&x); printf("Zadej cele cislo y:\n "); scanf(" %d",&y); z=(float)(2*x+3)/(3*y);
// musíme přetypovat
printf("\n Hodnota promenne vyrazu= %4.2f",z); getch(); return(0); }
Příklad Sestavte program na výpočet aritmetického průměru ze tří zadaných celých čísel. Řešení: #include<stdio.h> #include int main() { int a,b,c; float vysledek; printf("Zadej tri cela cisla"); scanf("%d %d %d",&a,&b,&c);
93 vysledek=(a+b+c)/ (float)3;
// přetypování jinak- vysledek=(a+b+c)/3.0;
printf("Aritmeticky prumer je %.3f",vysledek); // Výpočet ve výpisu: printf("Aritmet. prumer cisel %d;%d;%d je %.3f\n",a,b,c,(float)(a+b+c)/3); getch(); return(0); }
15.2 Matematické funkce Standardní knihovna <math.h> obsahuje spoustu funkcí, které vykonávají běžné matematické operace. Jejich parametry i návratové hodnoty jsou většinou typu double: double round(double x); Zaokrouhlí číslo na nejbližší celé číslo. double exp(double x);
Vrací hodnotu e umocněnou na x.
double log(double x);
Vrací hodnotu přirozeného algoritmu x.
double log10(double x);
Vrací hodnotu desítkového logaritmu x.
double pow(double x, double y); Vrací hodnotu x na y . double sqr(double x);
Vrací druhou mocninu z čísla x.
double sqrt(double x);
Vrací odmocninu z čísla x.
double sin(double x);
Vrací sinus argumentu.
double cos(double x);
Vrací kosinus argumentu.
double tan(double x);
Vrací tangens argumentu.
Kromě funkcí, nalezneme v této knihovně také užitečnou konstantu M_PI π - Ludolfovo číslo - 3,14159265… V knihovně <stdlib.h> nalezneme funkci vracející absolutní hodnotu argumentu typu int. int abs(int x); Jak budeme zapisovat mocniny a odmocniny? Druhou mocninu nejsnáze vypočteme, když číslo násobíme samo sebou, nebo použijeme funkci sqr() či pow(). y = x2 převedeme y = x * x nebo na y = sqr(x) či y = pow(x, 2) Druhou odmocninu y=
x převedeme na y = sqrt(x) nebo na y = pow(x, 0.5)
94
Příklad Zapište v jazyce C následující matematické výrazy: 1) x2 x
převedeme na pow(x,2) * pow(x,0.5) nebo na
2) x3 + x2 + x
převedeme na pow(x,3) + pow(x,2) + x nebo na
3) y = (x + 2x3) 2
x + 2y + 3
4
sqr(x + 2 * pow(x,3))
převedeme na z = pow(x + 2 * y, 0.5) + 3
nebo na 5) y =
pow(x,3) + sqr( x) + x
převedeme na y = pow(x + 2 * pow(x ,3),2)
nebo na 4) z =
sqr(x) * sqrt(x)
sqrt(x + 2 * y) + 3
převedeme na y = pow(x + 1, 0.25)
x +1
Příklad Sestavte program na výpočet přepony pravoúhlého trojúhelníka. Řešení: #include <stdio.h> // pro funkčnost printf( ) #include // pro funkčnost getch() #include <math.h> // pro použití matematických funkcí int main() { int a,b; float c; printf("zadej 2 odvěsny"); scanf("%d%d" ,&a ,&b); c=sqrt(a*a+b*b);
// nebo c = pow( pow(a,2) + pow(b,2), 0.5)
printf("odvěsna je %f",c); getch(); return 0; }
95
Příklad Sestavte program, který převede zadané celé číslo (i záporné) na číslo nezáporné s použitím abs(x). Řešení: #include <stdio.h> #include #include <stdlib.h> int x,y; int main() { printf("Zadej cele cislo x:"); scanf(" %d",&x); y =(x<0)? abs(x): x; printf("\n Hodnota promenne y = %d",y); getch(); return(0); }
Příklad Sestavte program na výpočet obvodu kružnice a obsahu kruhu při zadání poloměru. Řešení: #include <stdio.h> #include #include <math.h> int main() { int r; float O,S; printf("Zadej polomer kruznice:"); scanf(" %d",&r); O = 2*M_PI * r; printf("\n Obvod kruznice je %4.5f",O);
96 S= M_PI * pow(r, 2); printf("\n Obsah kruhu je %4.5f",S); getch(); return(0); }
Příklad Vypočítejte: a) 1/3
// 0
b) 7/2
//3
c) 0/5
//0
d) 1%3
// 1
e) 7%2
// 1
f) 0%5
// 0
g) -5/3
// -1
h) 5/ -3
// -1
i) -5/ -3
// 1
j) -5 % 3
// -2
k) 5% -3
// 2
Příklad Sledujte na následujícím fragmentu programu použití ternárního operátoru k určení sudosti nebo lichosti celého čísla. Řešení: int main() { int a; printf("Zadej cele cislo \n"); scanf("%d",&a); (a%2==0) ? printf("je sude") : printf("je liche"); ….}
97
Příklad Promyslete si na následujícím fragmentu programu použití vícenásobného přiřazení a konverzi typu. int a; float b; b=a=3.14159;
Příklad Na následujícím fragmentu programu si promyslete použití vícenásobného (několikanásobného) přiřazení. int main() {double a,b,c,d; a=3; b=4; c=5; d=34; d/=c+=b*=a; //Tento příkaz má stejný význam jako: d/=(c+=(b*=a)); // a tedy jako příkaz:
d=d/(c=c+(b=b*a));
….}
Příklad Převeďte do jazyka C: a) a ≥ 5
// a>=5
b) x není 0
// x!=0
c) 2 ≤ z ≤ 5,3
// (z>=2) && (z<=5.3)
d) x> 6 nebo x< -3
// (x>6) || ( x<-3)
e) x>2 a zároveň x<10,5
// (x>2) && ( x<10.5)
f) x ∈ <2; 5.3)
// (x>=2 ) && ( x<5.3)
g) x ∉ ( 2;5>
// (x<=2) || ( x>5)
Příklad Vyhodnoťte relace: a) 3 > 5 <=( 7< 3)
// false <= false = true
b) 2 = 2 > ( 5 = 5)
// true > true = false
98
Shrnutí kapitoly V této kapitole jsme si prostřednictvím ukázkových příkladů a programů zopakovali znalosti z předcházejících kapitol, které byly věnovány výrazům, operátorům a prioritě operátorů.
Kontrolní otázky a úkoly 1) Vytvořte program s proměnnými int i=5, j,k;. Pro tyto proměnné vypište výsledky (všechny tři proměnné) následujících příkazů a přiřazení (správnost zkontrolujte vlastním výpočtem): a) i++; b) k=++i; c) j =k--; d) k=--j+5; e) k=--i*j++ 2) Zapište v jazyce C následující matematické výrazy: a)
x + y + 3x 2
b) x 3 x − 1 3) Vytvořte program, který načte od uživatele poloměr a výšku. Vypočtěte a vypište objem válce a kužele s danými rozměry zaokrouhlený na 3 desetinná místa. Hodnotu π definujte jako konstantu rovnu hodnotě 3,14159265. Válec - V = π ⋅ r 2 ⋅ v
1 Kužel - V = π ⋅ r 2 ⋅ v 3
4) Je dán poloměr podstavy a výška nádoby tvaru válce (v centimetrech). Vypočítejte objem vody (v litrech), která se vejde do nádoby. 5) Vytvořte program, který načte od uživatele souřadnice dvou bodů v rovině. Vypočtěte vzdálenost těchto bodů. 6) Načtěte od uživatele reálné číslo. Vypočtěte a vypište zaokrouhlené výsledky : a) absolutní hodnotu zadaného čísla b) druhou a třetí mocninu zadaného čísla c) druhou a třetí odmocninu jeho absolutní hodnoty
99
16 Vstup a výstup Obsah hodiny Seznámíme se s funkcemi pro vstup a výstup čísel a znaků.
Cíl hodiny Po této hodině budete schopni: ● ● ●
správně načíst a vypsat číslo nebo znak vhodně navrhnout formátové specifikace účelně používat escape sekvence
Klíčová slova Formátová specifikace, adresní operátor, konverze, escape sekvence, přesnost.
Protože programovací jazyk C má malé jádro, musí většinu funkcí připojovat. K tomu je však potřeba do zdrojového souboru přidat příslušnou hlavičku funkce, které jsou nejčastěji umístěny v hlavičkových souborech s příponou *.h. Pro formátovaný vstup a výstup musíme přidat do programu příkaz: #include <stdio.h> // zde není středník !!
16.1 Formátovaný vstup a výstup Aby uživatel mohl s programem aktivně pracovat, používáme vstupní a výstupní funkce. Formátovaný vstup a výstup zajišťují tyto funkce: pro vstup
scanf (“ formátovací řetězec”, adresy);
pro výstup
printf (“formátovací řetězec “, proměnné či výrazy);
První parametr, který je ohraničen uvozovkami, určuje formát vstupu či výstupu. Dále následují jména proměnných, která se načítají či vypisují.
100
Příklad scanf("%d", &a); //načte dekadické celé číslo a uloží na adresu proměnné &a - představuje adresu místa v paměti. Informuje překladač, kde leží proměnná a, do níž se uloží přečtená hodnota. printf("%d", a);
// vypíše v dekadickém tvaru obsah proměnné a
Příklad Program načte z klávesnice dvě celá čísla, uloží jejich hodnoty do proměnných. Proměnné vypíše. Dále vypíše jejich součin a rozdíl. #include <stdio.h> #include
// pro funkčnost getch()
int main( ) { int a,b; printf("Zadej dve celočíselne promenne "); scanf("%d", &a); scanf("%d", &b); // nebo scanf("%d %d", &a ,&b); /* Nesmíte zapomenout uvést adresní operátor &, jinak se načtená hodnota uloží někam do paměti a ne na adresu určené proměnné */ printf("a = %d ", a); printf("b = %d", b); // nebo printf("a = %d: b = %d", a,b); printf("Soucin cisel %d a %d je %d\n",a, b, a * b); printf("Rozdil cisel %d a %d je %d\n",a, b, a - b); getch(); return 0; }
101
16.2 Formátová specifikace Formátová specifikace má obecně následující tvar: % [ přesnost ] [ modifikátor ] konverze Konverze je označena jedním znakem, mezi znakem % a označením konverze mohou být umístěné další (nepovinné) parametry jako modifikátory či přesnost. Konverze pro printf() a scanf() jsou stejné. c
znak
d
desítkové číslo typu signet int
ld
desítkové číslo typu long int
u
desítkové číslo typu unsigned int
lu
desítkové číslo typu unsigned long int
f
float
Lf
long double
lf
double
x
hexadecimální číslo (např. 1a2)
X
hexadecimální číslo (např. 1A2)
E
výpis v semilogaritmickém tvaru ( např. 0,123 bude 1.23 E-002)
o
oktálové číslo
s
řetězec
Příklad Následující program vypíše hodnotu proměnné a v desítkovém, oktálovém a hexadecimálním tvaru takto: 28, 34, 1c, 1C. Zkontrolujte správnost výpisu prostřednictvím ASCII tabulky. #include <stdio.h> #include main() { int a=28; printf(“ %d, %o, %x, %X”, a, a, a, a); getch(); return(0); }
102
16.2.1
Přesnost
Zapisuje se desetinnou tečkou. Přesnost je dekadické číslo, které pro konverze d, i, o, u, x, X znamená minimální počet cifer na výstupu, pro konverze f znamená počet cifer za desetinnou tečkou a pro konverzi s maximální počet znaků.
Příklad Jak by jste vypsali pomocí funkce printf() číslo 123,456 jen na dvě desetinná místa? Řešení: printf( “% 0.2f ”, 123.456);
Příklad Napište program, který načte desetinné číslo a pak zvlášť zobrazí jeho celou a desetinnou část. #include <stdio.h> #include int main() { int i,j; printf("Zadejte desitinne cislo: "); scanf(" %d.%d",&i,&j); printf("Cela cast: %d, desetinna cast: %d",i,j); getch(); return (0); }
16.3 Používané řídicí znaky Ve výstupních funkcích používáme pro zápis speciálních a negrafických znaků tzv. escape sekvence, které začínají lomítkem. ‘\n‘
nová řádka
‘\a‘
pípnutí
‘\r‘
návrat na začátek řádky
‘\t‘
tabulátor
103 ‘\f‘
nová stránka či obrazovka
‘\\‘
\ (zpětné lomítko)
‘\‘‘
‘ (apostrof)
‘\‘‘‘
‘’ (úvozovky)
Příklad Jak by jste vypsali pomocí funkce printf() text: Sleva 50% puvodni ceny ? Řešení: printf( “Sleva 50%% puvodni ceny”); Jaký výstup bude mít následující program ? #include <stdio.h> main() { int a=5; float b=2.3; printf(“ Kolik stoji %s pivo? \n”, “jedno”); printf(“\n Promenna a= %d”,a); printf(“\t Promenna b= %5.2f”,b); printf(“ \n Celociselna promenna je %d, realna promenna je %f”,a, b); return(0);}
Příklad Jaký výstup bude mít následující program ? #include <stdio.h> #include main() { printf("James Bond \\ \" Agent 007 \" \\ 150 \% zaruka \nSpol. s rucenim neomezenym"); getch(); return(0); }
104
Příklad Program načte z klávesnice dvě celá čísla, vypíše je v opačném pořadí a uloží jejich hodnoty do proměnných. Proměnné vypíše. Dále vypíše jejich součin a rozdíl. Načte reálné číslo a vypíše jej na dvě desetinná místa. #include <stdio.h> #include
/ pro funkčnost getch()
int main() { int x,y; float a; printf("Zadej dve cela cisla: "); scanf("%d%d",&x,&y); printf("%d %d\n",y,x);
// "%d%d" nenapíše mezeru mezi čísly
printf("Soucet cisel %d a %d je %d",x,y,x+y); printf("\nZadej realne cislo: "); // \n přechod na nový řádek scanf("%f",&a); printf("\n Zadane cislo: %10.2f",a); getch(); return(0); }
16.4 Vstup a výstup znaku Pro vstup znaku je určena funkce getchar( ) ze standardního vstupu. Pro výstup znaků na standardní výstup je určena funkce putchar( ). Používá se pro ně následující zápis: getchar (znak); putchar (znak ); Pro vstup znaku můžeme použít funkci getch( ), která se nachází v hlavičkovém souboru . Rozdíl mezi getch() a getchar() je v tom, že getchar() čeká na stisknutí klávesy Enter, kdežto getch() okamžitě reaguje na vstup.
105
Příklad Načtěte z klávesnice znak a následně jej vypište na obrazovku. #include <stdio.h> int main( ) { int znak;
//obě funkce pracují s proměnnými typu int
znak = getchar( ); putchar(znak); return(0); }
16.5 Bloky Blokem se v jazyce C rozumí část zdrojového souboru obsahující deklarace, definice a příkazy umístěné ve složených závorkách { a }. V programovacím jazyku C je možné na začátku každého bloku definovat lokální proměnné. Následující ukázka je typickým příkladem použití s dodeklarováním další potřebné pomocné proměnné.
bloku
příkazů
Příklad Sestavte program pro záměnu dvou proměnných s použitím třetí lokální proměnné. #include <stdio.h> int main() { int a=3, b=5; { int pom=a;
// deklarace lokální proměnné s inicializací
a=b; b=pom; printf(“ Po zamene a=%d, b=%d”, a,b); } // zde již proměnnou pom nemůžeme použít }
106
Shrnutí kapitoly Aby bylo možné správně používat všechny funkce pro vstup a výstup, je nutné na začátku programu připojit popis těchto funkcí. Ten se nachází v hlavičkovém souboru, který se připojí k našemu programu pomocí příkazu: # include <stdio.h>. Od té chvíle můžeme používat funkce pro vstup či výstup: printf(), scanf(), getchar(), putchar(). Pro int x; Příkaz: scanf(“%d”,,&x); •
přečte z klávesnice celé číslo a uloží ho do proměnné x
•
“%d” určuje formát čtení
•
&x je adresa proměnné x
Příkaz: printf(“%d”,,x); •
vytiskne na obrazovku hodnotu proměnné x
•
“%d” určuje formát celočíselného výpisu
Pro char zn = ’}’; Příkaz: printf((“Znak ‘ %c ’ ma ASCII kod %d a hexa kod %X”,zn, zn); •
%c určuje formát znakového výpisu
•
‘%c’ zajistí výpis znaku v apostrofech
•
%X určuje formát výpisu znaku v hexa kódu s velkými písmeny
•
vytiskne na obrazovku: Znak ’}’ ma ASCII kod 125 a hexa kod 7D.
107
Kontrolní otázky a úkoly Sestavte programy následujících příkladů: 1) Načtěte celé číslo (v rozsahu 33 – 255) a vypište jeho znakovou, oktálovou a hexadecimální hodnotu. 2) Načtěte reálné číslo x a a) vypište ho b) vypište ho zaokrouhlené na 2 desetinná místa c) vypište ho s šířkou 7 a 2 desetinnými místy d) vypište ho v semilogaritmickém tvaru 3) Načtěte od uživatele dvě celá čísla a vypište a) jejich součet, rozdíl a součin b) výsledek celočíselného dělení a zbytek po celočíselném dělení c) výsledek reálného dělení 4) Načtěte od uživatele tři malá písmena a vypište je jako tři velká písmena v obráceném pořadí.
108
17 Založení projektu konzolové aplikace Obsah hodiny Nastíníme si základní obsluhu vývojového prostředí Turbo C++ v jeho konzolové aplikaci.
Cíl hodiny Po této hodině budete schopni: ● ● ● ●
spustit konzolovou aplikaci orientovat se v základech používání vývojového prostředí vyhledávat, editovat a ukádat vlastní programy vytvářet logickou stromovou strukturu svých programů
Klíčová slova Vývojové prostředí, uživatelské rozhraní, konzolová aplikace, grafické rozhraní, stromová struktura
Turbo C++ je nástroj, se kterým budeme moci rychle a efektivně pracovat. Proto bychom měli věnovat pozornost jeho tzv. vývojovému prostředí – uživatelskému rozhraní. Která okna zde nalezneme? Jak vkládáme program? Jak začneme? Po spuštění Turbo C++ se nám otevře následující obrazovka, v níž klikneme na New Project. Z okna New Items vybereme Console Application. Ujistíme se že Source Type je nastaven na C a je zaškrtnuto Console Application a klikneme na OK. Konzolová aplikace představuje program, jenž běží v okně příkazového řádku. Je to tedy program, který pracuje s textovým vstupem a výstupem. Konzolová aplikace je velmi výhodná, neboť uživatel není zatížen tvorbou grafického rozhraní programu, a tak se plně soustředí na proces vymýšlení a zapisování algoritmů. Dialog uživatele s konzolovou aplikací je veden tímto stylem: uživatel zadá vstupní data, která pak program zpracuje a oznámí uživateli výsledek své činnosti. Samozřejmě, že v jazyce C lze psát i „okenní“ aplikace, tedy programy s přívětivým vizuálním prostředím. Problém je v tom, že abychom byli schopni vytvořit aplikaci s grafickým uživatelským
109 rozhraním, musíme být pokročilými programátory v C. Snad se jimi stanete po zvládnutí tohoto modulu.
Automaticky se zobrazí kostra programu. Červeně zdůrazněné řádky nejsou pro nás nějak důležité, můžeme je tedy smazat.
Navíc hned doporučuji doplnit jednu knihovnu, která je pro většinu programů nezbytná, a to knihovnu, kterou potřebujeme pro funkci getch(). # include
110
Příklad Sestavte program na výpis součtu a součinu dvou celých čísel a, b. Řešení: #include <stdio.h> #include int main() { Int a,b,soucet, soucin; printf("Zadej prvni číslo : \n"); scanf(" %d",&a); printf("Zadej druhé cislo : \n "); scanf(" %d",&b); soucet=a + b; soucin=a * b; printf("Soucet cisel = %d \n",soucet); printf("\Soucin cisel = %d \n",soucin); getch(); return (0); }
111 Po napsání prvního programu nadešel čas k jeho překladu a spuštění. V horní liště vybereme Run, a v kontextové nabídce znovu Run (a nebo zmáčkneme klávesu F9)
Program se zkompiluje. Tento proces by neměl trvat dlouho, podle složitosti programu a HW konfigurace počítače nejvýše pár sekund. Během kompilace již nic neměníme a nejlépe na nic neklikáme.
Sestavili jsme první program v Editoru, do práce byl povolán preprocesor a Compiler se spojovacím programem Linkerem, jejichž společným úsilím vznikl spustitelný (*. exe) soubor našeho prvního programu.
112 Vyzkoušejte si tedy jeho správnou funkci. Heuréka – takle rychle jsme vytvořili náš první program. Chcete-li jej ukončit, klikněte na uzavírací symbol v pravém horním rohu uživatelského okna ( černé okno) a Turbo C++ opět převezme řízení. Před spuštěním každého programu by mělo předcházet jeho uložení. Když ukládáte poprvé, tak si z nabídky File vyberte Save As.. a program uložte. Potom při práci vám stačí pouze klávesová zkratka Ctrl + S, která vám zdrojový kód uloží pod stále stejným názvem, nemusíte tedy pořád ukládat „jako“ něco jiného.
Pro ukládání vámi vytvořených školních souborů si vytvořte složku PROGRAMOVANI, kterou si rozdělíte na jednotlivá cvičení:CV1, CV2…Vámi vytvořené programy pak budete ukládat pod vhodně zvolenými jmény s příponou ( *.c) nebo ( *.cpp) právě do připravených složek jednotlivých cvičení. Spustitelné soubory ( *.exe) vám doporučuji průběžně mazat, neboť vám zaberou mnoho místa a vy si je můžete kdykoliv vytvořit po spuštění souboru ( *.c) resp.(*.cpp). Pokud si budete chtít otevřít již vytvořený soubor, tak si z nabídky File vyberte Open…Vytvořený soubor můžete dále upravovat, přepracovávat a uložit buď pod stejným jménem (File - Save) nebo soubor můžete přejmenovat (File - Save as). V průběhu vaší práce můžete mít otevřeno více souborů. Práci s nimi můžete ukončovat jednitlivě (File - Close) nebo najednou (File - Close All). Pokud chcete ukončit svou práci v Turbo C++, doporučuji nejdříve uzavřít všechny soubory (File - Close All), a potom ukončit přes (File - Exit).
113 Jak by mohla vypadat stromová struktura vašich souborů:
Shrnutí kapitoly Naučili jsme se spustit konzolovou aplikaci vývojového prostředí Turbo C++. Zorientovali jsme se s možnostmi tvorby, editace a ukládání námi vytvořených programů.
Kontrolní otázky a úkoly 1) Jak se jmenuje vývojové prostředí ve kterém budeme programovat? 2) Proč budeme zatím používat jen konzolovou aplikaci? 3) Navrhněte a připravte si vlastní stromovou strukturu ve vašem kontu!
114
18 Sekvence a řídící struktury Obsah hodiny Seznámíme se s dělením základních řídících struktur. V této kapitole se zaměříme na jednu ze tří základních typů algoritmu, a to na sekvenci.
Cíl hodiny Po této hodině budete schopni: ● ● ●
sestavit algoritmus dané úlohy zakreslit vývojový diagram a jemu odpovídající program vytvářet sekvenční programy
Klíčová slova Řídící struktury, sekvence, alternativa, iterace, sekvenční bloky
18.1 Řídící struktury V kapitole algoritmizace jsme se naučili formulovat problém, analyzovat úlohu, vytvořit algoritmus a sestavit vývojový diagram. Po zvládnutí základů programovacího jazyka můžeme přistoupit k poslednímu kroku algoritmizace, a to k sestavení programu na základě tří základních řídících struktur: a) Sekvence - posloupnosti b) Alternativy - větvení c) Iterace – cyklů, opakování
18.2 Sekvence - posloupnost Sekvence jsou jedním ze základních stavebních kamenů algoritmů. Existuje sice málo postupů, ve kterých by jste vystačili pouze se sekvencí, ale právě sekvence jsou součástí všech algoritmů, tedy i těch nejsložitějších. Sekvence je sled za sebou navazujících dílčích kroků, jejichž pořadí je předem pevně dáno a žádný krok nemůže být vynechán.
115 Každá sekvence příkazů má svůj začátek a konec, které jsou ohraničeny znaky { } – sekvenční bloky. V těchto složených závorkách mohou být jak libovolné příkazy, tak i další sekvence.
18.2.1
Sekvence s jedním sekvenčním blokem Zapis v jazyce C { Příkaz 1; Příkaz 2; }
Příklad Sestavte vývojový diagram a program na výpis vaší vizitky. Řešení: #include<stdio.h> #include int main() { printf("\n Ing. Jan Novak"); printf("\n Svazacka 22 \nOstrava - jih \n700 30"); getch(); return(0); }
116
Příklad Sestavte vývojový diagram a program na výpočet matematického výrazu: 2a + 3 3b Řešení: #include <stdio.h> #include int main() { //deklarace lokálních proměnných int a,b; float c; printf("Zadej dve cela cisla - a,b:"); scanf(" %d %d ",&a, &b); c=(float)(2*a+3)/(3*b); printf("\n Hodnota promenne c = %4.2f",c); getch(); return(0); }
Příklad Sestav vývojový diagram a program, který načte malé písmeno a převede jej na písmeno velké. Řešeni: Při řešení příkladu využijeme znalosti ASCII tabulky. Zde je pořadí malého a jeho odpovídajícího velkého písmene nižší o 32 míst.
117 #include <stdio.h> #include int main() { char z; printf("Zadej male pismeno: "); scanf(" %c",&z); z=z-('a'-'A'); // z=z-32; printf("Velke pismeno: %c",z); getch(); return(0); }
Příklad Jak se změní kód programu, pokud budeme požadovat vypsat na výstupu kromě velkého písmena i jeho oktálovou a hexadecimální hodnotu ? Nástin úpravy řešeni: { char z; printf("Zadej male pismeno: "); scanf(" %c",&z); z=z-('a'-'A'); // z=z-32; printf("Velke pism.:%c,oktalova: %O a hexadecimalní:%X hodnota",z,z,z); …..}
118
18.2.2
Sekvence se dvěma sekvenčními bloky
Sekvenční řízení programu se skládá z bloků, které mohou být vnořeny jeden do druhého. Do bloku uzavíráme sekvenci dvou a více příkazů, které spolu logicky souvisejí. Každý blok musíme uzavřít mezi { a }. V bloku můžeme, kromě již zmíněné realizace dvou a vice příkazů, provádět lokální deklaraci a definici. Ty ovšem pouze na začátku bloku. Jejich platnost je omezena na blok a případné další vnořené bloky. Není na škodu si uvědomit, že tělo každé funkce je blokem. Proto jsme mohli v těle funkce main( ) deklarovat a používat lokální proměnné.
Nástin možného zápisu: int main( ) { Deklarace lokálních proměnných pro funkci main( ); Příkaz 1; Příkaz 2; { Deklarace lokálních proměnných pro blok ; Příkaz 1_podbloku; Příkaz 2_podbloku; Příkaz 3_podbloku; } }
Příklad Sestavte vývojový diagram a program na záměnu dvou proměnných. Řešení: S algoritmem tohoto příkladu jsme se již seznámili v kapitole Grafické vyjádření algoritmu. Proto si jen připomeňme, že záměnu dvou proměnných jsme prováděli prostřednictvím třetí proměnné – pom.
119
#include <stdio.h> #include int main() { int a,b; printf("Zadej dve cela cisla:a,b\n"); scanf("%d%d",&a,&b); printf("Pred zamenou:a=%d, b=%d\n ",a,b); // Zacatek vnoreneho bloku { // Deklarace lokalnich promennych bloku int pom; pom=a; a=b; b=pom; // Konec vnoreneho bloku } printf("Po zamene:a=%d, b=%d\n ",a,b); getch(); return(0); }
120
Shrnutí kapitoly Algoritmus jakéhokoliv programu může být sestaven ze tří řídících struktur – sekvence, alternativy a iterace. V této kapitole jsme vytvářeli pouze posloupnost příkazů bez opakování nebo větvení. Pracovali jsme tedy s nejjednodušší řídící strukturou - sekvencí. Sekvenční řízení programu se skládá z bloků, které mohou být vnořeny jeden do druhého. Do bloku uzavíráme sekvenci dvou a více příkazů, které spolu logicky souvisejí. Každý blok musí být vždy uzavřen mezi {a}.
Kontrolní otázky a úkoly
Zakreslete vývojový diagram na jehož základě sestavíte program následujících příkladů: 1) Zadejte stranu, výšku pravoúhlého trojúhelníka a vypočtěte jeho obsah. 2) Zadejte 2 celá čísla a vypočtěte jejich součet, součin, celočíselný, reálný podíl a zbytek po celočíselném dělení. 3) Je dán poloměr podstavy a výška nádoby tvaru válce (v centimetrech). Vypočítejte objem vody ( v litrech), která se vejde do nádoby. V = π ⋅r2 ⋅v, 4) Zadanou rychlost v m/s převeďte na km/h. 5) Je dán poloměr koule. Spočítejte její objem a povrch podle známých 4 matematických vzorců. V = πr 3 , S = 4πr 2 3 6) Spočítejte výšku rotačního kužele, je-li zadán jeho objem a poloměr 1 podstavy. V = π ⋅ r 2 v 3 7) Zadej velké písmeno a vypište jeho odpovídající malé písmeno s pořadím v ASCII tabulce. 8) Jsou dány hodnoty dvou odporů v ohmech. Určete hodnotu celkového odporu při jejich sériovém a paralelním zapojení. 9) Napište program, který připočítává 20% daň k ceně zboží. Např.: zadejte cenu bez daně 100 Kč, pak prodejní cena s daní bude 120 Kč 10) Načtěte od uživatele počet odpracovaných hodin a hodinovou sazbu a vypočtěte výši mzdy po zdanění (20%).
121
19 Typy větvení, větvení úplné Obsah hodiny Rozlišíme větvení na několik typů. Seznámíme se s tvorbou typických algoritmů a programů s úplnou alternativou - větvením.
Cíl hodiny Po této hodině budete schopni: ● ● ●
sestavit algoritmus úlohy s úplným větvením sestavit algoritmus úplného větvení se sekvencí příkazů zakreslit vývojový diagram a jemu odpovídající program
Klíčová slova Alternativa, if (jestliže), else (jinak), { (začátek) a } (konec) – uzavírají sekvenci, alternativa se sekvencí příkazů
Větvení neboli alternativu použijeme tam, kde podle okolností mají být některé kroky v posloupnosti vynechány, přidány nebo nahrazeny jinými. Větvení obsahuje obvykle tři části. První částí je otázka, na kterou existuje kladná nebo záporná odpověď. Druhou částí je krok, který se provede v případě kladné odpovědi na otázku. Třetí částí je krok, který se provede v případě záporné odpovědi na otázku. První část větvení (otázka) je povinná, zbylé dvě části jsou nepovinné. Pokud však současně chybí druhý i třetí krok, ztrácí větvení smysl. Rozlišujeme několik typů větvení - alternativy: a) úplné b) neúplné c) vnořené d) několikanásobné Každý z výše jmenovaných typů větvení může být i se sekvencí příkazů v jednotlivých částech větvení.
122 V úplném větvení jsou zařazeny kroky pro kladnou i zápornou odpověď. Zápis v jazyce C: if (podmínka) Příkaz_1; else Příkaz_2; Za klíčovým slovem if následuje podmínka povinně uzavřená do závorek. Je-li podmínka pravdivá (nenulová), potom se provede Příkaz_1, je-li podmínka nepravdivá (nulová) provede se Příkaz_2. Protože if jednoduše testuje číselnou hodnotu podmínky, je možné použít jisté programátorské zkratky. Příkladem, který se nám nabízí je: if ( podmínka) místo if ( podmínka !=0)
Příklad Pro načtené reálné číslo a zjistěte, zda je nebo není prvkem intervalu <2;5). Sestavte vývojový diagram a program. Řešení: #include<stdio.h> #include int main( ) { float a; printf("\nZadej cislo: "); scanf("%f",&a); if ((a>=2)&&(a<5)) printf("Cislo je v intervalu"); else printf(" Cislo neni v intervalu"); getch(); return(0); }
123
Příklad Ve vývojovém diagramu nemusíme používat jen syntaxi jazyka C. V podmínkách se může objevit i matematický zápis, proto si zopakujme převod matematického zápisu do zápisu jazyka C: a) 2 ≤ z ≤ 5,3
// (z>=2) && (z<=5.3)
b) x> 6 ∪ x< -3
// (x>6) || (x<-3)
c) x>2 ∩ x<10,5
// (x>2) && (x<10.5)
d) x ∈ <2; 5.3)
// (x>=2) && (x< 5.3)
e) x ∉ ( 2;5>
// (x<=2) || (x>5)
f) c ∈ < ‘A’,’Z’>
// (c>=’A’) && (c<=’Z’)
124
Příklad Jak se změní program a jemu odpovídající vývojový diagram, pokud hranice intervalu zadáme až na vstupu ?
Řešení:
125 #include<stdio.h> #include int main( ) { float a; int D,H; printf("\nZadej cislo: "); scanf("%f",&a); printf("\nZadej dolni a horni hranici intervalu: "); scanf("%d",&D); scanf("%d",&H); if ((a>=D)&&(a
Příklad Sestavte program a vývojový diagram. Přečtěte znak, a není-li to ani písmeno ani číslice, pak vytiskněte hlášení: „Interpunkční znak“, v ostatních případech pak vytiskněte hlášení: „Alfanumerický znak“. Řešení: kostra programu int main() {
char c;
printf("Zadej znak: \n"); scanf(" %c",&c); if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9')) printf("Alfanumericky znak \n"); else printf("Interpunkcni znak \n"); … }
126
Ve vývojovém diagramu nemusíme používat jen syntaxi jazyka C. V podmínce se může objevit i matematický zápis: c ∈ < ‘A’,’Z’> ∪ < ‘a’,’z’> ∪ < ‘0’,’9’>
127
Příklad Zadejte bod v rovině a zjistěte, zda leží uvnitř nebo vně obdélníka ohraničeného body [0,0],[2,0],[2,2] a [0,4]. Sestavte vývojový diagram k vytvořenému programu. Řešení 1: int main() { int x,y; printf("Zadej souradnici x = "); scanf("%d",&x); printf("Zadej souradnici y = "); scanf("%d",&y); if ((x>=0) && (x<=2) && (y>=0) && (y<=4)) printf("Bod nalezi obdelniku."); else printf("Bod nenalezi obdelniku."); return(0); } Řešení 2: použijeme celočíselnou proměnnou hodnota, které bude přiřazena 0, pokud bod v obdélníku neleží. {int x,y, hodnota; printf("Zadej souradnici x = "); scanf("%d",&x); printf("Zadej souradnici y = "); scanf("%d",&y); hodnota = (x>=0) && (x<=2) && (y>=0) && (y<=4); if (hodnota)
// totéž jako if (hodnota != 0)
printf("Bod lezi v obdelniku."); else printf("Bod nenalezi obdelniku."); return(0); }
128
19.1 Úplné větvení se sekvencí příkazů V úplném větvení se sekvencí příkazů jsou opět zařazeny kroky pro kladnou i zápornou odpověď. Avšak v alespoň jedné větvi se nachází sekvence dvou nebo více příkazů:P_1,P_2,.....P_n, nebo O_1,O_2,….O_n. Již dva po sobě jdoucí příkazy tvoří sekvenci a musíme je uzavřít mezi {(begin – začátek) a } (end – konec). Zápis v jazyce C: if (podmínka) { P_1; P_2; …} else { O_1; O_2; O_3; …} Štábní kultura – doporučení: Příkazy logicky související uzavřené mezi { (begin) a } (end) pište pod sebe, neboť špatné odsazení textu ve zdrojovém kódu může mást.
129
Příklad Sestavte vývojový diagram a program, který načte dvě celočíselné proměnné a vypíše je dle velikosti. V bloku použijeme lokální definiční deklaraci:(int pom=a;)
Řešení:
#include <stdio.h> #include int main() { int a,b ; printf("Zadej cislo: "); scanf("%d",&a); printf("Zadej cislo: "); scanf("%d",&b); if (a>b) { int pom=a; a=b; b=pom; printf("%d %d",a,b); } else printf("%d %d",a,b); getch(); return(0); }
130
Příklad Sestavte program, který převádí zadanou délku ve stopách na metry nebo z metrů na stopy. Řešení: Všimněte si, že použití bloku příkazů umožňuje programu vyžádat si konkrétní jednotku délky. int main() { int volba; float delka; printf(" 1: Stopy na metry. 2: Metry na stopy.\n"); printf(" Zadej volbu \n"); scanf("%d",&volba); if (volba==1) { printf(" Zadej pocet stop:\n"); scanf("%f",&delka); printf(" Metry: %f ", delka/3.28); } if (volba==2) { printf(" Zadej pocet metru:\n"); scanf("%f",&delka); printf(" Stopy: %f ", delka * 3.28); } return(0); }
131
Shrnutí kapitoly Alternativa neboli větvení nám zajišťuje provedení příkazu na základě podmínky. Rozlišujeme alternativu – úplnou, neúplnou, vnořenou a vícenásobnou. Obecný zápis úpné alternativy: if (podmínka) příkaz_1; else příkaz_2; Za klíčovým slovem if následuje podmínka povinně uzavřená do závorek. Je-li podmínka pravdivá (nenulová), potom se provede příkaz_1, je-li podmínka nepravdivá (nulová) provede se příkaz_2. V úplném větvení se sekvencí příkazů jsou zařazeny kroky pro kladnou i zápornou odpověď. Avšak alespoň v jedné větvi se nachází sekvence dvou či více příkazů, které jsou uzavřeny mezi { a }. V tomto bloku můžeme deklarovat lokální proměnné s účinností v rámci bloku.
Kontrolní otázky a úkoly Zakreslete vývojový diagram, na jehož základě sestavíte program následujících příkladů: 1) Zadej celé číslo a napište, zda je nebo není větší než 5. Program vyzkoušejte pro hodnoty : -3, 5 a 7. 2) Pro zadané celé číslo určete, zda je sudé nebo liché. Použijte celočíselné dělení. 3) Napište program, který pro načtené celé číslo určí, zda je toto číslo dělitelné 3 bezezbytku. 4) Bez použití funkce abs() vypočítejte absolutní hodnotu celého čísla. 5) Načtěte dvě celá čísla, a půjde-li to, vypočítejte jejich celočíselný podíl a zbytek po celočíselném dělení. 6) Napište program, který načte od uživatele souřadnice bodu v rovině. Zjistěte, zda tento bod leží nebo neleží na přímce: 3x + 2y – 3 = 0. 7) Načtěte bod v rovině a zjistěte, zda leží či neleží uvnitř obdélníka, jehož vrcholy zadáte. 8) U načteného znaku zjistěte, zda je či není alfanumerický. 9) U načteného znaku zjistěte, zda je či není interpunkční znak ( ‘?’,’.’,’!’). 10) Načtěte dva znaky a vypište znak s menší ordinální hodnotou (s nižším pořadím v ASCII tabulce).
132
20 Větvení - ternární operátor Obsah hodiny Seznámíme s použitím podmíněného - ternárního operátoru při tvorbě programů na úplnou alternativu.
Cíl hodiny Po této hodině budete schopni: ● ●
správně zapsat ternární operátor vhodně navrhnout program s použitím podmíněného operátoru
Klíčová slova Ternární operátor, podmíněný operátor
Jazyk C nabízí pro úplnou alternativu náhradu ve formě podmíněného operátoru – ternárního operátoru (? :). Příklad kódu vidíme na následujících řádcích: if (a
133 Pomocí ternárního operátoru řešte úkoly v následujících příkladech:
Příklad Jak slovně popíšete následující zápis ? int x; x = (x>5) ? 1 : 0; Řešení: Pokud je proměnná x větší než 5, přiřaď do proměnné x hodnotu 1, jinak x přiřaď hodnotu 0.
Příklad Sestavte program, který vypíše, zda načtené číslo je sudé nebo liché. Řešení: int main() { int a; printf("Zadej cislo \n"); scanf("%d",&a); (a%2==0) ? printf(" cislo je sude") : printf(" cislo je liche"); return 0; }
Příklad Načtěte znak a rozhodněte, zda byl načtený znak otazník. Řešení: int main() { char a; printf ("Zadej znak\n"); scanf (" %c", &a); (a=='?')? printf("Zadal jsi otaznik"):printf("Zadal jsi jiny znak"); getch(); return 0; }
134
Příklad Zadejte dvě celá čísla a půjde-li to, vypočtěte jejich podíl. Sestavte program, který vypíše výsledek dělení nebo text“ Nelze delit 0 !“ Řešení: int main() { int a,b; printf("Zadej dve cela cisla:\n"); scanf("%d %d",&a, &b); (b!=0)?printf("%d / %d =%6.2f\n",a,b,(float)a/b):printf("Nelze delit 0!"); return 0; }
Příklad Sestavte program, který vypíše, zda načtený bod v rovině je či není prvkem obdélníka daného následujícími body [0,0],[2,0],[2,4] a [0,4]. Řešení: int main() { int x_b,y_b,hodnota; printf("Zadej souradnici x = "); scanf("%d",&x_b); printf("Zadej souradnici y = "); scanf("%d",&y_b); hodnota=((x_b>=0) && (x_b<=2) && (y_b>=0) && (y_b<=4)); if (hodnota==1)
// totez jako if (hodnota != 0)
printf("Bod nalezi obdelniku."); else printf("Bod nenalezi obdelniku."); return(0); }
135
20.1 Generátor náhodných čísel Náhodné číslo generuje program z času preprocesoru. Ten se neustále, v každém zlomku sekundy mění. Takže po přidání známých i neznámých proměnných vzniká generátor náhodných čísel. Naši předchůdci vytvořili dva nástroje pro práci s náhodnými čísly: rand() a srand(), které jsou definovány ve standardním hlavičkovém souboru <stdlib.h>. Funkce rand() vrací pseudonáhodné číslo v rozmezí <0;RAND_MAX). Do x je uloženo náhodné celé číslo v rozsahu <dolni_mez;horni_mez), tedy <dolni_mez; horni_mez -1>: x = rand()%(horni_mez – dolni_mez + 1) + dolni_mez; Příklad použití: Do x1 je uloženo náhodné celé číslo v rozsahu<0;100) tedy <0; 99>: x1=rand()%100 ; Do x2 generuje náhodné celé číslo z intervalu <3,34) tedy <3;33>: x2= rand()% 31 +3; Pseudonáhodné proto, protože vrací čísla z číselné řady generované na základě nějakých matematických podmínek. Aby tato čísla nebyla při spuštění programu generována vždy stejně, nastaví se počátek této řady pomocí funkce srand(), pro níž potřebujeme hlavičkový soubor .
Příklad Vygenerujte a vypište číslo z intervalu <0; 9> = <0;10) a <-10;10> Řešení: #include <stdio.h> // Pro funkčnost printf() #include // Pro funkčnost getch() #include <stdlib.h> // Pro funkčnost srand() a rand() #include // Pro funkčnost time() int main( ) {int cislo; srand (time(NULL));
//inicializace generátoru náhodných čísel
cislo = rand()%10; //generuje náhodné celé číslo z intervalu <0,9>
136 printf("Nahodne cislo je %d \n", cislo); //generuje náhodné celé číslo z intervalu <-10,10> cislo = rand()% 21-10; printf("Nahodne cislo je %d", cislo); getch(); return 0; }
Příklad Vygenerujte číslo z intervalu <-50,20) a zjistěte, zda bylo vygenerováno číslo z intervalu (-10,10>. Řešení: Do programu nezapomeňte vložit všechny potřebné knihovny: #include <stdio.h> #include <stdlib.h> #include #include int main( ) {int x; srand (time(NULL)); x=rand()%71-50; printf("Cislo :%d",x); ((x>-10)&&(x<=10))?printf("je z intervalu"):printf("neni z intervalu"); getch(); return 0; }
Otázky k zamyšlení 1) Sestavte vývojový diagram výše uvedeného programu. 2) Jak vygenerujete náhodné číslo typu float? 3) Můžete vygenerovat i znak?
137
Shrnutí kapitoly Ternární operátor ? : má stejný význam jako příkaz if – else. Používáme jej v těch případech, kdy je jeho použití výhodnější kvůli kratšímu zápisu na jeden řádek: a ? b : c . Nejprve se vyhodnotí logická hodnota a. Je-li splněna, je výsledkem výrazu b, v opačném případu c.
Kontrolní otázky a úkoly Pomocí generátoru náhodných čísel řešte úkoly v následujících příkladech: 1) Vygenerujte celé číslo a vypište jen to, které je sudé a patří do intervalu <2;22>. 2) Vygenerujte celé číslo z intervalu < 3;33> a vypište jen to, které není dělitelné číslem 3. 3) Vygenerujte celé číslo a rozhodněte, zda patří nebo nepatří do intervalu <5;25> nebo <33;66>. ( Napište jednou podmínkou!) Pomocí ternárního operátoru řešte úkoly v následujících příkladech: 4) Načtěte znak a rozhodněte, zda to bylo písmeno malé abecedy. 5) Načtěte znak. Jestliže bylo načteno písmeno malé abecedy, změňte jej na písmeno velké abecedy. 6) Vytvořte program, který bude na základě volby uživatele počítat obvod nebo obsah čtverce se zadanou délkou strany. Mějte tři celočíselné proměnné ctverec, volba a strana. Načtěte proměnné volba a strana. Jestliže byla do proměnné volba načtena 1, uložte do proměnné ctverec obsah čtverce o zadané straně strana. Jinak do ctverec uložte jeho obvod. Hodnotu ctverec vypište. 7) Napište program, který načte tři reálná čísla. Rozhodněte, zda lze sestrojit trojúhelník s délkami stran, které byly zadány.
138
21 Větvení - ošetření nežádoucích důsledků Obsah hodiny Seznámíme se s tvorbou typických algoritmů a programů s úplnou alternativou - větvením. Upozorníme na využití větvení k ošetření nežádoucích důsledků při tvorbě algoritmu a programu.
Cíl hodiny Po této hodině budete schopni: ošetřit nežádoucí důsledky v algoritmech rozvětvit algoritmus v případech, kdy přichází v úvahu nějaké nežádoucí možnosti
● ●
Klíčová slova Alternativa, if, else, dělení, výraz s odmocninou, funkce
21.1 Ošetření nežádoucích důsledků Jedním z nejčastějších a nejdůležitějších důvodů, proč používáme v algoritmu větvení je ošetření nežádoucích důsledků. Jak už víme, správný algoritmus – program, musí dojít vždy do konce. Musí mít připravenou cestu pro všechny možnosti, které mohou nastat, tedy i pro ty, kde zadaná úloha nemá řešení a došlo by k havárii (ať už v běžném životě, nebo ve virtuální realitě počítačového programu). Je to především: •
dělení
•
výpočet výrazu s odmocninou
•
některé další funkce (například geometrické – tangens)
Při tvorbě algoritmu je potřeba pečlivě zvážit, zda v některém kroku není skryto nebezpečí havárie. Pokud krok toto nebezpečí skrývá, musíte nejdříve otestovat, zda jej můžete provést. Na základě výsledku testu se algoritmus rozvětví – krok buď provedete, nebo volíte jinou cestu, ve které se krok neprovede. Typickým příkladem pro použití rozhodovacího nežádoucích důsledků je operace dělení.
bloku
k odvrácení
139
Příklad Sestavte vývojový diagram dělení dvou čísel. Jsou dána čísla A a B, o nichž není známo nic bližšího. Sestavte vývojový diagram a následně program pro výpočet jejich podílu: C = A / B. S analýzou a následnou tvorbou algoritmu jsme se již setkali v kapitole Etapy řešení algoritmické úlohy. Připomeňme si jeho vývojový diagram a sestavme nástin programu: Řešení: int main() { int A,B; printf("Zadej dve cela cisla: "); scanf(" %d %d",&A, &B); if (B!=0) { int C;
// Deklarace lokální proměnné pro blok
C=(float)A/B;
// Přetypování
printf(" Podil je %5.2f“, C); } else printf(" Nulou nelze delit"); return(0); }
140
141
Příklad Vytvořte algoritmus pro výpočet výrazu se zlomkem. x=
a+b c+d
Řešení: Zlomkovou čáru nahradíme lomítkem: x = (a + b) / (c + d) Přepisujeme-li výraz se zlomkovou čárou do tvaru s lomítkem, nezapomeneme čitatele i jmenovatele ( každého zvlášť) uzavřít do závorek, abychom zachovali původní pořadí vyhodnocování matematických operací.
#include <stdio.h> #include int main() { int a,b,c,d; float x; printf ("Zadej a,b,c,d \n"); scanf ("%d",&a); scanf ("%d",&b); scanf ("%d",&c); scanf ("%d",&d); if(a+b==0)printf("Deleni nulou "); else { x=(float)(a+b)/(c+d); printf(" x = %f ",x); } getch(); return(0); }
142
Příklad Vytvořte algoritmus pro výpočet výrazu s odmocninou. a+b
Řešení: Přepisujeme-li výraz pod odmocninou do tvaru s použitím funkce sqrt() nebo pow(), nezapomeneme vše, co bylo původně pod odmocninou, uzavřít do závorek, abychom zachovali původní pořadí vyhodnocování matematických operací. V podmínce se vyhodnotí situace – proběhne testování. V případě nevyhovující možnosti musí být v algoritmu – programu připraveno řešení. #include <stdio.h> #include int main() { int a,b,c,d; float x; printf ("Zadej a,b \n"); scanf ("%d",&a); scanf ("%d",&b); if (a+b<0) printf("Neexistuje reseni v R "); else { x=pow((a+b),0.5); printf("x = %f ",x); } getch(); return(0); }
143
Shrnutí kapitoly Správný algoritmus – program, musí vždy dojít ke zdárnému konci. Proto musíme mít připraveny možnosti, které mohou nastat při ošetření nežádoucích důsledků.
Kontrolní otázky a úkoly Zakreslete vývojový diagram, na jehož základě sestavíte program k výpočtu následujících výrazů: 1)
3a + b b−2
2)
a+5
3) a 2 a 4)
a+3 b−2
5)
3 + b −1 a−2
6)
2a + 3
b+4 5
149
22 Větvení neúplné Obsah hodiny Seznámíme se s tvorbou algoritmů a programů s použitím neúplné alternativy – větvení.
Cíl hodiny Po této hodině budete schopni: ● ●
vhodně navrhnout vývojový diagram s neúplným větvením sestavit program s použitím neúplné alternativy
Klíčová slova Neúplná alternativa, neúplné větvení, if ( jestliže)
Abychom lépe pochopili rozdíl mezi úplnou a neúplnou alternativou– větvením, zopakujme si nejprve alternativu úplnou. V úplném větvení jsou zařazeny kroky pro kladnou i zápornou odpověď. if (podmínka) Příkaz_1; else Příkaz_2; Za klíčovým slovem if následuje podmínka povinně uzavřená do závorek. Je-li podmínka pravdivá (nenulová), potom se provede Příkaz_1, je-li podmínka nepravdivá (nulová) provede se Příkaz_2. V neúplné alternativě jsou zařazeny kroky pouze pro kladnou odpověď: if (podmínka) Příkaz_1; Za klíčovým slovem if následuje podmínka povinně uzavřená do závorek. Je-li podmínka pravdivá (nenulová), potom se provede Příkaz_1, je-li podmínka nepravdivá (nulová) pokračuje se v programu dále.
150
Příklad Sestavte vývojový diagram a program, který určí, zda načtené číslo je větší, rovno nebo menší než nula.
Řešení:
int main( ) { int cislo; printf("\n Zadej cele cislo: "); scanf("%d",&cislo); if (cislo<0) printf("Cislo je mensi nez nula"); if (cislo==0) printf("Cislo se rovna nule"); if (cislo>0) printf("Cislo je vetsi nez nula"); getch(); return(0); }
151
Příklad Sestavte program, ve kterém načtete souřadnice levého horního a pravého dolního rohu obdélníka. Pak zadejte souřadnice libovolného bodu v rovině a rozhodněte, zda bod leží či neleží v obdélníku. Řešení: int main() { int xlh,ylh,xps,yps,x,y; printf("Zadejte souradnice leveho horniho rohu ve tvaru x,y : "); scanf("%d,%d",&xlh,&ylh); printf("Zadejte souradnice praveho spodniho rohu ve tvaru x,y : "); scanf("%d,%d",&xps,&yps); printf("Zadejte souradnice libovolneho bodu ve tvaru x,y : "); scanf("%d,%d",&x,&y); if((x < xlh) || (x > xps) || (y > yps) || (y < ylh)) printf("Zadany bod nelezi v obdelniku"); else printf("Zadany bod lezi v obdelniku"); if (x == xlh) printf("\nBod lezi na horni hrane obdelnika"); if (y == ylh) printf("\nBod lezi na leve hrane obdelnika"); if (x == xps) printf("\nBod lezi na spodni hrane obdelnika"); if (y == yps) printf("\nBod lezi na prave hrane obdelnika"); getch(); return(0); }
152
Příklad Načtěte čtyři samostatné znaky 0 nebo 1, které budou společně představovat jednocené číslo zapsané ve dvojkové soustavě. Vyjádřete toto číslo v desítkové soustavě. Řešení: #include<stdio.h> #include int main() { char a,b,c,d; int v=0; printf("Zadej bit cislo 3: "); scanf(" %c",&a);
// uvodni mezera ve format. retezci nevadi
printf("Zadej bit cislo 2: "); scanf(" %c",&b);
// uvodni mezera ve format.retezci zpusobi preskoceni
// znaku CR po stisku klavesy ENTER v minulem scanf printf("Zadej bit cislo 1: "); scanf(" %c",&c);
// uvodni mezera ve format.retezci zpusobi preskoceni
// znaku CR po stisku klavesy ENTER v minulem scanf printf("Zadej bit cislo 0: "); scanf(" %c",&d); // znaku CR po stisku klavesy ENTER v minulem scanf printf("\nCislo v bin. soustave: %c%c%c%c",a,b,c,d); if (a=='1') v += 8; if (b=='1') v += 4; if (c=='1') v += 2; if (d=='1') v += 1; printf("\nCislo v des.soustave: %d",v); getch(); return(0); }
153
22.1 Neúplné větvení se sekvencí příkazů V neúplném větvení se sekvencí příkazů je opět zařazena pouze část pro kladnou odpověď. Tato část však obsahuje sekvenci dvou nebo více příkazů:P_1,P_2,.....P_n. Již dva po sobě jdoucí příkazy tvoří sekvenci a musíme je uzavřít mezi {begin – začátek) a } (end – konec). Zápis v jazyce C: if (podmínka) { P_1; P_2; }
154
Shrnutí kapitoly Rozhodovací – podmíněný příkaz if jednostranné podmínky. Jeho obecný zápis:
umožňuje
větvení
podle
if ( podmínka) příkaz; Neúplná alternativa je shodná s úplnou pouze s tím rozdílem, že v ní chybí příkaz else. Je-li podmínka nepravdivá (nulová), pokračuje se dále v programu.
Kontrolní otázky a úkoly Zakreslete vývojový diagram, na jehož základě sestavíte program následujících příkladů: 1) Načtěte celé číslo a určete, zda je dělitelné 3 bezezbytku. 2) Načtěte celé číslo a určete, zda je sudé, liché nebo rovno nule. 3) Načtené celé číslo a určete, zda je uvnitř, vně nebo na hranici intervalu <-10;10>. 4) Vypočtěte absolutní hodnotu načteného celého čísla. Přičemž platí, že absolutní hodnota záporného čísla je totéž číslo s opačným znaménkem. 5) Pokud zadaný znak bude malé písmeno, převeďte jej na velké. 6) Přečtěte tři velká písmena a napište je uspořádaná podle abecedy. 7) Napište program pro výpočet reálných kořenů kvadratické rovnice : Ax2 + Bx + C = 0. Uživatel zadá hodnoty koeficientů A, B, C. Ošetřete nulový a záporný diskriminant. 8) Načtěte souřadnice bodu v rovině a určete, ve kterém kvadrantu takto zadaný bod leží. 9) Načtěte od uživatele souřadnice bodu v rovině. Zjistěte, zda tento bod leží na, pod nebo nad přímkou 3x + 2y – 3 = 0. 10) Načtěte souřadnice bodu v rovině. Zjistěte, zda tento bod leží uvnitř, vně nebo na obvodu kruhu o poloměru 10 se středem v bodě [0,0]. (Pro body kružnice platí vzorec x 2 + y 2 = 100 )
155
23 Větvení vnořené Obsah hodiny Seznámíme se s tvorbou algoritmů a programů s použitím vnořené alternativy – vnořeného větvení.
Cíl hodiny Po této hodině budete schopni: ● ● ●
vhodně navrhnout vývojový diagram s vnořenou alternativou sestavit program s použitím vnořené alternativy využít vnořené alternativy se sekvencí příkazů
Klíčová slova if (jestliže, když), else (jinak)
Vnořené větvení znamená, že krok pro kladnou nebo pro zápornou odpověď (nebo pro obě odpovědi) je tvořen opět větvením, které se vnoří – vloží do původního větvení. if (podmínka_1) Příkaz_1; else
if (podmínka_2) Příkaz_2; else Příkaz_3;
Za klíčovým slovem if následuje podmínka povinně uzavřená do závorek. Je-li podmínka_1 pravdivá (nenulová), potom se provede Příkaz_1, je-li podmínka_1 nepravdivá (nulová) následuje opětovné větvení na základě podmínky_2. Je-li podmínka_2 pravdivá (nenulová), potom se provede Příkaz_2, je-li podmínka_2 nepravdivá (nulová) provede se Příkaz_3. Pomocí několika příkazů if často realizujeme konstrukci, které se říká ifelse-if. Nejde o žádný speciální příkaz, pouze často používanou konstrukci, pro níž se vžil tento název. Pomocí této konstrukce realizujeme složitější rozhodovací algoritmy a umožňuje nám řídit chod programu do několika větví. Štábní kultura – doporučení: Související if a else pište pod sebe,
156 neboť špatné odsazení textu ve zdrojovém kódu může mást.
Příklad Sestavte program a vývojový diagram algoritmu, který zjistí, zda číslo je menší nebo větší nebo rovno nule. Rozbor a řešení: Při rozhodování musíme řešit tři různé situace. Je možné sestavit tři neúplná větvení, která jsme použili v kapitole „Neúplné větvení“. Vhodnější je však použít vnořené větvení, které celý rozhodovací proces zkrátí a zjednoduší (nemusíme sestavovat třetí podmínku). int main( ) { int cislo; printf("\nZadej cele cislo: "); scanf("%d",&cislo); if (cislo<0) printf("Cislo %d je mensi nez nula",cislo); else if (cislo>0) printf("Cislo %d je vetsi nez nula",cislo); else printf("Cislo %d se rovna nule",cislo); return(0); }
157
Uvedený příklad je dosti elementární a možná si nyní řeknete, že vnořené větvení je zbytečné. Jeho velký přínos objevíte tehdy, když budete muset řešit nějakou situaci, která má tři varianty a jedna z těchto variant je obtížně vyjádřitelná podmínkou.
Příklad Příkladem může být situace, kdy budete muset zjistit, zda znak je malé, nebo velké písmeno nebo to vůbec není písmeno. A tady doporučuji vnořené větvení, které vám dá možnost třetí podmínku nesestavovat.
158
int main() {char zn; printf("Zadej znak: "); scanf(" %c",&zn); if ( zn>= 'A' && zn<='Z') printf(" Je to velke pismeno "); else if ( zn>= 'a' && zn<='z') printf(" Je to male pismeno "); else printf(" Neni to pismeno "); return(0); }
159
Příklad Zadejte celé číslo a napište, zda leží vně nebo na hranici nebo uvnitř intervalu <10; 100>. Sestavte vývojový diagram a program. Řešení: Algoritmus se větví do tří větví, proto stačí použít dva do sebe vnořené podmíněné příkazy.
160
int main() {int cislo; printf ("Zadej cislo "); scanf ("%d",&cislo); if ((cislo>10) && (cislo<100)) printf(" Cislo je uvnitr <10;100>"); else if ((cislo==10)||(cislo==100)) printf("Cislo na hranici <10;100>"); else printf(" Cislo je vne <10;100>"); return(0); }
Příklad Sestavte program podle následujícího vývojového diagramu. K čemu tento algoritmus slouží ?
161
Shrnutí kapitoly U vnořeného větvení dochází u kladné nebo záporné větve nebo i obou větví k opětovnému rozvětvení. Kostra zápisu vnořeného větvení v záporné části větve: if ( podmínka_1) Příkaz_1; else if ( podmínka_2) Příkaz_2; else Příkaz_3; Vnořené větvení použijeme v situaci, která má tři varianty a jedna z těchto variant je obtížně vyjádřitelná podmínkou.
Kontrolní otázky a úkoly Zakreslete vývojový diagram, na jehož základě sestavíte program následujících příkladů: 1) Pro zadané celé číslo zjistěte, zda je sudé, liché nebo rovno nule. 2) Pro náhodně vygenerované číslo z intervalu <11;99> určete, zda je liché nebo sudé nebo nula. 3) Načtěte číslo, vytiskněte zda číslo leží uvnitř nebo mimo nebo na hranici intervalu <-2;22). 4) Načtěte meze intervalu a reálné číslo R. Vypište, zda číslo je uvnitř nebo vně nebo na hranici intervalu. 5) Vypočtěte reálné kvadratické rovnice Ax2 + Bx + C = 0. Uživatel zadá hodnoty koeficientů A, B, C. Ošetřete nulový a záporný diskriminant. 6) Pro zadaný bod v rovině zjistěte, zda tento bod leží na nebo pod nebo nad přímkou 4x + 2y – 5 = 0. 7) Pro načtená tři reálná čísla představující délky stran trojúhelníka rozhodněte, zda lze tento trojúhelník sestrojit. 8) Pro zadané celé číslo zjistěte, zda jednociferné, dvojciferné nebo víceciferné. Upravte program tak, aby číslo bylo náhodně generováno z intervalu <0,321>. 9) Načtěte znak a vypište, zda jde o malé písmeno, velké písmeno nebo o jeden z interpunkčních znaků ´!´, ´.´ nebo ´?´. Upravte program tak, aby byl znak náhodně generován z intervalu <40,200>. 10) Pro načtený bod v rovině určete, zda tento bod leží uvnitř nebo vně nebo na obvodu kruhu o poloměru 10 se středem v bodě [0,0]. (Pro body kružnice platí vzorec x 2 + y 2 = 100 )
162
24 Větvení vícenásobné Obsah hodiny Seznámíme se s tvorbou vývojových diagramů a programů s použitím vícenásobného (několikanásobného) větvení – několikanásobné alternativy.
Cíl hodiny Po této hodině budete schopni: ● ● ● ●
navrhnout vývojový diagram s vícenásobnou alternativou sestavit program s použitím vícenásobné alternativy využít bloku příkazů v jedné větvi vícenásobné vhodně použít nebo vynechat break v jednotlivých větvích switche
Klíčová slova Selektor, switch, case, break, default
V případě vyhodnocování složitých výrazů, které způsobují větvení algoritmu do mnoha různých částí, není příliš praktické používat podmínky, protože je to nepřehledné. Daleko lepší je použít tzv. přepínač, který pohodlně rozdělí algoritmus na libovolný počet různých větví. Hovoříme pak o vícenásobné alternativě – vícenásobném větvení. Toto větvení slouží k rozdělení běhu programu do několika směrů na základě celočíselné hodnoty selektoru. Syntaxe vypadá následovně: switch (selector) { case hod_1: příkaz_P1; break; case hod_2: { příkaz_Q1; příkaz_Q2; break; } case hod_3: { příkaz_R1; příkaz_R2; příkaz_R3; break; } // sekvenci příkazů uzavřeme mezi složené závorky begin - end { } default: příkaz_D1; break; }
//na posledním řádku nemusí být break
163 Vícenásobná alternativa se vyhodnocuje tak, že se porovná selektor s celočíselnými nebo znakovými hodnotami ze seznamu a dojde-li ke shodě, provede se příslušný příkaz nebo sekvence příkazů. Pokud se má provést více než jeden příkaz v jedné větvi, je nutné uzavřít příslušný blok příkazů mezi { a }. Příkaz break způsobí ukončení provádění příkazu switch. Za jeho absence by se provedly i následující příkazy až po break. Příkaz default není povinný. Provede se v případě, pokud podmínce nevyhovuje žádná z nabízených hodnot. Pokud není větev default součástí příkazu switch a nenalezne shodu ani v jedné z dostupných větví case, rozhodování automaticky končí, čímž dochází k opuštění celého rozhodovacího příkazu. Vývojový diagram uvedené konstrukce:
164
Příklad Sestavte program simulující hod kostkou. Řešení: #include <stdio.h> // pro funkčnost printf() #include // pro funkčnost getch() #include <stdlib.h> // pro funkčnost srand() a rand() #include // pro funkčnost time() int main() { int c; printf(" Hazim kostkou \n"); srand((unsigned) time(NULL)); c=rand()%6+1; switch (c) { case 1:printf("padla jednicka");break; case 2:printf("padla dvojka");break; case 3:printf("padla trojka");break; case 4:printf("padla ctyrka");break; case 5:printf("padla petka");break; case 6:printf("padla sestka");break; } getch(); return(0); }.
165
Příklad Vytvořte jednoduchou kalkulačku s operacemi sčítání, odčítání, násobení a dělení. Načtěte dvě čísla x1 a x2 a zadejte aritmetickou operaci. Podle zadaného znaku aritmetické operace (+, -, *, /) program vypočítá a vypíše výsledek. Řešení:
int main() { char znak,operace; float x1,x2; printf("Zadejte prvni cislo : "); scanf("%f",&x1); printf("Zadejte operaci (+ - * /) : "); operace=getche(); printf("\n"); printf("Zadejte druhe cislo : "); scanf("%f",&x2); switch(operace) { case '+': printf("%f %c %f = %f\n",x1,operace,x2,x1+x2); break; case '-': printf("%f %c %f = %f\n",x1,operace,x2,x1-x2); break; case '*': printf("%f %c %f = %f\n",x1,operace,x2,x1*x2); break; case '/': if(x2 == 0.0) printf("Chyba - deleni nulou !\n"); else printf("%f %c %f = %f\n",x1,operace,x2,x1/x2); break; default: printf("Neznamy typ operace\n"); } getch(); return 0; }
166
Příklad Pro načtený znak rozhodněte, zda patří do skupiny znaků ( a,b,c,g) nebo do skupiny (f,i,o,p) případně do žádné. Řešení:
int main() { char znak; znak=getche(); switch(znak) { case 'a': case 'b': case 'c': case 'g': printf("\nZnak \"%c\" je ze skupiny 1\n",znak); break; case 'f': case 'i': case 'o': case 'p': printf("\nZnak \"%c\" je ze skupiny 2\n" ,znak); break; default : printf("\nZnak \"%c\" nepatri do zadne skupiny\n" ,znak); } getch(); return 0; }
167
Shrnutí kapitoly Příkaz switch plní funkci přepínače, který zjistí hodnotu selektoru a podle ní jednu z možných činností. Syntaxe jeho konstrukce je následující: switch (selector) {
case hodnota_1: příkaz_P1; break; case hodnota_2: { příkaz_Q1; příkaz_Q2; break; } default: příkaz_D1; break;
} Pokud se má provést více než jeden příkaz, je nutné uzavřít příslušný blok příkazů mezi { a }. Příkaz break je velmi důležitý. Pokud ho neuvedeme, provádějí se všechny příkazy od větve s hledanou hodnotou, až po první příkaz break. Větev default, která nemusí být nutně uvedena jako poslední, se vybírá v případě, že žádná z ostatních větví nevyhovuje.
Kontrolní otázky a úkoly Zakreslete vývojový diagram, na jehož základě sestavíte program následujících příkladů: 1) Sestavte nabídku výpočtu součtu, rozdílu, součinu a podílu dvou zadaných celých čísel. 2) Vypočtěte odpor dvou rezistorů při seriovém nebo paralelním zapojení. Při seriovém zapojení je výsledný odpor: R=R1+R2, při R1 . R2 paralelním zapojení je výsledný odpor: R = R1 + R2 3) Sestavte nabídku výpočtu obvodu a obsahu plošných obrazců. Uživatel zadá, zda chce vypočítat obvod nebo obsah čtverce, obdélníka, trojúhelníka nebo kruhu. Podle vybraného obrazce načte potřebné délky stran, výšek či poloměrů. 4) Sestavte nabídku výpočtu objemu prostorových obrazců. Uživatel zadá, zda chce vypočítat objem kvádru, válce, kužele nebo koule. Podle vybraného tělesa uživatel načte potřebné délky stran, výšek či 1 4 poloměrů.Válec - V = π ⋅ r 2 ⋅ v , kužel - V = π ⋅ r 2 ⋅ v , koule - V = π .r 3 3 3 5) Načtěte číslo měsíce a vypište jeho slovní podobu (Například. 3 březen). Pomocí dalšího switch vypište, do kterého ročního období tento měsíc patří (prosinec, leden, únor – zima; březen, duben, květen – jaro atd.)
168
25 Větvení – procvičování Obsah hodiny Na ukázkových příkladech si procvičíme všechny druhy větvení.
Cíl hodiny Po této hodině budete schopni: ● ● ● ● ●
vhodně navrhnout vývojový diagram sestavit program s volbou vhodného typu alternativy zapsat vhodně zvolenou podmínku využít ternární operátor v programu prostřednictvím vícenásobné alternativy řešit v jednom programu více příkladů
Klíčová slova Podmínky úplné, neúplné, vnořené a vícenásobné. Break, blok příkazů, default.
Větvení je vlastně výběr jedné možnosti na základě splnění určité podmínky. Po splnění podmínky se může vykonat příkaz nebo sekvence příkazů nebo další alternativa. Zopakujme si typy větvení, v předcházejících kapitolách:
které
jsme
se
naučili
používat
•
Úplné větvení – realizuje se jedna ze dvou možností na základě splnění nebo nesplnění podmínky.
•
Neúplné větvení – realizuje se jedna možnost na základě splnění podmínky. Pokud je podmínka nesplněna, nevykoná se nic.
•
Vnořené větvení – realizuje se opětovné rozvětvení u kladné nebo záporné větve nebo i obou větví.
•
Vícenásobné větvení – podle hodnoty selektoru (přepínače) se realizuje jedna z nabízených možností.
Všechny uvedené typy větvení si procvičíme na následujících příkladech.
169
Příklad Ve funkci main vytvořte pomocí příkazu switch menu, ve kterém budou volby 1 až 3 pro jednotlive úkoly : 1)
Načtěte celé číslo a s využitím ternárního operátoru vypište, zda je toto číslo sudé nebo liché.
2)
Načtěte znak - zn, vypište zda je to malé písmeno, velké písmeno nebo číslice.
3)
Načtěte celé cislo x. Jestliže je číslo x z intervalu <-15;10) vypočtěte jeho převrácenou hodnotu 1/x zaokrouhlenou na tři destinná místa, jinak vypište jeho druhou mocninu.
Řešení: int main() { int volba; printf("Zadejte cislo prikladu(1, 2 nebo 3): "); scanf(" %d", &volba); switch (volba) { case 1:{ int a; printf("Zadejte cislo: "); scanf(" %d", &a); z=a%2; (a == 0) ? printf("Cislo je sude"): printf("Cislo je liche"); }break; case 2:{ char zn; printf("Zadejte znak: "); scanf(" %c", &zn); if(zn >= ‘0‘&& zn <= ‘9‘) printf("Zadali jste cislici"); else{ if(zn >= ‘A‘&& zn <= ‘Z‘)
170 printf("Zadali jste veke pismeno"); else{ if(zn >= ‘a‘&& zn <= ‘z‘) printf("Zadali jste male pismeno"); else{ printf("Zadali jste znak,ktery neni ani pismeno ani cislice"); }}}}break; case 3:{ int x; printf("Zadejte cele cislo: "); scanf(" %d", &x); if( x >= -5 && x < 10 ) printf("Prevracena hodnota zadaneho cisla je %.3f", (float)1/x); else{ printf("Druha mocnina zadaneho cisla je %d", x*x); } } break ; default:printf("\a\a\a Zadali jste jiny znak nez 1,2 nebo 3");break; } getch(); return(0); }
Příklad Sestavte vývojový diagram k výše uvedenému programu.
Otázka k zamyšlení Jak se změní konstrukce uvedeného programu, pokud volba čísla příkladu bude dána generátorem náhodných čísel?
171
Shrnutí kapitoly Podmíněný příkaz má tvar: if (podmínka) příkaz; nebo if (podmínka) příkaz1; else příkaz2; Jazyk C umožňuje podmíněný výraz s ternárním operátorem, který má tvar: (vyraz) ? příkaz1 : příkaz2; Pro vícenásobné větvení používá programovací jazyk C příkaz switch, který se zapisuje například v následujícím tvaru: switch (selektor) {
case hodnota_1: příkaz_P1; break; case hodnota_2: { příkaz_Q1; příkaz_Q2; break; } default: příkaz_D1; break;
} Bloky příkazů jsou ohraničeny složenými závorkami { a }. V programovacím jazyku C je možné na začátku každého bloku definovat lokální proměnné, jejichž životnost je ohraničena právě tímto blokem. Následující příkaz názorně ukáže pro proměnné: int i; char zn; výhodnost použití příkazu switch: switch (i) {case 1:zn='A';break; case 2:zn='B';break; case 3:zn='C';break; default zn='D'; } Stejného výsledku by pochopitelně bylo možné dosáhnout pomocí podmíněného příkazu if – else. Stejný kód by pak vypadal: if (i==1) zn='A'; else if (i==2) zn='B'; else if (i==3) zn='C'; else zn='D'; Je zřejmé, že použití přepínače switch, je mnohem jednodušší a přehlednější.
172
Kontrolní otázky a úkoly Ve funkci main vytvořte pomocí příkazu switch menu, ve kterém budou volby 1 až 7 pro jednotlive úkoly : 1) Vypočtěte rozdíl dvou třetích mocnin zadaných přirozených čísel. Pokud tento rozdíl bude sudé číslo, zadaná čísla sečtěte a vypište jen součty z intervalu < 20;50). 2) Načtěte reálné číslo a zjistěte, zda neleží v intervalu <-5;5). Pozor! Podmínku musíte vytvořit pro podmínku neleží! 3) Načtěte celé číslo, které může být i záporné. Jestliže toto číslo bude liché, vytvořte jeho absolutní hodnotu. Řešte pomocí ternárního operátoru. 4) Vygenerujte celé číslo z intervalu <-20;30>. Pokud bude záporné, vypište jeho absolutní hodnotu. Pokud bude kladné, vypište jeho druhou mocninu. Řešte pomocí ternárního operátoru. 5) Načtěte od uživatele pH prostředí. Na základě jeho velikosti vypište, zda je toto prostředí kyselé, neutrální nebo zásadité. (Pokud je pH<7, pak je prostředí kyselé, pokud je pH=7, pak je neutrální. Pokud je pH >7, pak je prostředí zásadité). 6) Načtěte dvě celá čísla. Vypočtěte jejich celočíselný podíl, který přiřadíte do proměnné Podíl a zbytek po celočíselném dělení přiřaďte do proměnné Zbytek. Proměnnou Podíl sečtěte s proměnnou Zbytek a pokud výsledek bude nezáporný, vytiskněte tento text: „Součet je nezáporný.“ 7) Načtěte znak. Jestliže načtený znak bude malé písmeno, vypište jeho ordinální hodnotu (pořadí v ASCII tabulce). Dále vypište jeho předchůdce a následovníka. S použitím příkazu switch sestavte programy k následujícím příkladům: a) Uživatele zadá počet mobilů, které chce zakoupit. Cena za 1 mobil je 6999, - Kč, při odběru 2 nebo 3 mobilů je cena 5999, - Kč, při odběru 4, 5, nebo 6 kusů je cena 4999,- Kč a při odběru nad 7 kusů je cena jednoho 3999, - Kč. Určete celkovou částku, kterou kupující zaplatí. b) Vytvořte program „ Parkoviště “, jehož vstupem bude počet hodin (max. 12) plánovaného parkování a výstupem bude cena parkování podle uvedeného ceníku: 1 hodina 2 až 3 hodiny 4 až 6 hodin 7 až 12 hodin
20 Kč 40 Kč 60 Kč 100 Kč
173
26 Typy cyklů, cyklus s podmínkou na začátku Obsah hodiny Rozlišíme několik typů cyklů. Seznámíme se s tvorbou vývojových diagramů a programů s použitím cyklu s podmínkou na začátku.
Cíl hodiny Po této hodině budete schopni: ● ● ●
sestavit algoritmus úlohy s použitím cyklu while zakreslit vývojový diagram a jemu odpovídající program vhodně sestavit algoritmus cyklu s podmínkou na začátku, jehož tělo bude obsahovat sekvenci nebo alternativu příkazů
Klíčová slova Iterace, while(pokud), podmínka, tělo cyklu, true, false, do-while, for, řídící proměnná.
Cykly použijeme vždy tam, kde nastane potřeba některé činnosti zopakovat. To, zda se opakování provede či nikoliv, závisí na vyhodnocení určité podmínky. Průchod cyklem se terminologii programování označuje iterací cyklu. Iterace tedy označuje jedno opakování cyklu. Během jedné iterace cyklu jsou postupně zpracovány všechny programové příkazy, které jsou umístěny v těle cyklu. Po zpracování každé iterace přijímá cyklus rozhodnutí o tom,zda bude provedena další iterace cyklu, či nikoliv. Toto rozhodnutí většinou vyplývá z vyhodnocení určitého rozhodovacího výrazu (podmínky).
26.1 Typy cyklů Rozlišujeme tři typy cyklů - iterace: a) cyklus s podmínkou na začátku: while b) cyklus s podmínkou na konci: do-while c) cyklus s řídící proměnnou: for V následujících kapitolách si vysvětlíme všechny výše uvedené cykly.
174
26.2 Cyklus s podmínkou na začátku Příkaz while je prvním ze tří cyklů, které si uvedeme. Pomocí cyklů realizujeme opakování určitého příkazu v závislosti na hodnotě podmínky. Obecně tedy konstrukce while vypadá: while (podmínka) Příkaz;
// Hlavička cyklu // Tělo cyklu
Hodnota podmínky (výrazu) musí být různá od nuly (logická pravda – logická 1 - true), aby cyklus mohl pokračovat. Můžeme také říci, že výraz tvořící podmínku musí platit pro pokračování cyklu. Analogicky, bude-li podmínka nepravdivá (logická nepravda - logická 0 – false), činnost cyklu se končí a běh programu pokračuje zpracováním nejbližšího možného příkazu za cyklem. Protože test na pravdivost výrazu se provádí ještě před započetím průchodu cyklem, může nastat situace, ve které výraz neplatí již před průchodem a tělo cyklu se nikdy nevykoná. Tělo samotné je tvořeno příkazem, který může být i složený. V těle cyklu se může nacházet sekvence, větvení nebo může být vnořen i další cyklus. V případě, že tělo cyklu obsahuje pouze jeden příkaz, není nutné složené závorky použít. Konstrukce cyklu while se složeným tělem cyklu vypadá: while (podmínka) {
Příkaz_1; Příkaz_2; … Příkaz_n;
}
// Hlavička cyklu // Složené tělo cyklu
175
Příklad Sestavte program, který vypíše na obrazovku 10 krát pod sebe text: „PRG je super!“. Řešení: int main() {int i=1; while (i<=10) { printf(" %d. PRG je super!\n", i ); i++; } return (0); }
Otázky k zamyšlení 1) Sestavte vývojový diagram pro výše uvedený program. 2) Proč je ve výpisu: printf(" %d. PRG je super!\n", i ); formátová specifikace %d? 3) Jak se změní výše uvedený program pro následující zadání: a) Změňte text výpisu. „PRG umím na 100% !“ b) Změňte hodnotu i v deklaraci s inicializací. c) Přesuňte počítadlo (i++;) před printf().
176
Příklad Vypočítejte součet čísel přirozených čísel od 1 do N, kde N definujete jako konstantu. Řešte cyklem s podmínkou na začátku. Řešení: #define N 10 int main() { int suma=0, i=1; while (i<=N) { suma += i; i++; } printf("%d\n",suma); return(0); }
Otázky k zamyšlení 1) Sestavte vývojový diagram výše uvedeného programu. 2) Jak se změní program pro následující zadání: a) Zaměňte pořadí řádků: suma += i; a i++; b) Je nutná deklarace s inicializací: int suma=0, i=1; c) Vypočítejte součet přirozených čísel z intervalu < a;b>, kde a i b načtete z klávesnice. Zajistěte kontrolu a, která jsou dělitelná 3.
177
Shrnutí kapitoly Nejdříve se vyhodnotí podmínka. Má-li celočíselnou hodnotu různou od nuly, provede se tělo cyklu (jeden nebo více příkazů) a pak se provede automaticky návrat k podmínce, ta se opět vyhodnotí. Pokud má podmínka opět hodnotu různou od nuly, celá činnost se opakuje. Cyklus je ukončen až tehdy, když podmínka nabude hodnoty nula. Obecně tedy konstrukce while vypadá : while (podmínka) Příkaz;
// Hlavička cyklu // Tělo cyklu
U tohoto typu cyklu se může stát, že se tělo cyklu neprovede ani jednou! To nastane v případě, že podmínka má hodnotu nulovou již při prvním vyhodnocení.
Kontrolní otázky a úkoly Zakreslete vývojový diagram, na jehož základě sestavíte program následujících příkladů: 1) Napište na obrazovku pod sebe: a) tři krát svou vizitku b) N krát své jméno, kde N zadáte z klávesnice 2) Načítejte celá čísla do koncové značky 0. Vypište : a) počet čísel dělitelných 3 b) počet čísel v intervalu <5; 25> c) součet sudých čísel a počet lichých čísel 3) Načítejte celá čísla až do zadání čísla 888 (koncová značka). Vypište: a)
aritmetický průměr zadaných čísel
b)
počet kladných a počet záporných čísel
c)
počet zadaných čísel z intervalu , kde D a H načtete
d)
maximální a minimální zadané číslo
4) Načtěte 5 znaků z klávesnice. Vypište kolik bylo zadáno velkých a kolik malých písmen. Ostatních znaků si nevšímejte. 5) Načítejte znaky z klávesnice až do koncového znaku ‘k’ nebo’K‘. Vypište: a)
počet velkých a počet malých písmen
b)
kolik je písmen z intervalu <’L’; ‘P’>
178
27 Cyklus s podmínkou na konci Obsah hodiny Seznámíme se s tvorbou vývojových diagramů a programů s použitím cyklu s podmínkou na konci.
Cíl hodiny Po této hodině budete schopni: ● ●
sestavit algoritmus úlohy s použitím cyklu do - while zakreslit vývojový diagram a jemu odpovídající program
Klíčová slova Iterace, do - while, tělo cyklu, konstrukce.
Příkaz do - while je druhým ze tří cyklů, které si uvedeme. Jestliže jsme pochopili, jak vypadá cyklus while, tak ani cyklus do - while nám nebude připadat složitý. Musíme si zapamatovat jednu důležitou věc: cyklus do–while proběhne vždy alespoň jednou. Uskuteční se tedy alespoň jedna jeho iterace. Tato skutečnost je způsobena umístěním podmínky až za tělo samotného cyklu. Poněvadž tělo cyklu předchází testu podmínky, cyklus zahájí svou činnost vykonáním všech příkazů, které jsou v těle cyklu.
Obecně tedy konstrukce do - while vypadá :
179 do { Příkaz;
// Tělo cyklu
} while (podmínka);
// Podmínka
Má-li podmínka (výraz) celočíselnou hodnotu různou od nuly ( logickou 1 – true), provede se návrat na začátek těla cyklu, provedou se příkazy těla cyklu a opět se vyhodnotí podmínka. Tato činnost se opakuje tak dlouho, až podmínka nabude hodnotu rovnou nule ( logické 0 – false). Pak je cyklus ukončen. Tělo samotné je tvořeno příkazem, který může být i složený. V těle cyklu se může nacházet sekvence, větvení nebo může být vnořen i další cyklus. V případě, že tělo cyklu obsahuje pouze jeden příkaz, není nutné složené závorky použít. Konstrukce cyklu do - while se složeným tělem vypadá: do {
Příkaz_1;
// Složené tělo cyklu
… Příkaz_n; } while (podmínka);
Příklad Sestavte program, který vypíše na obrazovku 10 krát pod sebe text: „PRG je super!“. Řešení: int main() { int i=1; do {printf("%d. PRG je super!\n", i); i++; } while(i<=10); return (0); }
180
Otázky k zamyšlení 1)
Sestavte vývojový diagram pro výše uvedený program.
2)
Změňte deklaraci s inicializací int i=1; na int i=0;
3)
Zaměňte pořadí řádků: i++; a printf("%d. PRG je super!\n", i);
4)
Jak se změní výše uvedený program pro následující zadání: b) Zadejte N z intervalu <1; 10> jako počet výpisů daného textu. c) Počet výpisů daného textu definujte jako konstantu K.
Příklad Vypočítejte součet přirozených čísel od 1 do N, kde N definujete jako konstantu. Řešte cyklem s podmínkou na konci. Řešení: #define N 10 int main() {int suma=0, i=1; do
{ suma +=i; i++; } while (i<=N);
printf("%d\n",suma); return (0); }
Otázky k zamyšlení 1) Sestavte vývojový diagram výše uvedeného programu. 2) Jak se změní program pro následující zadání: a) Zaměňte pořadí dvou řádků: suma +=i; a i++; b) Inicializujte proměnnou i=0; c) Změňte podmínku: while (i>N); d) Vypočítej součet lichých přirozených čísel <1; N>, kde N načtete z klávesnice e) Vypočítejte součet přirozených čísel od a do b, kde a i b načtete z klávesnice. Zajistěte kontrolu a
181
Příklad Sestavte program. Načítejte celá čísla až do zadání čísla 0 (koncová značka). Vypočtěte a vypište: a) aritmetický průměr zadaných čísel b) počet čísel z intervalu <-10;10> Řešení: #include <stdio.h> int main() { int a, s=0, p=0, pint=0; float pru; do { printf("\n Zadej cislo: "); scanf(" %d",&a); // aritmetický průměr s=s+a; p=p+1; // počet zadaných čísel z intervalu< -10;10> if ((a>=-10) && (a<=10)) pint++; } while (a!=0); pru=(float)s/p; printf("Prumer cisel je %4.2f",pru); printf("\nPocet zadanych cisel v intervalu je %d",pint); getch (); return 0; }
Otázky k zamyšlení 1) Sestavte vývojový diagram výše uvedeného programu. 2) V programu změňte a komentujte výstup: a)
Zaměňte dva řádky: s=s+a; a p=p+1;
b)
Zrušte inicializaci s=0, p=0, pint=0; jen deklarujte.
c)
Proměnnou pru deklarujte typu int.
182
Příklad Sestavte program, který pro zadanou větu ukončenou tečkou nebo vykřičníkem, vypíše: počet znaků, počet malých písmen, počet mezer a počet slov ve větě. (Předpokládejte mezi slovy jednu mezeru a žádnou mezeru před závěrečnou tečkou nebo vykřičníkem.) Řešení: int main( ) { char zn; int p=0, pm=0, pmez=0, ps=0; puts("Zadejte znak \n"); do { scanf(" %c",&zn); if(zn!='\n') { p++; if(zn>='a' && zn<='z') pm++; if(zn==' ') pmez++; } } while( (zn!='.') && (zn!='!')); printf("\nPocet znaku je %d , pocet malych pismen je %d , pocet mezer je %d , pocet slov je %d ", p, pm, pmez, pmez+1); return (0); }
Otázky k zamyšlení 2) Sestavte vývojový diagram výše uvedeného programu. 3) V programu změňte a komentujte výstup: a) Je nutná deklarace s inicializací: int p=0, pm=0, pmez=0, ps=0; b) Zaměňte podmínku za while( (zn=='.') && (zn=='!')); c) Jak se změní načtení znaku, pokud nevložíte mezeru před %c ve scanf("%c",&zn); ?
183
Shrnutí kapitoly Nejdříve se vykoná tělo cyklu, pak se provede vyhodnocení podmínky. Má-li podmínka hodnotu pravda (logické 1 – true), provede se návrat na začátek těla cyklu, provedou se příkazy těla cyklu a opět se vyhodnotí podmínka. Tato činnost se opakuje tak dlouho, až podmínka nabude hodnotu nepravdy (logické 0 – false). Pak je cyklus ukončen. do { Příkaz; } while (podmínka); Při této konstrukci příkazu cyklu se tělo cyklu provede vždy alespoň jednou!
Kontrolní otázky a úkoly Zakreslete vývojový diagram, na jehož základě sestavíte program následujících příkladů: 1) Vypočtěte obvod a obsah čtverce o straně a. Zajistěte, aby výpočet proběhl pouze tehdy, jestliže strana a bude mít velikost větší než nula. (V opačném případě nemá smysl výpočet provádět). 2) Vypište posloupnost čísel 1,2,…n, kde každé číslo bude napsáno na samostatném řádku. Nejvyšší napsané číslo musíte zadat z intervalu <1;30>. 3) Přečtěte P čísel z klávesnice (P zadáte také z klávesnice). Pro každý vstup vypište: Zadej 1. číslo, Zadej 2. číslo Z těchto čísel určete, kolik jich leží v intervalu < 1;25>. Zeptejte se, zda chcete opakovat A/N. 4) Načítejte celá čísla do koncové značky 888. Vypište : a) počet čísel dělitelných 5 b) počet čísel v intervalu <-10; 10> c) součet lichých čísel 5) Načítejte celá čísla do koncové značky 999. Vypište : a) počet lichých čísel v intervalu < 3; 33> b) minimální a maximální hodnotu c) pořadí minima a pořadí maxima d) součet lichých čísel
184
28 Cykly řízené podmínkou - procvičování Obsah hodiny Shrneme výhody a nevýhody cyklů řízených podmínkou.
Cíl hodiny Po této hodině budete schopni: • • •
využívat v algoritmech cykly s podmínkou rozpoznat, kterou variantu cyklu je vhodné do algoritmu zařadit vysvětlit rozdíl mezi rozhodováním a cykly
V algoritmech velmi často nastává situace, kdy musíme některé činnosti zopakovat. To, zda se opakování provede či nikoliv, závisí vždy na vyhodnocení určité podmínky (otázky). Buď přesně známe, kolikrát se má činnost opakovat, pak podmínkou kontrolujeme, zda již bylo opakování provedeno v potřebném počtu. Nebo opakování závisí na vzniku určité situace, např. při výpočtu dojde k překročení nějaké extrémní hodnoty, pak podmínkou kontrolujeme vznik této situace. Existují dva základní typy cyklů, a sice cyklus do-while, který nejdříve vykoná určité příkazy a pak teprve vyhodnocuje podmínku opakování, a pak cyklus while, který nejdříve vyhodnocuje podmínku opakování a pak provádí příkazy. V další kapitole je zařazen ještě cyklus s řídící proměnnou for, který je určitým zjednodušením cyklu s podmínkou na začátku. Tento cyklus je velkým zjednodušením práce programátora.
Příklad Ve funkci main vytvořte pomocí příkazu switch menu, ve kterém budou volby 1 až 11 pro jednotlive úkoly : 1)
Vypočítejte součin dvou celých čísel pomocí sčítání.
2)
Vypočítejte druhou mocninu celých čísel pomocí sčítání.
3)
Vypočítejte třetí mocninu celého čísla pomocí opakovaného sčítání.
4)
Načtěte tři celá čísla d , h , b a vypočtěte součet čísel od d do h bez čísel dělitelných číslem b. Ošetřete případ d
185 5)
Načítejte celá čísla do koncové značky K nebo k. Vypište : a) počet čísel dělitelných 5 b) počet čísel v intervalu <5; 25> c) počet sudých čísel a součet lichých čísel
6)
Načítejte čísla do koncové značky 0. V tomto souboru vyhledejte minimální a maximální hodnotu a jejich pořadí v načteném souboru.
7)
Načítejte čísla do koncové značky 333. V tomto souboru vyhledejte dvě nejmenší hodnoty a dvě největší hodnoty.
8)
Načtěte tři celá čísla d , h , b a vypočtěte součet čísel od d do h bez čísel dělitelných číslem b. Ošetřete případ d
9)
Vypočítejte kapacitu paralelního a seriového zapojení dvou kondenzátorů o zadaných kapacitách. Celkovou kapacitu počítejte jen v případě, že obě kapacity budou kladné. Kapacita paralelního spojení dvou kondenzátorů: C=C1+C2, při seriovém zapojení je výsledná kapacita: C =
C1.C2 C1 + C2
10) Vypočítejte výkon pro zadanou hodnotu odporu rezistoru a velikost protékajícího stejnosměrného proudu. Uvažte přípustné hodnoty odporu a proudu. Výpočet provádějte opakovaně. 11) Napište program pro režiséra pohádky „Dlouhý, Široký a Bystrozraký“, který v hereckém týmu hledá představitele Dlouhého. Program bude přijímat hodnoty o výškách jednotlivých herců. Po zadání nulové výšky vypíše výšku nejvyššího herce.
Kontrolní otázky a úkoly 1) 2) 3) 4)
Co je to iterace? Kdy používáme cyklus? Jaké typy cyklů znáte? V čem se liší cyklus s podmínkou na začátku s cyklem s podmínkou na konci? 5) Která s podmínek while, do – while se vždy provede alespoň jednou? 6) Platí proměnná deklarována v těle cyklu while i v závorkách za klíčovým slovem while? 7) Platí proměnná deklarována v těle cyklu do – while i v závorkách za klíčovým slovem while?
186
29 Cyklus s řídící proměnnou Obsah hodiny Seznámíme se s tvorbou vývojových diagramů a programů s použitím cyklu s řídící proměnnou.
Cíl hodiny Po této hodině budete schopni: ● ● ●
sestavit algoritmus úlohy s použitím cyklu for zakreslit vývojový diagram a jemu odpovídající program vhodně zvolit řídící proměnnou
Klíčová slova Iterace (opakování), for, start_výraz, inicializace (nastavení počátečních hodnot), podmíněný_výraz, prázdný výraz, řídící proměnná, parametr, konstrukce.
Příkaz for je posledním typem cyklu, který nám jazyk C nabízí. Předchozí typy cyklů jsou ve všech programovacích jazycích téměř totožné. Příkaz for se však svou syntaxí od ostatních jazyků liší. Jeho obecná konstrukce: for (start_výraz; podmíněný_výraz; iterační_výraz) Příkaz; Za klíčovým slovem for následují v kulatých závorkách tři výrazy. Start_výraz je vyhodnocen pouze jedenkrát, ještě před vyhodnocením podmíněného_výrazu. Slouží k inicializaci proměnných, kterou by bylo možné provést těsně před cyklem for. Start_výraz není povinný a může být i vypuštěn. Zůstane tak po něm pouze středník. Podmíněný_výraz řídí opakování cyklu a je vyhodnocen ještě před vykonáním Příkazu. Znamená to, stejně jako u cyklu while, že při neplatnosti podmínky nemusí být Příkaz nikdy vykonán. I tento výraz může být vynechán. Zní to možná zvláštně, ale prázdný výraz je jazykem C chápán jako pravdivý, a tak cyklus s chybějícím podmíněným_výrazem bude nekonečný.
187 Iterační výraz je vyhodnocován po každém průchodu cyklem. To znamená tolikrát, kolikrát je podmínka daná prostředním výrazem pravdivá. Výraz většinou slouží k úpravě proměnných, na kterých závisí další opakování. Stejně jako předchozí dva výrazy, i tento může být vynechán. Při vynechání všech tří výrazů získáme nekonečný cyklus, který nic neinicializuje a neprovádí žádné výrazy po dokončení cyklu. for ( ; ; ; ) { // Tělo cyklu }
29.1 Řídící proměnná - parametr Cyklus je řízen řídící proměnnou. Programátoři používají nejčastěji jako její identifikátor: i, j, k. Hodnoty řídící proměnné jsou omezeny počáteční start_výraz a koncovou podmíněný_výraz hodnotou cyklu. for (i = 1; i <=N; i++) { // Tělo cyklu Prikazy; }
Na začátku provádění cyklu se do řídící proměnné uloží počáteční hodnota. Pokud je pak hodnota řídící proměnné menší nebo rovna koncové hodnotě, pak se provedou tyto činnosti: •
Vykoná se tělo cyklu.
•
Provede se návrat na začátek cyklu.
•
Automaticky se zvýší hodnota řídící proměnné o 1.
•
Pokud je pak hodnota řídící proměnné menší nebo rovna koncové hodnotě (podmíněný_výraz), celá činnost se opakuje.
•
Cyklus končí tehdy, když řídící proměnná má hodnotu vyšší než je hodnota koncová.
188
Pozor chyba! Studenti často nesprávně zapisují cyklus for, kde proměnná i začíná na 1 a končí na hodnotě 10, takto: for (i=1;i ==10;i++) Příkazy; Uvědomte si, že druhý výraz v závorce je podmínka, která říká, kdy cyklus běží! Není to tedy mezní hodnota parametru cyklu. Pro lepší porozumění cyklu for si jej můžeme nahradit i cyklem while, který je na první pohled čitelnější: start_výraz; while (podmíněný_výraz) { Příkaz; iterační_výraz; } Z této konstrukce je patrné, že cyklus while a for jsou zcela zaměnitelné a záleží pouze na programátorovi, který použije.
Příklad Sestavte program, který vypíše na obrazovku 10 krát pod sebe text: „PRG je super!“. Řešení: int main() { int i=1; for (i=1;i<11; i++) { printf("%d. PRG je super!\n", i); } return (0); }
189
Otázky k zamyšlení 1)
Sestavte vývojový diagram.
2)
Jak se změní výše uvedený program pro následující zadání: a)
Změňte deklaraci s inicializací int i=1; na int i=0;
b)
Změňte hodnotu i<11 na i<= 10
c) 10>
Zadejte počet výpisů textu jako proměnnou N z intervalu <1;
d)
Počet výpisů daného textu definujte jako konstantu K.
Příklad Vypočítejte součet přirozených čísel od 1 do N, kde N definujete jako konstantu. Řešte cyklem s řídící proměnnou. Řešení: #define N 10 int main() { int suma=0, i=1; for ( i=1; i<=N;i++) {suma += i; } printf("%d\n",suma); return(0); }
Otázky k zamyšlení 1) Sestavte vývojový diagram výše uvedeného programu. 2) Jak se změní program pro následující zadání: a) Je nutné uzavřít příkaz suma += i; do { } b) Je nutná deklarace s inicializací: int suma=0, i =1; c) Vypočítejte součet přirozených čísel z intervalu < a;b>, kde a i b načtete z klávesnice. Zajistěte kontrolu a, která jsou sudá. Dolní a horní hranici intervalu načtete.
190
Shrnutí kapitoly Pro cyklus s řídící proměnnou, u kterého je znám počet opakování, se používá zápisu: for (start_výraz; podmíněný_výraz; iterační_výraz) { Příkazy; } Kde první část závorky představuje inicializaci počáteční hodnoty proměnné, která představuje čítač cyklu. Prostřední část vyjadřuje podmínku, při které se cyklus opakuje, a poslední část vyjadřuje krok o kolik se čítač mění.
Kontrolní otázky a úkoly Zakreslete vývojový diagram, na jehož základě sestavíte program následujících příkladů: 1) Vypište 10x na obrazovku : „Mám rád programování!“ 2) Načtěte počet opakování od uživatele a vypište na obrazovku daný počet své vizitky. 3) Načtěte od uživatele dvě celá čísla – hranice intervalu a vypište všechna celá čísla ze zadaného intervalu. 4) Načtěte tři celá čísla D, H, B a vypište celá čísla, která jsou dělitelná číslem B a jsou mezi . Ošetřete případ D < H. 5) Načtěte 10 znaků z klávesnice. Vypište kolik bylo zadáno velkých a kolik malých písmen. Ostatních znaků si nevšímejte. 6) Vypište tabulku ASCII kódů. Zadejte počáteční a koncovou hodnotu. a) Prohlédněte si různé části tabulky, zejména chování v oblasti znaků s ASCII kódem <0; 31> ( řídící znaky) b) Jak pozastavíte výpis tabulky na obrazovku, má-li tabulka více řádků než obrazovka ?
191
30 Skoky, přerušení a ukončení cyklu Obsah hodiny Seznámíme se se způsobem předčasného ukončení, přerušení nebo přeskoku v cyklech.
Cíl hodiny Po této hodině budete schopni: ● ● ●
vhodně použít příkaz break využívat goto s rozmyslem používat continue
Klíčová slova Break, switch, continue, goto, návěští
30.1 Break S příkazem break jsme se již setkali u příkazu switch. V cyklu for se break používá většinou v rámci nějaké podmínky. Když na něj program narazí, cyklus okamžitě skončí, i kdyby podmínka cyklu ještě platila. Říkáme, že break ukončuje nejvnitřnější cyklus. Můžeme jej použít ve všech třech typech cyklů.
Příklad Následující ukázkový program vytiskne v cyklu jen čísla od 1 do 10, přestože pracuje s cyklem for(i=1; i<=100; i++) int main() {int i; for(i=1; i<=100; i++) {printf("%d\n", i); if(i ==10) break; } return 0; }
192
Příklad Sestavte program, který nejvýše na tři pokusy uhádne číslo od 1 do 10. Řesení: Když uživatel uhádne na první nebo na druhý pokus, nemá smysl po něm chtít,aby hádal znovu. Proto v takovém případě využijeme příkaz break, který hádací smyčku ukončí. Naše tajné číslo je uloženo v proměnné tajne = 3. int main() { int i, odhad, tajne =3; printf("Hádej cislo od 1 do 10\n"); printf("Mas na to nejvyse 3 pokusy\n"); for ( i=1; i<=3;i++) { printf("Vas tip:\n"); scanf("%d",&odhad); if (odhad == tajne) {printf("Gratuluji! Uhadli jste!\n"); break; } } printf("Konec programu!\n"); return(0); } Příkaz break by jste měli používat jen střídmě. Běžná smyčka for by měla skončit jen jedním způsobem, a to nesplněním podmínky uvedené v záhlaví. Jakmile do cyklu přidáme příkaz break, už může skončit dvěma různými způsoby, váš kód se tak znepřehlední a snadno dojde k chybě.
193
30.2 Continue V rámci cyklu for se dá použít i příkaz continue. Podobně jako break se používá v těle cyklu a většinou v rámci nějaké podmínky. Když na něj program narazí, přestane provádět aktuální iteraci cyklu a pustí se do další.
Příklad Sestavte program, který uživateli účtuje po 10 Kč za každou položku, ale každý třináctý kus dává zdarma. Řesení: Po spuštění níže uvedeného programu uvidíte, že cena za 12 a 13 kusů bude stejná, zatímco za 14 kusů už zákazník zaplatí 10 Kč navíc. Za každý třináctý kus se nic neúčtuje, protože program narazí na příkaz continue a pustí se rovnou do další otáčky cyklu, aniž by přičítal 10 Kč k celkové částce. int main() { int i,pocet,celkem = 0; printf("Zadej pocet kusu:"); scanf("%d",&pocet); for(i=1; i<=pocet; i++) { if (i % 13==0) continue; celkem += 10; } printf("Cena za %d kusu je celkem %d Korun \n",pocet,celkem ); return(0); } Také příkaz continue vám doporučuji používat s rozmyslem. Jakmile do cyklu for přidáte příkaz continue, jeho logika se zkomplikuje, zdrojový kód nebude čitelný a vy můžete něco přehlédnout.
194
30.3 Goto a návěští Kromě skokových příkazů break a continue, které určeným způsobem upravují provádění cyklu, existují další příkazy na odskok z daného místa programu na jiné. Známým příkazem, hlavně z jiných programovacích jazyků, je příkaz goto. Jeho účelem je přenést běh programu na přesně označené místo. Označení místa se provádí pomocí tzv. návěští. V jazyku C je návěští jméno identifikátoru následované dvojtečkou. Například následující goto přeskočí příkaz printf( ): goto navesti; // Odtud program odskočí až do míst uvozených návěštím printf(“ Toto se nevytiskne”); navesti: printf(“ Toto se vytiskne”);
// zde bude program pokračovat
Existují situace, ve kterých může být jeho použití výhodné. Přes všechny výhody vám však doporučuji, pokud je to jen trochu možné, raději se jeho použití vyvarujte.
Příklad Tento program používá příkaz goto pro vytvoření ekvivalentu cyklu for vypisujícího čísla od 1 do 10. int main() { int i=1; znovu: printf("%d",i); i++; if ( i<=10) goto znovu; return(0); }
Dalším skokovým příkazem je return, který ukončí provádění dané funkce, ve které je zapsán a vrátí určenou hodnotu. Zatím jsme tento příkaz používali u funkce main( ).
195
Shrnutí kapitoly Break se používá v cyklu v rámci nějaké podmínky. Když na něj program narazí, cyklus okamžitě skončí, i kdyby podmínka cyklu ještě platila. Říkáme, že break ukončuje nejvnitřnější cyklus. Continue přerušuje provádění těla cyklu, vrací se zpět k podmínce cyklu a teprve podle jejího vyhodnocení se rozhodne, zda bude cyklus pokračovat či nikoliv. Goto přenáší běh programu na přesně označené místo, kterému se říká návěští.
Kontrolní otázky a úkoly 1) Napište si sami několik krátkých programů, které používají break pro ukončení cyklu. Vyzkoušejte si všechny tři příkazy cyklu. 2) Sestavte program, který vypisuje pouze lichá čísla mezi 1 až 100. Použijte cyklus for. Abyste zabránili tisku sudých čísel, použijte příkaz continue. 3) Sestavte program, který používá goto pro vytvoření ekvivalentu cyklu while k výpočtu součtu čísel od 1 do 100.
196
31 Cykly – vnořené a procvičování cyklů Obsah hodiny Procvičíme si tvorbu algoritmu všech druhů cyklů. Seznámíme se s vzájemným vnořováním cyklů.
Cíl hodiny Po této hodině budete schopni: ● ● ●
vhodně navrhnout vývojový diagram s cyklem sestavit program s volbou vhodného typu cyklu řešit prostřednictvím vícenásobné alternativy více příkladů v jednom programu
Klíčová slova Cyklus s podmínkou na začátku, cyklus s podmínkou na konci, cyklus s řídící proměnnou, vnořené cykly, vnější cyklus, vnitřní cyklus.
31.1 Vnořené cykly Cykly se dají, stejně jako větvení, vzájemně do sebe vnořovat. Efektivitu vzájemného vnořování cyklů oceníme při práci s maticí.
Příklad Vytiskněte matici o daném počtu řádků, sloupců a načteném znaku.
i - řádkový index
Řešení:
1.
X
X
X
2.
X
X
X
3.
X
X
X
4.
X
X
X
1.
2.
3.
j - sloupcový index
197 int main() { int p_radku = 4, p_sloupcu = 3; int i, j;
// indexy řídících proměnných
char zn; printf("Zadej znak:"); scanf(" %c",&zn); // Vnější cyklus
for(i = 1;i <= p_radku;i++) { printf("\n");
// Přesun kurzoru na nový řádek
for(j = 1;j <= p_sloupcu;j++)
// Vnitřní cyklus
printf("%c ", zn); } return 0; } První cyklus s řídící proměnnou i je tzv. vnější cyklus. Druhý cyklus s řídící proměnnou j se označuje jako vnitřni cyklus. S každou iterací vnějšího cyklu se provedou všechny iterace vnitřního cyklu. Kdybychom měli oba cykly přirovnat k hodinám, pak vnější cyklus by byl minutová ručička a vnitřní cyklus by byl vteřinová ručička. S každým pohybem minutové ručičky obejde vteřinovka celý ciferník. V našem programu s počtem řádků (p_radku=4) a počtem sloupců (p_sloupcu=3) projde vnitřní smyčka s každou iterací vnější smyčky všechny tři otáčky ( p_sloupcu), takže vypíše třikrát X. Vnější smyčka pak doplní přesun kurzoru na nový řádek a spustí další otáčku, takže vnitřní smyčka zase proběhne třikrát, zase vypíše tři X, vnější smyčka uzavře řádek a tak dále. Vnější smyčka se opakuje tolikrát kolik je řádků, tedy p_radku krát. Společně obě smyčky vypíší čtyři řádky po třech X. Pro i = 1 projde vnitřní smyčka: j = 1, 2, 3 a vypíše:
XXX
Pro: i = 2 opět projde j = 1, 2, 3 a připíše druhý řádek:
XXX
Pro: i = 3 opět projde j = 1, 2, 3 a připíše třetí řádek:
XXX
Pro: i = 4 opět projde j = 1, 2, 3 a připíše čtvrtý řádek:
XXX
198
Otázky k zamyšlení Jak se změní program pro následující zadání: a)
Počet řádků a sloupců definujte jako konstanty
b)
Počet řádků a sloupců načtěte v programu
c)
Můžete v programu přesunout řádek: printf("\n");?
d)
Jsou nutné fialové složené závorky { }
199
31.2 Procvičování cyklů Hlavním cílem této kapitoly je procvičit si používání všech druhů cyklů v různých algoritmech příkladů. K dispozici máme tři typy cyklů. Každý z uvedených typů cyklů je jiný a je na nás, který zvolíme. Nejvíce obecný je cyklus s podmínkou na začátku a dá se říci, že by nám úplně stačil jen tento cyklus pro vyřešení všech cyklických situaci. Ostatní dva cykly jsou zařazeny pro zjednodušení práce programátora a nesou sebou při použití určitá omezení či rizika. Omezení se týká cyklu s řídící proměnnou, kdy musíte předem znát počet opakování. Rizika jsou spojena zase s cyklem s výstupní podmínkou, kdy může dojít ke zkreslení výsledku vlivem toho, že vždy alespoň jednou se tělo cyklu vykoná.
Příklad Ve funkci main vytvořte pomocí příkazu switch menu, ve kterém budou volby 1 až 3 pro jednotlive úkoly. Ve všech příkladech ošetřete zadávání. Jestliže nebude načtena požadovaná hodnota proměnné, opakujte načítání: 1) Vygenerujte 12 celých čísel z intervalu <5;50>. Čísla vypište. Dále vypište kolik vygenerovaných čísel je dělitelných třemi a které číslo je maximální. 2) Načtěte od uživatele znaky až do zadání znaku K. Vypište kolik bylo zadáno znaků a kolik bylo zadáno znaků malé abecedy. 3) Načtěte dvě kladná celá čísla f a g a pak vypiše všechna sudá celá čísla v intervalu .
Řešení: int v;
// globální proměnná
int main() { printf("Zadejte volbu 1-3\n"); scanf(" %d",&v); switch(v) { // začátek switch
200 // Vygenerujte 12 celých čísel z intervalu case 1:{ int a=0,d=0,max=0,i=12; srand(time(NULL)); while(i>0) {
a=rand()%46+5; printf("%d\n",a); if((a%3)==0) d++; if(a>max) max=a; i--;
} // while printf("Pocet delitelnych 3 je %d\n",d); printf("Maximalni je %d",max); getch(); };break; // Načtěte od uživatele znaky až do zadání znaku K…. case 2: { char z; int m=0,p=0; printf("zadejte znak\n"); scanf(" %c",&z); while(z!='K') {
p++; if((z>='a')&&(z<='z')) m++; printf("zadejte znak\n"); scanf(" %c",&z);
} // while printf("pocet znaku je %d\n",p); printf("pocet malych je %d\n",m); getch(); };break;
201 // Načtěte dvě kladná celá čísla f a g a pak vypiše všechna sudá… case 3: { int f,g; printf("zadejte hranice intervalu"); scanf("%d %d",&f,&g); if (f
Doporučení Pro větší přehlednost v programu se snažte udržet tzv. štábní kulturu. Je to doporučení, jak psát program čitelně a přehledně. a)
Používejte významové identifikátory •
i, j, k – pro indexy, parametry cyklů
•
f, g, r – pro reálná čísla
•
c, z, zn – pro znaky
b)
V případě většího počtu složených závorek { }, dopisujte osvětlující jednořádkové komentáře.
c)
Uvádějte komentáře před každou logickou ucelenou částí kódu.
202
Kontrolní otázky a úkoly Ve funkci main vytvořte pomocí příkazu switch menu, ve kterém budou volby 1 až 6 pro jednotlive úkoly: 1)
Vytiskněte čtvercovou matici typu 4 x 4 zadaného znaku.
2)
Vytiskněte matici typu 5 x 7 náhodně vybraným znakem z ASCII tabulky.
3)
Vytvořte program, jehož vstupem je celé číslo a celočíselný exponent. Výstupem programu je mocnina čísla na zadaný exponent.
4)
Vytvořte program, jehož vstupem bude celé číslo a výstupem bude výpis všech přirozených dělitelů zadaného čísla.
5)
Z řady N čísel, kde N zadáte, vypište maximální a minimální hodnotu.
6)
Určete známkový průměr z PRG ve třídě, kde počet žáků není předem znám. Postupně zadávejte výslednou známku každého žáka až do koncové značky 0. Kromě průměru vypište i počet žáků. a) Upravte program tak, aby respektoval rozsah známek <1;5> b) Zjednodušte program, pokud znáte počet žáků ve třídě.
203
32 Ladění programu Obsah hodiny Na konkrétních příkladech si procvičíme tvorbu jednoduchých programů na základě aplikace již probrané teorie.
Cíl hodiny Po této hodině budete schopni: ● ● ●
rozlišit syntaktickou a logickou chybu orientovat se v chybovém hlášení krokovat program a sledovat hodnoty proměnných
Klíčová slova Syntaktická chyba, logická chyba, chybová hlášení, debuger
V kapitole Etapy řešení algoritmické úlohy jsme si rozdělili řešení úlohy na několik částí: formulace problému, analýza úlohy, vytvoření algoritmu, sestavení vývojového diagramu a sestavení programu. Nyní si probereme poslední etapu, která následuje po vytvoření programu. Poslední etapou řešení úlohy je ladění programu. Zde se snažíme zbavit všech syntaktických a logických chyb. Syntaktická chyba vzniká nesprávným použitím gramatiky programovacího jazyka. Je to vše co způsobí, že kód programu je neplatný, neproveditelný, nepřeložitelný. Většinou vzniká různými překlepy, nevhodně používanými parametry, odkazy na neexistující proměnné, atd. Logická chyba vzniká špatnou algoritmizací úlohy, špatným postupem řešení. Nalézt logické chyby bývá zpravidla složitější a obtížnější. Ve stadiu ladění programu jsou důležitá chybová hlášení, která identifikují druh a místo chyby. Chybová hlášení umožňují rychlé odstranění těchto chyb v programu, ale nepostihují chyby vzniklé špatnou algoritmizací. Program může formálně dobře probíhat, ale nemusí splňovat zadání úlohy. Debugger je ladící program, který běží zároveň se spuštěným programem a hledá chyby, které nastanou při běhu programu. Je určený také pro krokování programu, neboť umožňuje sledovat běh programu řádek po řádku
204 a sledovat při tom hodnoty proměnných. TurboC++ má Integrovaný debugger, který spouštíme příkazem Menu - Run (F9).
Pro zkoumání činnosti programu jej musíme nejprve zastavit : Menu Run – Program Pause. Zobrazí se okno s výpisem aktuálního obsahu registru a seznam instrukcí, které má procesor v následujících krocích provést.
Okno s instrukcemi zavřeme.
205 Objeví se editor kódu. Další spuštění programu – Run - Run.
32.1 Činnost programu krok za krokem Jaké chyby lze odhalit? Krokováním lze odhalit chyby ve struktuře kódu. F8 / Run – Step Over = krokování programu, povolení jen jednoho příkazu a jeho činnost se zastaví. V editoru kódu se objeví modrá šipka, která ukazuje na příkaz, který se má vykonat. Pokud se narazí na funkci, vykoná se v jediném kroku. F7 / Run – Trace Into – pro vykonávání i funkcí (procedur) krok po kroku.
206
32.2 Sledování proměnných Watch list okno – umístíme proměnné, které chceme sledovat. Proměnnou pro sledování přidáme do okna přes příkaz: Run – AddWatch..., nebo z místní nabídky editoru kódu: Debug – addWatchatCursor.
Pro zjištění hodnoty proměnné v daném okamžiku – najedeme myší na proměnnou a chvíli počkáme.
207
32.3 Změna hodnoty proměnné za běhu programu Přes menu Run – Evaluate/Modify – lze změnit hodnotu proměnné za běhu programu. Z rozevírací nabídky si vybereme proměnnou – klikem na tlačítko Evaluate se zobrazí aktuální stav proměnné. Do políčka New value se zadá nová hodnota a tlačítkem Modify jej uložíme.
208 Pro zkoumání činnosti programu jej musíme nejprve zastavit : Menu Run – Program Pause. Zobrazí se okno s výpisem aktuálního obsahu registru a seznam instrukcí, které má procesor v následujících krocích provést. Okno s instrukcemi zavřeme. Objeví se editor kódu. Další spuštění programu – Run - Run.
32.4 Činnost programu krok za krokem Jaké chyby lze odhalit? Krokováním lze odhalit chyby ve struktuře kódu. F8 / Run – Step Over = krokování programu, povolení jen jednoho příkazu a jeho činnost se zastaví. V editoru kódu se objeví modrá šipka, která ukazuje na příkaz, který se má vykonat. Pokud se narazí na funkci (proceduru), vykoná se v jediném kroku. F7 / Run – Trace Into – pro vykonávání i funkcí (procedur) krok po kroku.
32.5 Sledování proměnných Watch list okno – umístíme proměnné, které chceme sledovat. Proměnnou pro sledování přidáme do okna přes příkaz: Run – Add Watch..., nebo z místní nabídky editoru kódu: Debug – add Watch at Cursor. Pro zjištění hodnoty proměnné v daném okamžiku – najet myší na proměnnou a chvíli počkat.
Shrnutí kapitoly TurboC++ má integrovaný ladící program Debugger, který běží zároveň se spuštěným programem a hledá chyby, které nastanou při běhu programu. Je určený také pro krokování programu, neboť umožňuje sledovat běh programu řádek po řádku a sledovat při tom hodnoty proměnných.
Kontrolní otázky a úkoly Na vašich řešených příkladech z předcházejících kapitol si vyzkoušejte krokování programu s následným sledováním hodnot proměnných.
209
33 Faktoriál Obsah hodiny Procvičíme všechny druhy cyklů na výpočtu faktoriálu přirozeného čísla.
Cíl hodiny Po této hodině budete schopni: ● ● ●
vypočíst faktoriál přirozeného čísla aplikovat znalosti iterace při výpočtu n! použít n! v algoritmu příkladů
Klíčová slova Faktoriál, n!
Faktoriál čísla n je součin všech přirozených čísel od 1 do n, nebo od n do 1. Pro záporná čísla není faktoriál definován, neboť je definován pouze pro přirozená čísla n. ∀ n ∈ N ∪ { 0 } platí:
n! = n*(n -1)! =n*(n -1)*(n -2)!= … = n*(n-1)*(n -2)*…*3*2*1 přičemž 0! = 1 Faktoriál několika prvních čísel: 1! = 1 2! = 2 *1= 2 3! = 3 * 2 * 1 = 6 4! = 4 * 3 * 2 * 1 = 24 5! = 5 * 4 * 3 * 2 * 1 = 120 6! = 6 * 5 * 4 * 3 * 2 * 1 = 720 7! = 7 * 6 * 5 * 4 * 3 * 2 * 1 = 5 040 …. 12! = 479 001 600
210
Otázky k zamyšlení Z jakého nejvyššího přirozeného čísla můžete vypočítat n! jehož výsledek bude typu: a) int b) long int Zopakujte si učivo kapitoly Datové typy - Celočíselné datové typy
33.1 Faktoriál řešený cyklem for int main () { int n,i; long int fakt = 1; printf("Zadej prirozene cislo n \n"); scanf("%d",&n); for (i=2; i<=n; i++) { fakt *= i; } printf(" %d! je %ld \n", n, fakt); return 0; }
Otázky k zamyšlení 1) Sestavte vývojový diagram k výše uvedenému programu. 2) V programu změňte kód a komentujte výstup: a) Proč je v úvodní deklaraci s inicializací přiřazeno fakt = 1? b) Proč je řídící proměnná nastavena na i=2? c) Nastavte řídící proměnnou na i=1. d) Změňte deklaraci proměnné fakt z long int na int. e) Ošetřete program za předpokladu, že uživatel může načíst celé číslo, tedy i záporné.
211
33.2 Faktoriál řešený cyklem while Principiálně je algoritmus velmi podobný algoritmu z předcházejícího řešení pomocí cyklu for. Řešení cyklem while int main () { int n; printf("Zadej prirozene cislo n \n"); scanf("%d",&n); if (n>1) { int i=1; long int fakt = 1; while(i<=n) { fakt *=i; ++i; } printf("faktorial %d je %ld \n", n, fakt); } return (0); }
Otázky k zamyšlení V programu změňte kód a komentujte výstup: a) Proč je v úvodní deklaraci s inicializací přiřazeno long int fakt = 1? b) Nastavte řídící proměnnou na int i=0. c) Změňte podmínku while(i
212
33.3 Faktoriál řešený cyklem do - while V následujícím řešení je zahrnuta i kontrola načtení celého čísla, tedy i záporného. int main () {int n=0; printf("Zadej cislo n \n"); scanf("%d",&n); if(n>1) { long int fakt = 1; int i=1; do { fakt *=i; ++i; } while(i<=n); printf("faktorial %ld je %d\n",n,fakt); } else if ((n == 0) || (n==1)) printf("faktorial daneho cisla je 1"); else printf("Faktorial pro dane cislo neexistuje"); return (0); }
Otázky k zamyšlení 1) Sestavte vývojový diagram k výše uvedenému programu. 2) Ve které části uvedeného kódu je kontrola rozsahu zadaného čísla n ? 3) Zvyšte rozsah hodnot n použitím float nebo dalších jeho podtypů
213
Shrnutí kapitoly Prostřednictvím všech druhů cyklů jsme se naučili vypočítat n! zadaného přirozeného čísla. K výpočtu jsme používali typ int a jeho podtypy společně s typem float.
Kontrolní otázky a úkoly Programy na výpočet n! využijte při řešení následujících příkladů: 1)
7! / 5!
2)
(7! + 5!) / 3!
3)
Vypočtěte n!, kde n vygenerujete jako celé číslo z intervalu <1;6>
4)
n! , kde n zadáte z klávesnice 2
5)
(n! + k), kde k zadáte jako konstantu
6)
Určete součet všech čtyřciferných čísel sestavených z číslic: 1, 3, 5 a 7 – bez opakování číslic. Použijte permutaci bez opakování.
7)
V urně je šest lístků téhož tvaru očíslovaných 1, 2, …6. Kolika různými způsoby lze jej postupně vytáhnout, jestliže se tažený lístek do urny nevrací a přihlíží se k pořadí, v jakém byly lístky taženy ?
8)
Kolik permutací OSTRAVA ?
s opakováním
lze
vytvořit
z písmen
slova:
214
34 Sumy a řady Obsah hodiny Aplikuje poznatky z kapitol věnovaných cyklům při výpočtech součtů různých číselných řad.
Cíl hodiny Po této hodině budete schopni: ● ● ●
sestavit algoritmus součtu číselné řady použít vhodného druhu cyklu modifikovat program na součet číselné řady podle zadání
Klíčová slova Nekonečná řada, člen nekonečné řady, suma
Výraz tvaru: a1 + a2 + a3 + a4 + a5 + a6 + . . . an kde a1, a2 ,. . an jsou členy posloupnosti { an } se nazývá nekonečná řada. Členům a1, a2 ,. . an se pak říká členy nekonečné řady. Příklady nekonečných řad: 1 + 2 + 3 + 4 + 5 +…+ n + … 1+
1 1 1 1 + + + ... + n −1 2 4 6 2
1 2 3 n + + + ... + 2 3 4 n +1
Nekonečná řada s obecným n-tým členem an se často zapisuje zkráceně ∞
ve tvaru:
∑a
n
n =1
V programování je našim častým úkolem sestavit algoritmus úlohy, která vypočítá součet řady o daném počtu prvků.
215
Příklad Vypočítejte součet přirozených čísel od 1 do N (1 + 2 + 3 + 3 + 5 +…+ N), kde N definujete jako konstantu. Řešení: Tuto úlohu jsme v předcházejících kapitolách řešili všemi druhy cyklu. Připomeneme si řešení s cyklem s řídící proměnnou. #define N 10 int main() { int suma=0, i=1; for ( i=1; i<=N;i++) { suma += i; } printf("%d\n",suma); return(0); }
Otázky k zamyšlení 1) Sestavte vývojový diagram k výše uvedenému programu. 2) Sestavte program na výpočet součtu této číselné řady, kde N zadáte z klávesnice. 3) Jak změníte kód programu, pokud chcete sečíst jen : a) prvky se sudými indexy: a2 + a4 + a6 + . . . an b) sudá čísla: 2+4+6+…+ N c) lichá čísla d) čísla dělitelná 5 e) čísla od ak do al . Kde ak i al zadáte. Například od < 8; 28>
216
Příklad Sestavte program na výpočet součtu číselné řady: -1 +
1 1 1 1 1 1 1 + − + . . − + + ( − ) , kde n zadáte z klávesnice. 2 3 4 5 6 7 n
Řešení: int main () { int n, i; float suma = 0; // s = 1- 1/2 + 1/3 - 1/4 .......+(-) 1/n printf(" Zadej n: \n", ); scanf(“%d”, &n); for (i = 1; i <= n; i++) { if (i % 2 == 0) suma -= 1.0 / i; else suma += 1.0 / i; } printf("Suma: %f\n", suma); getch(); return(0); }
Otázky k zamyšlení 1) Sestavte vývojový diagram k výše uvedenému programu. 2) Sestavte program na výpočet součtu této číselné řady, kde n zadáte jako konstantu. 3) Jak změníte kód programu, pokud chcete v řadě sečíst jen liché prvky: 1+
1 1 1 1 + . . + + ... 3 5 7 n
4) Jak změníte kód programu, pokud chcete v této řadě sečíst jen prvky ze zadaného intervalu. Například: <
1 1 ; > 3 9
217
Kontrolní otázky a úkoly Sestavte vývojový diagram a program k následujícím příkladům: 1) Sestavte program na výpočet součtu číselné řady: 1+
1 1 1 1 1 1 1 + + + . . + + + ... , kde n zadáte z klávesnice. 2 3 4 5 6 7 n
a) Jak změníte kód programu, pokud chcete v této řadě sečíst jen sudé prvky: 1 1 1 1 1 + + . + + ... 2 4 6 8 n
b) Jak změníte kód programu, pokud chcete v této řadě sečíst jen prvky ze zadaného intervalu. Například: <
1 1 ; > 2 12
2) Sestavte program na výpočet součtu číselné řady: 1 1 1 1 1 , kde n, k ∈ Z + + +. . + ... ( n + 0 ) ( n + 1) ( n + 2 ) ( n + 3) (n + k )
3) Sestavte program na výpočet součtu číselné řady: 1 1 1 1 ( − 1) k , kde n, k ∈ Z − + −. . + ... ( n + 0 ) ( n + 1) ( n + 2 ) ( n + 3) (n + k )
4) Sestavte program na výpočet součtu číselné řady: n n n n n , kde n, k ∈ Z + + +. . + ... ( n + 0 ) ( n + 1) ( n + 2 ) ( n + 3) (n + k ) 5)
Sestavte program na vypočet hodnoty Ludolfova čísla π s přesností na 0,001 pomocí rozvojové řady: 1 1 1 1 1 π = 4 .(1 − + . . − + − ( + )... ) 3 5 7 9 n
218
35 Opakování probrané látky Obsah hodiny Prověříte si své znalosti, které jste získali studiem předloženého výukového modulu.
Cíl hodiny Po této hodině budete schopni: analyzovat, kterou část učiva jste zvládli a kterou část učiva musíte ještě prostudovat posoudit vlastní úspěšnost
● ●
Následující test poskytuje příležitost ověřit si svoje skutečné znalosti z algoritmizace a základů programovacího jazyka C. Správné zodpovězení otázek vyžaduje poměrně dobrou orientaci ve znalostech probraného modulu, neboť nabízené odpovědi se často liší jen v drobných detailech a jen maličkost rozhoduje o správnosti.
Kvíz Prověřte své znalosti v testových otázkách, v nichž je vždy jedna správná odpověď. V závěru kapitoly naleznete správná řešení. 1. Operátor / má význam: a) dělení dvou celých čísel b) zbytek po dělení dvou celých čísel c) dělení dvou jakýchkoliv čísel d) dělení celého čísla dvěma 2. Jsou-li X a Y typu int , bude po příkazech X= 9; Y=X%4; mít proměnná Y hodnotu: a) 2 b) 2,125 c) 1 d) příkaz je syntakticky chybný
219 3. Jsou-li X a Y typu float, bude po příkazech X= 9; Y=X%4; mít proměnná Y hodnotu: a) 2 b) 2,125 c) 1 d) příkaz není povolen 4. Násobíme-li dvě čísla, z nichž jedno je typu int a druhé typu float, je výsledek: a) typu int b) typu float c) nahlásí se chyba při překladu d) nahlásí se chyba při běhu programu 5. Který z těchto výroků není správný? a) reálné proměnné (float) lze přiřadit konstantu int b) v aritmetickém výrazu smí být promíchány typy int a float c) reálné proměnné ( float) lze přiřadit výraz typu int d) proměnné typu int lze přiřadit konstantu typu float 6. V jazyce C operátor % znamená: a) dělení dvou celých čísel b) zbytek po dělení dvou celých čísel c) dělení dvou jakýchkoliv čísel d) dělení celého čísla dvěma 7. Výraz 2 + 3 * 4 má hodnotu: a) 20 b) 14 c) nelze vypočítat d) špatný zápis, neboť chybí závorky 8. Funkce sqrt(9) nabývá hodnoty a) 81 b) 18 c) 3 d) zápis je chybný
220 9. Proměnné int a=1, b=2, c=3; jsou po přiřazení : c - = ++ b + a ++; a) a=1, b=2, c=2 b) a=2, b=2, c=2 c) a=2, b=3, c=-1 d) a=1, b=2, c=3 10. Která z následujících konstant není typu float? a) 2.5 b) 3000 c) 1e20 d) 0.45E21 11. Které z následujících číselných proměnných se automaticky nulují již při deklaraci bez inicializace? a) globální proměnné b) lokální proměnné c) všechny typy proměnných d) žádné proměnné 12. Jsou-li X a Y typu int, jakou hodnotu bude mít proměnná X po příkazech: X = 9; Y = 5; X = X + (int)Y; ? a) 13 b) 14 c) 6 d) 15 13. Proměnné int a=1, b=2, c=3; jsou po přiřazení : c + = - b + a ++; a) a=1, b=2, c=2 b) a=2, b=2, c=2 c) a=2, b=2, c=3 d) a=1, b=2, c=3 14. Rozsah platnosti lokální proměnné je: a) od začátku do konce bloku, ve kterém jsou deklarovány b) od začátku do konce programu c) od deklarování do konce programu d) od začátku do konce hlavní funkce main ( )
221 15. Jsou-li X a Y typu int, jakou hodnotu bude mít proměnná X po přiřazeních: X=9; Y=2; X=X / Y * 2; ? a) 2 b) 8 c) 1 d) 9 16. Matematickou podmínku A leží v interval <0;1) v jazyce C zapíšeme: a) (A>=0) && (A<1) b) (A>=1) || (A<0) c) A>=0 && A<1 d) (A<=1) || (A<1) 17. Jak vypadá zápis ternárního operátoru ? a) (vyraz) ? prikaz1 : prikaz2; b) (vyraz) : prikaz1 ? prikaz2; c) (vyraz) ? prikaz1 else prikaz2; d) (vyraz) ? prikaz1 ; prikaz2; 18. Která z následujících podmínek bude splněna a provede se příkaz1? Pro int x=10, y=20; a) if (x <= y) příkaz1; b) if (x > y) příkaz1; c) if (x = y) příkaz1; d) if (x == y) příkaz1; 19. Matematickou podmínku A leží mimo interval <0;1) v jazyce C zapíšeme: a) (A>=0) && (A<1) b) (A>=1) || (A<0) c) A>=0 && A<1 d) (A<=1) || (A<1) 20. Která proměnná nemůže být použita jako selektor v příkazu case ? a) char b) int c) float d) long int
222 21. Který z následujících příkazů převede malá písmena na velká? Platí: char c; a) c = (c>='a' &&&& c<='z') ? c-('a'-'A'):c; b) c = (c>='a' || c<='z') ? c-('a'-'A'):c; c) c = (c>='a' && c<='z') ? c-('a'-'A'):c; d) c = (c>'a' &&&& c<'z') ? c-('a'-'A'):c; 22. Jsou-li X a Y typu int, jakou hodnotu bude mít proměnná X po přiřazeních: X=9; Y=2; X=X % Y * 2; ? a) 2 b) 8 c) 1 d) 9 23. O cyklu while platí: a) proběhne vždy alespoň jednou b) nemusí proběhnout ani jednou c) vykoná tělo cyklu, pokud je podmínka neplatná d) řídící proměnná se vždy zvýší o 1 24. Jakou hodnotu nabyde proměnná a po následujících příkazech? int a=4; switch (a) {
case 1:a=a+1;break; case 2: case 3: case 4: case 5:a=a+2;break; case 6: case 7: a=0;break; } a) 5 b) 6 c) 0 d) není definována
223 25. Kolikrát proběhne následující cyklu ? for (i=0; i==10; i++) Příkaz; a) 11 b) 10 c) 0 d) 9 26. O cyklu do while platí: a) nemusí proběhnout ani jednou b) končí, je-li koncová podmínka neplatná c) vykoná tělo cyklu, pokud je podmínka neplatná d) řídící proměnná se vždy zvýší o 1 27. O cyklu for platí: a) proběhne vždy alespoň jednou b) nemusí proběhnout ani jednou c) vykoná tělo cyklu, pokud je podmínka neplatná d) řídící proměnná se vždy zvýší o 1 28. Která proměnná nemůže být použita jako řídící proměnná příkazu for ? a) typu int b) typu char c) typu float d) typu long int 29. Který z následujících cyklů proběhne deset krát? a) for (i=0; i<10; i++) prikaz; b) for (i=0; i<=10; i++) prikaz; c) for (i=1; i=10; i++) prikaz; d) for (i=1; i==10; i++) prikaz; 30. Který z následujících příkazů zcela ukončí provádění cyklu? a) continue b) break c) return d) goto
224
Řešení: 1.
c
2.
c
3.
d
4.
b
5.
d
6.
b
7.
b
8.
c
9.
c
10.
b
11.
a
12.
b
13.
b
14.
a
15.
b
16.
a
17.
a
18.
a
19.
b
20.
c
21.
c
22.
a
23.
b
24.
b
25.
c
26.
b
27.
b
28.
c
29.
a
30.
b