Programování I. - Střední průmyslová škola elektrotechniky a

Transkript

Programování I. - Střední průmyslová škola elektrotechniky a
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<http://docs.linux.cz/programming/c/c_saloun/>
Kračmar, S., Vogel, J. Programovací jazyk C, [online]. 1995. Dostupné na
www: <http://www.fs.cvut.cz/cz/U201/skrc.html>
© 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<conio.h>
// 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 <conio.h>
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 <conio.h>
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<conio.h>
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 <conio.h>
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 <conio.h>
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 <conio.h>
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 <conio.h>
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<y
>=
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<conio.h>
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 <conio.h>
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<conio.h>
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 <conio.h> // 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 <conio.h>
#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 <conio.h>
#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<conio.h>
// 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 <conio.h>
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 <conio.h>
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 <conio.h>
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<conio.h>
/ 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 <conio.h>. 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 <conio.h>
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 <conio.h>
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<conio.h>
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 <conio.h>
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 <conio.h>
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 <conio.h>
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<conio.h>
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<conio.h>
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<H)) printf(" Cislo je v intervalu");
else printf(" Cislo neni v intervalu");
getch();
return(0);
}
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 <conio.h>
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<b) min = a;
else min=b;
Zápis můžeme slovně popsat jako: Pokud je proměnná a menší než b, přiřaď
proměnné min hodnotu proměnné a, jinak ji přiřaď hodnotu b.
Pomocí ternárního operátoru můžeme stejný kód zapsat:
min = (a < b) ? a : b;
Obecná syntaxe použití ternárního operátoru je následující:
(výraz_rozhodovací) ? výraz_1 : výraz_2 ;
Hodnota výrazu výraz_rozhodovací je po vyhodnocení považována za
logickou. Pokud je tato hodnota logická pravda, operator vyhodnotí výraz_1
a vrátí jeho hodnotu, zatímco v případě logické nepravdy
vyraz_rozhodovací je vyhodnocen výraz výraz_2 a je vrácena jeho
hodnota.
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 <time.h>.
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 <conio.h> // Pro funkčnost getch()
#include <stdlib.h> // Pro funkčnost srand() a rand()
#include <time.h> // 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 <conio.h>
#include <time.h>
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 <conio.h>
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 <conio.h>
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<conio.h>
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 <D; H> 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 <conio.h> // pro funkčnost getch()
#include <stdlib.h> // pro funkčnost srand() a rand()
#include <time.h> // 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<b.
d) Vypočítejte součet přirozených čísel z intervalu < a;b>, 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 <D;H>, 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<b.
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<h.
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<h.
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<b.
d) Vypočítejte součet přirozených čísel z intervalu < a;b>, 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 <D;H>. 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 <f,g>.
Ř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<g)
{ while(f<=g)
{ if((f%2)==0)
printf("%d\n",f);
f++;
} // if
} // while
else
printf("Spatny interval");
getch();
};break;
} // konec switch
return (0);
}
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<n)
d) Ošetřete program za předpokladu, že uživatel může načíst celé
číslo, tedy i záporné.
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

Podobné dokumenty

Hledání chyb na směrovačích

Hledání chyb na směrovačích z nich pak používá kombinaci tohoto dynamického směrování a ručního nastavení statických cest. Bez ohledu na to, jakou metodu zvolíme router rozhodne o nejvýhodnější cestě k cíly a tuto cestu pak z...

Více

přehled vzorců v exelu

přehled vzorců v exelu Argumenty představují informace, které funkce používá k vytvoření nové hodnoty nebo k provedení nějaké akce. Jsou vždy uvedeny vpravo od názvu funkce a uzavřeny v závorkách. Většina argumentů předp...

Více

MIKROPOČÍTAČE

MIKROPOČÍTAČE 4.4.7 Nastavení adresy v paměti RWM u generátoru znaků ................................................. 7 4.4.8 Nastavení adresy v paměti zobrazovaného textu .........................................

Více

msdos.

msdos. okna se zobrazí rozbalovacím menu, v něm zvolte volbu Vlastnosti a poté už je to jednoduché. Ve Windows 9x, ME je místo cmd příkaz command. Ten má mnohem menší paletu příkazů a je bližší čistokrev...

Více

ADS1-ZFS

ADS1-ZFS Obsah učebního textu navazuje především na znalosti získané předchozím studiem předmětu “Programovací jazyky a operační systémy“ s cílem rozšířit znalosti a používání základních datových typů o slo...

Více

Kysličníková skla

Kysličníková skla Speciální použití skel

Více