Programování v jazyce C

Transkript

Programování v jazyce C
{
#inclu
ude
de <s
<stdi
tdio
td
io.h
h>
/*
* Imp
m po
or
rt m
ma
ate
em
ma
at
ti
ické
ic
ého hl
hlav
vič
ičk
ko
o vé h
#i
inc
clu
lude <m
<mat
at
a
th.h>
>
#inclu
#in
cl de <s
clu
cl
<s dio
<stdio
io
io.h
o.h>
.h
h>
h>
/*
/
* Defi
De
efi n
ni
ničn
ič
ční
čn
ní
í i
in
inici
nici
ic
ci
c
iali
i
int
t m ai
ain()
()
flo
fl
oat
at pi
pi = 3
3.1
3.
. 415
15
5f
f;
;
{
/* Defi
/*
efin
ni
ic
ce lo
loká
oká
káln
l
ntí
íc
cmma
ch
h
p(r
prom
oměn
mě ný
nýc
ch
int
i
nt
main(
ain
in(
npr
n(
n()
) om
{
int A
A_x, A_
A _ y, B
B_x
_x
_x,
x, B_
B_ y;
y;
un
nsi
ns
ig
gn
g
ne
ed
int pol
int
/ Defi
/*
efinice lokáln
kál
ká
ln
ní uns
p
pr
rign
om
o
m
ědn né,
do
p
print
print
in
ntf(
nt
f(”Zadejte p
f(”
doub
ble vzd
zdal
alen
nos
ost
tB
Bod
odu;
u;
scanf
scanf(”%d”, &pol
lo
/* Inicial
al
liza
izac
iz
ace lo
ace
lokprintf(
promě
ě
pálních
printf(”
”Obvod
kru
uh
uh
return
0;
A_x = 2; A_y = 5;
}
B_x = 10; B_y = 17;
/* Vypočtení vzdálenosti
no
no
mezi d
}
Programování
v jazyce C
Ján Hanák
Nakladatelství a vydavatelství
w w w. co m p u t e r m e d i a . c z
R
Obsah
Obsah
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
Úvod ........................................................................................................................................ 6
1. Definice základních termínů ................................................................................................ 8
2. Klasifikace programovacích jazyků .................................................................................... 9
3. Základní paradigmata programování ................................................................................ 10
4. Historie programovacích jazyků C, C++ a C++/CLI ........................................................... 12
5. Spuštění Visual C++ 2010 Express a založení prvního projektu jazyka C
ve vývojovém prostředí .................................................................................................... 22
5.1. Instalace produktu Visual C++ 2010 Express a první dotek s vývojovým prostředím .................................. 22
5.2. Visual C++ 2010 Express, programovací jazyky a vývoj softwaru ........................................................................ 24
5.3. Založení prvního projektu jazyka C .............................................................................................................................. 25
5.4. Zdrojový kód prvního programu v jazyce C ........................................................................................................... 29
6. Sestavení programu jazyka C .......................................................................................... 32
7. Spuštění programu jazyka C a charakteristika exekučních modelů
jedno- a vícevláknových programů jazyka C ................................................................... 34
7.1. Exekuční modely jedno- a vícevláknových programů ............................................................................................ 39
8. Základní řídící konstrukce strukturovaného programování ............................................ 42
9. Program = data + algoritmy .............................................................................................. 45
9.1. Konstrukce algoritmu pro vypočtení kořenů kvadratické rovnice .................................................................... 46
9.2. Konstrukce algoritmu pro zjištění hmotnostního indexu BMI osoby ................................................................. 47
9.3. Konstrukce algoritmu grafické transformace pro invertování bitové mapy .................................................... 48
9.4. Konstrukce algoritmu pro šifrování otevřeného textu pomocí Cézarovy šifry ......................................... 50
10. Vlastnosti algoritmů ...................................................................................................... 51
11. Výpočetní složitost algoritmů ......................................................................................... 55
11.1. Matematická definice O-notace ................................................................................................................................. 58
11.2. Matematická definice
11.3. Matematická definice
Ω-notace
Θ-notace
................................................................................................................................. 58
................................................................................................................................. 59
12. Prostředky pro reprezentaci algoritmů ............................................................................ 63
13. Datové typy ..................................................................................................................... 71
14. Definice proměnných ...................................................................................................... 75
14.1. Agregovaná definice více proměnných v jednom definičním příkazu .......................................................... 79
15. Přiřazovací příkaz ........................................................................................................... 80
15.1. Definiční inicializace proměnných .............................................................................................................................. 82
15.2. Agregovaná definiční inicializace více proměnných v jednom příkazu .................................................... 83
15.3. Vícenásobné přiřazení .................................................................................................................................................... 85
16. Praktické cvičení: program pro výpočet hmotnostního indexu BMI ............................. 86
3
Programování v jaz yce C
17. Číselné soustavy ............................................................................................................. 92
17.1. Desítková (decimální) číselná soustava ..................................................................................................................... 92
17.2. Osmičková (oktálová) číselná soustava ..................................................................................................................... 92
17.3. Šestnáctková (hexadecimální) číselná soustava .................................................................................................. 93
17.4. Dvojková (binární) číselná soustava .......................................................................................................................... 94
18. Konstanty ......................................................................................................................... 95
18.1. Celočíselné konstanty ...................................................................................................................................................... 95
18.2. Reálné konstanty ................................................................................................................................................................. 95
18.3. Znakové konstanty ............................................................................................................................................................. 97
18.4. Řetězcové konstanty ........................................................................................................................................................... 98
19. Praktické cvičení: program pro vypočtení vzdálenosti mezi dvěma body v rovině ......... 99
20. Globální proměnné .......................................................................................................... 101
21. Konstantní proměnné ..................................................................................................... 104
22. Direktiva preprocesoru #define a definice symbolických konstant .............................. 106
23. Typové konverze ............................................................................................................ 108
23.1. Implicitní typové konverze ........................................................................................................................................... 108
23.2. Explicitní typové konverze ........................................................................................................................................... 110
24. Alokační kapacita proměnných .................................................................................... 113
25. Operátory ....................................................................................................................... 115
25.1. Aritmetické operátory ..................................................................................................................................................... 117
25.2. Operátory pro inkrementaci a dekrementaci ........................................................................................................ 121
25.3. Logické operátory ............................................................................................................................................................ 123
25.4. Relační operátory ............................................................................................................................................................. 124
25.5. Přiřazovací operátory ..................................................................................................................................................... 125
25.6. Bitové operátory ................................................................................................................................................................ 126
25.7. Operátory bitového posunu ....................................................................................................................................... 127
26. Priorita a asociativita operátorů .................................................................................... 130
27. Rozhodovací příkazy ...................................................................................................... 133
27.1. Rozhodovací příkaz if ..................................................................................................................................................... 134
27.2. Rozhodovací příkaz if-else ........................................................................................................................................... 135
27.3. Rozhodovací příkaz if-else if… .................................................................................................................................... 138
27.4. Rozhodovací příkaz if-else if-else ............................................................................................................................... 139
27.5. Praktické cvičení: program na detekci kolize mezi automobilem a chodcem ............................................ 141
27.6. Rozhodovací příkaz switch ......................................................................................................................................... 143
27.7. Dvojcestné rozhodování pomocí ternárního operátoru (?:) ................................................................................ 146
28. Programové cykly ........................................................................................................... 148
28.1. Cyklus for ............................................................................................................................................................................. 148
4
Nadpis kapitoly
28.2. Cyklus while ...................................................................................................................................................................... 153
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
28.3. Cyklus do-while ............................................................................................................................................................... 155
29. Funkce ............................................................................................................................ 157
29.1. Praktické cvičení: programy s funkcemi pro přesný a aproximovaný výpočet n! ....................................... 163
29.2. Funkce a statické lokální proměnné ........................................................................................................................ 166
30. Struktury ........................................................................................................................ 169
30.1. Deklarace struktury ........................................................................................................................................................ 171
30.2. Instanciace struktury ....................................................................................................................................................... 172
30.3. Inicializace instance struktury ................................................................................................................................. 173
30.4. Použití inicializované instance struktury .............................................................................................................. 175
30.5. Alokační kapacita instance struktury ...................................................................................................................... 178
31. Pole ................................................................................................................................. 180
31.1. Praktické cvičení: program na vyhledání minimální a maximální hodnoty v jednorozměrném
automatickém poli ........................................................................................................................................................... 185
31.2. Kopírování jednorozměrného automatického pole ............................................................................................... 187
31.3. Alokační kapacita jednorozměrného automatického pole ............................................................................... 188
31.4. Jednorozměrné automatické pole instancí struktur ............................................................................................. 190
31.5. Dvojrozměrné automatické pole .............................................................................................................................. 191
32. Ukazatele ....................................................................................................................... 197
32.1. Získání hodnoty ukazatele ............................................................................................................................................ 202
32.2. Přiřazování ukazatelů ..................................................................................................................................................... 203
33. Pokročilá práce s funkcemi .......................................................................................... 205
33.1. Mechanismy předávání argumentů parametrickým funkcím ................................................................... 205
33.2. Rekurze a rekurzivní funkce .................................................................................................................................... 208
33.3. Funkce a pole .................................................................................................................................................................. 210
33.4. Funkce a instance struktur ........................................................................................................................................... 212
Závěr .................................................................................................................................... 214
O autorovi ........................................................................................................................... 214
5
Programování v jaz yce C
3.
Základní paradigmata
programování
Za poslední desetiletí se v informatice vyvinula tři základní paradigmata programování:
1. Strukturované (procedurální) programování.
Popis: Program je množinou funkcí (někdy též označovaných jako podprogramy),
které implementují parciální algoritmy, jež řeší delegované úlohy.
Vizualizace:
Obr. 1: Grafi cký model strukturovaného programu
10
3. Základní paradigmata programování
2. Objektově orientované programování (OOP).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
Popis: Program je kolekcí diskrétních virtuálních objektů. Virtuální objekt je
abstraktním modelem reálného objektu skutečného světa, přičemž v sobě zapouzdřuje
data a metody. Objekty mezi sebou komunikují prostřednictvím zpráv.
Vizualizace:
Obr. 2: Grafi cký model objektově orientovaného programu
3. Komponentové programování.
Popis: Program je sadou komponent. Komponenta je softwarová součástka, která
disponuje vyšší úrovní abstrakce a zavádí pokročilou funkcionalitu. Interně je každá
komponenta složena z konečné a neprázdné množiny objektů, které mezi sebou vedou
informačně prospěšný dialog.
Vizualizace:
Obr. 3: Grafi cký model komponentového programu
11
7. Spuštění programu jazyka C
7.1.
Exekuční modely jedno- a vícevláknových programů
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
Jedno- a vícevláknové programy se liší svými exekučními modely. Exekuční model neboli
model zpracování programu nám umožňuje zkoumat, jak budou prováděny algoritmy,
jež program implementuje. Teorie programování rozlišuje následující exekuční modely
jedno- a vícevláknových programů:
1. Sekvenční exekuční model. Sekvenční exekuční model je typický pro jednovláknové
programy. Jak jsme již zmínili, jednovláknový program realizuje zpracování algoritmů
sekvenčně, tedy na sériové bázi. Bez ohledu na to, na jak výkonném počítačovém
systému jednovláknový program spustíme, program bude obsazovat pouze jedno
z dostupných výpočetních jader procesoru. Na jednojádrovém procesoru je takovéto
rozvržení pochopitelné. Pokud ovšem máme vícejádrový procesor, tak zjišťujeme, že
jednovláknový program se sekvenčním exekučním modelem není schopen využít
všechnu výpočetní kapacitu takto dimenzovaného procesoru. Při 4jádrovém procesoru
budou tři výpočetní jádra nevyužita, a to samozřejmě není to, co bychom chtěli.
V informatice a v programování obecně je naším cílem vytvářet takové programy, které
se dovedou přizpůsobit jakékoliv hardwarové platformě a umí z ní vytěžit maximální
porci výkonu.
Obr. 14: Vizualizace sekvenčního exekučního modelu
2. Pseudoparalelní exekuční model. Pseudoparalelní exekuční model se vztahuje
k vícevláknovým programům. Jelikož se nechceme pouštět do rigorózních vědeckých
analýz, přijmeme domluvu, podle níž budeme říkat, že vícevláknové programy jsou
zpracovávány pseudoparalelně tehdy, pokud běží na počítačovém systému, jenž
obsahuje jeden jednojádrový procesor. Když je něco „pseudo“, tak se to tváří jinak, než
jak to ve skutečnosti je. Pseudoparalelní zpracování tedy není skutečně paralelní, jenom
z vnějšku, z pohledu vnějšího pozorovatele se zdá, že paralelní je. Pseudoparalelní
zpracování vícevláknového programu na jednoprocesorovém systému probíhá
iterativním preemptivním stylem, v němž procesor střídavě provádí instrukce všech
programových vláken.
39
Programování v jaz yce C
8.
Základní řídící konstrukce
strukturovaného programování
Kterýkoliv strukturovaný program můžeme vytvořit pouze s třemi základními řídícími
konstrukcemi, jimiž jsou sekvence, selekce a iterace.
Sekvence znamená postupné zpracování lineární posloupnosti programových příkazů. Tyto
příkazy jsou realizovány sekvenčně, tedy jeden za druhým, a to v takovém pořadí, v jakém
jsou zapsány ve zdrojovém kódu programu.
Obr. 18: Sekvence
Na obr. 18 vidíme sekvenční zpracování třech programových příkazů P1, P2 a P3. Nejprve je
zpracován příkaz P1, poté příkaz P2 a nakonec příkaz P3.
Selekce je základní rozhodovací konstrukce. Na základě rozhodovacího výrazu může program
přijmout v určitém čase rozhodnutí o tom, jaký bude jeho další průběh. Když je v programu
diagnostikována rozhodovací řídící konstrukce, existuje více variant dalšího toku programu.
Říkáme, že program se větví. Větvení programu představuje existenci konečné a neprázdné
množiny cest, jimiž se smí zpracování programu ubírat. Selekce je vždy jednoznačná
a deterministická. To se projevuje v tom, že program si po přijetí rozhodnutí (tedy po vyhodnocení
rozhodovacího výrazu) vybere právě jednu z možných větví a tou bude pokračovat dál.
Obr. 19: Selekce se dvěma větvemi (dvojcestné rozhodování)
42
10. Vlastnosti algoritmů
10. Vlastnosti algoritmů
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
Na předchozích řádcích jsme nadnesli zjednodušenou definici algoritmu, podle níž jsme za
algoritmus považovali jakýkoliv postup složený z konečného počtu kroků, který nás dovede
k určitým výsledkům. Ve skutečnosti jsou však na algoritmy kladeny mnohem rigoróznější
požadavky, které zřetelně definují, jaké vlastnosti musí algoritmus mít. Za algoritmus je
obecně považován pouze takový postup, který splňuje následující kritéria:
1. Všeobecnost. Algoritmus je předpis, který vede k řešení všeobecné kategorie neboli
třídy úloh (problémových oblastí). Kupříkladu algoritmus pro řešení kvadratické
rovnice se dá použít pro nalezení kořenů jakékoliv rovnice, která disponuje
kvadratickým, lineárním a absolutním členem. Totéž lze konstatovat o algoritmu pro
výpočet indexu BMI. Pomocí zmíněného algoritmu je možné vypočítat hmotnostní
index jakéhokoliv člověka, autora této knihy či ctěného čtenáře nevyjímaje. Algoritmy
tedy mají generickou povahu, mění se pouze vstupní data a vypočtené výsledky.
2. Jednoznačnost. Každý algoritmus musí být jednoznačný, což znamená, že v kterémkoliv
jeho kroku musí být jasně předepsáno, jak se bude postupovat dál. Není jednoduše
možné, abychom měli algoritmus, který si v jistém okamžiku nebude „vědět rady“
s dalším postupem. Algoritmická jednoznačnost znamená, že algoritmus se musí za
každých okolností umět rozhodnout, jakou činnost vykoná v příštím kroku. Definice
algoritmu z hlediska jednoznačnosti musí být absolutně přesná: algoritmus nesmí zůstat
na pochybách ani tehdy, když před ním vyvstane několik variant dalšího postupu.
Oba uváděné algoritmy jsou jednoznačné. Kupříkladu když vypočteme hodnotu
diskriminantu, dovedeme určit, zda bude množina kořenů kvadratické rovnice prázdná,
či nikoliv. Stejně tak nám nečiní potíže vynést soud o hmotnosti osoby, když jsme pomocí
vzorečku vypočetli její hmotnostní index.
3. Konečnost. Za algoritmus je dle definice považován pouze takový postup, který je
složen z konečného počtu elementárních kroků. Těch kroků, které musí algoritmus
provést v zájmu dosažení výsledku, může být třeba 10, 100 nebo milion, ale vždy se
musí jednat o konečnou cifru. Postup, který se nedovede k výsledku dopracovat po
absolvování konečného počtu kroků, nemůžeme nazývat algoritmem. Například nelze
sestrojit algoritmus pro výpočet součtu všech přirozených čísel, poněvadž těchto čísel
je nekonečné množství. Oba naše ukázkové algoritmy jsou konečné, neboť k jejich
realizaci si vystačíme s několika málo úkony.
4. Rezultativnost. Rezultativnost je velice důležitá vlastnost algoritmu, která praví
toto: Po realizaci konečného počtu kroků nás musí algoritmus dovést k finálnímu
výsledku. Definice tedy jednoznačně stanovuje, že postup daný algoritmem musí
vyústit do jistého řešení zkoumaného problému. Jakkoliv efektivní a promyšlený může
algoritmus být, jestliže nás nedovede ke kýženému výsledku, je nám naprosto k ničemu.
Jinými slovy, na co by nám byl takový algoritmus vyřešení kvadratické rovnice, který by
51
Programování v jaz yce C
11.1. Matematická definice O-notace
Ať f(n) a g(n) jsou dvě nezáporné funkce definované na množině přirozených čísel (N).
Říkáme, že f(n) je velké O od funkce g(n), a zapisujeme f(n)=O(g(n)) nebo též f(n) ∈ O(g(n)),
jestliže existuje přirozené číslo n0 a konstanta c>0 takové, že pro každé n ≥ n0 platí f(n) ≤ c × g(n).
Ve zkratce lze O-notaci definovat takto:
f(n)∈O(g(n) ) ⇔ ∃ c >0,∃ n 0>0: ∀n ≥ n 0 : f(n) ≤ c × g(n)
Pokud je f(n)=O(g(n)), můžeme prohlásit, že řád funkce f(n) je menší nebo nanejvýš rovný
řádu funkce g(n). O(g(n)) proto slouží jako horní odhad složitosti funkce f(n). O naší funkci
T(n)=an 2 + bn + c tak povíme, že její asymptotická časová složitost je v O(n 2 ). Méně formálně:
můžeme identifikovat takovou kladnou konstantu c, že počínaje nějakým číslem n0 bude
graf funkce f(n) ležet vždy „pod“ grafem funkce c × g(n). Tuto situaci znázorňuje obr. 26.
Obr. 26: Vizualizace horního odhadu asymptotické časové složitosti algoritmu pomocí
O-notace
Pro informatiky je nejdůležitější O-notace, protože jim dává garanci horního odhadu
asymptotické časové složitosti algoritmu. Pomaleji, než udává O-notace, algoritmus už
nepoběží. Kromě O-notace, která slouží k vyjádření horní meze časové složitosti algoritmu,
jsou však zajímavé také další odhady, a sice odhad dolní a průměrné složitosti. Pro
asymptotické dolní ohraničení složitosti algoritmu se používá Ω-notace (Ω je Omega) a pro
asymptotické průměrné ohraničení složitosti algoritmu se zase aplikuje Θ-notace (Θje Théta).
11.2. Matematická definice Ω-notace
Ať f(n) a g(n) jsou dvě nezáporné funkce definované na množině přirozených čísel (N).
Říkáme, že f(n) je Ω od funkce g(n), a zapisujeme f(n)=Ω(g(n)) nebo též f(n)∈Ω(g(n)),
jestliže existuje přirozené číslo n0 a konstanta c>0 takové, že pro každé n ≥n0 platí
f(n) ≥ c × g(n).
58
11. Výpočetní složitost algoritmů
Ve zkratce lze Ω-notaci definovat takto:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
f(n)∈Ω(g(n) ) ⇔ ∃ c >0,∃ n 0>0: ∀n ≥ n 0 : f(n) ≥ c × g(n)
Obr. 27: Vizualizace dolního odhadu asymptotické časové složitosti algoritmu pomocí Ω -notace
11.3. Matematická definice Θ-notace
Ať f(n) a g(n) jsou dvě nezáporné funkce definované na množině přirozených čísel (N).
Říkáme, že f(n) je Θ od funkce g(n), a zapisujeme f(n)=Θ(g(n)) nebo též f(n) ∈ Θg(n)),
právě tehdy, když současně platí f(n)=O(g(n)) a f(n)=Ω(g(n)). Přesněji lze definici Θ-notace
přepsat pomocí přirozených konstant c1 a c 2 následujícím způsobem:
f(n)∈ Θ(g(n) ) ⇔ ∃ c1,c2>0, ∃n 0>0: ∀n ≥ n 0 : c1 × g(n) ≤ f(n) ≤ c2 × g(n)
Při použití Θ-notace se zkoumá asymptotické oboustranné omezení funkce f(n).
Obr. 28: Vizualizace průměrného odhadu asymptotické časové složitosti algoritmu pomocí
Θ-notace
59
14. Definice proměnných
14. Definice proměnných
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
Proměnné vytváříme v jazyce C pomocí definičního příkazu, jehož všeobecná podoba
vypadá takto:
DatovyTyp IdentifikatorPromenne;
Příkaz, který zavádí do programu novou proměnnou, se skládá ze tří částí:
1. Datový typ. Každá proměnná musí disponovat svým datovým typem. To je důležité hned
ze dvou důvodů. Zaprvé, již od okamžiku vytvoření proměnné musí být jasné, jaký typ
dat neboli hodnot může být do dotyčné proměnné ukládán. Zadruhé, překladač musí
poznat datový typ proměnné, aby pro ni mohl alokovat dostatečně rozsáhlý paměťový
prostor. V této souvislosti je zapotřebí poznamenat, že v definičním příkazu existuje
mezi datovým typem a proměnnou relace 1:1. Jinými slovy, proměnná je spojena vždy
s právě jedním datovým typem. Není jednoduše možné, abychom proměnné přisoudili
dva datové typy, neboť to bychom uvedli překladač do nesnází (ten by ovšem kontroval
generováním chybového hlášení). Jako datový typ proměnné může posloužit kterýkoliv
z primitivních nebo uživatelsky deklarovaných datových typů.
2. Identifikátor proměnné. Identifikátor proměnné čili název proměnné představuje
uživatelsky přívětivé pojmenovávání, které může programátor proměnné přiřadit.
V jazyce C platí pro názvosloví proměnných jisté pojmenovací konvence. Povězme si
tedy, na co bychom si měli při pojmenovávání proměnných dát pozor:
• Název proměnné nesmí obsahovat mezery.
• Název proměnné nesmí začínat číslicí.
• Název proměnné nesmí být totožný s klíčovým slovem nebo spojením klíčových
slov jazyka C.
• Název proměnné se nesmí shodovat s názvem jiné proměnné, která byla ve zdrojovém
kódu jazyka C již dříve definována.
Nejčastější chybou u začínajících programátorů je snaha složit název proměnné z více
slov, které podle intuice oddělují mezerami. Pro mezeru v identifikátoru proměnné
ovšem není místo. Pokud se nelze vyhnout víceslovnému názvu, máme na výběr
z několika alternativ:
• Jednotlivá slova v názvu proměnné budeme separovat symbolem podtržení (_).
Proměnná se tedy může jmenovat třeba Moje_Mala_Promenna nebo také
moje_mala_promenna.
• V praxi se často uplatňuje velbloudí notace, podle níž se slova ve víceslovném názvu
nijak neoddělují a první slovo je psáno s malým začátečním písmenem. Všechna
další slova jsou však již psána s velkými začátečními písmeny. Název dřívější
proměnné se tak použitím velbloudí notace změní na mojeMalaPromenna.
75
Programování v jaz yce C
16. Praktické cvičení: program pro
výpočet hmotnostního indexu BMI
Vyzbrojeni základními znalostmi o proměnných, přiřazovacích příkazech, operátorech
a operandech se můžeme směle pokusit o zkonstruování složitějšího programu. Co takhle
program pro výpočet hmotnostního indexu BMI? Děkujeme pěkně, sem s ním.
#include <stdio.h>
int main()
{
int hmotnost = 70;
float vyska = 1.77, indexBMI;
indexBMI = hmotnost / (vyska * vyska);
printf(”Index BMI osoby, ktera meri %f m ”
”a vazi %d kg je %f.”, vyska, hmotnost, indexBMI);
return 0;
}
Komentář k zdrojovému kódu jazyka C: První 2 příkazy v těle hlavní funkce main
zakládají 3 lokální proměnné (hmotnost, vyska a indexBMI), přičemž dvě z nich rovněž
explicitně inicializují. Program předpokládá, že hmotnost uživatele bude zadána jako
celé číslo, a proto lokální proměnné hmotnost při její definici přisuzuje datový typ int.
Lokální proměnná vyska je typu float – i to je v pořádku, poněvadž matematický vzorec
pro výpočet hmotnostního indexu počítá s tím, že výška osoby bude zadána v desetinné
podobě (jde o výšku v metrech). Lokální proměnná indexBMI je rovněž typu float, neboť
výsledný hmotnostní index bude mít podobu reálné hodnoty. Na celém programu je
patrně nejsložitější přiřazovací příkaz, jenž provádí inicializaci proměnné indexBMI:
indexBMI = hmotnost / (vyska * vyska);
Dobrá, v tomto momentě nás nejvíc zajímá, jak bude probíhat inicializace proměnné
indexBMI, není-liž pravda? Nejprve musíme určit hodnotu aritmetického výrazu, jenž
se rozprostírá na pravé straně od operátoru =. Zdejší výraz je bezesporu složitější než ten,
o němž jsme již psali. Jestliže se ptáte proč, máme pro vás tyto důvody:
1. V aritmetickém výrazu se nacházejí dva operátory:
1. Operátor / (lomítko) uskutečňující operaci dělení.
2. Operátor * (hvězdička) provádějící operaci násobení.
2. Aritmetické operátory / a * mají stejnou prioritu. Jelikož index BMI vypočítáme tak,
že hmotnost osoby vydělíme druhou mocninou její výšky, musíme nejprve vypočítat
tuto druhou mocninu. Operace násobení tak musí být vykonána jako první, proto její
prioritu zvyšujeme použitím závorek.
86
16. Praktické cvičení
Závorky zde plní stejnou roli jako v běžné matematice: nařizují, která operace má být
uskutečněna dřív. Užití závorek v uvedeném aritmetickém výrazu je velice důležité,
poněvadž bez jejich asistence by program počítal nesprávné hodnoty hmotnostních indexů.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
Překladač bude při vyhodnocení aritmetického výrazu postupovat tak, jak znázorňuje
následující model (operace, které jsou v jednotlivých krocích modelu realizovány, jsou
vyznačeny šedou podkladovou barvou):
1. Zjistí aktuální hodnotu lokální proměnné vyska:
indexBMI = hmotnost / (vyska
vyska * vyska);
vyska
2. Vypočte druhou mocninu aktuální hodnoty lokální proměnné vyska:
indexBMI = hmotnost / (vyska
vyska * vyska
vyska);
3. Aktuální hodnotu lokální proměnné hmotnost vydělí hodnotou součinu, jenž byl
zjištěn v předcházejícím kroku tohoto modelu:
indexBMI = hmotnost / (vyska * vyska)
vyska);
4. Vypočtenou hodnotu hmotnostního indexu přiřadí do lokální proměnné
indexBMI:
indexBMI = hmotnost / (vyska * vyska)
vyska);
Když program sestavíme, překladač zahlásí jedno varování, které se pojí s řádkem, v němž
je definována lokální proměnná vyska:
float vyska = 1.77, indexBMI;
Jak se dozvíme v jedné z příštích kapitol této publikace, samostatně stojící (diskrétní) číselné
hodnoty, jako je 1.77 v našem zdrojovém kódu, jsou považovány za číselné konstanty.
Konstanta 1.77 je reálnou konstantou, které překladač implicitně přisoudí datový typ
double. Když se podíváme na fragment zdrojového kódu, tak zjistíme, že se snažíme reálnou
konstantu 1.77 typu double přiřadit do lokální proměnné vyska, jejímž typem je float. Tuto
přiřazovací operaci ovšem nelze provést přímo, protože se liší datové typy entit po obou
stranách přiřazovacího operátoru (float ↔ double). Aby překladač vyřešil vzniklou situaci,
automaticky změní datový typ reálné konstanty 1.77 z double na float, čímž problém spojený
s nesouladem datových typů rázem zmizí. Operace, kterou překladač právě provedl, se
v programování označuje termínem implicitní typová konverze. Ačkoliv změna datového
typu reálné konstanty nebude mít v našem případě žádný negativní dopad, ne vždy je
tomu tak. Musíme si totiž uvědomit, že překladač implicitně převádí hodnotu přesnějšího
typu double na hodnotu méně přesného typu float. Takováto typová konverze může
být poznačena ztrátou dat. A právě z tohoto důvodu generuje překladač varování. I když
totiž překladač typovou konverzi zpracuje ve své vlastní režii, emituje varování, které má
programátora upozornit na fakt uskutečnění implicitní typové konverze, která může mít
potenciálně nebezpečné implikace.
87
Programování v jaz yce C
17. Číselné soustavy
17.1. Desítková (decimální) číselná soustava
Jakoukoliv hodnotu desítkové soustavy můžeme zapsat v podobě součtu mocnin čísla 10.
Uvažujme například o číslu 1253:
(1253)10=1×1000+2×100+5×10+3×1
(1253)10=1×103+2×102+5×101+3×100
Poznámka: Při pojednání o reprezentaci čísel v různých pozičních číselných soustavách platí
konvence, že samotná číselná hodnota je zapsána v závorkách a základ číselné soustavy, v níž je hodnota
udána, je umístěn v dolním indexu. Tuto konvenci budeme na stránkách naší knihy dodržovat, neboť
je nejenom efektivní, nýbrž také dobře vizuálně čitelná. Pokaždé, když se podíváte na dolní index
dotyčné číselné hodnoty, budete okamžitě vědět, v jaké soustavě je tato hodnota interpretována.
Desítková soustava používá pro vyjádření číselných hodnot deset číslic: 0, 1, 2, 3, 4, 5, 6, 7, 8 a 9.
17.2. Osmičková (oktálová) číselná soustava
Osmičková soustava pracuje s mocninami čísla 8, přičemž libovolná hodnota je v této
číselné soustavě vyjádřena posloupností cifer z intervalu <0, 7>.
(6203)8=6×83+2×82+0×81+3×80
Pro převedení osmičkové konstanty 6203 do desítkové soustavy rozvineme mocniny čísla
8 a vypočteme celý součet, poté obdržíme ekvivalent čísla 6203 v desítkové soustavě.
(6203)8=6×512+2×64+0×8+3×1
(6203)8=3072+128+0+3
(6203)8=(3203)10
Jak je vidět, dospěli jsme k závěru, že osmičkové hodnotě 6203 připadá číslo 3203 v desítkové
číselné soustavě. Čtenáři se zvídavější povahou mohou v této chvíli namítnout, zda jsme
s to nabídnout důkaz o zpětné konverzi. Jednoduše řečeno, jak dokážeme, že číslo 3203
v desítkové soustavě je doopravdy protějškem čísla 6203 v osmičkové soustavě? Důkaz
o této skutečnosti podáme tak, že desítkovou číselnou hodnotu budeme neustále dělit osmi,
přičemž si vždycky poznačíme zbytek po dělení. Matematický algoritmus, jenž charakterizuje
tento proces, uvádí tab. 2.
Tab. 2: Algoritmus pro převod celočíselné hodnoty z desítkové do osmičkové číselné soustavy
92
Pořadí operací
Podíl
Zbytek po dělení
3203 : 8
400
3
400 : 8
50
0
50 : 8
6
2
6:8
0
6
20. Globální proměnné
20. Globální proměnné
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
Proměnné se v programování dělí na dvě základné skupiny: lokální proměnné a globální
proměnné. Klasifikačním kritériem pro zařazení proměnné do jedné z uvedených skupin
je její oblast platnosti. Lokální proměnné, s nimiž jsme prozatím intenzivně pracovali,
se vážou na funkci, v níž jsou definovány. Všechny proměnné definované v hlavní
funkci main jsou lokální proměnné, protože jejich oblastí platnosti je tělo této funkce.
Lokální proměnné nelze přímo použít jinde, tedy mimo funkci, ve které jsou situovány
jejich definiční příkazy. Jestliže je nutno zvětšit programový blok, v rámci kterého bude
proměnná dosažitelná neboli viditelná, můžeme s výhodou využít globální proměnné.
Definiční příkaz zakládající globální proměnnou není umístěn v těle žádné funkce.
Ve skutečnosti se definice globální proměnné nachází „nad“ všemi přítomnými funkcemi.
Vzhledem k tomu, že stavbu uživatelsky definovaných funkcí budeme rozebírat až
později, v této kapitole se budeme soustředit pouze na zkoumání vztahu mezi globálními
proměnnými a hlavní funkcí main.
Definice globální proměnné se uskutečňuje přesně podle generického syntaktického
vzoru, který platí rovněž pro lokální proměnné. Každá globální proměnná musí být svůj
datový typ a identifikátor. Globální proměnné jsou překladačem jazyka C implicitně
inicializovány, což znamená, že v závislosti na svých datových typech vždy obdrží
určité výchozí inicializační hodnoty. Pro globální proměnné integrálních datových typů
je implicitní inicializační hodnotou celočíselná nula. Pro globální proměnné reálných
datových typů je implicitní inicializační hodnotou reálná nula. Pro globální proměnné
znakového datového typu char je implicitní inicializační hodnotou nulový znak.
Upozornění: Zatímco globální proměnné jsou překladačem jazyka C implicitně inicializovány,
pro lokální proměnné to neplatí. Jsme-li spokojeni s implicitní inicializační hodnotou globální
proměnné, můžeme tuto proměnnou okamžitě použít v kterémkoliv platném výrazu nebo
příkazu libovolné funkce, jež tvoří syntaktický skelet programu jazyka C. Definované, ovšem
explicitně neinicializované lokální proměnné nemohou být použity tímto způsobem, poněvadž
jejich inicializační hodnoty nejsou implicitně definovány. Lokální proměnné musejí být vždy
nejprve explicitně inicializovány a až poté se smí vyskytnout ve výrazech a příkazech jazyka C.
Následující program jazyka C demonstruje práci s globální proměnnou:
#include <stdio.h>
/* Definiční inicializace globální proměnné. */
float pi = 3.1415f;
int main()
{
unsigned int polomer;
printf(”Zadejte polomer kruhu (jako cele cislo): ”);
scanf(”%d”, &polomer);
printf(”Obvod kruhu s polomerem %d je %.2f.\n”, polomer, 2 * pi * polomer);
return 0;
}
101
Programování v jaz yce C
21. Konstantní proměnné
Proměnnou jsme definovali jako datový objekt, do kterého je možné ukládat hodnoty
určitého datového typu. Ukázali jsme si, jak se proměnné definují a jak se do nich přiřazují
hodnoty. Přitom jsme se vší důkladností pravili, že jakmile je proměnná na světě, můžeme
její hodnotu měnit tolikrát, kolikrát budeme chtít. Proměnná coby datový kontejner může
měnit svou hodnotu, to je fakt, který plyne již ze samotného názvu „proměnná“. Nyní
bychom se měli obeznámit s konstantními proměnnými, což jsou proměnné, jež nesmí po
svých prvotních inicializacích měnit své hodnoty.
Poznámka: V programovací hantýrce jsou konstantní proměnné velice často označovány za
konstanty. Nicméně takováto interpretace vede ke konfliktům s „opravdovými“ konstantami,
o nichž jsme mluvili v předcházejících podkapitolách této publikace. Abychom dodrželi jasnou
a přehlednou linii výkladu, budeme proměnné, jež nelze reinicializovat, nazývat konstantními
proměnnými.
Konstantní proměnné v jazyce C poznáme docela snadno, protože v jejich definičních
příkazech se vyskytuje modifikátor const:
const DatovyTyp IdentifikatorPromenne = InicializacniHodnota;
– nebo –
DatovyTyp const IdentifikatorPromenne = InicializacniHodnota;
Když se v definici proměnné objeví modifikátor const, máme jasný důkaz o tom, že se
jedná o konstantní proměnnou. Ze syntaktického hlediska se může modifikátor const
nacházet před specifikací datového typu konstantní proměnné, nebo až za ní.
Tip: Domníváme se, že lepším řešením je uvádět modifikátor const před datovým typem
konstantní proměnné, protože je tak okamžitě zřejmé, že manipulujeme s konstantní proměnnou.
Tato vizuální pomůcka nabývá na ceně zejména při práci s robustnějšími strukturovanými
programy.
Konstantní proměnná musí mít samozřejmě svůj identifikátor, v tomto ohledu se nijak
neodlišuje od běžné čili nekonstantní proměnné.
Jistě si vzpomínáte na program pro výpočet obvodu kruhu. V tomto programu jsme
definovali globální proměnnou pi, která uchovávala aproximovanou hodnotu čísla π.
Vzhledem k tomu, že hodnota této reálné konstanty se nikdy nebude měnit, jako logický
nám přijde návrh přetvořit globální proměnnou na globální konstantní proměnnou.
104
25. Operátory
25. Operátory
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
Přestože jsme se v uplynulých kapitolách seznámili s některými aritmetickými operátory,
jako jsou +, – či *, operátory mají v jazyce C, a potažmo v celém oboru programování,
tak silnou pozici, že by byla naprostá chyba, kdybychom jim v této publikaci nevěnovali
samostatnou kapitolu. Již víme, že operátory jsou symboly, které předepisují provedení
rozličných programových operací. Tak kupříkladu operátor + sčítá hodnoty, zatímco
operátor * je násobí. Rovněž jsme si řekli, že entity, s nimiž operátory pracují, se nazývají
operandy. Výraz jsme potom definovali jako smysluplnou posloupnost operandů
a operátorů, která produkuje hodnotu jistého datového typu. Ve výbavě jazyka C se
nachází celá hromada operátorů. Abychom se ve všech těch operátorech rychle neztratili,
rozdělíme je do homogenních skupin podle 2 elementárních klasifikačních kritérií. První
kritérium je funkční: jeho užitím budeme operátory třídit podle jejich funkce, tedy podle
druhu programových operací, které uskutečňují. Z funkčního hlediska jsou v jazyce C
k dispozici následující kategorie operátorů:
1. Aritmetické operátory
2. Operátory pro inkrementaci a dekrementaci
3. Logické operátory
4. Relační operátory
5. Přiřazovací operátory
6. Bitové operátory
7. Operátory bitového posunu
8. Speciální operátory
Na operátory ovšem nemusíme nahlížet pouze striktně ve vztahu k jejich funkci. Operátory
totiž můžeme klasifikovat také podle počtu operandů, s nimiž pracují. Tak dostáváme
mnohem užší, přesněji tříprvkovou, množinu operátorů přítomných v jazyce C:
1. Unární operátory – spolupracují s jedním operandem.
2. Binární operátory – spolupracují se dvěma operandy.
3. Ternární operátory – spolupracují se třemi operandy.
Pokud operátor ke své práci vyžaduje pouze jeden operand (například jednu proměnnou),
pak je to operátor unární. Označíme-li unární operátor symbolem α a operand symbolem
O, pak jejich vzájemný vztah můžeme zapsat takto:
αO
a v některých případech, u inkrementačních a dekrementačních operátorů, také takto:
Oα
α
115
25. Operátory
25.1. Aritmetické operátory
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
Matematické operace patří k nejčastěji vykonávaným úkonům v programování. Provádění
základních aritmetických operací, jako jsou sčítání, odečítání, násobení a dělení, nám
umožňují následující aritmetické operátory:
•
•
•
•
•
operátor pro sčítání +,
operátor pro odečítání – ,
operátor pro násobení *,
operátor pro dělení /,
operátor pro zjištění zbytku po celočíselném dělení %.
Se čtveřicí operátorů +, –, * a / jsme se již setkali, takže víme, jak pracují. Všechno jsou
to vesměs binární operátory, které reflektují základní matematické operace prováděné
s operandy. Jako praktické cvičení pro zopakování základních aritmetických operátorů si
napíšeme program, který bude zobrazovat kalorickou hodnotu vybraného jídla. Prostudujme
následující fragment zdrojového kódu jazyka C:
#include <stdio.h>
int main()
{
int bilkoviny, cukry, tuky;
int energetickyObsah;
float denniPodil;
printf(”Zadejte, kolik gramu bilkovin obsahuje vase jidlo: ”);
scanf(”%d”, &bilkoviny);
printf(”Zadejte, kolik gramu cukru obsahuje vase jidlo: ”);
scanf(”%d”, &cukry);
printf(”Zadejte, kolik gramu tuku obsahuje vase jidlo: ”);
scanf(”%d”, &tuky);
energetickyObsah = (bilkoviny * 4) + (cukry * 4) + (tuky * 9);
denniPodil = ((float)energetickyObsah / 2000) * 100;
printf(”\nVase jidlo obsahuje %d kcal.”, energetickyObsah);
printf(”\nKonzumaci tohoto jidla jste pokryli %.2f %% z vaseho ”
”optimalniho \ndenniho energetickeho prijmu potravy.\n”, denniPodil);
return 0;
}
Komentář k zdrojovému kódu jazyka C: Náš program si nejprve od uživatele vyžádá
informace o jídle. Stěžejní je přitom množství (v gramech) spotřebovaných živin, jimiž
jsou bílkoviny, cukry a tuky. K úschově těchto hodnot definujeme tři celočíselné lokální
proměnné, jejichž názvy jsme zvolili tak, aby nám napovídaly, k čemu slouží. Vstupní data,
která obdržíme od uživatele, ukládáme do předem připravených lokálních proměnných.
Jakmile víme, kolik gramů bílkovin, cukrů a tuků spotřebované jídlo obsahuje, vypočteme
jeho energetickou hodnotu v kilokaloriích (kcal).
117
Programování v jaz yce C
26. Priorita a asociativita operátorů
Všechny operátory jazyka C mají svou prioritu. Priorita říká, v jakém pořadí budou
realizovány programové operace, které jsou předepsané jednotlivými operátory. Kdyby
nebyla stanovena přesná prioritní pravidla, tak by překladač nedovedl správně vyhodnocovat
programové výrazy.
Kupříkladu výraz a * b – c bude překladač vyhodnocovat jako (a * b) – c, poněvadž ze
zapsaných aritmetických operátorů má operátor součinu (*) vyšší prioritu než operátor rozdílu
(–). Jistě, zmíněný aritmetický výraz je triviální, neboť nám dovoluje přímo aplikovat pravidla,
která známe z matematiky. Ovšem věděli bychom, jak postupovat, kdyby bylo znění výrazu
takovéto: a * b % c? Modulo neboli operátor zbytku po celočíselném dělení (%) vypočte zbytek
po celočíselném dělení svých operandů a ten vrátí v podobě své návratové hodnoty. Otázkou
ale zůstává, zda bude překladač vyhodnocovat výraz a * b % c jako (a * b) c anebo jako
a * (b % c). Za předpokladu, že je výraz zapsán korektně, tak překladač musí vždy vědět, jak
určit jeho hodnotu. A to i za těch okolností, kdy se bude potýkat s vpravdě komplikovanými
výrazy.
Překladač se při své práci nejprve řídí prioritou operátorů. Podle priority smíme operátory
jazyka C kategorizovat do homogenních prioritních tříd, přičemž v každé prioritní třídě
se nacházejí operátory se stejnou prioritou. Například binární aritmetické operátory *, /
a % sdílejí stejnou prioritní třídu (označme ji pro lepší orientaci identifikátorem PT1), což
znamená, že disponují totožnou prioritou. Další binární aritmetické operátory + a – jsou
umístěny v jiné prioritní třídě (PT2) a opět sdílejí stejnou prioritu.
Prioritní třídy vytvářejí komplexní hierarchii. Přitom platí, že priorita operátorů patřících do
jednotlivých prioritních tříd klesá ve směru odshora dolů. Omezíme-li se na prioritní třídy
PT1 a PT2, pak můžeme konstatovat, že prioritní třída PT1 disponuje v celkové hierarchii
vyšší prioritou než prioritní třída PT2. Z toho samozřejmě plyne, že binární aritmetické
operátory *, / a % mají přednost před operátory + a –. Hierarchii prioritních tříd vybraných
operátorů jazyka C uvádíme v tab. 11.
Někdy se stává, že prioritní pravidla pro jednoznačné vyhodnocení výrazů nestačí. To se
děje tehdy, sejdou-li se v jednom výrazu (nebo podvýrazu) operátory se stejnou prioritou (čili
operátory z totožné prioritní třídy). Jak vidíme, v tomto kontextu jsou překladači pravidla pro
stanovení priority k ničemu, neboť pomocí nich nedovede přijmout kvalifikované rozhodnutí.
Proto potřebujeme další mechanismus, jenž bude schopen vzniklou nejednoznačnost
odstranit. Tímto mechanismem jsou asociativní pravidla, která nařizují, v jakém pořadí
budou prováděny operace předepsané operátory se stejnou prioritou.
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í determinované asociativitou operátorů bude
vždy dáno dvěma směry: buď zleva doprava, nebo zprava doleva. Pro lepší názornost použijeme
směrové šipky: → pro operátory asociativní zleva doprava a ← pro operátory asociativní zprava
doleva. Tak třeba všechny binární aritmetické operátory jsou asociativní zleva doprava (→).
130
26. Priorita a asociativita operátorů
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
Tab. 11: Hierarchie prioritních tříd vybraných operátorů jazyka C
Prioritní třída
Operátory
Asociativita
1.
() [] -> .
zleva doprava (→)
2.
! ~ ++ -- + - * & (Typ) sizeof
zprava doleva (←)
3.
*/%
zleva doprava (→)
4.
+-
zleva doprava (→)
5.
<< >>
zleva doprava (→)
6.
< <= > >=
zleva doprava (→)
7.
== !=
zleva doprava (→)
8.
&
zleva doprava (→)
9.
^
zleva doprava (→)
10.
|
zleva doprava (→)
11.
&&
zleva doprava (→)
12.
||
zleva doprava (→)
13.
?:
zprava doleva (←)
14.
= += -= *= /= %= &= ^= |= <<= >>=
zprava doleva (←)
15.
,
zleva doprava (→)
Vraťme se nyní k vyhodnocení výrazu a * b % c. Vzhledem k tomu, že operátory * a %
mají stejnou prioritu, musí si překladač pomoci jejich asociativitou. Ta má orientaci →, což
znamená, že výraz bude vyhodnocen jako (a * b) % c. Pokud předpokládáme následující
inicializaci proměnných: a = 50, b = 2 a c = 4, tak hodnotou výrazu bude 0 (100 % 4 = 0).
Přirozeně, ne všechny operátory jsou asociativní →, nemálo z nich má přesně opačnou
asociativitu. Jedním z takovýchto operátorů je přiřazovací operátor (=). Asociativitu operátoru
= jsme objevili již dávno a implicitně jsme s ní pracovali, aniž bychom ji nazvali příslušným
odborným termínem. Jednoduše řečeno, v příkazu p = V; , kde p je proměnná zvoleného
datového typu a V je výraz, bude vždy nejprve vyhodnocen výraz V a až poté bude hodnota
výrazu V přiřazena do proměnné p. Podotkněme, že v závislosti na datovém typu proměnné
a datovém typu hodnoty výrazu mohou (ovšem nemusí) být zpracovány implicitní typové
konverze. Rozvineme-li úvahy o asociativitě operátoru =, pak okamžitě vyřešíme i otázku
vícenásobného přiřazení. Příkaz m = n = o = p; bude vyhodnocen jako m = (n = (o = p));.
Tip: Pokud si nejsme jisti, jakou prioritu a asociativitu mají operátory v zapsaném výrazu, můžeme
si pomoci uzávorkováním těch částí výrazu (čili podvýrazů), které mají být provedeny před ostatními.
Vložíme-li podvýraz do závorek, zvyšujeme preferenci jeho zpracování. S prioritou tak ovlivňujeme
rovněž asociativitu operátorů. Jenom prosím nezapomínejme na skutečnost, že v kterémkoliv výrazu
musí být sudý počet závorek.
131
27. Rozhodovací příkazy
27. Rozhodovací příkazy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
S rozhodovacími problémy se v běžném životě setkáváme velice často. Přijetí jistého
rozhodnutí se odvíjí od charakteru rozhodovacího problému, vstupních dat a potenciálních
alternativ, jimiž se může naše rozhodování ubírat. Proces rozhodování lze graficky
znázornit pomocí rozhodovacího stromu. Na obr. 35 je znázorněn vývojový diagram
s rozhodovacím stromem, který řeší rozhodování o koupi nového auta.
Obr. 35: Vývojový diagram rozhodovacího stromu řešící rozhodování o zakoupení nového auta
Programovací jazyk C obsahuje sadu rozhodovacích příkazů, jejichž pomocí mohou vývojáři
realizovat programová rozhodnutí a větvit tak tok programu. Jde o následující příkazy:
• Příkaz if pro realizaci jednocestného rozhodování.
• Příkaz if-else pro realizaci dvojcestného rozhodování.
• Příkaz if-else if… pro realizaci vícecestného rozhodování.
• Příkaz if-else if-else pro realizaci vícecestného rozhodování.
• Příkaz switch pro realizaci vícecestného rozhodování.
• Ternární operátor ?: pro realizaci dvojcestného rozhodování.
Všechny zmíněné rozhodovací příkazy rozebereme v textu následujících podkapitol.
133
Programování v jaz yce C
27.1. Rozhodovací příkaz if
Rozhodovací příkaz if umožňuje větvení toku programu podle jednostranné podmínky.
Jeho generický syntaktický model vypadá takto:
if(PV)
P1;
– nebo –
if(PV)
{
P1; P2; ... Pn;
}
kde:
• PV je podmínkový výraz, jehož hodnotou bude buď logická pravda, nebo logická
nepravda.
• P1, P2, … Pn jsou příkazy jazyka C, jež budou zpracovány pokaždé, když bude hodnotou
PV logická pravda.
Rozhodování pomocí příkazu if se uskutečňuje takto:
1. Vyhodnotí se PV.
2. Jestliže je hodnotou PV logická pravda, tak se zpracují příkazy umístěné v těle větve if.
Pokud je v těle větve if situován právě jeden příkaz, není nutno explicitně vyznačovat
její tělo pomocí složených závorek. Naopak, nacházejí-li se v těle větve if alespoň dva
příkazy, musí být její tělo explicitně vyznačeno složenými závorkami.
3. Jestliže je hodnotou PV logická nepravda, tak rozhodování končí. Dochází k opuštění
rozhodovacího příkazu if a ke zpracování nejbližšího možného příkazu, jenž následuje
za rozhodovacím příkazem if.
Vizualizaci jednocestného rozhodování pomocí příkazu if můžeme vidět na obr. 36.
Jednocestné rozhodování nám sdělí, zda přirozené číslo, které zadal uživatel na vstupu, je sudé:
#include <stdio.h>
int main()
{
int cislo;
printf(”Zadejte prirozene cislo: ”);
scanf(”%d”, &cislo);
if(cislo % 2 == 0)
printf(”Bylo zadano sude cislo.\n”);
return 0;
}
134
27. Rozhodovací příkazy
Tento program nemá žádná kritická místa, jenom si musíme uvědomit, že sudé přirozené
číslo je každé číslo, jehož zbytek po dělení dvojkou je nulový.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
Obr. 36: Pracovní model příkazu if
27.2. Rozhodovací příkaz if-else
Rozhodovací příkaz if-else uskutečňuje řízení toku programu podle oboustranné
podmínky. Jeho generický syntaktický model je následující:
if(PV)
P1;
else
R1;
– nebo –
if(PV)
{
P1; P2; ... Pn;
}
else
{
R1; R2; ... Rn;
}
kde:
• PV je podmínkový výraz, jehož logickou hodnotu lze určit.
• P1, P2, … Pn jsou příkazy, které budou provedeny tehdy, bude-li hodnotou PV logická pravda.
• R1, R2, … Rn jsou příkazy, jež budou zpracovány v případě, kdy bude hodnotou PV logická
nepravda.
135
27. Rozhodovací příkazy
27.5. Praktické cvičení: program na detekci kolize mezi
automobilem a chodcem
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
Představme si tuto modelovou situaci: Automobil jede po cestě, když se v jisté vzdálenosti od
něj objeví chodec. Cílem našeho dalšího praktického cvičení je zjistit, zda mezi dopravním
prostředkem a člověkem dojde ke kolizi, či nikoliv. Budeme přitom postupovat následovně:
1. Celkovou vzdálenost, která dělí automobil od chodce, označíme identifikátorem SC.
Dodejme, že celková vzdálenost je dána dráhou, která dělí automobil a chodce v čase t0
čili v čase, kdy auto jede počáteční rychlostí v0 a řidič spatří chodce na cestě před sebou.
2. Při analýze pohybu automobilu rozdělíme celou dráhu na dvě menší dráhy: jedna
z nich bude reakční dráha (SR) a druhá bude brzdná dráha (SB). Reakční dráha je dráha,
kterou automobil urazí během reakčního času (tR), tedy času, jenž je vymezen časovým
intervalem, na jehož konci si řidič automobilu uvědomí, že v zájmu zabránění kolize
s objektem na cestě má sešlápnout brzdový pedál a snížit tak rychlost auta. Brzdná
dráha je pak dráha, která je nutná k úplnému zastavení vozidla. Jelikož počítáme
s úplným zabrzděním, konečná rychlost automobilu (vF) bude nulová.
3. Problém detekce kolize má fyzikální charakter, přičemž pro jeho vyřešení využijeme
několik matematických vztahů z mechaniky, jedné z disciplín moderní fyziky. Je zřejmé,
že ke kolizi nedojde v případě, že SR + SB < SC. Protože reakční dráhu ujede automobil
v počáteční rychlosti v0, můžeme ji vypočítat takto:
SR = v0 tR
4. Výpočet brzdné dráhy je o něco komplikovanější, neboť v něm musíme uvažovat se
zpomalením automobilu v důsledku aktivace brzdných mechanizmů. Všeobecný
vzorec pro výpočet brzdné dráhy má tuto podobu:
SB =
v F2- v 02
2a
kde:
• vF je konečná rychlost automobilu,
• v0 je počáteční rychlost automobilu,
• a je koeficient zpomalení.
Jelikož z našich předpokladů vyplývá, že vF = 0, tak samozřejmě i vF2 = 0. Všeobecný
vzorec pro stanovení brzdné dráhy proto smíme upravit následujícím způsobem:
SB =
- v 02
2a
141
Programování v jaz yce C
Ovšem co to ve skutečnosti znamená? Pomozme si praktickou ukázkou. Povězme,
že počáteční rychlost automobilu bude 60 km/h, celková vzdálenost (SC) bude 50 m,
reakční čas (tR) bude 0,45 s a koeficient zpomalení (a) bude -6,5 m/s2.
Poznámka: Ještě než začneme s dosazováním hodnot do vzorců, musíme unifikovat jednotky
všech veličin. Jelikož budeme chtít mít všechny veličiny zadány v metrech nebo v sekundách,
budeme muset počáteční rychlost auta převést z km/h na m/s. To znamená dělit rychlost
zadanou v km/h reálnou konstantou 3,6. Platí, že 60 km/h se přibližně rovná 16,67 m/s.
5. Reakční a brzdnou dráhu vypočítáme takto:
SR = 16,67 × 0,45 = 7,5 m
SB =
- 16,672
=
2×(- 6,5)
- 277,89
= 21,38 m
- 13
ST = SR + SB = 7,5 + 21,38 ≅ 29 m
V našem fyzikálním modelu tedy automobil zcela zastaví po ujetí 29 metrů, takže
ke kolizi s chodcem naštěstí nedojde.
Obr. 40: Detekce kolize mezi automobilem a chodcem
142
27. Rozhodovací příkazy
Přejděme nyní k algoritmizaci fyzikální úlohy:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <stdio.h>
int main()
{
int celkovaDraha;
float pocatecniRychlost, reakcniCas, zpomaleni;
float reakcniDraha, brzdnaDraha;
printf(”Zadejte pocatecni rychlost auta (v km/h): ”);
scanf(”%f”, &pocatecniRychlost);
pocatecniRychlost /= 3.6f;
printf(”Zadejte celkovou drahu mezi autem a chodcem (v m): ”);
scanf(”%d”, &celkovaDraha);
printf(”Zadejte delku reakcniho casu (v s): ”);
scanf(”%f”, &reakcniCas);
printf(”Zadejte zpomaleni (v m/s2): ”);
scanf(”%f”, &zpomaleni);
reakcniDraha = pocatecniRychlost * reakcniCas;
brzdnaDraha = -(pocatecniRychlost * pocatecniRychlost) / (2 * zpomaleni);
printf(”Reakcni draha je %.2f m.\n”, reakcniDraha);
printf(”Brzdna dráha je %.2f m.\n”, brzdnaDraha);
printf(”Auto zcela zabrzdi po ujeti %.2f m.\n”, reakcniDraha + brzdnaDraha);
if (reakcniDraha + brzdnaDraha < celkovaDraha)
{
printf(”Mezi autem a chodcem nedojde ke kolizi.”);
}
else
{
printf(”Mezi autem a chodcem dojde ke kolizi.”);
}
return 0;
}
Komentář k zdrojovému kódu jazyka C: Program věrně kopíruje fyzikální výklad,
jejž jsme uvedli, a proto se domníváme, že byste se neměli setkat s žádnými kritickými
pasážemi. Jenom připomínáme, že program očekává zadání záporné hodnoty pro
koeficient zpomalení.
27.6. Rozhodovací příkaz switch
Rozhodovací příkaz switch byl navržen speciálně pro vícecestné rozhodování. Nejprve
uvedeme jeho generický syntaktický skelet a pak si vysvětlíme, jak tento příkaz provádí
své rozhodování.
143
Programování v jaz yce C
28. Programové cykly
Programový cyklus nebo jen cyklus je označení pro iterativní syntaktickou konstrukci, která
umožňuje opakované zpracování množiny příkazů, zpravidla na základě vyhodnocení
stanoveného rozhodovacího výrazu. Programovací jazyk C zná tři základní typy cyklů:
1. Cyklus for
2. Cyklus while
3. Cyklus do-while.
Průchod cyklem se v terminologii programování označuje iterací cyklu. Iterace cyklu tedy
označuje jedno opakování cyklu. Během jedné iterace cyklu jsou postupně zpracovány
všechny programové příkazy, jež jsou umístěny v těle cyklu. Po zpracování každé iterace
přijímá cyklus rozhodnutí o tom, zda bude provedena rovněž další iterace cyklu, či nikoliv.
Toto rozhodnutí obvykle vyplývá z vyhodnocení určitého rozhodovacího výrazu (nebo
podmínky, jak někdy také zkráceně říkáme). V následujících podkapitolách podáme výklad
všech zmíněných cyklů jazyka C.
Obr. 41: Schematický model programového cyklu
28.1. Cyklus for
Schematický model cyklu for má následující podobu:
for(IV; RV; M V)
{
P1; P2; ... Pn;
}
148
28. Programové cykly
První řádek definice cyklu for tvoří hlavičku cyklu. V hlavičce cyklu jsou seskupeny tři
součásti uzavřené v závorkách. Těmito součástmi jsou:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
• IV – inicializační výraz. IV inicializuje řídící proměnnou cyklu for. Každý cyklus,
nejenom cyklus for, pracuje s proměnnou, která řídí jeho život. Z uvedeného důvodu se
tato proměnná označuje termínem řídící proměnná cyklu. I když je na programátorovi,
jaký datový typ, identifikátor a inicializační hodnotu bude řídící proměnná cyklu mít,
v praxi se nejčastěji setkáváme s celočíselnými řídícími proměnnými. V jazyce C musí
být řídící proměnná cyklu for definována před tímto cyklem. Jazyk C neumožňuje, na
rozdíl od jazyků C++, C++/CLI a C#, aby byla řídící proměnná cyklu for definována
přímo v jeho hlavičce. Řídící proměnnou cyklu for tak bude v naprosté většině případů
lokální proměnná, která bude definována v těle funkce, v níž je cyklus for situován. Po
zpracování IV obsahuje řídící proměnná cyklu for požadovanou inicializační hodnotu.
• RV – rozhodovací výraz. Rozhodovací výraz tvoří nutnou součást hlavičky cyklu for,
poněvadž podle hodnoty rozhodovacího výrazu přijímá cyklus rozhodnutí o provedení
své další iterace. Rozhodovacím výrazem smí být jakýkoliv syntakticky korektně
zapsaný a sémanticky smysluplný výraz, jehož hodnotou je buď logická pravda, nebo
logická nepravda. Jestliže je hodnotou RV logická pravda, vykoná se další iterace cyklu
for. Pokud bude naopak hodnotou RV logická nepravda, další iterace cyklu for se
neuskuteční. Za těchto okolností cyklus for končí svou činnost.
• MV – manipulační výraz. Manipulační výraz aplikuje jistou, zpravidla aritmetickou,
manipulační operaci na řídící proměnnou cyklu for. Manipulačním výrazem bývá
inkrementační výraz, jehož smyslem je inkrementovat hodnotu řídící proměnné cyklu
for před vstupem do následující iterace tohoto cyklu. Podobně může manipulačním
výrazem být také dekrementační výraz, který dekrementuje hodnotu řídící proměnné
cyklu for. Ve všeobecnosti ale smíme konstatovat, že manipulačním výrazem cyklu
for může být jakýkoliv validní výraz, který požadovaným způsobem modifikuje stav
řídící proměnné tohoto cyklu.
Tělo cyklu for tvoří konečná a neprázdná množina programových příkazů P1, P2, … Pn,
které jsou ohraničeny složenými závorkami {}. Jestliže bude provedena iterace cyklu for,
dojde ke zpracování všech příkazů uložených v jeho těle.
Podle všeobecného modelu dále zkonstruujeme konkrétní cyklus for a vysvětlíme jeho
pracovní model.
#include <stdio.h>
int main()
{
int i;
for(i = 1; i <= 10; i++)
{
printf(”%d\n”, i);
}
return 0;
}
149
Programování v jaz yce C
Předestřený cyklus for bude zpracován takto:
1. Při vstupu do cyklu se nejprve provede IV. Tento výraz inicializuje řídící proměnnou
cyklu for (s identifikátorem i a datovým typem int). Explicitní inicializační hodnotou
řídící proměnné cyklu je 1.
2. Vyhodnotí se rozhodovací výraz i<=10. Přesněji řečeno, rozhodovací výraz je v tomto
konkrétním případě relačním výrazem. (K tomuto závěru dojdeme snadno, neboť
operátor <= je binárním relačním operátorem.) Rozhodovací výraz vyhodnotíme tak,
že za identifikátor proměnné i dosadíme aktuální hodnotu řídící proměnné cyklu for.
Tou je 1, vyhodnocujeme tedy výraz 1<=10. Relační operátor zjistí, že mezi operandy
1 a 10 existuje relace, protože jednička je menší hodnota než desítka. Hodnotou
rozhodovacího výrazu je logická pravda (1), což cyklus for přiměje k tomu, aby
vykonal svou 1. iteraci. Během ní je vykonán příkaz, jenž se nachází v těle cyklu.
Tento příkaz je dobře srozumitelný: jeho úloha spočívá v zobrazení aktuální hodnoty
řídící proměnné cyklu for (ano, tou bude v 1. iteraci 1).
3. Po vykonání příkazu v těle cyklu for přichází na řadu zpracování manipulačního
výrazu. Tímto výrazem je i++ čili postfixová inkrementace řídící proměnné cyklu.
Všimněme si prosím, že na konci 1. iterace cyklu zvyšujeme hodnotu jeho řídící
proměnné. Z jedničky děláme dvojku a tu vzápětí přiřazujeme do proměnné i. Tím je
1. iterace cyklu for u konce a začíná se další iterace.
4. Ve své 2. iteraci cyklus pomíjí IV a rovnou přechází na testování rozhodovacího
výrazu. Bude dobré, když budeme mít na paměti skutečnost, že IV je zpracováván
pouze jednou, a to při vstupu do cyklu for. Vyhodnocení rozhodovacího výrazu
znamená testování relace mezi operandy 2 a 10 (připomeňme, že aktuální hodnotou
řídící proměnné cyklu je v 2. iteraci dvojka). Přirozeně, tato podmínka je splněna,
a proto cyklus for provede příkaz, který zobrazí aktuální hodnotu řídící proměnné.
Cyklus pokračuje inkrementací řídící proměnné (na hodnotu 3), čímž se končí jeho 2.
iterace.
5. 3. iterace cyklu má podobný průběh jako ta předcházející: cyklus vyhodnocuje
rozhodovací výraz, a protože výsledkem tohoto procesu je opět logická pravda (3<10),
znovu se na výstupu zobrazí aktuální hodnota řídící proměnné cyklu.
6. Charakterizovaná posloupnost operací se opakuje tak dlouho, dokud nebude
hodnotou rozhodovacího výrazu logická nepravda. To se děje v 11. iteraci cyklu,
v níž bude řídící proměnná obsahovat hodnotu 11. Vzhledem k tomu, že výraz 11<=10
není pravdivý, jeho hodnotou bude logická nepravda (0). V této situaci cyklus for
zamítá provedení další iterace a končí svou činnost. Praktickou implikací pracovního
modelu cyklu for je skutečnost, že program obsahující náš cyklus zobrazí na výstupu
posloupnost celých čísel z intervalu <1, 10>.
150
28. Programové cykly
Grafickou podobu pracovního modelu cyklu for uvádíme na obr. 42.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
Obr. 42: Pracovní model cyklu for
Cyklus for nám poslouží například při výpočtu faktoriálu libovolného čísla. Jak víme
z matematiky, definice faktoriálu má rekurentně-rekurzivní povahu:
n! = n ×( n-1)! pro každé n ∈ N ∪ {0}, přičemž 0! = 1.
Zdrojový kód programu v jazyce C má následující syntaktický obraz:
#include <stdio.h>
int main()
{
int i, n, faktorial = 1;
printf(”Zadejte n: ”);
scanf(”%d”, &n);
/* Výpočet n! provádí cyklus for. */
for(i = 2; i <= n; i++)
{
faktorial *= i;
}
printf(”%d! je %d.\n”, n, faktorial);
return 0;
}
151
Programování v jaz yce C
Komentář k zdrojovému kódu jazyka C: Zadání pro výpočet faktoriálu patří mezi úlohy,
které elegantně vyřešíme pomocí programového cyklu. V našem případě jsme upotřebili
cyklus for s tímto nastavením:
• V hlavičce cyklu je inicializována řídící proměnná cyklu i typu int. Explicitní inicializační
hodnotou řídící proměnné je 2, což je vzhledem k povaze úlohy pochopitelné.
• Rozhodovací výraz zjišťuje, zda je hodnota řídící proměnné cyklu menší nebo rovna
hodnotě proměnné n (v této proměnné je uložen člen, jehož faktoriál hodláme
vypočítat).
• Manipulačním výrazem je postfixová inkrementace řídící proměnné, což znamená, že na
konci každé iterace cyklu bude hodnota proměnné i zvýšena o 1.
• Do těla cyklu jsme vložili jediný příkaz, který postupně, s probíhajícími iteracemi cyklu,
vypočítavá faktoriál zadaného čísla.
Poznámka: Podotkněme, že příkaz
faktorial *= i;
můžeme ekvivalentně nahradit příkazem
faktorial = faktorial * i;
Pro lepší názornost budeme analyzovat zpracování cyklu for po jednotlivých iteracích pro
výpočet 5! (tab. 12).
Tab. 12: Analýza iterativního výpočtu 5! pomocí cyklu for
Iterace
RV
Je hodnotou RV
logická pravda?
Výraz
Hodnota výrazu (uložena
v proměnné faktorial)
1.
2 <= 5
Ano
1*2
2
2.
3 <= 5
Ano
2*3
6
3.
4 <= 5
Ano
6*4
24
4.
5 <= 5
Ano
24 * 5
120
5.
6 <= 5
Ne
-
120
Jak se dozvíme po spuštění programu, 5! je 120. Zkusme s programem trošičku
experimentovat a zjišťujme faktoriály dalších přirozených čísel. Jenom berme v potaz,
že hodnoty faktoriálů rostou docela rychle. Kupříkladu 10! představuje číslo větší než
3,6 milionu.
152
29. Funkce
29. Funkce
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
V ryze strukturovaném programovacím jazyce, jakým je jazyk C, je funkce základní
stavební buňkou každého správně navrženého strukturovaného programu. Mnozí autoři
funkci velice často definují jako podprogram, který provádí exaktní algoritmizaci řešené
úlohy. Techničtěji bychom mohli funkci popsat jako vyhrazený blok programového kódu,
který obsahuje konečnou a neprázdnou množinu programových příkazů. Tyto příkazy
implementují určitý algoritmus a jejich zpracování vede k vykonání algoritmu a k nalezení
řešení úlohy.
Každý strukturovaný program obsahuje hlavní funkci main, která vystupuje jako vstupní
bod tohoto programu. Když uživatel vydá pokyn na spuštění programu, operační systém
automaticky zavolá hlavní funkci main a zahájí zpracování jejích příkazů.
Poznámka: Podobně na funkce nahlížejí i programovací jazyky, k nimž řadíme C++, C# nebo
C++/CLI – ty ovšem navíc funkce zapouzdřují do tříd coby abstraktních objektových uživatelsky
deklarovaných datových typů. O těchto jazycích říkáme, že jsou hybridní, což je dáno tím, že
kromě strukturovaného paradigmatu zavádějí rovněž objektově orientované paradigma vývoje
počítačového softwaru. Ve všeobecnosti platí, že když je programovací jazyk hybridní, tak v sobě
integruje syntakticko-sémantické konstrukce pro podporu více programovacích paradigmat.
Všechny programy jazyka C, které jsme dosud společně vytvořili, obsahují hlavní funkci
main. V této kapitole se naučíme, jak mohou programátoři vytvářet své vlastní, takzvané
uživatelsky definované funkce. Poté si ukážeme, jak se uskutečňuje komunikační dialog
mezi hlavní funkcí main a uživatelsky definovanými funkcemi.
Když budeme chtít v jazyce C vytvořit svou vlastní funkci, budeme ji muset deklarovat
a definovat. V terminologii programování jsou termíny „deklarace funkce“ a „definice
funkce“ velice významné. Není správné tyto termíny zaměňovat, neboť každý determinuje
odlišnou programovou konstrukci.
Deklarace funkce je příkaz, který překladači oznamuje, že chceme vytvořit svou
vlastní funkci. Když funkci deklarujeme, zavedeme do zdrojového kódu jazyka C její
prototyp. Dovolíme si poznamenat, že v praxi se termíny „deklarace funkce“ a „prototyp
funkce“, respektive „deklarace funkce“ a „funkční prototyp“ volně zaměňují. To je
v pořádku, protože oba termíny mají synonymický význam, přičemž identifikují totožnou
programovou konstrukci.
Prototyp funkce sděluje překladači následující informace o funkci:
• Datový typ návratové hodnoty funkce
• Identifikátor funkce
• Seznam formálních parametrů funkce
157
30. Struktury
30. Struktury
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
Struktura je v programovacím jazyce C agregovaný heterogenní uživatelsky deklarovaný
datový typ (UDDT). Struktura se skládá z konečné a neprázdné množiny datových členů, jež
jsou ze syntaktické stránky nejčastěji reprezentovány proměnnými primitivních datových
typů. Každý datový člen správně deklarované struktury musí mít svůj identifikátor
a datový typ.
Struktury umožňují efektivně modelovat datové entity reálného světa. Díky tomu, že
struktury provádějí zapouzdření datových členů do jednoho logického celku, dovolují
nám pracovat s množinou spřízněných datových členů jako s jedním datovým objektem.
Pomocí struktur dovedeme modelovat například následující entity:
1. Student – charakterizovaný svým jménem, příjmením, adresou, ročníkem studia,
počtem zapsaných předmětů, počtem dosažených kreditů atd.
2. Vysokoškolský pedagog – charakterizovaný svým jménem, příjmením, adresou,
mzdou, funkčním zařazením, počtem vyučovaných předmětů, počtem odborných
publikací a vědeckých prací atd.
3. Počítač – charakterizovaný procesorem, počtem výpočetních jader uvnitř procesoru,
kapacitou operační paměti, úložním prostorem pevného disku, modelem zvukové
a grafické karty, cenou atd.
4. MP3 přehrávač – charakterizovaný kapacitou operační paměti, počtem skladeb, počtem
podporovaných multimediálních formátů, barvou svého krytu, cenou, možností
přehrávat videosoubory atd.
5. Automobil – charakterizovaný výkonem motoru (v KW), spotřebou (v litrech na 100 km),
cenou, počtem míst na sezení, počtem dveří, barvou karoserie, délkou, šířkou a výškou atd.
6. Výrobek – charakterizovaný svým identifikačním číslem, názvem, cenou, složením
komponent atd.
7. Matematický vektor – charakterizovaný uspořádanou n-ticí celočíselných nebo
reálných hodnot.
8. Programové vlákno fyzického procesu programu jazyka C – charakterizované svým
identifikátorem, alokační kapacitou přiděleného paměťového prostoru, prioritou,
stavem, celkovým časem provádění atd.
Jak si můžeme všimnout, pomocí struktur můžeme modelovat nejenom živé entity
(student, vysokoškolský učitel), ale i neživé entity (počítač, automobil). Neživé entity lze
rozdělit na hmotné neživé entity a nehmotné (abstraktní) neživé entity. Abstraktní entitou
je třeba vektor, ale také integrál, rovnice nebo jakýkoliv jiný matematický objekt. Struktury
samozřejmě umí popsat datové složení všech zmíněných typů entit.
169
30. Struktury
30.4. Použití inicializované instance struktury
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
Po instanciaci a inicializaci instance může být tato nabídnuta klientům k přímé manipulaci.
Klienti mohou číst hodnoty datových členů instance nebo je měnit podle svých potřeb.
Následující ukázka mění složky 3D vektoru a vzápětí je zobrazuje na výstupu:
#include <stdio.h>
struct Vektor3D
{
int x, y, z;
};
int main()
{
struct Vektor3D vektor;
vektor.x = vektor.y = vektor.z = 1;
printf(”Slozky 3D vektoru po inicializaci: %d, %d, %d.\n”,
vektor.x, vektor.y, vektor.z);
vektor.x += 1;
vektor.y += 2;
vektor.z += 3;
printf(”Slozky 3D vektoru po reinicializaci: %d, %d, %d.\n”,
vektor.x, vektor.y, vektor.z);
return 0;
}
Komentář k zdrojovému kódu jazyka C: Ihned poté, co vytvoříme a inicializujeme nový
3D vektor, zobrazujeme jeho složky na výstupu. V další etapě pak provádíme reinicializaci
3D vektoru, přičemž upravenou podobu jeho složek rovněž zobrazujeme na výstupu.
Samozřejmě můžeme stávající zdrojový kód upravit tak, abychom dovedli s 3D vektorem
uskutečnit jistou manipulační operaci, kupříkladu jej vynásobit skalárem:
#include <stdio.h>
struct Vektor3D
{
int x, y, z;
};
int main()
{
struct Vektor3D vektor;
int skalar;
printf(”Zadejte slozky 3D vektoru (jako cela cisla oddelena mezerami): ”);
scanf(”%d %d %d”, &vektor.x, &vektor.y, &vektor.z);
printf(”Zadejte skalar (jako cele cislo), jenz bude pouzit k modifikaci 3D vektoru: ”);
scanf(”%d”, &skalar);
printf(”Puvodni 3D vektor: %d, %d, %d.\n”, vektor.x, vektor.y, vektor.z);
vektor.x *= skalar;
vektor.y *= skalar;
vektor.z *= skalar;
printf(”Novy 3D vektor: %d, %d, %d.\n”, vektor.x, vektor.y, vektor.z);
return 0;
}
175
Programování v jaz yce C
Komentář k zdrojovému kódu jazyka C: Pomineme-li standardní pracovní postup se
strukturou Vektor3D, tak jedinou obměnou je uživatelská inicializace vytvořeného 3D
vektoru (uživatel sám zadá na vstupu hodnoty, jež budou posléze uloženy do příslušných
datových členů instance struktury Vektor3D).
Poznámka: Když voláme funkci scanf za účelem načtení více hodnot najednou, zadáváme více
formátových specifikátorů (v našem případě jsou 3). V řídícím řetězci funkce scanf jsou tyto
formátové specifikátory odděleny mezerami. To znamená, že uživatel zadá na vstupu 3 celočíselné
hodnoty (složky 3D vektoru), které budou také odděleny mezerami (ekvivalentně mohou být tyto
hodnoty odděleny rovněž symboly nového řádku, které vložíme stiskem klávesy ENTER).
Program na výstupu zobrazí nejprve složky 3D vektoru neprodleně po jeho uživatelské
inicializaci a poté nás obeznámí rovněž s podobou nového 3D vektoru, který vzešel
z multiplikativní operace se skalárem.
Kromě vynásobení 3D vektoru skalárem smíme uskutečnit také součet a rozdíl dvou 3D
vektorů. Více informací již podává další program jazyka C:
#include <stdio.h>
struct Vektor3D
{
int x, y, z;
};
int main()
{
/* Vytvoření 4 3D vektorů. */
struct Vektor3D vektor1, vektor2;
struct Vektor3D souctovyVektor, rozdilovyVektor;
/* Inicializace vytvořených 3D vektorů. */
printf(”Zadejte slozky 1. 3D vektoru (jako cela cisla oddelena mezerami): ”);
scanf(”%d %d %d”, &vektor1.x, &vektor1.y, &vektor1.z);
printf(”Zadejte slozky 2. 3D vektoru (jako cela cisla oddelena mezerami): ”);
scanf(”%d %d %d”, &vektor2.x, &vektor2.y, &vektor2.z);
/* Vypočtení součtového 3D vektoru. */
souctovyVektor.x = vektor1.x + vektor2.x;
souctovyVektor.y = vektor1.y + vektor2.y;
souctovyVektor.z = vektor1.z + vektor2.z;
/* Vypočtení rozdílového 3D vektoru. */
rozdilovyVektor.x = vektor1.x - vektor2.x;
rozdilovyVektor.y = vektor1.y - vektor2.y;
rozdilovyVektor.z = vektor1.z - vektor2.z;
/* Zobrazení složek všech 3D vektorů na výstupu. */
printf(”1. 3D vektor: %d, %d, %d.\n”, vektor1.x, vektor1.y, vektor1.z);
printf(”2. 3D vektor: %d, %d, %d.\n”, vektor2.x, vektor2.y, vektor2.z);
printf(”Souctovy vektor: %d, %d, %d.\n”, souctovyVektor.x, souctovyVektor.y,
souctovyVektor.z);
printf(”Rozdilovy vektor: %d, %d, %d.\n”, rozdilovyVektor.x, rozdilovyVektor.y,
rozdilovyVektor.z);
return 0;
}
176
Programování v jaz yce C
Závěr
Když zvládnete algoritmizaci a programování v jazyce C, přičemž najdete v programování
zalíbení, je rozumné zvážit potenciální cesty budoucího rozvoje vašeho odborného profilu.
Abyste měli představu, co vám může tento svět nabídnout, uvádíme možné směry dalšího
postupu:
1. Seznamte se s datovými strukturami a algoritmy, které s nimi manipulují.
2. Absolvujte pokročilý kurz programátorských technik v jazyce C.
3. Naučte se jazyk C++ a ovládněte základy objektově orientovaného programování
(OOP).
4. Studujte jazyk C# a naučte se vytvářet programy s grafickým uživatelským rozhraním
s podporou OOP.
5. Věnujte čas paralelnímu a paralelnímu objektově orientovanému programování
(POOP) v jazycích C, C++ a C#.
Zvládnete-li tuto pětihvězdičkovou sadu programátorských kurzů, pak z vás budou
opravdové IT hvězdy. Vaše hodnota na trhu práce bude enormně vysoká a možnosti takřka
nekonečné. A můžete udělat vše pro to, aby se z tohoto světa stalo lepší místo pro život!
O autorovi
Ing. Ján Hanák, Ph.D., MVP, vystudoval Ekonomickou univerzitu v Bratislavě. Pracuje jako
vysokoškolský pedagog na zdejší Katedře aplikované informatiky Fakulty hospodářské
informatiky (KAI FHI). Přednáší a vede semináře týkající se programování a vývoje
počítačového softwaru v programovacích jazycích C, C++ a C#. Kromě zmíněné trojice
jazyků patří k jeho oblíbeným programovacím prostředkům také Visual Basic, C++/CLI
a F#. Je nadšeným autorem odborné počítačové literatury. V jeho portfoliu můžete najít
následující knižní tituly:
1. Programování v jazyce C. Kralice na Hané: Computer Media, 2010.
2. C++: Akademický výučbový kurz. Bratislava: Vydavateľstvo EKONÓM, 2010.
3. Inovácie v jazykoch Visual Basic 2010, C# 4.0 a C++. Brno: Artax, 2010.
4. Visual Basic 2010 – Hotové riešenia. Bratislava: Microsoft Slovakia, 2010.
5. C#: Akademický výučbový kurz, 2. aktualizované a rozšírené vydanie. Bratislava:
Vydavateľstvo EKONÓM, 2010.
6. Praktické paralelné programovanie v jazykoch C# 4.0 a C++. Brno: Artax, 2009.
7. C++/CLI – Praktické príklady. Brno: Artax, 2009.
214
Nadpis kapitoly
8. C# 3.0 – Programování na platformě .NET 3.5. Brno: Zoner Press, 2009.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
9. C++/CLI – Začínáme programovat. Brno: Artax, 2009.
10. C#: Akademický výučbový kurz. Bratislava: Vydavateľstvo EKONÓM, 2009.
11. Základy paralelného programovania v jazyku C# 3.0. Brno: Artax, 2009.
12. Objektovo orientované programovanie v jazyku C# 3.0. Brno: Artax, 2008.
13. Inovácie v jazyku Visual Basic 2008. Praha: Microsoft, 2008.
14. Visual Basic 2008: Grafické transformácie a ich optimalizácie. Bratislava: Microsoft
Slovakia, 2008.
15. Programovanie B – Zbierka prednášok (Učebná pomôcka na programovanie v jazyku
C++). Bratislava: Vydavateľstvo EKONÓM, 2008.
16. Programovanie A – Zbierka prednášok (Učebná pomôcka na programovanie
v jazyku C). Bratislava: Vydavateľstvo EKONÓM, 2008.
17. Expanzívne šablóny: Príručka pre tvorbu "code snippets" pre Visual Studio.
Bratislava: Microsoft Slovakia, 2008.
18. Kryptografia: Príručka pre praktické odskúšanie symetrického šifrovania v .NET
Framework-u. Bratislava: Microsoft Slovakia, 2007.
19. Príručka pre praktické odskúšanie vývoja nad Windows Mobile 6.0. Bratislava:
Microsoft Slovakia, 2007.
20. Príručka pre praktické odskúšanie vývoja nad DirectX. Bratislava: Microsoft Slovakia,
2007.
21. Príručka pre praktické odskúšanie automatizácie aplikácií Microsoft Office 2007.
Bratislava: Microsoft Slovakia, 2007.
22. Visual Basic 2005 pro pokročilé. Brno: Zoner Press, 2006.
23. C# – praktické příklady. Praha: Grada Publishing, 2006.
24. Programujeme v jazycích C++ s Managed Extensions a C++/CLI. Praha: Microsoft,
2006.
25. Přecházíme z jazyka Visual Basic 6.0 na jazyk Visual Basic 2005. Praha: Microsoft,
2005.
26. Visual Basic .NET 2003 – Začínáme programovat. Praha: Grada Publishing, 2004.
V letech 2006 – 2010 byl jeho přínos vývojářským komunitám oceněn celosvětovými
vývojářskými tituly Microsoft Most Valuable Professional (MVP) s kompetencí Visual
Developer – Visual C++.
215
Programování v jaz yce C
Společnost Microsoft ČR udělila Ing. Jánovi Hanákovi, MVP, v roce 2009 ocenění za
mimořádně úspěšné odborné knižní publikace „Objektovo orientované programovanie
v jazyku C# 3.0“ a „Inovácie v jazyku Visual Basic 2008“.
Společnost Microsoft Slovakia udělila Ing. Jánovi Hanákovi, MVP, v roce 2009 ocenění
za zlepšování akademického ekosystému a za signifikantní rozšiřování technologií
a programovacích jazyků Microsoftu na akademické půdě.
Kontakt s vývojáři a programátory udržuje zejména prostřednictvím technických
seminářů a odborných konferencí, na nichž aktivně vystupuje. Za všechny vybíráme tyto:
• Technický seminář Vývojářské technologie a nástroje pro vývoj softwarových
produktů nové generace. KAI FHI EU a Microsoft Slovakia. Bratislava 29. 4. 2010.
• Technický seminář Paralelné programovanie. KAI FHI EU a Microsoft Slovakia.
Bratislava 21. 10. 2009.
• Konference Software Developer 2007, příspěvek na téma Představení produktu
Visual C# 2005 a jazyka C# 3.0. Praha 19. 6. 2007.
• Technický seminář Novinky ve Visual C# 2005. Microsoft Slovakia. Bratislava 3. 10. 2006.
• Technický seminář Visual Basic 2005 a jeho cesta k Windows Vista. Microsoft Slovakia.
Bratislava 27. 4. 2006.
Jako autor má letité zkušenosti s působením v elektronických a tištěných médiích. Během
své kariéry pracoval na pozici odborného autora nebo odborného redaktora v následujících
počítačových časopisech:
PC WORLD, SOFTWARE DEVELOPER, CONNECT!, COMPUTERWORLD, INFOWARE,
PC REVUE a CHIP.
Dohromady publikoval více než 250 odborných a populárních prací věnovaných vývoji
počítačového softwaru.
Autora můžete zastihnout na následující adrese elektronické pošty: [email protected].
216

Podobné dokumenty

Studijní text - Personalizace výuky prostřednictvím e

Studijní text  - Personalizace výuky prostřednictvím e cílového bodu v rastru, přičemž respektujte počáteční natočení psa.

Více

1 Prolog

1 Prolog Poslední pravidlo fail není nikdy splněno. Na obrázku 1 můžeme v blokovém modelu nechat jen vstup CALL, výstup FAIL a vnitřní průchod 4. Funkcionalita tak bude odpovídat bloku na obrázku 6.

Více

Programován´ı v C++ Prvn´ı kroky

Programován´ı v C++ Prvn´ı kroky soubor proměnných, které majı́ nějakou logickou souvislost a lze je jako celek nějakým způsobem použı́t. V tomto přı́padě jsme vytvořili strukturu TClovek která popisuje, jaké základn...

Více

zos-prednasky-komplet 6.49MB 21.01.2014 00:26:05

zos-prednasky-komplet 6.49MB 21.01.2014 00:26:05 Uživatel neví kde běží programy, kde jsou soubory

Více

WPM 3 Hlavní regulace

WPM 3 Hlavní regulace Požadovanou akci spustíte krátkým klepnutím na tlačítko. Při dlouhém dotyku ovládací prvek nereaguje.

Více