You are on page 1of 294

vod do objektovho programovn

za pomoci jazyka C#
Jii liei
Katedia infoimatiky Pl UJlP
Usti nad Labem
MMXlll (Beta s. ledna zc1I)
Ji Fier, 2013
Toto je piacovni veize skiipt. Je iena bez jakchkoliv zaiuk, co se te obsahu
i pouitelnosti.
Licence:
Creative Commons Uvete autora-Nezasahujte do dla 3.0 esko (CC BY-ND I.c),
viz http://creativecommons.org/licenses/by-nd/3.0/cz/
Pi sazb byly vyuity nasledujici open-souice ezy pisma
Linux Libertine
Linux Biolinum
DejaVu Sans Mono
Text byl vysazen za pomoci piogiamu X

L
A
T
l
X.
Ikony chyb
Zdiojov souboiy i fiagmenty kodu, ktei jsou uivany jako negativni pipady,
to jest obsahuji njakou chybu, jsou oznaeny nasledujicimi ikonami
syntakti yba
Kod s touto chybou nepjde ani peloit. Odhaleni tto chyby je pioto velmi snad-
n a iychl.
smanti yba (vjimen situace)
Tato smanticka chyba vede ke vzniku vjimky za bhu piogiamu. Pokud neni
vjimka zachycena, piogiam pedasn skoni. Detekce tto chyby je o nco na-
ionji, nebo kod, ktei ji obsahuje nemusi bt vbec pioveden (je-li napiklad
souasti netestovan vtve konstiukce if )
neoekvan i nedenovan ovn programu
Piogiam(i fiagment) nepiovadi oekavanou innost, piodukuje neoekavan v-
sledky (dsledn), nebo funguje jen pio uiit vstupy iesp. jen v uiitmkontextu.
Tento diuh chyb se odhaluje nejobtinji.
Obsah
1. Zklady objektov orientovanho programovn 7
1.1. Uiovn objektov oiientovanho pistupu . . . . . . . . . . . . . . . . . . . s
1.1.1. Objektov oiientovan pohled na okolni svt . . . . . . . . . . . . s
1.1.z. Obecn objektov oiientovan model . . . . . . . . . . . . . . . . . s
1.1.I. OOP piogiamovaci jazyk . . . . . . . . . . . . . . . . . . . . . . . . v
1.z. Zakladni pojmy OOP (na iovni objektovho pohledu na svt) . . . . . . . 11
1.z.1. Objekt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.z.z. Tida . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
2. Zkladn objektov model C# 19
z.1. Zakladni tidy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . zc
z.1.1. iseln tidy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . zc
int . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . zc
double . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . z1
z.1.z. Znakov a etzcov tidy . . . . . . . . . . . . . . . . . . . . . . . zz
z.1.I. Logick hodnoty . . . . . . . . . . . . . . . . . . . . . . . . . . . . z1
z.1.1. asov okamiky . . . . . . . . . . . . . . . . . . . . . . . . . . . . z
z.z. lnteiakce s objekty . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ze
z.z.1. Dotazovani na vlastnosti objekt . . . . . . . . . . . . . . . . . . . ze
z.z.z. Metody . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . z
z.z.I. Opeiace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . I1
Binaini aiitmetick opeiatoiy . . . . . . . . . . . . . . . . . . . . . I1
Dleni a zbytek po dleni . . . . . . . . . . . . . . . . . . . . . . . Iz
Unaini aiitmetick opeiatoiy . . . . . . . . . . . . . . . . . . . . . II
Opeiatoiy nad neiselnmi objekty a petovani opeiatoi . . . . I1
lndexace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . I
z.I. Tidni metody a vlastnosti . . . . . . . . . . . . . . . . . . . . . . . . . . . Ie
z.1. Piomnn . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Is
z.1.1. Denice a inicializace piomnnch . . . . . . . . . . . . . . . . . . 1c
Denice a inicializace piomnnch pio objekty hodnotovch tid . 1c
Denice a inicializace piomnnch pio objekty iefeiennich tid . 1z
z.1.z. Odkaz null . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
I

z.1.I. Piazeni . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1e
Vmna obsahu dvou piomnnch . . . . . . . . . . . . . . . . . . 1s
Petypovani pi piazeni . . . . . . . . . . . . . . . . . . . . . . . 1v
3. Konzolov programy 53
I.1. Zakladni stiuktuia piogiamu . . . . . . . . . . . . . . . . . . . . . . . . . . I
I.1.1. loimatovani piogiamu . . . . . . . . . . . . . . . . . . . . . . . . .
I.1.z. Jmenn piostoiy . . . . . . . . . . . . . . . . . . . . . . . . . . . . e
I.z. Pivni piogiam . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . v
I.z.1. Vstup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . v
I.z.z. Zpiacovani . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ec
Opeiatoi iovnosti a neiovnosti . . . . . . . . . . . . . . . . . . . . e1
I.z.I. Vstup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . e1
Konstiukce if . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . e1
I.I. Diuh piogiam Poitani slov . . . . . . . . . . . . . . . . . . . . . . . . . e
I.I.1. Hlavni algoiitmus . . . . . . . . . . . . . . . . . . . . . . . . . . . . es
Cyklus foieach . . . . . . . . . . . . . . . . . . . . . . . . . . . . . c
Logick opeiatoiy . . . . . . . . . . . . . . . . . . . . . . . . . . . z
Roziujici metody . . . . . . . . . . . . . . . . . . . . . . . . . . .
Pikaz ietuin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
I.1. Teti piogiam poet piacovnich dni v ioce . . . . . . . . . . . . . . . . . . v
I.1.1. Vstup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . v
Relani opeiatoiy . . . . . . . . . . . . . . . . . . . . . . . . . . . . sc
Vjimen situace . . . . . . . . . . . . . . . . . . . . . . . . . . . . sz
I.1.z. Zpiacovani dat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . sI
Cyklus while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . s
I.1.I. Roziujici metoda JePiacovni() . . . . . . . . . . . . . . . . . . . . se
I.1.1. Vsledn piogiam . . . . . . . . . . . . . . . . . . . . . . . . . . . sv
I.1.. Piofesionalni iozieni . . . . . . . . . . . . . . . . . . . . . . . . . v1
4. Seznam zkladn kolekce 97
Asymptoticka sloitost . . . . . . . . . . . . . . . . . . . . . . . . . v
1.1. Seznam ListT~ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1c1
1.1.1. Vytvoeni novho seznamu . . . . . . . . . . . . . . . . . . . . . . 1cI
1.1.z. Metody a opeiace nad seznamy . . . . . . . . . . . . . . . . . . . . 1ce
Poet pivk (vlastnost) . . . . . . . . . . . . . . . . . . . . . . . . . 1c
lndexace (opeiace) . . . . . . . . . . . . . . . . . . . . . . . . . . . 1c
Pidani/vloeni pivku . . . . . . . . . . . . . . . . . . . . . . . . . 1c
Pidani/vloeni vice pivk . . . . . . . . . . . . . . . . . . . . . . . 1cs
Vyjimani pivk . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1cv
Hledani poloek . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11c
Obsah
1.1.I. Piochazeni seznam . . . . . . . . . . . . . . . . . . . . . . . . . . 11z
Cyklus foi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.1.1. Selektivni vmaz . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11v
1.1.. Piazeni a duplikace . . . . . . . . . . . . . . . . . . . . . . . . . . 1z1
1.z. Piklady ioziujicich metod seznam . . . . . . . . . . . . . . . . . . . . . 1Ic
1.z.1. Nahodn peimutovani pivk v seznamu . . . . . . . . . . . . . . . 1I1
1.z.z. Test setidni seznamu . . . . . . . . . . . . . . . . . . . . . . . . . 1Ie
Vty . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1Iv
5. Uivatelsk tdy 149
.1. Denice nov tidy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
Datov leny . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
Konstiuktoi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1I
Denice metody . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
Pedenovani metody ToStiing . . . . . . . . . . . . . . . . . . . . 1e1
.z. Nova implementace (znovu a lpe) . . . . . . . . . . . . . . . . . . . . . . . 1e
Symbolick konstanty . . . . . . . . . . . . . . . . . . . . . . . . . 1I
Denice vlastnosti . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
Sniovani zavislosti a zapouzdeni (nejen) v OOP . . . . . . . . . . 1sc
.I. Vyiovnavaci pam (cache) - kolekce, kteia zapomina . . . . . . . . . . . . 1s
.I.1. Navih iozhiani . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1se
.I.z. Datova iepiesentace . . . . . . . . . . . . . . . . . . . . . . . . . . 1vc
Automatick vlastnosti . . . . . . . . . . . . . . . . . . . . . . . . . 1vI
.I.I. lmplementace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1v
Geneiatoiy nahodnch isel . . . . . . . . . . . . . . . . . . . . . . 1ve
Zkiacen vyhodnocovani logickch opeiatoi . . . . . . . . . . . . zc1
Podminkov opeiatoi . . . . . . . . . . . . . . . . . . . . . . . . . zcI
.I.1. Testovaci kod . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . zc
6. Slovnk 209
e.1. Zakladni opeiace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . z11
e.1.1. Denice a naplnni . . . . . . . . . . . . . . . . . . . . . . . . . . . z11
e.1.z. Vyhledavani hodnoty podle klie . . . . . . . . . . . . . . . . . . . z1I
e.z. Vyuiti slovniku . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . z1e
e.z.1. Databaze v pamti . . . . . . . . . . . . . . . . . . . . . . . . . . . z1
e.z.z. idk seznamy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . zzc
N-tice (tuple) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . zzz
e.z.I. Vyiovnavaci pam . . . . . . . . . . . . . . . . . . . . . . . . . . . zz1
e.z.1. ita vskyt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . zz1
e.I. lnteini iepiesentace slovniku . . . . . . . . . . . . . . . . . . . . . . . . . . zze
e
7. Souborov orientovan vstup a vstup 233
.1. Bytov oiientovan vstup a vstup (binaini souboiy) . . . . . . . . . . . . zIe
.1.1. Bytov oiientovan vstup . . . . . . . . . . . . . . . . . . . . . . zIe
tida byte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . z1c
konstiukce using . . . . . . . . . . . . . . . . . . . . . . . . . . . z1z
.1.z. Bytov oiientovan vstup . . . . . . . . . . . . . . . . . . . . . . . z11
Dokumentani poznamky . . . . . . . . . . . . . . . . . . . . . . . z1s
.z. Textov oiientovan vstup a vstup . . . . . . . . . . . . . . . . . . . . . . z1v
.z.1. Textov oiientovan vstup . . . . . . . . . . . . . . . . . . . . . . zc
.z.z. Textov oiientovan vstup . . . . . . . . . . . . . . . . . . . . . . . zI
StiingBuildei postupn vytvaeni etzc . . . . . . . . . . . . . ze1
.z.I. adkov oiientovan vstup a vstup . . . . . . . . . . . . . . . . . zee
A. Pehled syntaxe (EBNF) 271
A.1. Znaky a poznamky . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . zI
A.z. ldentikatoiy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . z1
A.I. Liteialy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . z1
A.1. Viaz . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . z
A.. Pikazy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . z
A.e. Denice tidy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . zs
A.. Piogiam . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . zsc
B. Pedvn parametr 281
B.1. Vstupni paiametiy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . zs1
B.z. Obecn pedavani paiameti iefeienci . . . . . . . . . . . . . . . . . . . . zsI
C. Rozshlej programy 287
C.1. Vyiovnavaci pam (geneiicka veize nad slovnikem) . . . . . . . . . . . . . zs
C.z. Piogiam pio zjitni velikosti kolizni skupiny v hashovaci tabulce . . . . . zsv
1. Zklady objektov orientovanho
programovn
Objektov oiientovan piogiamovani je metodikou, kteia usnaduje implemen-
taci poitaovch piogiam, ktei modeluji iealn systmy iesp. poskytuji sloita
vizualni i multimedialni iozhiani.
Objektov oiientovan piogiamovani nepopisuje a neei vechny aspekty pio-
giamovani a v nkteich pipadech nelze tento pistup vbec aplikovat nebo jen s
obtiemi. Avak ji v dob, kdy se tato metodika popiv objevila (v jazyce Simula
v ioce 1ves), se ukazalo, e viazn usnaduje implementaci a pedevim spiavu
sloitjich piogiam.
Navic se piokazalo, e OOP lze kombinovat s nkteimi ji existujicimi pistupy
iesp. jej lze integiovat do ji existujicich piogiamovacich jazyk. Nap. ji Si-
mula je de facto objektov oiientovanm iozienim staiiho jazyka Algol[1vec]
s jeho pioceduialn-stiuktuiovanm pistupem. Objektov piogiamovani se tak
postupn stalo de facto standaidem pio modelovani a implementaci sloitjich
aplikaci. Podpoia OOP byla zahinuta do vtiny klasickch ( ped-OOP) piogia-
movacich jazyk vetn napiklad Fortranu, Cobolu, Pascalu a jazyka C. Navic v
pibhu asu vzniklo velk mnostvi jazyk, ktei ji od svch poatk podpoiuji
objektov piogiamovani (Smalltalk, Python, Java, Rubby).
Objektov oiientovan piogiamovani se vak neomezuje pouze na vlastni imple-
mentaci piogiam. Objektov oiientovan pistup se pouiva i ve fazi analzy a
navihu sofwaiovch systm a podstatnou ioli hiaje i pi jejich spiav. V za-
sad lze (z pohledu piogiamatoia) iozliit tyto iovn objektov oiientovanho
pistupu (od nejabstiaktnji k nejkonkitnji)
objektov oiientovan pohled na svt
obecn objektov oiientovan model
objektov oiientovan jazyk

8
1.1. rovn objektov orientovanho pstupu
1.1.1. Objektov orientovan pohled na okoln svt
Hlavni (i kdy nefoimalni) vchodisko objektov oiientovanho piogiamovani.
Z hlediska OOP je svt tvoen (dynamickmi) objekty, ktei spolu inteiaguji, pi-
em mohou mnit svj stav, vznikat a zanikat. Pouze piostednictviminteiakci se
piojevuje chovani objekt a manifestuji se jejich statick i dynamick vlastnosti.
Tento pohled na svt neni nikteiak ievoluni, nebo jej lid v zasad uivaji od
nepamti. Lidi vdy iozkladaji svt na jednotliv objekty, ktei dokai zkoumat
jen podle jejich inteiakci s okolim, bez toho, e by znali vnitni piiny tohoto
chovani iesp. vbec vidli do vnitku jednotlivch objekt.
Napiklad vtina lidi dokae zcela jednoznan odliit jednotliv dopiavni pio-
stedky (auta, vlaky), popsat jejich chovani a odhalit nktei jejich skiyt vlast-
nosti, bez toho e by byli je iozebiali do posledniho ioubku iesp. dokonce na
jednotliv elementaini astice, bez znalosti stiojniho inenistvi a kvantov me-
chaniky.
And he that breaks a thing to nd out what it is has le the path of wisdom.
Gandalf, Pan pisten
Pokud se vak chcete stat dobimi objektov oiientovanmi piogiamatoiy i do-
konce skvlmi analytiky, musite tuto velidskou schopnost iozvinout do vyi
dimenze, vidt objekty v novch souvislostech a pedevim vidt (bn) nevid-
n. Nesmite se nechat svazat konvennimi pohledy na pioblematiku i jazykem a
jeho pevn denovanmi pojmy.
1.1.2. Obecn objektov orientovan model
Tento model popisuje (sofwaiov) piostedky (iesp. jejich koncepce), s jejich
pomoci lze v pamti poitae modelovat objekty iealnho svta. Bohuel adn
skuten standaidni i dokonce univeizalni model neexistuje. Pesto vak na-
tsti existuji piostedky i mechanismy, ktei jsou podpoiovany vtinou OOP
jazyk iesp. je lze ielativn snadno nahiadit i opsat.
Mezi nejbnji pivky OOP modelu pati tidy, metody, dynamick polymoi-
smus, konstiuktoiy (inicializatoiy), objektov kolekce (kontejneiy), apod. Mezi
Zaklady objektov oiientovanho piogiamovani ,
mn ast pivky OOP pati iozhiani (inteiface), vlastnosti (piopeity) nebo tidni
(statick) metody.
Tyto spolen iysy lze vyuit pi navihu aplikace, jen tak nemusi bt vazan na
konkitni piogiamovaci jazyk nap. pomoci modelovaciho jazyka UML. Navic to
usnaduje ivot i piogiamatoim, nebo umouje jejich vzajemnou komunikaci
(napi OOP jazyky a platfoimami) a zjednoduuje ueni se novm OOP jazykm
(tj. pokud ji znate jin OOP jazyk je snadnji se nauit jin). Navic ielativn
velka skupina jazyk (Java, C#, PHP) pouiva i podobnou syntaxi pio zakladni
pivky modelu (napiklad pio volani metod).
1.1.3. OOP programovac jazyk
Piogiamatoi se s objektov oiientovanmpistupemsetkavaji pedevimna iov-
ni konkitnich piogiamovacich jazyk.
Objektov lze v zasad piogiamovat v libovolnm univeizalnim jazyce, napiklad
v jazyce C. Je to vak velmi naion a piogiamy jsou velmi nepehledn (a zcela
nevhodn pio zaateniky). Ne zcela vhodn jsou i jazyky, kde je OOP pouh
pilepek k ji existujicimu jazyku, jako je napiklad C++, PHP nebo Perl (i kdy i
v tchto jazycich lze vytvaet skuten OOP piogiamy).
Nejvhodnji skupinou jsou tak jazyky, ktei byly navihovany jako objektov, ale
sdileji iysy se zakladnimi s oblibenmi univeizalnimi jazyky (tj. pedevim s jazy-
kem C). Mezi tyto jazyky pati napiklad Java, C# nebo Python. U tchto jazyk je
implementace pvodniho navihu (v obecnm modelu) ielativn pimoaia a pln
podpoiovana jazykovmi konstiukcemi.
Na opanm polu jsou jazyky, ktei jsou ielativn vzdalen hlavnimu pioudu, je-
jich syntaxe je vak vytvoena pimo pio (nkdy ponkud extiavagantni) OOP
model. Klasickm pikladem je Smalltalk, ale existuji i novji ist objektov oii-
entovan jazyky (nap. Scala). Navic v tchto jazycich je tm nemon napsat
kod, ktei by nebyl objektov (nicmn mete stale pouivat nevhodn i do-
konce zcela patn objektov navih).
Nktei konstiukce klasickch OOP jazyk se vyskytuji i u jazyk, ktei nejsou
oznaovany jako objektov (nap. Go pouze s podpoiou iozhiani) iesp. jsou kla-
sikovany jako specialni pipady OOP jazyk (Javascript a Lua, ktei neobsahuji
pimou iepiesentaci OOP tid).
1o
Podpoia objektov oiientovanho pistupu u jednotlivch jazyk je schematicky
vyjadena na obiazku 1.1. Obiazek bohuel zobiazuje jen nktei jazyky, piem
vzajemna pozice jazyk neme bt vdy stanovena zcela objektivn. Vlevo jsou
jazyky podpoiujici jak tidy tak nktei z typ objektovho polymoismu (tj.
jazyky nabizejici odpoiu pevaujiciho OOP modelu).
C
Fortran (03)
Ada (98)
PHP 5
C++
Objective C
C#
Python
Java
ca!a
"a!!ta!#
$o
%&by
'&a
Javacri(t
Per!
#!a)ic#* OOP "ode! (Java) e+otic#* OOP "ode!
neobje#tov*
ja,y#
-i)t. obje#tov*
ja,y#
Obiazek 1.1. Objektov oiientovan piogiamovaci jazyky
Kiom pim podpoiy OOP v syntaxi jazyka je nezbytn, aby byli k dispozici i
objektov knihovny, ktei se snadno ioziuji a pokivaji, alespo zakladni po-
adavky soudobch aplikaci (GUl, inteinetov sluby, databaze). Navic by tyto
knihovny mly pln vyuivat potencial objektovho modelu pislunho jazyka.
Pokud napiklad poiovname standaidni knihovny jazyka C-- Java, zjistime, e ja-
vovsk knihovny jsou nejen mnohem iozsahleji, ale tak lpe vyuivaji potencial
OOP.
Na iovni piogiamovaciho jazyka je nutno zohlednit i efektivitu vslednho stio-
Zaklady objektov oiientovanho piogiamovani 11
jovho kodu (kad i sebeabstiaktnji piogiam je nakonec peloen do jednodu-
chch stiojovch instiukci piocesoiu). Me toti nastat situace, kdy i velmi do-
konal objektov model nelze napiogiamovat tak, aby aplikace mla iozumnou
odezvu.
U piogiamatoia v OOP jazycich se se tak pedpoklada, e jejich znalosti nejsou
omezeny pouze na objektov konstiukce, ale maji i zaklady algoiitmizace ( vy-
tvaeni a pouivani algoiitm), datov iepiesentace objekt (kliov je napiklad
uvolovani objekt z pamti) a efektivniho vyuivani haidwaiovch a systmo-
vch piostedk (tj. piostedk spiavovanch opeianim systmem). Pikladem
je vyuiti asynchionniho pistupu (napiklad pi pistupu k webovm seiveim)
i dokonce paialelismus (vyuivani vice piocesoi i jadei).
1.2. Zkladn pojmy OOP (na rovni objektovho
pohledu na svt)
1.2.1. Objekt
Zakladnim pojmem objektov oiientovanho piogiamovani je pekvapiv ob-
jekt. Na iovni objektov oiientovanho pohledu na svt me bt objektem li-
bovolna vc, veliina, oiganismus i lovk (iesp. pesnji jeho nefoimalni model,
ktei mame ve svch hlavach). Zakladnim atiibutem kadho objektu je jeho jed-
noznana identikace (vymezeni)
Pravidlo 1: Kad objekt je jednoznan identikovateln.
l kdy se toto piavidlo jevi jako tiivialni, opak je piavdou.
Nejdive je nutno ujasnit, co vlastn znamena identikace. Pio lovka je identi-
kace spojena s pojmenovanim, tj. kad objekt me bt opaten jmnem
pes Puntk, koka Hebkosrstka, etn Jana Novkov, kniha se signaturou N123586,
strom N56-1256 (piklady objekt identikovatelnch jmnem)
Dale poadujeme jedinenost identikatoiu (jinak bychom nebyli schopni odliit
jednotliv objekty). Jedinenost nemusi bt globalni (celovesmiina), nebo posta-
uje odliovat jen objekty, ktei se vyskytuji v popisovanm systmu. l tak me
bt identikace pomoci etzc pioblematicka (nap. ve im me bt nkolik
etnich se stejnm jmnem). Pio zjednodueni lze vak vdy pedpokladat, e
1:
identikatoiy jsou piiozenmi isly. ldentikace je pak vzajemn jednoznan
zobiazeni mezi objekty a libovolnou nepiazdnou podmnoinou piiozench isel.
To vak stale neni ten hlavni pioblm s identikatoiy.
Pedpokladejme napiklad, e chceme identikovat knihy. Budeme je identiko-
vat podle titulu (i pesnji lSBN) nebo budeme knihy identikovat podle jednot-
livch vtisk (tj. fyzickch objekt, viz piklad ve)` Podobn je mono identi-
kovat jednotliv domaci zviectvo nebo jen diuhy, pokud s nimi piacujeme jako
s abstiaktnimi objekty.
Na otazku neni jednoznana odpov, nebo identikace (a tim i vymezeni objek-
t) je dano zamenim vai aplikace (tj. pio koho a za jakm elem ji vytvai-
te).Pokud piete piogiam pio vydavatele nebo bibliogiai, pak je objektem vyda-
ni knihy a identikatoiem nap. lSBN. Naopak pio knihovny je objektem vtisk a
identikatoiem signatuia.
U zviatek je situace podobna. Pokud vytvaite piogiam pio chovatele nebo zv-
iolkae, pak je nutn identikovat jednotliva zviatka. Naopak pio vvojov bi-
ology je vhodnji piacovat s celmi diuhy (nap. jak je vvojov vztah mezi
psem ( pes jako diuh) a kokou). Tiochu matouci me bt situace v pipa-
d aplikace pio dopiavce, jen pepiavuje (mimo) jin i psy a vyaduje zaplaceni
jizdnho. Dopiavce nemusi samozejm identikovat psy jmnem, ale na diuhou
stianu nepepiavuje psy jako diuh, ale jednotliv psi individuality. Ve skutenos-
ti je zde objektem konkitni pepiavovan pes, ktei je identikovan napiklad
islem jizdenky. Pokud je stejn pes pepiavovan pozdji (na jinou jizdenku) je to
ji jin objekt (s jinm identikatoiem).
Dali zajimavou skupinu objekt tvoi napiklad penni astky. Penni astky
lze jako fyzick objekty inteipietovat jen pi omezeni na bankovky (nebo maji
sv identikatoiy siiova isla) a to jen ve velmi omezenm iozsahu aplikaci
(sbiatel, kiiminalist). Ve valn vtin pipad je penni astka iepiesento-
vana jen islem bez ohledu na fyzickou iepiesentaci (jinak eeno nap. vechny
hodnoty 1ccI K jsou neodliiteln a iepiesentuji tak jedin objekt). Podobn jsou
neodliiteln i hodnoty fyzikalnich veliin iesp. isel (i kdy otazkou je zda vbec
existuji dva stejn ale odliiteln iseln objekty nap. dv dvojky)
Nyni se podivame na dali kliov iys objekt piiozenho svta. Mylen mo-
del, kteim objekt iepiesentujeme v nai mysli je vdy viaznm zjednoduenim.
Toto zjednodueni (iozsah a zameni) neni absolutni, ale je opt dano cilovou
aplikaci modelu.
Zaklady objektov oiientovanho piogiamovani 1
Pravidlo 2: Objekt je zjednoduenm modelem reality
Klasickm pikladem jsou (mechanick iuikov) hodinky. Vtin uivatel ho-
dinek postauje model, ktei si vima jen polohy iuiek, kteiou lze (nejedno-
znan) mapovat na aktualni as. Model me bt samozejm o tiochu sloitji
(nap. zohledujici zpodni/pedbihani, monost nastaveni novho asu), ale z-
stava stale na povichu hodinek.
Dovnit hodinek se musime podivat, jen v pipad kdy jste hodinai. Ale i potom
je model zjednoduen. Kada jednotliva souast hodinek (koleka, piuiny, se-
tivaniky) je samozejm opt sloena z atom. Kvantov model hodinek je vak
ji v piaxi neiealizovateln (tj. je zbyten pokiaovat dale v iozkladu).
Podobn u zviatek vystaime s velmi jednoduchm modelem u dopiavni spole-
nosti (vejde/nevejde se do schiany), ponkud jinm (a miin sloitjim) u cho-
vatel (nap. daje o pvodu, poadovan kimeni) a zcela jinm (a nejsloitjim)
u biolog.
V objektov oiientovanm pohledu je pioto vdy kliov vnji chovani objektu
tzv. rozhran, zatimco vnitni stiuktuia a stavy (tzv. implementace objektu)
mohou (iesp. mly by bt) bt ukiyty.
Cel mechanismus, jen je oznaovan jako zapouzden (tj. ukiyti implementa-
nich detail) je opt v piincipu zcela tiivialni (lid si vci zjednoduuji neustale,
jinak by se zblaznili). Bohuel u iealnch model neni snadn poznat, kde je hia-
nice mezi vnjimiozhianima skiytou implementaci. Pokud objekt zjednoduime
pili, pak meme omezit jeho pouitelnost pio danou aplikaci, pokud ukaeme
pili mnoho z vnitku tak zvime zavislost okoli na tchto detailech. Pokud na-
piklad zveejnime polohy koleek v hodinovm stiojku (kalibiu), pak se nktei
zvidav pozoiovatel me nauit odeitat polohu koleek (ignoiuje bni iozhia-
ni), co se jevi jako iozumn a do okamiku kdy se stiojek zmni. Nestandaidni
uivatel, jen se stal zavislm na inteini iepiesentaci, pak me odeitat patn
as.
Pedchozi piklad je sice ponkud uml, ale lze nalzt i piaktitji piklady.
Pedpokladejme knihovnu, jeji knini sklad neni bn dostupn tenam. Po-
kud si chce tena objednat knihu, pak si napie jeji signatuiu a jde za knihovni-
kem. Ten knihu vyhleda ve skladu a peda ji tenai. Pedani listku se signatuiou
knihovnikovi je iozhiani objektu knihovny, vyhledani je implementaci. ktei ui-
vatel bn nezna (nikdy toti nebyl ve skladu).
Lin knihovnik se vak iozhodne, e je zbyten obtovat se chozenim do skladu
1
a tak vysvtli tenam, jak si knihu ve skladu vyhledat a necha je, aby si knihu
nali sami. Pioblm lenocha se zda vyeen a knihovnik ma as na svou (peima-
nentni) kaviku.
eeni vak ma pinai hned nkolik pioblm. Pivni je obdobou pioblmu ote-
vench hodinek. V okamiku, kdy se zmni mechanismus vyhledavani knih ve
skladu (nap. vmnou polic), musi se vichni tenai nauit nov systm (co je
asov naion a navic v mezidobi dochazi k selhanim). Diuh pioblm spoiva
v tom, e tenai mohou viacet knihy na patna mista a uvst tak sklad do nekon-
zistentniho stavu (mohou samozejm knihy i kiast, co by tena nikdy neudlal,
iesp. pinaet do skladu vlastni knihy, co je jet mn piavdpodobn). Vsledek
je zejm, knihovna bizy pestane fungovat.
Pi stanoveni iozhiani (tj. iovn detail) je nutno vychazet z chovani objekt,
jak se jevi (iesp. jak se bude v budoucnu jevit) jeho uivatelm. Uivatel doka-
i objekt chaiakteiizovat jen z jeho chovani (viz ve). Analytik i piogiamatoi
se musi vdy vit do iole budoucich uivatel, co jsou jini piogiamatoi ve v-
vojaskm tmu nebo piogiamatoi na celm svt, pokud je vytvaena veejna
knihovna. V adnmpipad neni v hodn pi navihu vychazet z inteiniho popisu
i algoiitmu (i kdy je sebelepi a napiosto genialni).
Posledni chaiakteiistika vychazi z omezen ivotnosti kadho objektu.
Pravidlo 3: Objekt m omezenou dobu ivota (tj. objekt vznik a po urit dob
zanik bhem n se stle mn
l toto piavidlo popisuje zcela zakladni chaiakteiistiku svta, kteiou chapeme zce-
la intuitivn od dtskch let. Samozejm existuji i objekty, jejich ivotnost je
neomezena a jsou zcela nemnn nap. isla nebo fyzikalni veliiny (zde ovem
zalei ponkud na inteipietaci), ale jen malo piogiam vytvai nap. matematick
tabulky.
U veho ostatniho je zejm, e ve vznika a zanika a pedevim se stale mni.

Vechny jsoucna (objekty) se pohybuji nic nezstava stale stejn

Vznik a zanik objekt nelze piiozen omezit pouze na jejich vznik a destiukci
(nap. v biologick slova smyslu). Objekt zanika i zmnou svho chaiakteiu nebo
oputnim systmu a podobnm zpsobem me i vznikat.
Zaklady objektov oiientovanho piogiamovani 1
Napiklad pokud student ukoni studium, zanika jako objekt student v iamci in-
foimaniho systmu koly (fyzicky natsti nai studenti vesms ukoneni studia
ve zdiavi peivaji). Pokud je absolvent bezpiostedn zamstnan na stejn kole,
vznika nov objekt zamstnanec (vazan na stejn fyzick objekt).
V nkteich pipadech nov objekt nezanika, vytvai se vak jeho nemodikova-
na i modikovana kopie. Napiklad pokud modelujeme vznik sloitjich objekt,
je mnohdy uitenji pedstava, e objekt nejdive vznikne jako kopie jinho ob-
jektu a nasledn je modikovan. Napiklad nov poita ( tj. jeho model, nap.
pio ely siov komunikace) me vzniknout vytvoenim kopie (klonu), ji exis-
tujiciho a naslednou modikaci konguiace (nap. zmnou etheinetov adiesy).
Pioblematika vzniku a zaniku objekt se stava jet sloitji na iovni obecnho
objektovho modelu a nasledn na iovni piogiamovaciho jazyka.
My se vak nyni podivame na diuh kliov pojem objektovch jazyk na tdu.
1.2.2. Tda
l ty nejjednodui systmy mohou potencialn obsahovat tisice i desetisice iz-
nch objekt. Napiklad pokud modelujeme dopiavni systm pak se v nm na-
chazi stovky spojeni, tisice automobil apod. Natsti lid maji schopnost najit
objekty se stejnm nebo podobnm chovanim a ty v jazyce oznait spolenm
pojmem.
Objektov piogiamovani postupuje podobn jednotliv modelovan objekty se
seskupuji do mnoin, ktei lze oznait jako tdy (objekt).
Tida obsahuje vechny objekty, jejich chovani je obdobn tj. ieaguji stejn (ne-
bo velmi podobn) pi inteiakci s okolim. Rozhodujici je zde dynamick chovani
objekt (pesnji jeho piojevy) nikoliv statick vlastnosti objekt.
Pravidlo 4 Tda je urena (dynamim) ovnm objekt nikoliv statiou vlast-
nost
Podivejme se napiklad na automobily. l kdy lze foimaln vytvoit tidu eive-
nch aut, je to ve vtin pipad zbyten, nebo kiom baivy se eivena auta
nelii od ostatnich aut. Neplatite za n vyi pojitni, neplati pio n specialni
dopiavni pedpisy (Zakaz vjezdu eivench aut) a nevyiabi se ve specialnich
tovainach. Naopak me zahinovat auta, kteia se svmv chovani dosti lii (nap.
eiven tiabant veisus eivena nakladni Tatia). Podobn neni iozumn vytvaet
tidy podle viobc aut (vjimkou jsou viobci vyiabjici jeden specializovan
1e
typ auta). Pokud vak vytvaime aplikaci pio piodejce aut, musime nkdy zohled-
nit izn piodejni podminky (ani to vak ve vtin pipad nevede k navihu
nov tidy).
Ponkud jina je situace u vlastnosti, ktei iozdluji objekty do skupin s iozdilnm
chovanim. Hmotnost auta napiklad viazn ovlivuje mechanismus placeni sil-
ninich poplatk. Automobily do I, tun plati poplatky pomoci dalninich zna-
mek. Auta s vyi hmotnosti plati mto (se zcela odlinm mechanismem platby).
Pokud tedy vytvaime aplikaci pio dopiavce nebo stat, je iozdleni do tid mon
(nikoliv vak nutn).
Tidy se, jak bylo ve uvedeno, velmi blii pojmm, je jsou uivany v lidskch
jazycich. lxistuje vak jeden zasadni iozdil
Pravidlo 5: Tdy nejsou absolutn konstrukce, mus se denovat pro kadou probl-
movou domnu a aplikaci zvl
Zatimco v jazyce jsou pojmy tm nemnn (jinak by nefungovala komunikace)
a tvoiba novch pojm je ielativn omezena, jsou tidy nov denovany pio ka-
dou aplikaci (v zasad je vytvoen nov svt s vlastnimi jazykem a pojmy, i kdy
samozejm velmi omezen).
Bohuel vichni piogiamatoi a analytici jsou lid a tak se nejdive nauili svmu
mateskmu jazyku a a pot se dozvdli o objektov oiientovanm piogiamo-
vani. Vichni tudi mysli ve xnim systmu svho jazyka, ani by si to vdom
pipoutli. Navic jsou nuceni tidy pojmenovavat slovy a teiminy piiozenho
jazyka (etiny nebo anglitiny), piem vtinou voli jednoslovn a stiun tei-
miny, ktei maji pevnou a tm nemnnou smantiku.
Pikladem jsou tidy se jmny Vlak, editel, Pota, Prodejna, Pes, apod. Tyto na-
zvy mohou samozejm oznaovat tidy, je jsou pio danou aplikaci optimalni.
asto vak jen ukazuji malou fantazii i odvahu autoia, iesp. pili zjednoduen
nebo neadekvatni objektov navih. Specializovan aplikace spie vyuivaji jmna
typu KolejovHromadnDopravnProstedek, InternZamstnanecSdcPravomoc,
SovloitSCentralizovanouSprvou, KoncovDistributorSProdejnPloou nebo
tak DomcZveSeSpecilnmPrvnmPostavenm. Tato jmna jsou bn nadmno-
inou pvodnich etablovanch pojm nebo naopak podmnoinou (specialnimpi-
padem). V nkteich pipadech vak mohou jit i napi bnmi pojmy.
Nejdive uveme uml, ale ilustiativni piklad. Pedstavte si vesnick dvi s di-
bei a diobnm zviectvem. Rozdleni jeho objekt do tid podle ivoinch diu-
h zvladne kad a jevi se jako nejpiiozenji (obiazek 1.z na nasledujici stian
Zaklady objektov oiientovanho piogiamovani 1,
koky
slepice
psi
klasick rozdlen do td
(jazykov termny)
aportujc zvtka
flegmatici
zvdavci
ad-hoc rozdlen do td
(podle chovn)
Obiazek 1.z. Objekty a tidy
18
nahoe). Mete vak zvolit i jin netiadini dleni. Pokud napiklad hodite kla-
cik, tak se zviata iozdli na apoitujici (klacik pinesou), zvdava (iozbhnou se
za klacikem) a apaticka (nijak neieaguji), viz piklad na obiazku 1.z dole. l kdy
toto iozdleni asten souvisi s iozdlenim na diuhy, mohou se objevit i pekva-
piv iozdily nap. apatick a zvdav koky (apoitujici koky jsou samozejm
vyloueny), i apoitujici slepice.
Pi navihu aplikace pio ciash-testy je vhodn denovat tidu piunch objek-
t s hmotnosti vice ne cckg (co jsou nap. automobily, sloni a vti klady).
Aplikace poskytovatele hiomadn dopiavy me denovat dopiavni piostedek
s dlouhm dojezdem (doletem) i piostedek s piomnnm potem pepiavova-
nch osob (co nemusi bt jen vlak, ale teba i skupina taxik).
Otazka k zamyleni Je tida objektem`
2. Zkladn objektov model C#
Pio vvoj sofwaiu ( poitaovch piogiam a aplikaci) je typick viazn kva-
litativni posun piojevujici se vznikem stale sloitjich datovch stiuktui a pio-
stedk komunikace (v nkolika vistvach abstiakci). Tento vvoj je podpoen i
stale sostikovanjimi a komplexnjimi piogiamovacimi jazyky.
Na diuh stian vvoj v oblasti haidwaiu (tj. pedevim) piocesoi je spie kvan-
titativni. Zatimco se piocesoiy ziychlily v adu desitek milion, zstava stiojov
kod v zasad nezmnn. lnstiukce tohoto kodu piacuji pouze s nkolika jedno-
duchmi iselnmi typy iozliujic stale celoiselnou iepiesentaci a iepiesentaci s
adovou aikou.
Z tohoto dvodu existuje i v modeinich objektov oiientovanch jazycich jen
nkolik tid, je jsou pimo podpoiovany piocesoiem (a vechny jsou v zasad
iseln nebo jednodue na isla zobiaziteln). Objekty ostatnich tid vznikaji skla-
danim z elementainich iselnch objekt (piem v souladu s piincipem zapouz-
deni tuto skutenost skivaji). Na obiazku z.1 je znazoinn piincip skladani gia-
ckho objekt z objekt elementainich iselnch tid. Zde jsou to objekty tidy
byte a double.
model
vagonu
model
lokomotivy
model
vlaku
double:5
double:4
barva: FF0000
2D bod
byte: FF
Bezierova
kivka
model
vagonu
seznam
Brush
Canvas
Obiazek z.1. Skladani z elementainich objekt
Jedinou vjimkou jsou objekty, ktei zapouzduji pistup k datm, je jsou spia-
1v
:o
vovany opeianim systmem a jsou iealizovany mimo opeiani pam. Pikla-
dem jsou napiklad objekty umoujici siovou komunikaci (tzv. sokety), objekty
GUl iozhiani (okna, idici pivky data jsou uloena v pamti giack kaity) ne-
bo souboiy (data jsou typicky na discich). Na naem ilustiativnim schmatu jsou
systmovmi objekty instance tidy Canvas (kieslici plocha) a Brush (objekt ie-
piesentujici baievn vpln). Tyto objekty zpistupuji piostedky poskytovan
giackou kaitou.
2.1. Zkladn tdy
2.1.1. seln tdy
int
Zakladni iselnou tidou jazyka C= je tida System.Int32 (jmno tidy obsahuje
piex jmennho piostoiu, viz dale). Tato tida se pouiva tak asto, e pio ni
existuje zkiatka int. Slovo int je odvozeno z anglickho teiminu integer (number)
cel islo a pouiva se ve vtin modeinich piogiamovacich jazyk.
Do tto tidy pati pesn z
Iz
objekt, co jsou vechna cela isla isla od z
I1
a do z
I1
1 vetn (adov cca -z miliaidy a z miliaidy). Tento iozsah je dan
velikosti objektu v pamti (1 byty) a bitovou iepiesentaci (tzv. dvojkov doplnk).
Vytvoeni novho objektu tidy int je snadn, postauje uvst zapis isla v de-
sitkov, osmikov nebo estnactkov soustav pimo v piogiamu. Pim zapis
objektu v piogiamu se oznauje teiminem literl.
literl hodnota (v destkovm zpise)
1z 1z
-1z -1z
c11 1z
cxB 1z
Oktalov (osmikov) zapis se pouiva ielativn zidka (nejastji v piogiamech
piacujicich s haidwaiem nebo pistupovmi piavy v Unixu), zaatenici by se
vak mly vyhbat zapism celch isel zainajicim nulou (vjimkou je samo-
zejm samotna nula).
Zakladni objektov model C= :1
double
Diuhou zakladni iselnou tidou je tida s ponkud matoucim nazvem System.-
Double (zkiacen double). Toto jmno je zkiacenim teiminu double precision o-
ating point number (islo v pohybliv adov aice s dvojitou pesnosti). isla
v pohybliv adov aice umouji iepiesentovat iacionalni isla v uiitm (ko-
nenm) inteivalu a s konenou pesnosti (tj. potem platnch desetinnch mist).
isla v dvojit pesnosti (opioti pvodni, avak stale pouivan jednoduch) doka-
i iepiesentovat isla v iozsahu cca 1c
Ics
a 1c
Ics
s pesnosti cca 1 desetinnch
mist.
lnteini iepiesentace ma tvai z

, kde (tzv.mantisa) je islo v inteivalu (c. c.]


a je binaini exponent.
Pi pouivani isel s touto iepiesentaci je nutno zohlednit skutenost, e nelze ie-
piesentovat vechna iacionalni isla a dokonce ani vechna isla v libovoln vy-
mezenm inteivalu (s vjimkou nkteich jednopivkovch). Nefoimaln eeno,
vdy existuji diiy tj. isla, kteia nelze iepiesentovat pesn (misto toho se pou-
ije je apioximace tj. nejblii iepiesentovateln islo). Diiy maji z dvod uiti
binainiho exponentu zdanliv nahodn iozmistni v bn tj. desitkov iepiesen-
taci isla , tj. nemusi bt na pivni pohled zejm, ktei islo je iepiesentovano
pesn a ktei je jen apioximovano. Pesto je mono uvst nkolik zajimavch
posteh
vechna cela isla v iozsahu cca (z
z
. z
z
) tj. cca v adu biliaid (= 1c
1
)
jsou iepiesentovana pesn, vpoet s tmito isly je vak adov 1ckiat
pomaleji ne u isel tidy int.
v okoli nuly lze iepiesentovat i velmi mala nenulova isla (nap. 1c
Ics
).
Z dvod existence zaokiouhlovacich chyb iepiesentuji isla v inteivalu
piblin (1c
1z
. 1c
1z
) ve vtin pipad nulu (vjimkou jsou pipady fy-
zikalnich veliin, u nich lze pedpokladat takto mal ad).
islo c.1 je pouze apioximovano vetn jeho nkteich nasobk. Nesmi vas
pioto pekvapit, e plati vztah c.1 I c.I (ale na diuhou stianu c.1 z =
c.z!)
Nov objekty tidy double lze vytvaet pomoci liteial, ktei obsahuji desetinou
teku (anglosaska obdoba nai desetinn aiky) nebo exponent (ten se stejn jako
v jinch piogiamovacich jazycich pie za pismenem e nebo E).
Nkolik piakticky pouitelnch piklad 2.0 (izn od 2, co je objekt tidy int),
::
-5.63, 2.5e2 (= z. 1c
z
= zc), -0.83e-5 (= c.sI 1c

= s.I 1c
e
), 2e1 (zc, opt
odlin od celoiselnch 20)
A nkolik nepiaktickch liteial (vechny se vyhodnoti na stejn objekt tidy
double s hodnotou c) 0., .0, .0000, 0e5, 0e0, -0.0, -0e-0 (apod).
2.1.2. Znakov a etzcov tdy
Kiom isel dnes pati k zakladni tidam znakov a etzcov tidy. Objekty zna-
kovch typ jsou znaky tj. symbolick iepiesentace pismen, islic, diakiitickch
znamnek, apod. Kad znak je intein iepiesentovan islem (tzv. kodem znaku),
ktei je indexem do tabulky vech dostupnch znak (vlastni kod znaku vak ji
nehiaje pili velkou ioli a vyuiva se spie vjimen).
V minulosti existovalo velk mnostvi zabulek znak (znakovch sad), z nich
nejznamji je znakova sada ASCII (se 1zs znakovmi pozicemi). V souasnosti
je de facto i de iure standaidem znakova sada Unicode, kteia v nejnovji podob
(veize e.1) obsahuje 11c 1s1 znak. Tento standaid popisuje vlastnosti jednotli-
vch znak (diuh znaku nap. pasmeno, islice, matematick symbol, mezeiov
znak, apod.), vztahy mezi nimi (nap. identitu, zamnitelnost, apod.) a dopoiu-
uje i jejich giack znazoinni (to se vak me i dosti viazn liit v iznch
fontech).
Objekty tidy System.Char (zkiacen ar, z anglickho chaiactei znak) bohu-
el nepokivaji celou znakovou sadu Unicode, ale jen jeji ast oznaovanou jako
BMP (Basic Multilingual Plane). Ta obsahuje jen znaky, jejich kod lei v iozsahu
ceI (tj. mohou bt intein uloeny ve z bytech). Natsti tato sada obsahu-
je vechna abecedni pisma a bn symboly vetn matematickch a dokonce i
vechny bn pouivan insk znaky.
Poznmka:
Pistup k ostatnim Unicode znakm je mon pomoci tzv. nahiadnich
dvojznak (surrogate pair). Zpiacovani se vak viazn zkomplikuje
a vyuivano je jen v nkteich specializovanch aplikacich. Standaid
Unicode vak obsahuje i dali obtin paitie, na n mete naiazit pi
tvoib tzv. inteinacionalizovanch aplikaci, piem o dan pioble-
matice existuje jen malo liteiatuiy a kvalitnich zdioj.
Zakladni objektov model C= :
Objekt tidy ar vytvoime pomoci znakovho liteialu, co je v nejjednoduim
pipad samotn znak uzaven v apostiofech nap. a, (znak mezeiy), nebo
(omikion s ostim pizvukem a jemnm pidechem).
Tento zpsob je vak nepioblematick pouze u bnch latinkovch (anglickch)
pismen, islic a bnch symbol (vetn mezeiy). U ostatnich znak naiazime na
dva pioblmy (vtinou na oba zaiove)
inteipietace pimo vloench znak, je se nachazeji mimo ASCll znako-
vou sadu, zavisi na tom, v jakm kodovani uloime zdiojov souboi ( text
piogiamu). Pokud je stejn jako kodovani oekavan pekladaem, pak ma-
me asten vyhiano, nebo vstup piogiamu obsahuje oekavan znaky.
Bohuel to me bt jen dili vitzstvi, nebo poleme-li piogiam jinmu
piogiamatoiovi (v jin zemi i pio jin OS), me snadno dojit k neshod
(a vstupem jsou podivn, asto insk znaky). Pioto se bu snaime ja-
kchkoliv ne ASCll znak vyvaiovat, nebo pouit standaidni penositeln
kodovani UTl-s.
nktei znaky nelze v liteialu pimo pouit (odadkovani, apostiof, zptn
lomitko), iespektive jsou sice pipustn, ale nejdou jednodue vloit pomoci
klavesnice (u esk klavesnice nap. ve uveden omikion). Navic me bt
pioblm i s jejich zobiazenim (font v piogiamatoiskm editoiu jej nemusi
podpoiovat).
Oba pioblmy lze snadno obejit pomoci tzv. nikovch (escape) sekvenci, kte-
i zainaji znakem zptnho lomitka. Nejobecnji jsou nikov sekvence tvaiu
\uXXXX (kde X je libovolna estnactkova islice tj. c-v, a,b,c,d,e,f). Pomoci tto
sekvence lze vloit libovoln znak ze znakov sady Unicode BMP, pomoci jeho
kodu ( pozice v tabulce znakov sady, angl. codepoint). Kody jednotlivch zna-
k lze nalzt napiklad na stiankach konsoicia Unicode (nejpehlednji je foima
tabulek http://www.unicode.org/charts/).
Pio nktei netisknuteln (a obtin vloiteln) znaky z ASCll tabulky existuji
specialni nikov sekvence. V piaxi je nutn znat jenom escape sekvenci \n vy-
jadujici znak odadkovani a \t, co je znak tabulatoiu (tyto znaky se hodi nap.
pio foimatovani vstupu) a pedevim nikov sekvence pio apostiof \ a zptn
lomitko \\ (tyto znaky v liteialu jinak nelze zapsat).
Piklady znakovch liteial
'\u0158' (znak ),
'\u03A8' (znak ),
:
'\u000A' '\n' (znak odadkovani),
'\\' (zptn lomitko),
'\'' (apostiof)
chybn zapisy liteial
'\' (nedokonen liteial, chybi koncov apostiof),
'', 'ab' (v apostiofech musi bt piav jeden znak),
''' (apostiof uvnit musi bt zapsan jako nikova sekvence),
'\uFFFF' (neplatn Unicode znak)
Vtina piogiamovacich jazyk podpoiuje i objekty, ktei v sob uchovavaji cel
text tj. posloupnost znak. Objekty tohoto typu se ji nepamti (tj. cca od ioku
1vc) nazvaji etzce (angl. string). etzce mohou obsahovat tm libovoln
poet znak (od nuly do z
Iz
1).
Vpiogiamu lze etzce zapsat pomoci etzcovch liteialu sekvence znak v uvo-
zovkach. Znaky se zapisuji stejn jako u znakovch liteial vetn monosti vyu-
iti nikovch sekvenci. Pio zapis uvozovky uvnit liteialu je mono pouit ni-
kovou sekvenci \.
Piklady etzcovch liteial
"Gandalf"
"" / / jednoznakov etzec obsahujici mezeiu
"\u2C0D\u2C1F\u2C10\u2C21\u2C07\u2C20" / / dekodovani je domaci kol
"" / / piazdn etzec
"\"\"" / / etzec obsahujici dv uvozovky
2.1.3. Logick hodnoty
Posledni kliovou tidou jazyka C= je tida, jejimi instancemi (exemplai) jsou
pouze dva objekty oznaovan liteialy true a false. Objekt true symbolizuje piav-
du (piavdiv vsledek, piavdivou podminku, piavdiv pedpoklad), objekt false
nepiavdu (nepiavdivou podminku, vsledek, pedpoklad apod.)
Tida ma foimalni jmno System.Bool (lze psat zkiacen i bool). Toto podivn jm-
no (te se bu:l) je zkiatkou anglickho slova boolean (boolovsk), jim se oznauji
hodnoty foimalnimlogiky vytvoen matematikemGeorgemBoolem(ovemv ne-
foimalni podob znam ji mnohem mnohem dive).
Zakladni objektov model C= :
2.1.4. asov okamiky
Nezanedbatelna ast modeinich aplikaci piacuje s kalendanimi daty a asem.
Nejsou to jen izn kalendae a kolovniky, ale i etni aplikace, webov poi-
taly i hiy.
V .NlT jsou pio iepiesentaci asu vyuivany objekty standaidni tidy System.-
DateTime. Tyto objekty dokai iepiesentovat asov daj v iiokm iozsahu od
plnoci 1.1. ioku jedna p.K. do plnoci I1.1z vvvv s pesnosti, kteia dostauje pio
vtinu bnch aplikaci (1cc ns).
Poznmka:
Mapovani asovho daje na skuten asov okamik je ponkud
pioblematick. Objekt podpoiuje jen asten mechanismus asovch
pasem a jen jedin kalendani systm giegoiiansk (1.1. ioku jedna
se nov iok opiavdu neslavil). Pio data v iozsahu cca 1vcc a z1cc lze
pedpokladat cca minutovou pesnost (pokud je pouivana asova osa
bez pestupnch hodin vazana na iotaci Zem nap. UTC nebo UT1).
Kiatkodob (v iozsahu msic) je pesnost iepiesentace sekundova
(chyba me vzniknout vloenim pestupn sekundy, jen neni ob-
jekty DateTime podpoiovana). Detaily viz nap. http://en.wikipedia.
org/wiki/Coordinated_Universal_Time a http://en.wikipedia.org/wiki/Leap_
second.
Pio objekty asovch daj neexistuje v C= adn pim liteial a je nutno je vy-
tvaet pomoci tzv. volani konstiuktoiu
new System.DateTime(2012, 8, 9)
Zapis zaina kliovm slovem new za nim nasleduje jmno tidy a seznam pa-
iameti, ktei uiuji poateni stav objektu (zde je to nap. uieni konkitniho
asovho okamiku). V naem pipad je vytvoen objekt iepiesentujici plnoc
dne v.s zc1z.
Kiom konstiuktoiu se temi celoiselnmi paiametiy (iok, msic, den) existuje i
konstiuktoi se esti paiametiy umoujici uiit i okamik v pibhu danho dne
new System.DateTime(2012, 8, 9, 1, 37, 52)
/ / objekt iepiesentujici v.s. zc1z c1Iz
Mn piaktick je konstiuktoi s jednim paiametiem umoujicim zadat as jako
poet 1cc ns tik od poateniho data (1.1. 1 n.l).
:e
new DateTime(600000000000000000)
/ / objekt iepiesentujici Ic.1.1vcz 1c1ccc
Otzka: Paiameti konstiuktoiu v pedchozim pipad neni objekt tidy int. Pio`
Konstiuktoiy jsou nejobecnjim piostedkem pio vytvaeni objekt a v budouc-
nu se s nimi mnohokiat setkame (a blieji seznamime).
2.2. Interakce s objekty
Objekty OOP jazyk stejn jako objekty model iealnho svta mohou ieagovat
na podnty z okoli, mnit sv stavy nebo vytvaet nov objekty. Zakladni objekty
jsou velmi jednoduch a tudi i inteiakce s nimi je velmi jednoducha. Navic vech-
ny zakladni objekty jsou nemnn tj. nikdy nemni svj stav a to vetn instanci
tid string a System.DateTime.
2.2.1. Dotazovn na vlastnosti objekt
Nejjednoduim typem inteiakci s objekty jsou dotazy na jejich stav. Napiklad
etzec dokae viatit svou dlku tj. poet znak.
"Frodo".Length
Tento zapis v jazyce C= mete inteipietovat tak, e se ptame objektu tidy string
(iepiesentujici text liodo) na jeho vlastnost Length (dlka). Objekt ieaguje tak,
e vytvoi nov iseln objekt (tidy int) s poadovanou infoimaci. V naem pi-
pad je to tedy objekt iepiesentujici islo .
Obecn zapis pio zjitni vlastnosti objektu ma tedy tvai
objekt.Vlastnost
Vimnte se, e jmno vlastnosti zaina velkm pismenem (veizalkou). To sice
neni povinn (peklada to nekontioluje), ale je to bn zus, ktei by se ml
dodiovat. Rozhodn je dsledn dodiovan u vech tid standaidni objektov
knihovny, co je souboi tid, ktei jsou dostupn v kad instalaci .NlT a tvoi
zaklad vech .NlT piogiam.
Anglick teimin pio vlastnosti objekt je property.
Zakladni objektov model C= :,
2.2.2. Metody
Pokud vyadujeme od objektu naionji innost tj. bu zmnu stavu nebo vznik
novho objektu, ktei neni vyjadenim pouh dili vlastnosti objektu, zavolame
nad objektem tzv. metodu.
Metodu meme povaovat za hlavni piostedek inteiakce s objektem, za pokyn
aby objekt vykonal njakou (pesn denovanou) innost.
Metoda je vdy volana nad jednim konkitnim objektem (budeme jej dale ozna-
ovat jako adiesata metody), me vak mit jako paiametiy dali objekty, ktei
vsledek metody ovlivni.
Piklady
"Bilbo".Contains("B")
testuje zda objekt adiesat (zde je objekt tidy string tj. etzec Bilbo) obsahuje ja-
ko svou souast (pod)etzec B. Vsledkemje nov objekt tidy bool. Zde je to sa-
mozejm objekt true. Podobn je piavda vsledkemvolani "Bilbo".Contains("bo")
a dokonce i volani "Bilbo".Contains(""), nebo piazdn etzec je foimaln obsa-
en v kadm podetzci.
Poznmka:
Vyhledavani piazdnho podetzce se me jevit jako zcela okiajova
a tudi zanedbatelna monost (kdo kdy chce hledat piazdn pode-
tzec`). V piaxi vak vyhledavan etzec neni zadan pimo v pio-
giamu, ale uivatelem (nap. pomoci vstupniho pole v giack nebo
WWW aplikaci). Pokud napiklad vytvoime aplikaci pio telefonni
seznam a pouijeme metodu Contains pio vyhledavani jmen (Za-
dejte st jmna, a my vyhledme vena jmna, kter tento podet-
zec obsahuj ), pak piazdn vstupni pole pio vyhledavaci etzec vede
k vpisu vech jmen (vechna jmna obsahuji piazdn podetzec).
To se sice me jevit jako iozumn, ale neni tomu tak. Hiozi zahlceni
datovho pipojeni, nebo vsledek me mit nkolik MiB a ty nejsou
nap. datovm ioamingu zadaimo. Viazn to tak usnaduje zcizeni
dat.
Pio udieni kosmick iovnovahy jet nkolik pouiti metody Contains, ktei
viaceji nepiavdu
"Frodo".Contains("f") iozliuji se mala a velka pismena
:8
"Frodo".Contains("oo") podetzec musi bt v adiesatovi obsaen souvisle
Navic je nutno dodiovat poadovan tidy objekt (zde musi bt adiesat i paia-
meti objektem tidy stiing)
"Frodo".Contains('F') tento poadavek se me jevit jako iozumn, nebo lze
uvaovat, e znak (objekt tidy chai) je obsaen v etzci. Knihovna .NlT to vak
neumouje a dovoluje testovat jen pitomnost podetzc. Peklada tak oznami
chybu ji pi pekladu a nedovoli piogiam ani peloit (tj. ani jej nespustite).
Toto omezeni vak lze snadno obejit zapisem "Frodo".Contains("F"), ktei testuje,
zda je v etzci obsaen jednoznakov podetzec (tj. ponkud jin objekt, ktei
vak me v tomto kontextu znak zastoupit).
"1645".Contains(48) tento poadavek vak ji iozumn neni, nebo nema valn
smysl hledat v etzci islo. islo toti me bt iepiesentovano tm nekonen
mnoha texty. Me bt uvedeno v jin soustav (nap. jako Ic v estnactkov)
nebo islicemi jinch kultui (nap. jako XLVlll) nebo dokonce slovy.
Pioto se ani v tomto pipad nepodai piogiam peloit. Poita Vam tak dava
najevo, e jste zadali poadavek, kteimu neiozumi iesp. kteimu ani neme
iozumt.
eeni zavisi na tom co jste vlastn chtli. Pokud jste jen chtli najit vskyt dvou
znak islic v danm poadi, je eeni snadn. Jako paiameti pouijte pislun
dvojznakov etzec (tj. liteial v uvozovkach) tj. "1645".Contains("48"). Pokud jste
skuten mysleli islo (nap. v piogiamu, ktei hleda vskyt xni ceny v iamci
obchodnich smluv i piavnich dokument), musite napsat vlastni metodu, kteia
se vypoada se vemi Vaimi poadavky (nap. na jazyk dokumentu, foimatovani
apod.). Napsat kvalitni kod teba jen pio etinu vak neni tak snadn (a iozhodn
nevhodn pio zaateniky).
Pravidlo 6: Pi aplikaci metod a vlastnost je teba vnovat pozornost td objek-
tu adresta a tdm objekt ve funkci parametr (tj. tdm ve interagujc
objekt). Nkter kombinace nejsou vbec ppustn, nkter mohou vst k rznm
podivnm vsledkm.
Pipadem miin sloitji aplikace metody je nahiada podetzc
"tta".Replace("t", "m")
Vsledkem volani je nov etzec ( objekt tidy stiing), v nm jsou vechny
vskyty podetzce t (pivni paiameti) nahiazeny znakem m (diuh paiameti)
Zakladni objektov model C= :,
tj. etzec mama. Ostatni zastnn objekty-etzce (tata, t a m se nem-
ni).
Volani metod viacejicich nov objekty lze etzit. Metody jsou v tomto pipad
volany zleva dopiava
"Gandalf".Replace("an", "e").Replace("d","r").Replace("f", "t")
Pivni volani metody Replace vytvoi nov etzec Gedalf. Na tento nov et-
zec je volana metoda Replace s paiametiy d a i. Vsledkem je nov etzec
Geialf. Na ten je opt aplikovana metoda pio nahiadu podetzc, je vytvoi
cilov etzec Geialt.
Cel pioces je znazoinn na schmatu z.z na nasledujici stian. Vimnte si, e
i tak ielativn jednoduch inteiakce se astni deset iznch objekt (vechny
jsou tidy string).
Metodu Replace lze volat jen na objekty tidy string, nikoliv na isla nebo logick
hodnoty. Dvodem je skutenost, e objekty ostatnich nam znamch tid, nemaji
adnou vnitni stiuktuiu, kteia by mohla bt (asten) nahiazena.
Chybn poadavky 102.Replace("2``, "3") (islo neni posloupnost znak islic,
to je jen vnji iepiesentace), true.Replace("t", "") (logicka hodnota tak neni
etzcem znak).
lxistuji vak i metody, ktei lze volat nad objekty (tm) vech typ. Je to napi-
klad metoda ToString, kteia viaci bnou textovou iepiesentaci kadho objektu
(tj. text, ktei pokud mono jednoznan popisuje dan objekt). Vsledn objekt
je pouze vnji iepiesentaci, nikoliv samotnm objektem i jeho kopii (vjimkou
jsou samotn objekty tidy string).
2.ToString() / / z
/ / islo z je iepiesentovano textem s jedinou islici
0.0000002.ToString();
/ / zl-c (foimat isla se me zmnit opioti liteialu)
true.ToString()
/ / Tiue (piavdiva hodnota me bt iepiesentovana textem Tiue)
"Gondor".ToString()
/ / Gondoi (viati stejn text, a s nejvti piavdpodobnostni i stejn objekt)
(new DateTime(2013,1,5)).ToString()
/ / .1.zc1I ccccc
o
Gandalf
an
an
e
e
Replace
(dost o nhradu
podetzc)
parametry (dosti)
adrest (dosti)
reakce adresta
vytvoen novho o!"ektu tdy string
Gedalf
d
d
r
r
Replace
(dost o nhradu
podetzc)
parametry (dosti)
meziv#sledek
adrest (dosti)
reakce adresta
vytvoen novho o!"ektu tdy string
Geralf
f
f
t
t
Replace
(dost o nhradu
podetzc)
parametry (dosti)
meziv#sledek
adrest (dosti)
reakce adresta
vytvoen novho o!"ektu tdy string
Geralt
Geralt
vsledn objekt
Obiazek z.z. Zetzen volani metody
Zakladni objektov model C= 1
2.2.3. Operace
Pio objektov jazyky je typick volani metod ve tvaiu adrest.metoda(parametry)
(misto teky me bt v jinch jazycich odlin oddlova nap. dvojznak -~,
apod). Tento foimat volani ma dv vhody
adiesat je uveden jako pivni a je jasn oddlen od paiameti. To odpovida i
vtin piiozench jazyk, kde je adiesat tak bn uveden na zaatku a-
dosti nebo poadavku na innost (Pete, ukli to s poadim adiesat, pikaz
a paiameti to).
volani metody lze snadno etzit (nap. 123.ToString().Length)
Vnkteich specickch pipadech vak tento foimat volani neni optimalni. Tka
se to pedevim matematickch viaz, kde se bn pouivaji izn opeiatoiy
(opertor symbol vyjadujici opeiaci, typicky umistn mezi dvma hodnotami).
V ist objektovm jazyce by napiklad vpoet hodnoty z*(-1) mohl mit tvai
2.Vynasob(5.Pricti(1)), nebo z objektovho pohledu se jedna o adost, adiesova-
nou islu z, aby se vynasobilo s objektem-islem vzniklm aplikaci metody Pricti
na islo pt (s paiametiem 1). Vsledkem adosti je nov iseln objekt.
l kdy nktei objektov jazyky tivaji na tomto zapise (s anglickmi nazvy pi-
slunch metod), umouje vtina z nich i zapis blizk matematickmu (jen je
navic shodn s pvodnimi neobjektovmi jazyky jako Pascal i C). Z hlediska
OOP je vak pouiti opeiatoi jen zkiacenm a pehlednjim zapisem, ktei je
stale nutno inteipietovat objektov tj. jako aplikaci metod na objekty.
Binrn aritmetick opertory
Aiitmetick opeiatoiy v jazyce C= jsou v zasad beze zmn pevzaty z jazyka C.
Binaini opeiatoiy jsou vdy aplikovany na dva objekty.
operace znak priorita asociat.
sitani - 1 (nii)
odeitani - 1
nasobeni * I (vyi)
dleni / I
zbytek po dleni I
:
Posledni dva sloupce tabulky uiuji v jakm poadi se opeiatoiy vykonavaji, po-
kud se jich ve viazu vyskytuje vice. Ve valn vtin pipad se stai pamatovat,
e
opeiatoiy s vyi piioiitou se vyhodnocuji ped opeiatoiy s piioiitou nii.
Pokud jsou piioiity oznaeny iseln, pak se vtinou oznauji tak, e meni
islo vyjaduje vyi piioiitu (tj. opeiatoi s piioiitou z se vyhodnoti dive
ne opeiatoi s piioiitou I). Piioiita aiitmetickch opeiatoi je ve shod s
bnm matematickm zem.
pokud maji opeiatoiy stejnou piioiitu pak se vyhodnocuji podle tzv. aso-
ciativity bu zleva dopiava nebo zpiava doleva. Asociativita zleva dopiava
je zakladni (je ve smiu teni), opana je vjimkou.
poadi lze vdy zmnit nebo ovlivnit pomoci (kulatch) zavoiek. Zavoiky
se vak nkdy pouivaji i v pipad, kdy poadi nemni a to z dvod vyi
pehlednosti (pedevim v u sloitjich viaz nebo tehdy, kdy se stkaji
opeiatoiy, jejich ielativni piioiita neni veobecn znama).
Dlen a zbytek po dlen
Pesn vznam opeiaci dleni je dan tim, zda je opeiace aplikovana na objekty
celoiseln (tidy int), nebo s pohyblivou adovou aikou (double).
Pokud jsou oba opeiandy (tj. adiesat opeiace i paiameti) instancemi tidy int, pak
je dleni tzv. celoiselnm (oznaovano jako div) a zbytek po dleni lze vyjadit
vztahem = (), kde symbol vyjaduje celoiseln dleni, je dlenec,
dlitel a zbytek po dleni.'
Nkolik piklad
7 / 3 z ( cela ast zlomku /I)
7 % 3 1 (nebo - (I * z) 1)
-7 / 3 -z
-7 % 3 -1 (nebo - - (I * -z) - - e -1)
7 / -3 -z
7 % -3 1 (nebo - (-I * -z) - e 1)
'existuji i dali monosti denice zbytku po dleni, ktei lii pouze v pipad, e dlitel i dlenec
je zapoin. Piogiamovaci jazyky podpoiuji izn denice (tj. mohou poskytovat izn vsledky).
Pehled (s detailnim vysvtlenim pioblematiky) viz http://en.wikipedia.org/wiki/Modulo_
operation.
Zakladni objektov model C=
Celoiseln dleni se v piaxi vyuiva jen zidka (vjimkou jsou algoiitmy sou-
visejici s teoiii isel), zbytek po dleni je uitenji nap. pio testovani sudosti
i lichosti isla. Zbytek po dleni islem dva je u sudch isel samozejm c, u
lichch pak 1.
V pipad, e je alespo jeden z opeiand opeiace instanci tidy double, pak ope-
iatoi / znai bn dleni iacionalnich isel. Opeiatoi zbytku po dleni je zo-
becnn i pio iacionalni isla za pouiti stejnho vztahu jako ve.
Piklady
7.0 / 3.0 z.IIIIIIII (iepiesentace ma jen omezen poet desetinnch islic).
7.0 % 3.0 1.c (stejn jako u celch isel)
42.2 % 5 z.z (nebo 1z.z - * s z.z)
Tento zobecnn zbytek po dleni neni sice matematicky zcela koei, ale pio klad-
n opeiandy je v nkteich pipadech velmi uiten. Napiklad jej lze pouit pio
piavu obecnho hlu tak, aby leel v iozsahu c a Iec stup (nebo c a z).
456.25 % 360.0 ve.z
8 % (2*3.1416) 1.1es
Unrn aritmetick opertory
Kiom binainich opeiatoi existuji i opeiatoiy unaini tj. opeiatoiy aplikovan
na jedin objekt (jen je z objektovho adiesatem opeiatoiu-metody).
Zakladnim unainim aiitmetickm opeiatoiem je unaini minus, ktei viaci nov
iseln objekt s opanou hodnotou (pvodni objekt se nemni!)
-2 (zde je vak znak - souasti iselnho liteialu nikoliv opeiatoi, funkce je vak
obdobna)
-"x".Length je -1 (nejdive se ziska vlastnost Length etzce, co je objekt tidy int,
na nj se aplikuje unaini minus)
loimaln existuje i opeiatoi unaini plus, ten vak pouze viaci svj opeiand (iesp.
jeho kopii) a v piaxi se s nimpiavdpodobn vbec nesetkate. Me se vak objevit
v (po)chybnch zapisech nebo uebnicovch pikladech.
vimnte si, e znak - ma v jazyce C= nkolik vznamu je to binaini i unaini opeiatoi a tak me
bt pimou souasti iselnch liteial

Opertory nad neselnmi objekty a petovn opertor


Aiitmetick opeiatoiy byly do piogiamovani pevzaty z matematick notace a
nejastji se pouivaji pio iseln objekty. lxistuji vak i vjimky.
Napiklad opeiatoi - lze vyuit i pio spojovani etzc. Opeiandy jsou dva e-
tzce, vsledkemje nov etzec, ktei vznikne postupnmzetzenimjejich zna-
k.
esko - Slovensko (vsledek je etzec eskoSlovensko)
Stejn jako opeiatoiy / i ma opeiatoi - dv izn funkce. V jeho pipa-
d je to sitani (isel) a spojovani etzc. Tomuto chovani ikame petovn
opertor a je pio opeiatoiy typick.
Pi pouivani petiench opeiatoi se musite soustedit na tidu, ke ktei pati
jejich opeiandy. Pokud jsou napiklad oba opeiandy iseln, je vykonana opeiace
sitani a vsledkem je islo. Pokud jsou oba etzce, je vsledkem samozejm
spojen etzec.
Co se vak stane v pipad, e se tida opeiand lii. U opeiatoi / a vdy
zvitzil obecnji objekt tidy double (diuh opeiand se mu pizpsobil). Podobn
je tomu i v pipad opeiatoiu -, kde navich ziskava etzec a diuh opeiand se
na etzec pevede pomoci metody ToString().
2 + " koky" "2 koky" 2.ToString() + " koky"
"odpov: " + 42 "odpov: 42"
Kontiolni otazka Co je vsledkem viazu 2 + 2 + "2"`
V piaxi se vak snate pipadm opeiand iznch tid vyhnout a viaz iadji
iozepite do tvaiu, kdy jsou opeiandy explicitn pevedeny na spolenou tidu.
z.c / I.c je lepi ne z / I.c (i kdy oboji viaci stejn vsledek)
1.ToString() + "1" je jednoznanji ne 1 + "1".
Poznmka:
Petovani nemusi bt vdy tak zeteln jako je tomu v pipad ope-
iatoi /, a pedevim -.
Zkuste se napiklad zamyslet, jak je iozdil mezi viazy z * I a z.c *
I.c.
l kdy se jedna na pivni pohled o stejnou opeiaci (nasobeni), je jeji
piovedeni v piocesoiu viazn odlin. Pivni (s objekty tidy int) se
Zakladni objektov model C=
piovadi v celoiseln aiitmetick jednotce (ALU), diuha v tzv. lPU
(dive byla oznaovana jako tzv. kopiocesoi). Pivni opeiace je viaz-
n iychleji a to pedevimv pipad, e dan systmlPUneobsahuje
(v tomto pipad je piovadna pomoci specialni knihovni iutiny za
pomoci nkolika desitek celoiselnch opeiaci).
Dalim pikladem petieni je monost pouiti binainiho opeiatoiu - pio dva
opeiandy typu System.DateTime. Vsledkem iozdilu dvou dat je objekt tidy Sys-
tem.Timespan, ktei vyjaduje asov iozdil mezi dvma okamiky v ase. Rozdil
me bt vyjaden v sekundach, ale bnji je iepiesentace je vyich jednotkach
dnech, hodinach, minutach a sekundach (jet deli jednotky jako jsou msice ne-
bo ioky nemaji pevnou dlku).
(new DateTime(2012,8,8)) - (new DateTime(935,9,28));
/ / TimeSpanIvII1e.cccccc (IvI I1edn)
Objekt tidy TimeSpan ma ielativn velk poet vlastnosti, viacejici jeho iepie-
sentaci v iznch jednotkach.
Vlastnosti s nazvem Days, Hours, Minutes, Seconds viaci jednotliv asti asov-
ho iozdilu (tj. v naem pipad Days IvII1e, Hours c, Minutes c). Pokud
je poteba vyjadit cel iozdil v danch jednotkach je nutno vyuit vlastnosti se
jmny TotalDays, TotalHours apod.. Vsledkem je v tomto pipad iacionalni islo
( double) obsahujici i zlomky jednotek.
((new DateTime(2012,8,8))-(new DateTime(935,9,28))).TotalDays
/ / IvII1e
((new DateTime(2012,8,8))-(new DateTime(935,9,28))).TotalSeconds
/ / IIvszcz1cc,
Otazka Jak zjistite, kolik ubhlo let (pesnji julianskch iok Ie.z dn)`
Indexace
Piogiamovaci jazyky pevzali ze svta matematiky i dali zapis tzv. indexaci. ln-
dexace umouje zvolit -t pivek njak posloupnosti, vektoiu nebo uspoadan
mnoiny.

1
- pivni pivek posloupnosti (vektoiu, n-tice)
V piogiamovacim jazyce nelze pouit dolni index, ale pouivaji se nahiadni zapi-
sy. V C= (a C, C++, Jav, Pythonu, PHP, atd.) se indexy zapisuji pomoci specialniho
opeiatoiu hianatch zavoiek.
e
"Frodo"[3]
Tento zapis vyjaduje volani opeiatoiu indexace na etzcov objekt. V C= se in-
dexuje od nuly tj. index I indexuje tvit pivek (pivni ma index c, diuh index z,
atd). etzec je posloupnost znak tj. jeho pivky jsou objekty tidy ar. Vsled-
kem indexaniho viazu je tedy objekt ar:d (tvit znak). Vizualni znazoinni
viz obiazek z.I.
F r o d o
0 1 2 3 4 -1 5
indexy
Obiazek z.I. lndexace v etzci
Pokud pouijeme index mimo meze, v naem pipad napiklad zapis
"Frodo"[5]
(tj. pistup k estmu znaku v ptiznakovmetzce) dojde k vjimen situaci, co
vede k pedasnmu ukoneni piogiamu se zpiavou System.IndexOutOfRange-
Exception: Array index is out of range (zaizeni , na nm je zpiava vypsana zavisi
na kontextu, nejastji to bva chybov okno)
Pravidlo 7: etzce a dal tzv. indexovateln kolekce jsou indexovny od nuly a
posledn prvek m index length-1.
O nco piaktitji piklad a dali pokus o vysvtleni OnZOVaV
"abcdefghijklmnopqrstuvwxyz"[3].ToString() + "abcdefghijklmnopqrstuvwxyz"[1]
Otazkou neni, jak je konen vsledek (co je vtinou snadn), ale jak opeiace
a metody se vykonavaji (a v jakm poadi), iesp. jak objekty pi tom vznikaji a
zanikaji. Dobi piogiamatoi to ve musi detailn znat.
2.3. Tdn metody a vlastnosti
Objektov piogiamovani je zameno pedevim na objekty a inteiakce mezi ni-
mi. Tidy hiaji jen pomocnou (i kdy dleitou) ioli. l tidy vak mohou mit vlast-
Odpov na Zakladni Otazku ivota, Vesmiiu a vbec
Zakladni objektov model C= ,
nosti a dokonce i metody. Pikladem jsou vlastnosti viacejici zajimav objekty
tidy, infoimace o vech instancich iesp. metody vytvaejici nov instance (kdy
ji liteialy a konstiuktoiy nestai).
V nkteich piogiamovacich jazycich (nap. v Pythonu nebo Ruby) lze tidy cha-
pat jako specialni objekty (iepiesentujici tidu jako takovou). V .NlT vak tidy
nejsou objekty a dokonce nejsou za bhu aplikace pitomny v pamti .
Natsti lze alespo foimaln volat metody nad tidami a ziskavat tidni vlast-
nosti. Tidni metody a vlastnosti se z histoiickch dvod oznauji jako stati
(angl. static).
Statick (tj. tidni) vlastnosti se pouivaji podobn jako vlastnosti nad objekty
(oznaovan jako instanni). Jen namisto objektu je ped tekou uvedena tida
(iesp. jeji identikatoi).
int.MaxValue
Tato vlastnost tidy int viaci objekt obsahujici nejvti iepiesentovateln islo tj.
z111sIe1 ( z
I1
1). Vimnte si, e vlevo od teky je jmno tidy nikoliv objekt.
Podobn existuje i vlastnost int.MinValue (viacejici -z111sIe1s). Stejn pojme-
novan vlastnosti existuji i u ostatnich iselnch tid (nap. double.MaxValue) a
jinch uspoadanch mnoin vetn bool, ar a System.DateTime.
Dleitou ioli hiaji statick vlastnosti u tidy DateTime, nebo jen pomoci nich
lze ziskat objekty iepiesentujici aktualni asov okamik ( systmov as) iesp.
plnoc aktualniho dne (kliov pio kalendani vpoty)
DateTime.Now / / aktualni asov okamik (nap. s.s.zc1z 1s11)
DateTime.Today / / plnoc aktualniho dne (nap. s.s.zc1z ccccc)
Mezi zakladni statick metody pati ty, ktei pevadji etzcovou iepiesentaci
hodnoty na pislun objekt (tj. jsou do jist miiy inveizni k metod ToString()).
Tyto metody se ve svmidentikatoiu obsahuji slovo parse ( piovst syntaktick
iozboi).
int.Parse("42") / / objekt int1z
dvodem je vyuiti kliovho slova static, pevzat z jazyka C--. Piimainim vznamem je uloeni
ve statick oblast pamti, tj. oblasti pamti, kteia se alokuje ji pi sputni piogiamu a jeji iozsah
se pot nemni (situace v C= je ponkud jina, ale i zde jsou staticka data uloena ve specialni oblasti
pamti).
8
Paiametiem metody je objekt etzce, vsledkem je nov objekt, jen je instanci
tidy, ji staticka metoda pati. Vimnte si, e si metoda dokae poiadit s peby-
tenmi mezeiami ped a za islicemi. Bohuel tim jeji inteligence koni
int.Parse("42000")
/ / skoni s chybou (vjimkou)
/ / System.loimatlxception lnput stiing was not in the coiiect foimat
Podobn skoni pokus o pevedeni textu, je obsahuje libovoln neiseln a ne-
mezeiov znak (pipustn je jen znak minus nebo plus ped pivni islici).
Metodu Parse podpoiuji vechny iseln tidy (vetn double), tida bool (ioze-
znava etzce tiue a false bez ohledu na velikost pismen tj. nap. i Tiue nebo
dokonce tiue).
Ponkud sloitji je situace u tidy DateTime. Jeji metoda DateTime.Parse ioze-
znava zapis v lSO foimatu (nap. zc1z-1z-z1) a ve foimatu aktualnich jazyko-
vch vlastnosti (tj. nap. pokud je nastavena etina, pak iozezna napiklad et-
zec z1.1z.zc1z). Pokud chcete nastavit i denni as dopoiuuji lSOfoimat (funguje
vdy a vude)
DateTime.Parse("2008-10-12T12:00")
Je vak podpoiovano i mistni nastaveni (funguje jen v esk iepublice a blizkm
okoli)
DateTime.Parse("24.12.200812:00")
2.4. Promnn
Piomnn (angl. variable) umouji pidlit objektm jmna, co viazn usnad-
uje manipulaci s objekty. Piomnn si meme pedstavit jako pojmenovan
schianky, ktei obsahuji bu pimo objekt nebo jednoznan odkaz na nj.
Jako piklad z iealnho ivota, lze uvst napiklad identikaci neznamch zviat
kupikladu koek. Pokud je chceme identikovat, pak mame v zasad dv mo-
nosti
Pivni monosti je vytvoit klece se jmny, do nich jednotliv koky zaveme (tj.
pojmenovana schianka obsahuje pimo objekty s nimi piacujeme). Tento pistup
samozejm funguje, ale ma dv nevhody
Zakladni objektov model C= ,
jedna se o tiani koek (co je vak pio OOP objekty natsti iielevantni)
pokud chceme identikovat nehomogenni skupinu (nap. libovolnch ivo-
ich) je obtin vytvoit univeizalni klece (nap. pio pivoky i plejtvaky)
Diuhou monosti je vytvoit pojmenovan schianky (nap. popsan obalky), v
ni je pouze jednoznan odkaz na objekt (nap. fotogiae koky, jeji DNA otisk
apod.) Tento pistup je sice ponkud komplikovanji je vak univeizalnji (a
tak levnji!).
Podobn, pokud si chce policie jednoznan pojmenovat auto, pak lze sice uvao-
vat gaia, v nich dan auto uzave (a na dvee vyvsi SPZ), ale levnji je vedeni
iegistiu, v nm je pod jmnem auta (SPZ) jeho jednoznana identikace (popis,
islo motoiu, apod.). Navic se tim nebiani v uivani auta (vytvoeni duplikatu je
pili asov i nann naion).
Podobn i u objekt je astji pipad, kdy piomnna obsahuje pouze odkaz na
objekt (tj. nap. jeho adiesu v pamti). Vhodou je exibilita (piomnna me
odkazovat i na objekty iznch velikosti), monost sdileni (objekt me bt od-
kazovan iznmi jmny a tak vyuivan ve vice kontextech) a spoia pamti (co
vyplva z monosti sdileni).
Pim uloeni je vhodn pouze pio velmi jednoduch objekty, u nich je mona a
snadna duplikace (vytvoeni identickch kopii). To plati nap. pio iseln objek-
ty, ktei jsou velmi mal (v pamti asto zaujimaji meni misto, ne by zaujimal
odkaz) a je mono vytvaet identick kopie.
V jazyce C= lze pioto tidy iozdlit na hodnotov a referenn. Objekty hodnoto-
vch tid jsou ukladany pimo do piomnnch. Mezi hodnotov tidy pati vech-
ny iseln typy (int, double a dali, ktei jet nezname), znakov a logick typ.
Refeienni tidou je i tida System.DateTime (intein je to jednoducha iselna hod-
nota).
Objekty iefeiennich tid jsou z piomnnch pouze odkazovany (tj. nejsou v pio-
mnnch pimo uloeny). Mezi iefeienni tidy pati valna vtina ostatnich tid,
i kdy piozatim zname jednu jedinou iefeienni tidu string.
Rozdil mezi iefeiennimi a hodnotovmi tidami se piojevuje ji v okamiku vy-
tvaeni piomnnch.
o
2.4.1. Definice a inicializace promnnch
Abychom mohli piomnnou pouivat, musime ji nejdive vytvoit. Zapis, ktei
piomnnou vytvai se nazva denice promnn.
Denice piomnn ma zakladni tvai
identifiktor-tdy tda identifiktor-promnn = vraz-vracejc-inicializan-
objekt,
ldentikatoi tidy specikuje objekty, ktei lze do piomnn ukladat, identikatoi
( nazev) pak jednoznan identikuje piomnnou a tim nepimo i objekt v ni
uloen.
Vtina piogiamovacich jazyk omezuje pipustn foimat identikatoi piomn-
nch. Nkteia omezeni jsou povinna (tj. musi bt dodiena jinak se piogiam ne-
peloi), jina jsou pouze dopoiuenimi (ktei byste vak mli dodiovat)
povinn omezen: identikatoi musi zainat pismenem ( znak, ktei je v Uni-
code oznaen jako pismeno) a me pokiaovat bu pismeny nebo islice-
mi (tzv. alfanumeiick znaky). V identikatoiech je mono pouivat i znak
podtiitko, ale v C= jej iadji nepouivejte. Tato omezeni plati v zasad pio
vtinu bnch piogiamovacich jazyk (PHP, Java, C, Python apod.)
doporuen: identikatoi by ml zainat malm pismenem a pokud je viceslov-
n pak by kad slovo (kiom pivniho) mlo zainat velkm pismenem.
Obecn je vhodnji pouivat pouze anglickou abecedu (a euioaiabsk isli-
ce). Nepouivejte iadji zkiatky (pokud nejsou zaveden nap. HTML nebo
HTTP je samozejm OK, zapisuji se vak spie ve tvaiu Html a Hp)
Piklady platnch (a dopoiuenihodnch) identikatoi piomnnch
pocetPrvku, optimalniDopravniProstredek, aktualniUzelSite, currentNetNode, ma-
ximum, seznamObrazku, gureList
Vytvoeni piomnn pak piobiha ve dvou fazich. Pibh tchto fazi se lii podle
toho, je-li tida piomnn hodnotova nebo iefeienni (tj. zda-li piomnna bude
obsahovat objekt i jen odkaz na nj)
Definice a inicializace promnnch pro objekty hodnotovch td
U hodnotovch tid je nejdive alokovano misto pio piomnnou. Toto misto je
vynulovano tj. obsahuje jen nulov byty. Do takto alokovanho mista se zkopiiuje
inicializani objekt (byte po bytu).
Zakladni objektov model C= 1
Vsledkem je pamov misto, je je inicializovano kopii inicializaniho objektu.
Nikdy tak neme vzniknout piazdna piomnna i piomnna s nedenovanou
hodnotou! Cel pioces si mete piohldnout na obiazku z.1.1 na pedchozi stia-
n.
inicializan
objekt
inicializan
objekt
uloen
objekt
definice a inicializace promnn hodnotov tdy
nov inicializovan promnn
nulov
objekt
koprovn
alokace
inicializace
Obiazek z.1. Denice a inicializace piomnn pio objekty hodnotovch tid
Piklad
int velikost = 5;
Tato denice vytvoi piomnnou se jmnem (identikatoiem) velikost. Nejdive
se v pamti vyhiadi misto pio objekt o velikosti 1 byt (co je velikost objekt
tidy int). Toto misto obsahuje nejdive nulov objekt (objekt tvoen nulovmi
byty), ten je vak ihned pepsan kopii inicializaniho objektu (zde je to objekt isla
).
Dali piklady denici piomnnch
double x = 2 * 3.14; / / sloitji inicializani objekt objekt, jen je vsledkem nasobeni
double y = x / 2;
char koncovyZnak = 'q';
bool vysledek = true;
DateTime konecSveta = new DateTime(2012, 12, 21);
lnicializani ast denice je nepovinna. Pokud neni inicializace pouita, je pio-
mnna inicializovana nulovm objektem (tj. je piovedena jen alokani ast) z ob-
iazku z.1. l v tomto pipad je piomnna inicializovana a vznikne nov objekt.
:
Nulov objekt iepiesentuje u iselnch tid nulu, u tidy bool objekt false (tiochu
pesimistick pohled na svt). U ostatnich hodnotovch tid me bt inteipietace
sloitji.
int pocet; / / piomnna obsahuje objekt c
double p; / / piomnna obsahuje objekt c.c
char zeroChar;
Posledni piomnna obsahuje po denici znak s kodem c. Tento znak je idici a
nema giackou iepiesentaci (iozhodn to neni znak c!). lxplicitn lze tento znak
napsat nap. pomoci nikov sekvence \ucccc nebo \c).
DateTime pocatek; / / nejmeni iepiesentovateln datum 1.1.ioku 1 ccc
l kdy jazyk C= denice bez explicitni inicializace pipouti (tj. neni to chyba pi
pekladu), je pouiti explicitni denice vdy pehlednji a bezpenji. To plati i
v pipad, e je piomnna inicializovana nulovm objektem.
Pravidlo 8: Promnn by mla bt v rmci denice vdy explicitn inicializovna.
Definice a inicializace promnnch pro objekty referennch td
Zapis denice tchto piomnnch se nelii, smantika je vak jina.
V pivni (alokani) fazi se v pamti vytvoi misto pio piazdn odkaz na objekt
(alokovan misto je vdy stejn velk, 1 nebo s byt podle toho, zda je systm Iz
nebo e1 bitov). Nasledn se do uloi odkaz na inicializani objekt (tj. jeho adiesa
v pamti). Nedochazi k adnmu kopiiovani a nevznika adn nov objekt (me
vak bt vytvoen v inicializanim viaze). Pioces je znazoinn na obiazku z. na
nasledujici stian.
string buh = "Mithra";
Zde se nejdive vytvoi nov objekt tidy string (v inicializanim viaze, jen ma
podobu liteialu). Pak se vytvoi piomnna (se jmnem buh) a vloi se do ni
odkaz na dive vytvoen etzcov objekt.
lnicializace piomnnch vak me bt i sloitji
string slabika = "bar";
string slovo = slabika;
string vystup = slovo + "" + slabika + slabika;
Zakladni objektov model C=
definice a inicializace promnn referenn tdy
inicializan
objekt
inicializan
objekt
odkaz na
objekt
przdn
odkaz
nov inicializovan promnn
alokace
inicializace
Obiazek z.. Denice a inicializace piomnn pio objekty iefeienni tidy
l v tomto pipad se nejdive vytvoi nov etzcov objekt (s textem bai). Od-
kazemna tento objekt je inicializovana piomnna slabika. Nasledn je tento odkaz
(nikoliv objekt!) zkopiiovan do nov denovan piomnn slovo. Ob piomnn
tak od tto chvile odkazuji na stejn objekt.
Posledni piomnna (vstup) je inicializovana odkazem na objekt, ktei vznikne in-
teiakci hned nkolika objekt. Nejdive je vytvoen doasn objekt, jen obsahuje
etzec tvoen jedinou mezeiou. Ten je nasledn paiametiem opeiace (metody),
kteia spojuje dva etzce. Adiesatem ( pivnim opeiandem) opeiace/metody je
objekt odkazovan piomnnou slovo. Vsledkem je nov etzec (s textem bai).
Tento objekt vstupuje do nov opeiace zetzeni a je spojen s objektem na nj
odkazuje piomnna slabika (co je jak ji vime stejn objekt jako u piomnn slo-
vo). To ve se jet jednou opakuje. linalnim vsledkem inicializaniho viazu je
nakonec objekt s etzcembai baibai. Na tento objekt zane ukazovat piomnna
vstup. Giack znazoinni naleznete na obiazku z.e na nasledujici stian.
Vimnte si, e i kdy v pibhu vykonavani ve uvedenho fiagmentu kodu
vznikne celkem est objekt, jen dva z nich jsou po ukoneni piovadni odkazo-
vany z piomnn (iesp. pesnji z alespo jedn piomnn). Jen tyto dva objek-
ty budou dostupn ve zbytku piogiamu. Ostatni ji nejsou poteba a mohou bt
uvolnny z pamti.
Pozoinji tenai si mona vimli, e o nco ve byl uveden podivn teimin
piazdn odkaz a nebyl naleit vysvtlen. Nyni se vak k nmu viatime.
uvolnni se vak nepiovede hned, ale a v okamiku, kdy dojde pam

string slabika = "bar";


string slovo = slabika;
string vystup = slovo + "" + slabika + slabika;
slabika
slabika
string: "bar"
string: "bar"
slovo
slovo
vystup
vystup
string: " "
string: " "
string: "bar "
string: "bar "
string: "bar "
string: "bar "
string: "bar barbar"
string: "bar barbar"
string: "bar "
string: "bar "
Obiazek z.e. Sloitji denice a inicializace
Zakladni objektov model C=
2.4.2. Odkaz null
Piomnna vytvoena pio ukladani objekt iefeiennich tid me obsahovat i tzv.
piazdn (ang. null) odkaz. Piazdn odkaz iepiesentuje stav, kdy piomnna neod-
kazuje adn odkaz (tj. lze ji povaovat za piazdnou i lpe neinicializovanou).
Piomnnou s piazdnm odkazem lze nejlpe vytvoit pomoci inicializace speci-
alni hodnotou null (tato hodnota neni objektem!).
string jmeno = null;
Piomnna s piazdnm odkazem se pouiva v nkolika pipadech
iepiesentace neexistujici i nedostupn hodnoty
v naem pipad se jmnem to me vyjadovat nkolik situaci jmno ne-
existuje, jmno se nepodailo zjistit iesp. jej nelze uvst (nap. z dvod
ochiany osobnosti)
objekt neme (piozatim) v danm kontextu vzniknout (ale piomnna ji
musi bt denovana) tento pipad se vyskytuje pouze ve sloitjich pio-
giamovch konstiukcich
Piomnna obsahujici piazdn odkaz vak neni plnohodnotnou piomnnou, nebo
ji nelze pouivat na mist, kde je oekavan (skuten) objekt. Napiklad pi pokusu
volat nad piomnnou metodu, opeiaci i ziskat nkteiou z vlastnosti je piogiam
pedasn ukonen s hlaenim, e odkaz neodkazuje objekt.
System.NullReferenceException: Object reference not set to an instance of an object
Piklady ybnho pouiti piomnnch s piazdnm odkazem
string text = null;
text.Length; / / nelze zjistit poet znak v neexistujicim etzci
text + "x"; / / nelze spojit neexistujici etzec s jinm (existujicim)
Piazdn odkaz na okamik vznika i pi bn inicializaci, ale zde je ihned pepsan
odkazem na skuten objekt (viz obiazek z.1). Vjimkou je situace, kdy jde pou-
ita denice bez inicializace. To je sice foimaln pipustn, ale velmi nebezpen,
nebo tato situace vznika nejastji jako vsledek opomenuti (omylem zapomene-
te vytvoit poadovan objekt). Tj. pi denici vdy iovnou inicializujte (vetn
hodnoty null).
string jmeno;
jmeno.Lengt / / piogiam pedasn skoni s chybou
/ / (viz piklad ve, zde to vak me bt vice pekvapujici)
e
Upozornn:
Hodnotu null je teba dsledn odliovat od nuly (i kdy v etin
se alespo v textov podob ob slova pili nelii). Nula je skuten
iseln objekt a me bt ukladan jen do piomnnch pislunch
iselnch typ. Piomnna je v tomto pipad pln inicializovana a
mohou na ni bt volany metody (nap. aiitmetick opeiace).
Hodnota null me bt pouita v libovoln piomnn iefeienni ti-
dy a vyjaduje neexistenci objektu. U piomnnch hodnotovch tid
(vetn iselnch) ji pouit nelze.
Chybn pklady:
string slovo = 0;
/ / piomnou tidy stiing nelze inicializovat objektem tidy c
int i = null;
/ / piomnn hodnotovch tid nemohou bt piazdn (obsahuji toti pimo objekt)
Odlieni je nutn i v pipad implicitni inicializace (i kdy i zde je
lepi implicitni inicializaci zcela eliminovat).
string slovo; / / piomnna neodkazuje adn objekt
slovo + "" / / chyba (za bhu), pouiti piazdn iefeience
int cislo; / / piomnna obsahuje objekt c
cislo + 10
/ / syntakticky OK (seteni c a desitky), ale me vst k nedoiozumni
2.4.3. Piazen
V jazyce C= lze piomnn modikovat tj. lze zamovat objekty, ktei jsou v
piomnn uloeny iesp. jsou z piomnn odkazovany. Ve skutenosti jsou zm-
ny piomnnch zakladnim mechanismem jazyka (a piomnn si tudi svj nazev
zasloui).
Hodnotu piomnn lze modikovat pedevim tzv. piazenm (angl. assignment).
Zakladni tvai piazeni je velmi jednoduch (a nelii se od vtiny ostatnich ja-
zyk)
promnn = vraz
Piklady
Zakladni objektov model C= ,
jmeno = "Bilbo";
/ / pedpoklada se, e piomnna je tidy stiing
Syntaxe piazeni se pili nelii od inicializace (viz pedchozi kapitola). Ve sku-
tenosti ma s inicializaci mnoho spolenho, zasadn se vak lii v jedn kliov
vci piazovat lze jen do ji existujici piomnn!
Tento iozdil ma nkolik dsledk
pi piazeni nevznika adn nov objekt (a to ani u objekt hodnotovch
tid)
na diuh stian me dojit k zaniku objektu (uloenho i odkazovanho)
Pi piazeni do hodnotov promnn dojde k pekopiiovani objektu a pvodni
objekt je pepsan (im zanikne).
Piklad
int i = 1;
int j = 2;
i = j
Objekt uloen v piomnn i (int1) je pepsan kopii objektu z piomnn j (intz).
Objekt int1 tedy zanika a existuji dv kopie objektu intz.
U iefeiennich piomnnch je situace opt odlina. Piotoe se kopiiuje odkaz z
jedn piomnn do diuh je vsledkem dvojice odkaz na stejn objekt. Odkaz
na pvodni objekt zanika, samotn vak me peit, pokud na nj odkazuje jina
piomnna (pimo i nepimo).
Piklad
string aktualniLoh = "Londn";
string pristiLoh = "RiodeJaneiro"
aktualniLoh = pristiLoh;
Ped piovedenimpiazeni mame dv piomnn, ktei odkazuji dva (izn) objek-
ty. Po piazeni odkazuji ob na objekt etzce string:Rio de Janeiro. Na etzec
Londn nic neodkazuje, tj. je pio piogiam nedostupn a me bt uvolnn z
pamti.
Poznmka:
Piazeni v C= se podobn jako v ostatnich jazycich odvozench z C
(C--, Java, PHP) chova jako opeiatoi. Plati to pedevim pio syntaxi,
8
nebo i v C= lze pouivat piazeni i uvnit viaz. Z hlediska objek-
tov smantiky vak piazeni neni opeiatoiem, nebo se aplikuje na
piomnnou nikoliv na objekt (vimnte si, e pi piazeni se mni
piomnna nikoliv uloen i odkazovan objekt).
Z opeiatoiovho pohledu je piazeni opeiatoi s velmi nizkou (ve
skutenosti nejnii) piioiitou a asociativitou zpiava doleva (tj. opa-
nou). l kdy lze v zasad opeiatoi piazeni pouit kdekoliv ve viazu,
je v piaxi pouivana jen jedina konstiukce piazeni jedn hodnoty
do vice piomnnch,
int a;
int b;
a = b = 10;
Diky asociativit je to zkiatka za viaz a (b c). Tj, nejdive se pi-
adi do piomnn b (podviaz v zavoikach). Vsledkem podviazu
je piazovan objekt, jen je nasledn piazen do piomnn a.
Nevhodn zapisy (nepehledn a navic nepouiteln mimo C-iodinu
jazyk)
a + (b = 3)
m.Replace(text=vstup)
Vmna obsahu dvou promnnch
Vmna (angl. swap) obsahu dvou piomnnch je asto vyuivan piogiamatoi-
sk obiat. l kdy se jedna o velmi jednoduchou opeiaci, jeji implementace neni
zcela tiivialni. Dvodem je skutenost, e pi piazeni zanika (iesp. se stava ne-
dostupnm) objekt odkazovan piomnnou na lev stian piazeni.
Z tohoto dvodu je nutno pouit pomocnou piomnou pio doasn uloeni i
odkazovani objektu a ti piazeni, kteia hodnoty piomnnch cyklicky zamni
(jedno z piazeni me bt iealizovano piostednictvim inicializace nov pio-
mnn). Vizualni znazoinni viz obiazek z. na nasledujici stian.
Piklad
double x = 0.0;
double y = 1.0;
/ / vmna x a y
Zakladni objektov model C= ,
double p = x; / / vytvoeni pomocn piomnn a jeji inicializace
x = y; / / pim pesun
y = p; / / ukonovaci pesun (z kopie v doasn piomnn)
0,0 1,0
x y
?
p
0,0 1,0
x y
0,0
p
1,0 1,0
x y
0,0
p
1,0 0,0
x y
0,0
p
1.krok
2.krok
3.krok
vsledek
Obiazek z.. Vmna obsahu dvou piomnnch
Petypovn pi piazen
Pi piazeni musi bt tida piazovanho objektu shodna se tidou pouitou pi
deklaiaci objektu. Tuto shodu testuje ji peklada a pi nedodieni ukonuje pe-
klad s pislunou chybou.
Pklad:
int i = 0;
i = "jedna";
Kontiola tohoto diuhu je pio jazyk C= typicka. S podobnou kontiolou jsme se se-
znamili ji u paiameti metod iesp. opeiaci a je piovadna i u inicializace. Vdy
je kontiolovano, zda je pouit objekt spiavn tidy tj. zda ma dana metoda/ope-
iace/inicializace k dispozici oekavan objekt .
Na diuhou stianu neni jazyk C= pi tto kontiole zcela stiiktni. Vjimkou jsou pi-
pady, kdy jsou objekty smanticky tak blizk, e je lze tiansfoimovat beze ztiaty
infoimace (tj, napiklad se zmni jen jejich datova iepiesentace).
o
U aiitmetickch binainich opeiatoi jsou timto zpsobem eeny situace, kdy
jsou opeiandy iznch iselnch tid (nap. jeden je int a diuh double). eenim
je pevedeni objektu tidy int na objekt tidy double. Je to zcela bezpen, nebo
mnoina vech objekt tidy double je nadmnoinou objekt tidy int, tj. kad
islo iepiesentovateln ve tid int lze iepiesentovat i ve tid double.
U piazeni funguje podobna tiansfoimace, kteia se oznauje jako petypovani
(angl. casting). Pokud piazujeme islo tidy int do piomnn uien pio objekty
typu double, je nam jazyk napomocen a automaticky pevede objekt jedn tidy
na diuh (tzv. implicitni petypovani). Piogiamse peloi bez chyby a ve funguje
jak oekavame. Petypovani pi piazeni je navic jet jednodui ne u binainich
opeiatoi, nebo je hned zejm z jakho typu na jak se bude petypovavat.
Piklad
double x ;
x = 3; / / nutn petypovani ze tidy int na double
l kdy je tento typ petypovani zcela piiozen a pochopiteln a nepinai adn
pioblmy se ztiatou infoimaci, neni zcela zadaimo. Nesnesitelna lehkost impli-
citniho petypovani me mit negativni vliv na efektivitu piogiamu. Zmna ie-
piesentace si toti vyada pomocn kod nebo alespo pouiti konveizni instiukce
na piocesoiu (v naem pipad se musi islo pevst z celoiseln iepiesentace na
iepiesentaci v pohybliv adov aice, piem se vyuije alespo jeden dodate-
n iegisti navic). lmplicitni petypovani pioto iadji pouivejte co nejmn (tj.
kdy u neni zbyti).
Co se vak stane pokud chceme piovst petypovani v opanm gaidu`
int x;
x = 3.0;
V tomto pipad ji neni automaticka konveize mona. Cilova tida (int) toti ne-
dokae iepiesentovat vechny objekty tid (zdiojov) a potencialn tak dochazi
ke ztiat infoimaci (i kdy v konkitnim pipad tomu tak bt nemusi viz na
piklad). Peklada je vak opatin a zachova se podle zakladniho piavidla tj. ne-
dovoli neshodu tid. V pipad opeiaci jsme na tento pioblm nenaiazily, nebo
u opeiaci objekt se vdy pevadi na vyi (iozsahleji) typ.
l kdy neni implicitni a tudi zcela bezpen petypovani mon, pesto se me
hodit. Za piv me bt konkitni objekt petypovateln beze ztiaty (v naem
pipad je objekt doubleI.c skuten pln iepiesentovateln i ve tid int). Za
Zakladni objektov model C= 1
diuh me sice dojit ke ztiat infoimace, ta vak neni plna a pedevim je pl-
n piedikovatelna (tj. piogiamatoi jednoznan vi, co se cestou ztiati a co bude
vsledkem).
Pedstavme si napiklad nasledujici (neplatn) piazeni
int x;
x = 3.5;
Bezeztiatova konveize je nemona, nebo objekt ma desetinnou ast a tu nelze
u isel tidy int iepiesentovat. Dilim eenim je vak uloeni alespo cel asti
( odseknuti desetinn asti a zmna iepiesentace). To se zda dostaten jednodu-
ch a piedikovateln (otazkou vak je, zda je to jedin piiozen a vemi oekavan
eeni). Navic vtina piocesoi to umi pimo v instiukni sad.
Z tohoto dvodu je mon vynutit si mn bezpen petypovani pomoci expli-
citniho poadavku
int x;
double y = 3.5;
x = (int) y;
Poadavek se zapisuje pomoci specialniho tzv. petypovacho opertoru. jen se
zapisuje tak, e se nazev cilov tidy napie do kulatch zavoiek a napie se ped
viaz, jeho vsledek chceme petypovat. Pokud je viaz sloitji, musi bt i on
v zavoikach
x (int) (y + 3.0);
Sloitji pipady
y = (double)((int)(y) + 3)
lxplicitni petypovani lze pouit i v pipad, kdy neni nutn (tj. stailo by pouit
implicitni petypovani)
int i;
double y;
y = (double)(2*i);
l explicitni petypovani neni bez nebezpei. Za piv jej nelze pouit mezi vemi
typy, ale jen mezi typy dostaten blizkmi u nich lze oekavat, e konveize je
jednoznana a iychla. Nelze tudi psat napiklad
:
int cislo = (int)"25";
ale je nutno pouit (jet explicitnji) zapis
int cislo = int.Parse("25");
Pio sloitji objekty (nap. nam ji znam tidy System.DateTime) neni explicitni
petypovani (povtinou) k dispozici.
Za diuh, i kdy explicitni petypovani existuje nemusi bt tak piedikovateln,
jak by se mohlo zdat
int x = 2e10;
lnicializani objekt je tidy double a je z matematickho hlediska celoiseln (z
1c
1c
). Tak velk islo se vak do objekt tidy int nevejde. Piogiam se peloi, ale
pi piovadni dojde k vjimen situaci a piogiam se pedasn ukoni (co neni
to co bychom ekali).
Na konci (jako shinuti) nkolik piavidel o petypovani
Pravidlo 9: Petypovn pouvejte jen pokud je to nutn (a samozejm mon).
Pravidlo 10: I v ppad, e je mon implicitn konverze, pouijte explicitn zpis
(petypovac opertor)
3. Konzolov programy
3.1. Zkladn struktura programu
Piogiamy v objektov oiientovanm jazyce by mly ieektovat zakladni OOP
model vzajemnou inteiakci objekt. Tento model odpovida iealit (nap. intei-
akce lidi v zamstnani), jeho pevod do piogiamovho modelu vak neni zcela
tiivialni. Dvod je hned nkolik
pln uplatnni modelu vyaduje paialelni zpiacovani (tj. inteiakce piobi-
haji zaiove mezi mnoha objekty).
Pln paialelismus vak vede k nedeteiministickm piogiamm, ve kteich
vznikaji tko odhaliteln chyby v dsledku patn synchionizaci. Objekto-
v piogiam tak musi bt umle seiializovan (v kadm okamiku je aktivni
jen jeden objekt)
iealn systmy maji velmi sloit poateni stavy tj. ji na zaatku pio-
giamu by mlo existovat velk mnostvi vzajemn piovazanch objekt.
Optimalni eenim by byl systm, kde by objekty existovali neustale (tj. od
pivniho sputni by piogiam nebyl de facto peiuen, maximaln by byl
odkladan na disk). Tento pistup ma nap. Smalltalk (stav jeho instalaci je
vsledkem bhu, je de facto zaal ped vice ne dvaceti lety) a v omeze-
n mie i aplikace pio nktei platfoimy jako je nap. Java EE. Ve vtin
piklad vak znamena kad nov sputni aplikace, vytvoeni novho ob-
jektovho systmu (vechny nebo alespo vtina objekt musi bt znovu
vytvoena). To pinai pioblm typu vejce nebo slepice, nebo bn plati,
e objekty jsou vytvaeny pouze jinmi objekty (nic jinho aktivniho v is-
t objektovm systmu neni!). Otazkou zstava jak se vytvoi pivni objekt.
Rzn piogiamovaci jazyky to ei iznm zpsobem.
navih zakladni aplikani stiuktuiy je ovlivnn vnjimi poadavky aplikaci
a kompatibilitou s ji existujicimi eenimi a jazyky (ktei asto nejsou pili
objektov).
I

Poadavky iznch typ aplikaci (nap. konzolovch, webovch nebo GUl)


na stiuktuiu piogiamu se podstatn lii, stejn tak i mechanismy zaveden
staiimi piogiamovacimi jazyky.
V jazyce C= ma piogiam navenek objektovou stiuktuiu (nap. kad piogiam
musi, denovat alespo jednu tidu), ale ve skutenosti se pouiva mechanismus
pouivan ji jazykem C staitovaci funkce/metoda (tj. na poatku neexistuje
adn objekt). Tento mechanismus je ielativn jednoduch a obecn. Bohuel je
pimo pouiteln pouze pio konzolov aplikace a tak vyaduje zapis zbytenho
(a stale se opakujiciho) kodu.
Zakladni ablona piogiamu piazdnho piogiamu je dnes vtinou geneiovana
vvojovm piostedim. Monodevelop napiklad pi vytvoeni nov sestavy vyge-
neiuje tento jednoduch piogiam (podobn i dali vvojova piostedi).
using System;
namespace Generator
{
class MainClass
{
public static void Main (string[] args)
{
Console.WriteLine ("HelloWorld!");
}
}
}
Tento piogiamvypisuje na konzoli text Hello World! (odkaz na klasick piogiam
Hello, woild jazyka C). Pokud jej chceme pouit jako zaklad nov konzolov
aplikace, musime vymazat adek vypisujici text. Navic je vhodn vymazat dekla-
iaci vlastniho jmennho piostoiu (u jednoduchch aplikaci je zbytena) a smazat
lze i paiameti funkce Main, ktei se bn nevyuiva.
using System;
class MainClass {
public static void Main() {
}
}
Konzolov piogiamy
Tida MainClass je zde pouita ist foimaln, nebo tato tida nepopisuje adn
skuten objekty. Navic me mit zcela libovoln identikatoi. Bn se pouivaji
i dali jmna jako Piogiam, nazev piojektu apod.
Tato tida obsahuje jedinou metodu, kteia se mus se jmenovat Main, musi bt
staticka (tj. patici tid nikoliv objektu) a veejna (specikace public). Dvodem
je skutenost, e je volana zavadem piogiamu, ktei podle identikatoiu Main
najde staitovaci metodu (me bt v libovoln tid), zavola ji dive ne existuje
libovoln objekt (tj. musi bt volana nad tidou nikoliv nad objektem), piem zo-
hleduje viditelnost metod (jen veejn metody mohou bt volany kodem leicim
mimo tidu).
Pokud tomu piozatim moc neiozumite, nevadi, stai si jen zapamatovat povinn
text (k detailnimu vysvtleni se dostaneme pozdji). Kliov slovo void oznauje
skutenost, e metoda neviaci adnou hodnotu (nema to ani pili smysl, nebo ji
nelze nikde v piogiamu pouit) a povinn kulat zavoiky ikaji, e metoda nepi-
jima adn paiametiy.
Dleit jsou jen sloen zavoiky (za hlavikou Main), ktei ohianiuji kod, ktei
se piovede po sputni aplikace. Zatim jsou piazdn, ale bizy je vyplnime.
Ne se vak dostaneme k tto iozhodujici fazi (mona je to Va pivni piogiam v
ivot), eknme se nco k foimatovani piogiamu tj. k pouiti mezei a a odad-
kovani a k zapisu using System; na zaatku piogiamu.
3.1.1. Formtovn programu
Mezeiy a odadkovani jsou v zasad nepovinn a piogiam je mono napsat na
jedinm adku bez zbytench mezei (nktei mezeiy vak musi zstat nebo
oddluji slova jazyka).
using System;class MainClass{public static void Main(){Console.WriteLine("HelloWorld!");}}
l tento piogiamse peloi a pio poita je to dokonce jet snazi (navic jsme uet-
ili jsme pai byt v textovm souboiu!). Pio lovka je to vak kiajn nepehledn
a to je tento piogiam extimn kiatk (skuten piogiamy obsahuji desetitisice
i dokonce statisice znak). Piav pioto jsou vude nadbyten mezeiy a zcela
zbytena odadkovani.
e
S foimatovanim Vam dnes viazn pomahaji editoiy vvojovch piostedi a pio-
to si stai zapamatovat nkolik piavidel (piavidla nejsou univeizalni, existuje n-
kolik iznch styl)'
jednotliv iovn vnoeni piogiamu (bloky) jsou odsazeny, piem odsa-
zeni je 1 znaky (lepi je nastavit editoi tak, aby se pio odsazeni pouivaly
mezeiy, ne tabulatoiy)
otviiaci zavoiky blok se pii na konci adk (viz adky zainajici slovy class
a public)
zaviiaci zavoiky se pii se stejnm odsazenim jako nadazen blok (tj. jsou
pioti vlastnimu bloku pedsazeny)
voln adky se pii jen na mezi tidami a metodami (a po poateni sekci s
pikazy using)
mezeiy se pii v mistech kde jsou poteba, kolem opeiatoi, za aikami
a ped sloenmi zavoikami na konci adk (nebo ty ji de facto pati k
nasledujicimu adku piogiamu)
3.1.2. Jmenn prostory
Pivnim pikazem naeho piazdnho souboiu je deklaiace using. Tento pikaz ne-
ni povinn, ale viazn usnaduje pouiti nkteich bnch tid. C= (a obecn
.NlT) toti pouiva systm tzv. jmenn prostor, aby se zabianilo mon kolizi
identikatoi. Dvodem je skutenost, e i kdy je identikatoi v zasad tm
neomezen mnostvi (je estiznakovch identikatoi tvoench ze pismeny la-
tinsk abecedy je ze
e
Icv milion), jen nktei z nich jsou iozumnmi anglick-
mi (i eskmi) slovy i souslovimi. Navic mnoha slova maji v anglitin mnoho
vznam a inteipietaci (v oblasti lT nap. Frame, Monitor, Color apod.). Pioto
nejsou jmna knihovnich tid jednoducha, ale sloena z tzv. jmennho piostoiu a
vlastniho jmna.
Nyni se poadavek na jedinenost identikatoiu tidy iozloi na dva jednodueji
dosaiteln poadavky. Je to poadavek na jedinenost vlastniho jmna v iamci
jmennho piostoiu (co zajisti oiganizace nebo piogiamatoi, ktei jmenn pio-
stoi zavedl) a jedinenost jmennho piostoiu.
'zde piesentovan styl je styl pouivan autoiem, vychazejici ze stylu piogiamovaciho jazyka Java.
Tento styl je pehledn a pitom nazaujima zbyten mnoho mista veitikaln ani hoiizontaln
(kliov pi piesentaci kodu na datapiojektoiu)
Konzolov piogiamy ,
Navic lze i jmenn piostoiy hieiaichizovat do posloupnosti vnoench jmennch
piostoi, v ni je nutno zajistit jedinenost jmna jen na pislun iovni. Je to
systm podobn znammu DNS systmu, v nm jsou adiesy tvoeny hieiaichic-
kou posloupnosti jmen (nap. ki.ujep.cz)
Pklady:
System.Drawing.Color (skutena tida standaidni knihovny)
Jmenn piostoi je System.Drawing a vlastni jmno tidy je Color. ldentikatoi
jmennho piostoiu je sam sloen. Vnji jmenn piostoi je oznaen jmnem
System. Toto identikatoi je vyhiazen pio jmenn piostoi standaidni knihovny
(tuto knihovnu a jmenn piostoi spiavuje jeji tvice ima Microso). Uvnit je
jmenn (pod)piostoi Drawing, ktei shinuje tidy souvisejici s zD kieslenim (po-
moci systmov knihovny GDl-). Jen v iamci tohoto podpiostoiu je nutn zajistit
jedinenost identikatoiu Color.
Grendel.Base.Color
Tida iepiesentujici baivu v m giack knihovn. Vnji jmenn piostoi se jme-
nuje podle knihovny (jednoznanost by zde mohla bt pioblmem, piotoe mohou
existovat i dali .NlT knihovny s timto jmnem, ale knihovna neni pouivana vn
nai katediy). Jmno vnitniho jmennho piostoiu leni tidy podle funkce (zde
jsou to kliov tidy uivan v iamci cel knihovny)
Cz.Hyperso.Network.Iris.Hp.Connector (vymylen jmno tidy)
Toto dlouh jmno tidy obsahuje ptiiovov jmenn piostoi. Pivni dv iov-
n jsou vzaty (z hypotetick) DNS adiesy, aby byla zajitna celosvtova jedine-
nost, dali identikuje typ piojektu (iesp. piojektov tm), dali pak (hypotetick)
piojekt a nasledn jeho podknihovnu.
Zjednoduena hieiaichie jmennho piostoiu System a jeho podpiostoi je zna-
zoinna na obiazku I.1 na nasledujici stian. Obiazek ukazuje jen ty tidy, ktei
jsou detailnji popsany v tchto skiiptech (a pislun jmenn piostoiy). Ve sku-
tenosti existuje ve jmennm piostoiu System a jeho podpiostoiech tisice tid (a
stovky podpiostoi, z nich nktei jsou a tyiovov).
Pouiti jmennch piostoi ma vak i negativni efekt. Jmna tid jsou pili dlouha
a v kodu piogiamu by zaujimala pili velk misto (tim spie, e text piogiamu
by neml bt iii ne sc-1cc znak).Pioto jazyk C= zavadi deklaiaci using, kteia
umouje impoitovat jmenn piostoiy. Po impoitu jmennho piostoiu lze jmna,
kteia obsahuje, pouivat bez piexu (tzv. hol identikatoi).
8
System
IO
Collections
Generic
Text
StringBuilder
FileStream
TextWriter
Console
Dictionary<string, double>
DateTime
List<string>
Int3 !int"
Double
Obiazek I.1. Jmenn piostoi System a jeho podpiostoiy
Pklad:
kompletni jmno tidy System.DateTime
po pouiti deklaiace using System lze psat jen DateTime
Pio pouiti deklaiace using si stai pamatovat dv zasady
1. impoitovat lze jen cel jmenn piostoi nikoliv dili ast hieiaichickho
jmna. Napiklad po impoitu using System nelze pouivat (asten zkiace-
n) identikatoi Drawing.Color. eenim je bu vyuivani pln kvalikova-
nho jmna (System.Drawing.Color) nebo impoit celho jmennho piostoiu
(using System.Drawing), a pouivani holho identikatoiu Color.
z. obecn lze impoitovat i jmenn piostoiy s potencialnimi kolizemi identi-
katoi (tj. obsahujici stejn hol jmno). U kolidujicich identikatoi je
nutno pouivat pln kvalikovan jmno (jinak se piogiam nepeloi). Ta-
to situace natsti nastava jen velmi zidka, nebo piogiamy vyuivaji jen
omezen mnostvi jmennch piostoi.
Poznmka:
Jmenn piostoiy v jazyce C= pimo nesouvisi s fyzickm iozdlenim
piogiamu tj. s umistnim kodu v jednotlivch zdiojovch souboiech
iesp. sestavach (assembly dili DLL knihovna nebo spustiteln sou-
boi). Tim se C= lii nap. od Javy i Pythonu.
Konzolov piogiamy ,
3.2. Prvn program
Bn konzolov piogiam se sklada ze ti zakladnich asti
1. vstup daj (dje se z konzole tj. piostednictvim klavesnice)
z. zpiacovani vstupnich daj
I. vstup vsledk
Pokud se tyto asti dji postupn (ve ve uvedenm poadi) iesp. lze je do tohoto
uspoadani pevst, jedna se o tzv. proudov program, ktei lze v zasad vyuit i
pio davkov (neinteiaktivni) zpiacovani (v Unixu beze zmny diky mechanismu
tzv. pesmiovani standaidniho vstupu a vstupu).
U nkteich konzolovch piogiam je vak zohlednna i zptna vazba (nap. a-
dost o nov zadani, pokud je zadani chybn). Tyto piogiamy lze oznait jako in-
teraktivn, i kdy jejich inteiaktivnost je vzhledem k souasnm GUl a WWW
aplikacim ponkud ielativni.
Pio zaatek pedpokladejme velmi jednoduch zadani piogiamu (aplikaci bych to
jet nenazval)
vstup: islo (pesnji textova iepiesentace celho isla)
vstup: infoimace zda je islo sud nebo lich, tj. text sud nebo lich.
3.2.1. Vstup
Jadiem eeni je objekt iepiesentujici zadan cel islo. Tento objekt bude mit
piiozen tidu int, co mimo jin znamena, e nebude mono zpiacovavat isla
vti ne z
Iz
1.
Tento objekt vak musime nejdive vytvoit. Hlavnim piostedkem pio vytvoeni
objektu-isla je uvedeni jeho liteialu v piogiamu. Tento pistup vak nememe
pouit, nebo islo v dob psani (a pedevimv dob pekladu) piogiamu nezname.
islo je toti zadano a za bhu piogiamu (na konzoli).
Pio ziskani isla (iesp. jakhokoliv objektu) z konzole ( textovho vstupu) se pou-
iva mechanismus znam ji z nejstaiich piogiamovacich jazyk peteni textu
a vytvoeni objektu string a nasledna tiansfoimace (paisovani) etzce na cilov
objekt.
eo
Pio peteni textu a uloeni objektu-etzce lze vyuit statickou (tidni) metodu
tidy System.Console se jmnem ReadLine.
Signatuia tto metody je
string ReadLine()
Tuto signatuiu metody mete nalzt v dokumentaci standaidni knihovny (nap.
MSDN na URL http://msdn.microsoft.com/en-us/library/system.console.read.aspx).
Navic v modeinich vvojovch piostedich se vypie pi najeti ukazatele myi na
jmno metody v piogiamu piostednictvim tzv. naeptavae (hint).
Ze signatuiy lze snadno zjistit, e metoda viaci nov objekt tidy etzec (identi-
katoi na zaatku signatuiy) a nepijima adn paiametiy (piazdn kulat zavoiky
za jmnem metody).
Tento objekt musime nasledn pevst na odpovidajici iseln objekt. Jak ji vime,
pio paisovani textu na islo je mono vyuit statick metody int.Parse (signatuia
int Parse(string text)).
ast (fiagment) piogiamu zajiujici peteni textu a vytvoeni objektu me mit
tvai (pedpokladame vyuiti deklaiace using System)
string text = Console.ReadLine();
int cislo = int.Parse(text);
liagment se sklada ze dvou deklaiaci piomnnch, v iamci nich jsou vytvoeny
dva objekty a dv piomnn, z nich jedna odkazuje na objekt tidy string (string
je iefeienni tida) a diuha obsahuje objekt tidy int (int je hodnotova tida).
Piotoe objekt tidy etzec ji nebudeme v dali asti piogiamu potebovat (stai
nam jen islo) lze zapis jet zestiunit
int cislo = int.Parse(Console.ReadLine());
Zde je objekt s petenm textem pedan pimo jako paiameti paisovaci meto-
dy. Na tento objekt nasledn neodkazuje adna piomnna a me bt uvolnn z
pamti (tj. po pouiti zahozen). Vimnte si, e text piogiamu je sice kiati, ale
mona o tiochu mn pehledn.
3.2.2. Zpracovn
Ve diuh fazi musime tiansfoimovat islo na logick objekt, ktei nabva hod-
noty true, je-li zadan islo sud a false je-li lich (co je pio nas podstatna in-
Konzolov piogiamy e1
foimace). Tato tiansfoimace je jadiem piogiamu, nebo zde nelze vyuit adn
pedpipiaven eeni a musime sami pijit na tzv. algoiitmus tj. souboi opeiaci,
ktei nam pevedou jeden objekt na jin.
Vimnte si, e se zatim nezabvame tim, jak vsledek vypsat. Algoiitmus zjitni
sudosti toti neni (iesp. by neml bt) zavisl na tom, zda je piogiam konzolov
oiientovan, i zda je uit na WWW stiankach nebo desktopov GUl aplikaci.
Je pioto vhodnji napsat algoiitmus v univeizalni podob, kteia tiansfoimuje
islo na logick objekt.
Vlastni algoiitmus neni natsti sloit. Z pedchozi pipiavy ji toti vime, e
jadiem je opeiace viacejici zbytek po dleni dvma. Pokud toti tato opeiace viati
nulu, je islo sud, v opanm pipad (zbytek 1) je lich. V tto fazi tedy ji
umime pevst zadan islo na jin islo z mnoiny c, 1. Cile vak jet nebylo
dosaeno, nebo vsledkem algoiitmu ml bt objekt tidy bool (ten toti jako
jedin dokae jednoznan iepiesentovat piavdivost i nepiavdivost).
Opertor rovnosti a nerovnosti
Natsti lze pouit dali kliov opeiatoi piogiamovacich jazyk, opeiatoi iov-
nosti (angl. equality). Tento binaini opeiatoi poiovnava dva objekty a jako vsle-
dek viaci objekt tidy bool. Obecn lze poiovnavat jen objekty stejn tidy. jedinou
vjimkou jsou objekty, ktei lze automaticky pevst na stejnou tidu (podobn
jako v pipad aiitmetickch opeiatoi).
Opeiatoi iovnosti ma v jazyce C= podobu dvojznaku sloenho ze dvou iovnitek
(). Tento zapis se bohuel lii od matematickho zu (kde se pouiva jen jedno
iovnitko). Znak iovnitko se toti v C= pouiva pio jin ely, pio piazeni do
piomnn a pio inicializaci pi deklaiaci. Bohuel oba zapisy se obas zamuji,
natsti vtinu zamn odhali ji peklada.
Piklady
spiavn zapisy
2 == 3 / / false (objekty se neiovnaji)
5 == 5 / / tiue (iovnost)
"Gandalf" == "Bljezdec" / / false (etzce se neshoduji)
10 == int.Parse("2" + "2") - 12 / / tiue
'a' == 'a' / / tiue
(new DateTime(2012, 12, 22)) == DateTime.Now
/ / doasn piavdiv jen tehdy, pokud nenastal konec svta
e:
DateTime.Now == DateTime.Today
/ / piavda jen o plnoci lokalniho asu
syntakticky spiavn, ale ne zcela koei zapisy jsou zapisy vyuivajici implicitni
petypovani
5 == 5.0 / / tiue
(objekt na lev stian poiovnani se pevede na spolen typ zde double)
'0' == 48 / / tiue
(znak se pevede na islo)
ybn zpisy:
5 = 3 //piazovat lze jen do piomnn nebo jinho tivalho pamovho mista
(zamna piazeni a iovnosti)
'a' == "a" //syntakticka chyba, objekty jsou iznch tid, ktei navic nelze impli-
citn petypovat
Jazyk C= podpoiuje kiom opeiatoiu iovnosti i opeiatoi neiovnosti se zapisem
!. lunguje obdobn jako opeiatoi iovnosti, viaci vak opan vsledek. Oba
opeiatoiy maji ielativn malou piioiitu (iozhodn meni ne aiitmetick opeia-
toiy, avak vti ne piazeni).
Piklad (uml)
(a == a) != true vdy false, nebo pio libovoln objekt odkazovan piomnnou
a plati, e se iovna sam sob, tj. vsledek poiovnani v zavoice je true. Nyni se
testuje zda je objekt true izn od objektu true, co samozejm neni piavda, tj.
celkov vsledek je false
=
Nyni se viame k naemu piogiamu. Pio testovani, zda je islo sud, stai poiovnat
vsledek zbytku po dleni dvma s hodnotou nule (islo je sud piav tehdy kdy
je zbytek po jeho dleni ioven nule, jinak eeno islo je dvma dliteln beze
zbytku). Nyni ji meme napsat dali adek naeho piogiamu
tato zcela logicka vaha, bohuel nemusi bt piavdiva, nebo pedpoklada, e kad objekt je ioven
sam sob. l kdy se to me zdat podivn, ne vdy je to piavda. Napiklad pokud ma piomnna
a hodnotu double.NaN (co je specialni hodnota tidy double vyjadujici tzv. neislo) pak plati, e
a!a (neislo neni iovn ani samo sob!)
Konzolov piogiamy e
bool jeSude = (cislo % 2 == 0);
Nejdive si vimnte identikatoiu piomnn. Nazev jasn a jednoznan vyja-
duje jeji vznam. Pokud je uloena hodnota piavdiva, pak je islo sud. Je to v-
iazn lepi jmno, ne napiklad vysledek (funkce je mona zejma, ale smantika
neni jednoznana, nebo neni jasn co znamena kladna hodnota), nebo dokonce b
nebo x (zde u nelze z nazvu odhalit nic).
Pozoinost si zasloui zavoiky kolem inicializaniho viazu. Ty jsou zbyten, ne-
bo znak neni souasti viazu (je souasti deklaiace) a piioiita zde tudi ad-
nou ioli nehiaje. Vdy plati, e nejdive se vyhodnoti viaz a a pot se zkopiiuje
jeho vsledek do nov vytvoen piomnn. Zavoiky vak viazn zpehleduji
zapis, v nm se vyskytuje a pili mnoho znak .
Poznmka:
Pioblematika testovani iovnosti a neiovnosti neni v C= (a obecn v
jakmkoliv piogiamovacich jazycich) zcela jednoducha. Pioblm je v
pesn denici, co znamena, e dva objekty se iovnaji. U i v iealnm
svt je nutno odliovat identitu objekt od shody jejich obsahu (i
jen tch asti podle, nich objekty identikujeme).
Zamyslete, se zda se iovnaji nasledujici objekty
1. dv jablka se stejnou hmotnosti
z. dva vlaky, z nich kad jede v izn den, ale zajiuji stejn spoj
I. dva vtisky stejn knihy
1. planeta Mais v iznch polohach na sv diaze
Na adnou z tchto otazek neexistuje jednoznana odpov, nebo
zalei na kontextu iesp. pioblmov domn. Pokud napiklad vy-
tvaime bibliogiack piogiam iesp. aplikace po vydavatele, pak je
identita knihy dana vydanim (tedy nap. lSBN kodem). Pokud pie-
me piogiam pio liteiaini vdce, je kniha dana obsahem tj. i knihy z
iznch vydani jsou povaovany za shodn pokud nedolo k (viaz-
njim) zmnam textu. Naopak u knihovnik i knihkupc me bt
iovnost denovana pomoci identity vtisk (vtisk je shodn pouze
sam se sebou).
V jazyce C= je pouit jednoduch zakladni piincip u objekt iefe-
iennich tid je iovnost implicitn dana identitou (tj. siovnavaji se
e
odkazy nikoliv vlastni objekty) u hodnotovch pak obsahem (sho-
dou byt, je iepiesentuji objekty). Uobjekt nkteich tid vak m-
e bt pouito jin (specitji) hledisko. Napiklad u etzc (Sys-
tem.String je iefeienni tida) neni iovnost dana identitou, ale obsa-
hem. Tento obsah se vak nepoiovnava na iovni byt, ale na iovni
shody jednotlivch znak (v Unicode mohou bt shodn i znaky s
iznm kodovanim).
V C= me bt nkdy pioblmem i vyuiti opeiatoiu iovnosti, nebo
nemusi dobe fungovat pi vyuiti tzv. objektovho polymoismu.
Vnkteich specickch pipadech (nap. v geneiickmkodu) je lepi
vyuivat metodu Equals (ma ji kad objekt).
Tj. namisto x == y je nkdy vhodnji psat x.Equals(y) (natsti ne tak
asto jako v Jav). Pokud je vak pivni typ iefeienni, pak tento zapis
nefunguje v pipad, e je hodnota levho opeiandu iovna null (nad
ne-objektem nelze volat metodu). Pokud me tato situace nastat je
hodnji pouivat tidni veizi metody, tj. psat object.Equals(x,y) (kde
object je jmno tidy, od ni jsou vechny ostatni tidy odvozeny).
3.2.3. Vstup
Konen se dostavame k posledni innosti vpisu vsledku na konzoli. Ten
je nezbytn, nebo jinak by piogiam nepiodukoval adn vstup iesp. obecnji
nezmnil by okolni svt (s vjimkou tm nemitelnho zveni teploty pioce-
soiu). Piogiamy se vak pii pioto, aby svt mnily (i kdy mnohdy ovlivni jen
jednoho lovka svho piogiamatoia).
Piogiam se nyni tiochu komplikuje, nebo neexistuje adna jednoducha metoda,
kteia by tiansfoimovala hodnotu true na etzec sud a hodnotu false na etzec
lich.
Konstrukce if
Natsti i jazyk C= obsahuje konstiukci, kteia umi bh piogiamu iozvtvit na
zaklad logick hodnoty konstiukci if. Tato konstiukce umouje piogiam ioz-
dlit do dvou sekci, z nich jedna se piovede jen v pipad, e je testovan logick
objekt piavdiv ( tiue), diuh jen v pipad, e je nepiavdiv.
Syntaxe (zapis) tto konstiukce neni sloita
Konzolov piogiamy e
if (logick-vraz) {
/ / sekce piovadna, ma-li logicky viaz hodnotu tiue
}
else {
/ / sekce piovadna, ma-li logicky viaz hodnotu false
}
Logick viaz na zaatku konstiukce se bn oznauje jako podminka, nebo
podmiuje dali pibh vykonavani piogiamu. Me to bt libovoln viaz jeho
vyhodnocenim se ziska jako vsledek objekt tidy bool. V naem pipad to bude
piomnna, v ni je logick viaz uloen, ale me to bt i sloitji viaz (nkdy
i pes nkolik adek piogiamu)
Ve uveden zapis konstiukce me bt v nkteich pipadech zkiacen. Pede-
vim me chybt sekce else (tj. kliov slovo else a blok za ni). Pokud chybi a
podminka je nepiavdiva tak v iamci konstiukce if nic nepiovede.
Diuh zkiaceni je ist foimalni. Pokud je v bloku tj. sloench zavoikach jen je-
den pikaz, tak lze zavoiky vynechat. Pikazemje nap. piazeni i volani metody,
kteia zmni okolni svt (nap. nco vypie), ale me to bt i sloita konstiukce
jako napiklad dali (vnoen) if. V tom zda zavoiky vynechavat i nikoliv, nepa-
nuje mezi piogiamatoiy shoda. Nktei je nevynechavaji nikdy. Vhodou je vyi
pehlednost a pedevim je to viazn bezpenji, nebo nehiozi, e zapomenete
zavoiky doplnit, pokud se do sekce pida dali pikaz pi opiav i vylepovani
piogiamu (piklad si uvedeme za chvili).
Na diuhou stianu ti pinai jeden adek navic, co piogiam tiochu piodluuje (a
tak se nemusi vejit kliova ast na monitoi i datapiojektoi). Pioto nktei piogia-
matoi vynechavaji blokov zavoiky v pipad, e je pikaz velmi jednoduch (tj.
vejde se na adek). Diky odsazeni (ktei se musi tak jako tak dsledn dodiovat)
je zejm, e pikaz je v podminn sekci (tj. ne vdy se piovede). Mezi tyto pio-
giamatoiy patim i ja, avak z didaktickch dvod tuto monost nebudu iadji
pouivat.
=
V naem piogiamu budeme v podmince testovat piomnnou jeSude, a v jednotli-
vch sekcich budeme vypisovat (nemnn) etzec na konzoli.
Pio vpis budeme pouivat statickou (tidni) metodu nam ji znam tidy Console
s nasledujici signatuiou
v piaxi to vak nikdy nebva liteial true nebo false. Vite pio`
ee
void WriteLine(string text)
Metoda se oznauje jako WriteLine, nebo vypie text na konzoli jako adek. Pes-
nji eeno vypie text a nasledn znak odadkovani (je to znak \n) tj. po textu je
odadkovano (a text tak nesplyne s nasledn vypisovanm textem). Ze signatuiy
dale vyplva, e metoda oekava jako paiameti objekt etzce a nic neviaci. Kli-
ov slovo void na zaatku signatuiy neni jmnem tidy, ale vyjaduje, e adn
objekt pi volani metody nevznikne. Jedinm (vn metody viditelnm) efektem
volani tak je pouze vpis textu na konzoli.
Nyni tedy meme dokonit na piogiam.
if(jeSude) {
Console.WriteLine("sud");
} else {
Console.WriteLine("lich")
}
Smantika konstiukce if zajisti, e se vykona pouze jeden pikaz s vpisem textu
(pikazem je zde volani metody zakonen stednikem). Navic je zejm, e o tom
jak text se vypie iozhoduje hodnota piomnn jeSud a tim i nepimo sudost i
lichost zadanho isla.
Na zavi si ukaeme vpis celho piogiamu. Vimnte si, e cel piogiamje umis-
tn v tle metody Main.
using System; / / sudalia.cs
class MainClass {
public static void Main() {
string text = Console.ReadLine(); / / vstup
/ / zpiacovani vstupu
int cislo = int.Parse (text);
bool jeSude = (cislo % 2 == 0);
/ / vstup (vpis)
if(jeSude) {
Console.WriteLine("sud");
}
else {
Console.WriteLine("lich");
}
}
}
Konzolov piogiamy e,
V piogiamu jsou pio vti pehlednost pouity tzv. poznamky. Ty nejsou vyui-
vany pi kompilaci piogiamu, ale sloui jako dodatena infoimace pio piogiama-
toiy. Poznamky nejsou samozejm povinn, ale jsou velmi uiten a to jak pio
vlastniho tvice piogiamu tak i pio dali leny piogiamatoiskho tmu (pokud
je piogiam vytvaen tmov).
Poznmka:
Pokud ji mate zkuenosti s piogiamovanim, tak se Vam me jevit
piogiam jako zbyten iozsahl. Hlavnim cilem vak bylo iozdlit
jej viditeln do ti sekci (z nich piostedni neni zavisla na inteiakci
piogiamu s okolim) a explicitn pojmenovat vechny objekty (kiom
vypisovanch etzcovch liteial). Tlo piogiamu lze ve skutenosti
napsat jako jedin nepili dlouh pikaz.
Console.WriteLine(
int.Parse(Console.ReadLine()) % 2 == 0 ? "sud" : "lich"
);
tento zapis je vak obtin iteln i pio pokioileji piogiamatoiy a
pio zaateniky je to intina. Navic je piogiam zcela nestiuktuiova-
n (adek ma po odsazeni ss znak). Hlavni nevhodou je vak pat-
na ioziitelnost tohoto piogiamu. Napiklad, nelze snadno zajistit
vypsani zadanho isla ve vstupu iespektive opakovan zadani pi
chybnm vstupu.
3.3. Druh program: Potn slov
Dalim o nco sloitjim kolem bude piogiam pio poitani slov v etzci. Pi
piogiamovani se seznamime nejen s novmi opeiatoiy a piogiamovmi kon-
stiukcemi, ale pedevim se nauime nauime piogiam iozdlovat do logickch
asti ve foim tzv. ioziujicich metod.
Zadani piogiamu
vstup: adek textu
vstup: poet slov v textu. Slova jsou tvoena pismeny a islicemi. Vechny ostatni
znaky (mezeiy, pomocn symboly) sloui jako oddlovae.
e8
3.3.1. Hlavn algoritmus
Piogiam pio poitani slov bude mit klasickou stiuktuiu pioudovch konzolovch
aplikaci vstup, zpiacovani a vstup. Vstup a vstup je vak zcela tiivialni. V za-
sad stai naist text do etzce a na konci vypsat jedin islo. Z tohoto dvodu
se nejdive soustedime na jadio piogiamu na zpiacovani etzce.
Na poatku pedpokladejme, e text je uloen v objektu odkazovanmpiomnnou
vstup (nezajima nas jak byl ziskan)
string vstup = ... / / ziskani textu
Naimpivnimkolemje nalzt algoiitmus ( detailni pedpis) zjitni potu slov v
etzci. Uiitou vhodou zde me bt skutenost, e poitani slov v textu zvladne
tm kad a to ji od zakladni koly
Podivejte se na nasledujici etzec, spoitejte slova a hlavn si zkuste uvdomit
jak jste to udlali`
Ti prsteny pro krle elf pod nebem.
Mon algoiitmy (postupy pi eeni)
stail Vam jedin pohled (kaidinalni pistup)
postupn jste zleva napoitali slova (oidinalni pistup)
spoitali jste mezeiy a pietli jste jedniku
l kdy jsou vechny tyto algoiitmy v zasad spiavn, nelze bohuel ani jeden z
nich pimo pouit pio poitaov piogiam. Pivni a diuh je zaloen na giack
podob latinkovho pisma, diky ni slova tvoi jasn oddliteln giack tvaiy
(obdlniky). To bohuel nelze vyuit v pipad poitaov iepiesentace etzce,
v ni je etzec posloupnost iselnch kod. Kaidinalni pistup (poitani jednim
pohledem) navic vyaduje globalni pohled na sloen objekt, co je u poita
obtin iealizovateln (i kdy nikoliv zcela nemon).
Teti algoiitmus je viazn lepi. Vyuiva jen lokalni pohled (jedin znak) a me
bt snadno iealizovan poitaem (mezeiy lze iozeznat na zaklad jejich znakov-
ho kodu). Bohuel neni jet zcela dokonal. Stai vyzkouet tiochu divoeji text
gf nhgKMj. .jh? ^Jm,Jfm,m (M mMG/15Mm)l,-,.5.6) jM
Zde nelze vyuit adn algoiitmus zaloen na detekci tvai a nepostauje ani
spoitani mezei (iesp. oddlovacich tj. nepismennch a neiselnch znak). Zkus-
te se chvili zamyslet a jist pijdete na lepi algoiitmus (pio kontiolu text obsahuje
11 slov).
Konzolov piogiamy e,
Nejjednodui algoiitmus vychazi ze ti mechanism
1. etzec je piochazen znak po znaku (nap. zleva dopiava) a u kadho zna-
ku je kontiolovano, zda je znak alfanumeiick ( pismeno nebo islice) i
nikoliv
z. pi piochazeni je dleit pibn vdt, zda se nachazime uvnit (pio-
zatim nedokonenho) slova nebo mimo slovo (v piozatim nedokonen
sekvenci oddlova). V pibhu piochazeni etzce se mezi tmito dvma
stavy pepina.
I. naiazime-li na zaatek slova (co pozname podle aktualniho znaku a stavu)
navime o jedniku aktualni poet slov (na zaatku etzce je poet ioven
nule)
Pedpokladejme nasledujici ptiznakov testovaci etzec (viz tak obiazek I.z)
AB.,C
Na poatku se nachazime ve stavu mimo slovo (adn slovo jet nezaalo) a poet
slov je ioven nule.
Nejdive zpiacujeme pivni znak (A). Piotoe jsme ve stavu mimo slovo a znak je
alfanumeiick, musi se jednat o zaatek slova. Pioto zvime poet slov o jedniku
(pocetSlov je tedy ioven 1) a pibn stav se zmni na uvnit slova (zaali jsme
ist slovo, ktei jet neni ukoneno).
A B . , C
Zatek
slova
mimo uvnit uvnit mimo
01 12
Zatek
slova
Zatek
slova
Konec
slova
stav
poetSlov
Obiazek I.z. Poitani slov (piklad)
Pistoupime ke diuhmu znaku (B). Tento znak je alfanumeiick (pismeno). My
se vak nachazime ve stavu uvnit slova a pioto nemusime nic dlat (stav se
nemni, stale jsme v nedokonenm slov, nov slovo nezaina).
Pi zpiacovani tetiho znaku (.) detekujeme dokoneni slova, nebo znak je odd-
lovaem (neni ani pismenem ani islici) a pibn stav je uvnit slova. Musime
,o
pioto zmnit stav na mimo slovo. Poet slov se nemni, nebo slova poitame
jen na jejich zaatku.
Dalim (tvitm) slovem je aika (,). To je sice oddlova, ale my se nachazi-
me ve stavu mimo slovo. Nic se pioto nemni (oddlova je jen v dali v ad
oddlova). Nemni se piiozen ani poet slov.
Posledni znak je pismenem. Piotoe jsme ve stavu mimo slovo je zejm, e
zaina dali v poadi ji diuh slovo. Zvime o jedniku poet slov a zmnime
stav na uvnit slova.
Tim je zpiacovani etzce dokoneno a my ji vime kolik obsahuje slov. Ve sku-
tenosti bychom mohli znat i dali infoimace (nap. kde zaina a kde koni kad
slovo). Tyto infoimace nas vak nezajimaji a pioto jsme je nikam neukladali.
Vimnte si, e algoiitmus dlouhodobji uchovava jen dva objekty (islo a stav
vyjaditeln logickou hodnotou) a etzec je piochazen jen jednou. To znamena,
e algoiitmus nevyaduje pili mnoho piostedk (iozhodn nedojde k vyei-
pani pamti) a skoni v iozumnm ase (pio etzce bnch dlek de facto bez
viditeln ieakni doby).
Pioto jej meme pijmout a zait pepisovat do piogiamovaciho jazyka C=.
Kliovm mechanismem je postupn piochazeni vech znak etzce. To lze v
jazyce C= implementovat nkolika zpsoby, nejjednodui je pouiti cyklu forea.
Cyklus foreach
Jako cyklus oznauje v piogiamovani konstiukci, kteia umouje piovadni ui-
itho kodu opakovan. Pokud ignoiujeme tiivialni a exotick piklady, pak mezi
typick iysy cykl pati
poet opakovani je omezen. Nekonen cykly tivaji nekonenou dobu, co
iozhodn neni hlavnim cilem piogiamatoi
mezi jednotlivmi opakovanimi (iteiacemi) cykl se musi mnit stav pio-
giamu tj. stavy objekt i obsazeni piomnnch (v opanm pipad by se
piacovalo se stale stejnmi a nemnnmi objekty). Jinak eeno, kod se sice
opakuje, ale pokad nad jinmi nebo zmnnmi objekty.
Nejjednoduim cyklem jazyka C= je forea, ktei umouje vykonavat shodn
kod postupn nad pivky jist (konen) posloupnosti pivk. Pikladem jsou nap.
jednotliv znaky etzce.
Konzolov piogiamy ,1
Zapis cyklu forea je snadn
foreach (jmno-trdy jmno-promenn in posloupnost) {
opakovane-provden-prkazy;
}
Ani smantika neni sloita. Cyklus je pioveden postupn pio kad pivek po-
sloupnosti, piem jednotliv pivky jsou pokad piazeny do piomnn se jm-
nemjmno-promnn (deklaiovana tida piomnn musi odpovidat skuten tid
pivk). Je-li tida pivk hodnotova, pak je pivek do piomnn zkopiiovan (pio-
mnna tak neobsahuje pimo pivek, ale pouze jeho kopii). U iefeiennich tid se
do piomnn zkopiiuje odkaz (tj. piomnna obsahuje odkaz na pvodni pivek).
V obou pipadech je vak mono uvnit cyklu vyuivat tuto piomnnou pio pi-
stup k jednotlivm pivkm a tak postupn zpiacovavat posloupnost (od pivniho
do posledniho pivku).
Piaktick piklad
foreach (char znak in "0123456789") {
Console.WriteLine( znak );
}
etzec vech desitkovch islic je postupn piochazen a do piomnn z je v ka-
dm opakovani zkopiiovan dali znak posloupnosti (zde etzce).Uvnit cyklu je
tento znak vypsan (kad znak na nov adek). Vsledkem je tedy vpis deseti
adk, z nich kad obsahuje jednu islici (a tyto islice iostou od nuly do v).
l kdy je cyklus forea vyuivan piimain pio opakovan piovadni kodu, me
nastat situace e tlo cyklu je piovedeno jen jednou (je-li posloupnost jednopiv-
kova nap. etzec A) nebo dokonce neni piovedeno vbec (u piazdn posloup-
nosti, nap. u piazdnho etzce ).
=
Se znalosti cyklu forea se ji meme pokusit o nastin postupnho poitani slov
v etzci
foreach (char znak in vstup) {
if(stav je 'mimo slovo' a zaroven je znak alfanumerick) {
/ / zaatek slova
zvys pocet slov;
zmen stav na 'uvnitr slova';
}
,:
if(stav je 'uvnitr slova' a zroven znak nen alfanumerick) {
/ / konec slova
zmen stav na 'mimo slova';
}
}
Poet slov bude uloen v piomnn tidy int (co je vice ne dostaten). Stav je
mono iepiesentovat objektem tidy bool, nebo existuji jen dva stavy. Mapovani
mezi stavem a logickou hodnotou je dan zvolenm nazvem piomnn uvnit-
Slova.
Mapovani lze vyjadit i tabulkou
stav promnn
uvnitSlova
uvnit slova tiue
mimo slovo false
int pocetSlov = 0;
bool uvnitrSlova = false;
Tyto denice budou umistny jet ped cyklem, nebo ob piomnn existuji
bhem vech jeho iteiaci (jinak by vznikaly a zanikaly v kad iteiaci cyklu).
Uvnit cyklu jsou testovany dv podminky. Ob jsou tzv. sloen tj. obsahuji vice
elementainich test spojench logickou spojkou a zaiove. Jazyk C= podpoiuje
vechny zakladni logick opeiatoiy (a ostatni lze snadno opsat).
Logick opertory
Vjazyce C= lze nalzt vechny bn logick opeiatoiy ~Nb (a zaiove), ov (nebo)
a No1 (negace).
Logick opeiatoiy jsou aplikovateln pouze na boolovsk objekty a lze je tudi
snadno popsat pomoci piavdivostnich tabulek. l kdy pedpokladam, e je znate,
uvedu pio jistotu mal opakovani
AND false tiue
false false false
tiue false true
Konzolov piogiamy ,
OR false tiue
false false tiue
tiue tiue tiue
NOT
false tiue
tiue false
V C= se logick opeiatoiy zapisuji pomoci specialnich symbol (pevzatch z ja-
zyka C).
Detailni pehled logickch opeiatoi pinai nasledujici tabulka
opertor vznam priorita asocia-
tiv.
&& AND 11
OR 1z
! NOT z
Binaini ielani opeiatoiy maji velmi nizkou piioiitu a tak se jejich opeiandy
( elementaini podminky) bn nezavoikuji. Opeiatoi ~Nb ma stejn jako v ma-
tematice a technickch vdach ponkud vyi piioiitu (tj. aplikuje se dive ne
ov).
Unaini opeiatoi No1 ma stejn jako vechny unaini opeiatoiy vysokou piioiitu
(tj. velmi tsn se vae na svj opeiand). Pokud je opeiand sloitji musi bt v
zavoice. Asociativita je zpiava doleva, ale v piaxi se tm neuplatuje, nebo
neexistuje adn dali unaini opeiatoi poadujici i viacejici logickou hodnotu.
=
Zaneme s pepisem pivni podminky (stav je mimo slovo a zaiove je znak al-
fanumeiick)
!uvnitrSlova && char.IsLetterOrDigit (znak)
Pivni zakladni podminka je negaci boolovskho objektu uloenho v piomnn
uvnitrSlova. Tento viaz je piavdiv, jen tehdy, pokud je v piomnn uloen objekt
,
false tj. pibn stav je mimo slova. Ve diuh je vyuita staticka metoda tidy
ar se signatuiou
bool IsLetterOrDigit(char c)
Tato metoda pijima libovoln znak a viaci zda je klasikovan jako pismeno i
islice. To neni v Unicode elementaini opeiace, nebo podpoiovana jsou i nelatin-
kova pismena (vetn inskch znak) a neaiabsk islice. Ve skutenosti se musi
tato infoimace vyhledat v iozsahl databazi.
Poznmka Tida ar poskytuje i dali klasikani metody nap. IsLeer, IsDigit,
IsSpace apod.
Diuha podminka je obdobna (jen negace se pesune k diuh dili podmince).
Ped zapsanim vslednho kodu se podivame jet na kod pio zveni potu slov.
Zakladni zapis neni sloit, stai vzit objekt uloen v piomnn pocetSlov, piist
k nmu jedniku a vsledek uloit do stejn piomnn (a tim pepsat jeji pvodni
hodnotu)
pocetSlov = pocetSlov + 1;
Tento zapis je tak ast, e existuje i syntakticka zkiatka
pocetSlov += 1;
Tento zapis lze vyuit i pio jin aiitmetick binaini opeiatoiy a hodnoty, nap.
x *= 2 / / zkiatka za x x * z (x je iselna piomnna)
uhel %= 360 / / zkiatka za uhel uhel jmeno - ed, // misto jmeno jmeno - ed
Navic pio sitani a odeitani jedniky, existuje jet vti zkiaceni, opeiatoiy in-
kiementace a dekiementace (klasick opeiatoiy jazyka C)
pocetSlov++ / / zkiatka za pocetSlov pocetSlov - 1
Opeiatoi inkiementace je obdobn
x-- / / snieni hodnoty piomnn x o jedniku
Poznmka:
Opeiatoiy inkiementace a dekiementace jsou skutenmi opeiatoiy
a lze je vyuivat i uvnit sloitjich viaz. Bohuel to vede k nejed-
noznanostnem, ktei jsou jen asten eeny iozdlenim opeiato-
i do dvou veizi pieinkiementani (zapis --x, piomnna je nejdive
Konzolov piogiamy ,
inkiementovana a tak je ve viazu pouita zvena hodnota), a post-
inkiementani (zapis x--, ve viazu je pouita pvodni hodnota a a
pak je piomnna zvena). V zakladnim kuisu nebudeme inkiemen-
tace a dekiementace uvnit viaz pouivat.
Nyni ji meme napsat nalni podobu cyklu
int pocetSlov = 0;
bool uvnitrSlova = false;
foreach (char znak in vstup) {
if (!uvnitrSlova && char.IsLetterOrDigit(znak)) {
pocetSlov++;
uvnitrSlova = true;
}
if (uvnitrSlova && !char.IsLetterOrDigit(znak)) {
uvnitrSlova = false;
}
}
Piogiam je v zasad hotov, stai doplnit nateni etzce do piomnn s (ped cyk-
lem) a vpis piomnn pocetSlov (za cyklem). To ve se umisti do metody Main
tidy MainClass.
My vak pjdeme jet dale. Stai si uvdomit, e zjitni potu slov je docela
uitena funkce, kteiou lze uplatnit v mnoha piogiamech. Je bn vyuivana v
textovch editoiech nap. v iamci statistiky dokumentu. Bylo by pioto vhodn
napsat algoiitmus tak, aby byl snadno pouiteln i v dalich piogiamech.
Roziujc metody
Jednim a mona nejlepim eenim je vytvoeni tzv. ioziujici metody. Pomoci
ioziujicich metod lze pidavat metody k ji existujicim tidam a to bez zasahu
do tid (co vtinou neni ani mon, nebo bn nemame k dispozici jejich kody).
V naem pipad budeme pidavat metodu ke tid string.
Po implementaci iozien metody bude vyuiti poitaky slov snadn. Stai za-
volat nov vytvoenou metodu nad jakmkoliv etzcem.
Piklad jak nam to bude ji za chvili fungovat
int p = textDokumentu.PocetSlov();
,e
nebo
Console.WriteLine( "testovactext".PocetSlov());
Obdobu ioziujicich metod lze nalzt i v objektech iealnho svta (iesp. jejich
modelech)
1. lovk jako objekt poskytuje metody pio vidni, zpiacovani obiazu, ioz-
poznavani tvai, schopnosti ueni. Na zaklad tchto vestavnch metod,
lze vytvoit ioziujici metodu pio teni textu (a to bez zasahu do haidwaiu
lovka)
z. Opeiani systm Unix je vybaven shellem a zakladnimi pikazy pio zpia-
covani text (cat, cut, giep) a mechanismem ioui (kolon). Shell vetn na-
stioj tvoi iozhiani systm. Systm vak lze ioziit vytvoenim skiiptu
(za pomoci shellovskch nastioj) a to beze zmny opeianiho systmu.
Pi denici ioziujici metody je nutno zadat ielativn velk mnostvi daj na-
zev metody, nazev tidy, kteiou ioziujeme a pipadn paiametiy metody. C=
bohuel vyaduje i zadani pili mnoha kliovch slov a symbol, kteia jsou do
znan miiy zbytena, jsou vak vyadovany z dvod konzistence jazyka a zpt-
n kompatibility.
Jako piklad uveme minimalni denici pio ioziujici metodu JePracovn
static class StringExtensions {
public static int PocetSlov(this string s) {
/ / zde bude kod pio spoitani slov
}
}
Roziujici metody musi bt denovany ve zvlatni tid (odlin od ioziovan
tidy). Jmno tto tidy nehiaje adnou ioli tj. me bt zcela libovoln. Pioto-
e nae pomocna tida obsahuje metodu ioziujici tidu string, zvolil jsem nazev
StringExtensions (anglick mnon islo je pouito, nebo v pomocn tid me
bt umistn i vti poet ioziujicich metod). Povinn vak je kliov slovo sta-
tic ped hlavikou tidy (zde v nov funkci, uiuje, e tida obsahuje jen statick
metody)!
Roziujici metoda musi bt denovana jako veejna (public) a staticka (neni toti
metodou objekt-instanci tidy StringExtensions). Tato ast denice ioziujici
metody se nikdy nemni.
Konzolov piogiamy ,,
Po slov static vak nasleduje vlastni hlavika iesp. signatuia metody, kteia nejdi-
ve uiuje tidu objektu, ktei metoda vytvoi (a viati pio dali zpiacovani) zde je
to bool. Pot nasleduje jmno metody (PocetSlov). V zavoikach je obsaen seznam
paiameti metody, tj. specikace objekt s nimi metoda piacuje. Vdy zde musi
bt uveden adiesat metody (tj. objekt na nj bude metoda volana). Adiesat musi
bt uveden jako pivni a musi bt uvozen kliovm slovem this. Dale nasleduje
tida adiesata (zde je to string) a nazev piomnn, do ktei se vloi kopie adiesata
(u hodnotovch tid) nebo odkaz na nj (u iefeiennich). Tato piomnna existuje
jen po dobu tivani metody a me mit libovoln jmno.
lunkci ioziujici metody si objasnime, tim e pesn popieme co se bude dit pi
jejim volani
string text = ....;
....
text.PocetSlov() / / volani metody nad objektem tidy stiing
Ji pi pekladu kodu se zjisti, e ve tid string neni uvedena adna metoda Pocet-
Slov (knihovni tidy iozhodn nemaji adn esky pojmenovan metody). Pioto
se piohledaji vechny statick tidy a jejich statick metody, a hleda se metoda se
jmnem PocetSlov, jeji pivni paiameti je uvozen slovem this a ma deklaiovanu
tidu string. V naem pipad se nalezne nami denovana metoda a jeji volani se
vloi do vslednho stiojovho kodu.
Pi bhu piogiamu se tak na mist volani metody peda izeni ioziujici metod.
Navic se adiesat metody (objekt ped tekou ve volani metody) piadi do no-
v vytvoen piomnn se jmnem s (tzv. foimalni paiameti metody). Piotoe je
string iefeienni tida, dojde pouze k pekopiiovani odkazu. Piomnna existuje
jen uvnit metody. To vak bohat stai, nebo v iamci metody piovedeme ve-
keiou poadovanou innost (zde to bude spoitani slov) a vypoten objekt (zde
tidy int) viatime jako vsledek metody.
Pkaz return
Pio ukoneni metody a viaceni vslednho objektu se pouiva pikaz return. Syn-
taxe pikazu je velmi jednoducha
return vraz;
Smantika neni o mnoho sloitji. Viaz tvoici aigument pikazu je vyhodnocen
a vsledn objekt je pedan volajici funkci jako vsledek volani. Tida objektu se
,8
musi shodovat s naviatovou tidou specikovanou v signatue metody (pesnji
stai aby byl na naviatovou tidu implicitn petypovateln).
=
V naem pipad jsme zvolili signatuiu int PocetSlov(this string s), tj. return
musi viatit objekt tidy int.
Piotoe jsme poet slov v naem fiagmentu kodu ukladali do piomnn pocetSlov,
je viaceni vsledn hodnoty jednoduch
return pocetSlov;
Po implementaci ioziujici metody je vlastni kod aplikace v metod Main omezen
na dva adky. Nateni etzce a vpis viacenho isla. Pio jistotu si vypieme cel
piogiam i s ioziujici metodou a foimalnimi astmi.
using System; / / pocetslov.c
static class StringExtensions {
public static int PocetSlov(this string vstup) {
bool uvnitrSlova = false;
int pocetSlov = 0;
foreach (char znak in vstup) {
if (!uvnitrSlova && char.IsLetterOrDigit(znak)) {
pocetSlov++;
uvnitrSlova = true;
}
if (uvnitrSlova && !char.IsLetterOrDigit(znak)) {
uvnitrSlova = false;
}
}
return pocetSlov;
}
}
class MainClass {
public static void Main(string[] args) {
string text = Console.ReadLine();
Console.WriteLine(text.PocetSlov());
}
}
Konzolov piogiamy ,,
3.4. Tet program: poet pracovnch dn v roce
Na teti piogiam bude o nco uitenji. Na iozdil od oveni sudosti isla i
poitani slov, ktei zvladne kad absolvent zakladni koly, je zjitni potu pia-
covnich dni v uiitm ioce ielativn sloitou opeiaci, kteiou nelze zvladnout bez
poitae i alespo vtisku kalendae. Dvodem je sloitost naeho (ehoskho)
kalendae, v nm se piolinaji dva nesoudln cykly ioni (Ie dn) a tdenni
( dn). Roni cyklus je navic zkomplikovan existenci pestupnch iok, je jsou
vazany na dali ti (natsti ji soudln) cykly 1, 1cc a 1cc let. Msini kalen-
da s cykly 1v, Icc a zcc let uiujici velikonoce meme natsti zanedbat, nebo
i kdy velikononi pondli nema pevn datum (me to bt libovoln den mezi
zI.I a ze.1), je natsti vdy v pondli a navic v obdobi od zI.I a ze.1 neni adn
svatek kiom velikonoc.
Ne pejdeme k iozboiu piogiamu musime uvst jeho pesn zadani. Pesn za-
dani je kliov, nebo jen tak lze na zavi ovit, zda je piogiam skuten funkni
(v iealnch aplikacich je vak bohuel tk pesn denovat zadani a odliit tak
bug (evidentn chybn chovani) od featuie (poadovan i chtn iys aplika-
ce).
vstup: islo ioku (v iozsahu zcc1-zczv). Ostatni ioky nebude nutno kontiolovat.
Ped iokemzcc1 nktei statni svatky neexistovaly, jejich existence ve vzdalenji
budoucnosti je nejista. Rok zczv byl zvolen, nebo plati zczv zcc1 - zs, kde zs
let je cyklus, v nm se opakuji ioky se stejnm vzoiem tdn (viz http://en.
wikipedia.org/wiki/Solar_cycle_%28calendar%29).
vstup: poet piacovnich dni v danm giegoiianskm ioce (piacovni den libo-
voln den mimo sobotu, nedli a statni svatek), jin oznaeni fond pracovn doby
(pouivano pedevim v pipad, e je vyjaden v hodinach).
3.4.1. Vstup
Vstup je v pipad naeho piogiamu jednoduch. Vstupuje jen jedno islo (iok),
ktei uchovame v jedin piomnn
int rok = int.Parse(Console.ReadLine());
Meme vak navic ovit zda je pislun iok podpoiovan, i nikoliv. Jak plyne
ze zadani, podpoiovany by mly bt pouze ioky v inteivalu [zcc1, zccv].
Zakladni konstiukce testu je zejma
8o
if (rok-nen-podporovn) {
neocekavana-situace;
}
Rok neni podpoiovan pokud je meni ne zcc1 nebo vti ne zccv (matematick
zapis < zcc1 > zczv, kde je iok). Tuto podminku lze do jazyka C= pepsat
pomoci dvou typ opeiatoi ielanich a logickch.
Relan opertory
Relani opeiatoiy lze pouivat mezi objekty pio n existuje uspoadani (tj. nap.
ielace men ne). Zcela piiozen je uspoadani mezi iselnmi objekty (skuten
i v C= plati, e 1 z). U boolovskch objekt plati e true ~ false (piojev optimismu
piogiamatoi). U znak je uspoadani dano jejich kodem ve znakov sad Unico-
de (je iozumn denovano nap. mezi znaky islic, nebo i zde plati 1 z, u a
zakladnich latinkovch znak pak a b, A B, ale pozoi Z a a ~ z).
Nejsloitji uspoadani je denovano mezi etzci. Je oznaovano jako lexikogia-
ck tj. slovnikov. etzce se adi postupn podle jednotlivch znak. Nejdive
jsou poiovnany pivni znaky, je-li jeden z nich meni ( jeho kod je meni) pak
je meni i etzec. Jsou-li pivni znaky stejn, pak se poiovnavaji diuh, a tak da-
le. To jest koka pes nebo k p, koka ~ koza nebo ~ k (esk
znaky jsou ve znakov sad Unicode zaazeny a za bnmi latinkovmi). Toto
uspoadani neni bohuel pili piaktick pio etinu, nebo neodpovida eskmu
standaidu (kiom pioblm s diakiitikou, neumi spiavn adit digiaf ch, apod.)
Pio anglitinu je vak pouiteln, pokud etzec obsahuje jen velka i jen mala
pismena (tj. pozoi na pipady typu Adams ~ tovel).
Relani opeiatoiy si shineme v tabulce
opeiatoi vznam piioiita asociativita
meni e
meni nebo iovno e
~ vti e
~ vti nebo iovno e
Piioiita ielanich opeiatoi je meni ne u aiitmetickch, tj. zavoiky se kolem
poiovnavanch opeiand se ve vtin pipad nepii (a nedopoiuuji je ani psat).
Konzolov piogiamy 81
Piklad
2 * a > 3 + b
=
Viame se k naemu pioblmu testovani vstupni hodnoty. Zapis podminky <
zcc1 > zczv je v jazyce C= je pimoai (pouiji se nam ji znam logick
opeiatoiy)
rok < 2001 || rok > 2029
Pio plnost je teba uvst, e tut podminku lze vyjadit i za pomoci jinch lo-
gickch opeiatoi. Napiklad ji lze vyjadit jako negaci podminky, e iok lei v
danm iozmezi tj. ( zcc1 zczv), co lze v C= zapsat jako
!(rok >= 2001 && rok <=2029)
Tento tvai je deli a v piaxi se pili neuplatni. Pio piogiamatoia je vak nezbytn
znat nktei zakladni ekvivalence mezi logickmi viazy, a ji z dvod zkiaceni
zapis (nap. nai ekvivalenci lze pouit i v opanm smiu), tak jejich snadnji
kontioly (jednotliv vaiianty lze ziskat nezavislmi vahami, viz na piklad).
Nejuitenji ekvivalence (tautologie)

.
(dvojita negace)
( )
.
(De Moiganv zakon)
( )
.
(De Moiganv zakon)
Poznmka:
V jazyce C= jsou vechny ielani opeiatoiy jen syntaktickou zkiat-
kou za volani metody CompareTo. Tu maji vechny tidy, u nich je
poiovnani denovano (foimaln musi implementovat iozhiani ICom-
parable).
Tato metoda viaci nulu, pokud neni adiesat metody ani vti ani men-
i (tj. je z hlediska poiovnavani ekvivalentni shodn z hlediska iov-
nostii). Je-li adiesat vti ne paiameti metody, pak metoda viaci
kladn (nenulov) islo. V opanm pipad (paiameti je vti ne
v nkteich specialnich pipadech vak mohou bt dva objekty ekvivalentni z hlediska poiovnani,
pesto vak nemusi bt shodn z hlediska iovnosti. Tato situace neni natsti pili asta.
8:
adiesat) je samozejm viaceno islo zapoin (tomuto stylu poiov-
navani se bn ika trojcestn porovnn ).
if(x.CompareTo(y) > 0 && t.CompareTo(x) <= 0)
je ekvivalentni podmince
if(x > y && t <= x)
Metoda CompareTo se pimo vyuiva jen zidka (ale napiklad v ge-
neiickm kodu je nezbytnosti)
Vjimen situace
Podminku ji mame a nyni musime piodiskutovat ieakci na chybn vstup. Nej-
jednoduim eenim je pedasn ukoneni piogiamu. Tento pistup znate i z
ivota zadali mi patn daje (patn pikazy, koly), nebudu iadji nic dlat.
Tato ieakce je v mnoha pipadech dostatena, mla by vak zahinovat pedani
infoimace o dvodech pedasnho ukoneni, tj. v naem pipad stiun text
popisujici dvod ukoneni iesp. i iadu jak data zadat spiavn.
Samozejm lze uvaovat i dali sloitji eeni nap. adost o nov zadani, pouiti
implicitni hodnoty apod.
Tim vim se vak piogiam me viazn zkomplikovat. Je to tim hoii, e do-
daten kod ei situaci, kteia je spie vjimenou (uivatel v zajmu piaktick
vyuitelnosti piogiamu budou zadavat pedevim platn vstupy). Navic, pokud
chceme na kod pouit v iznch aplikacich, mohou se poadavky na eeni liit
(nap. u WWW aplikace neni pedasn ukoneni iozumnm eenim).
Nejjednodui a zaiove nejlepi ieakci na vznik vjimen situace, je tzv. akti-
vace (hovoiov vyhozeni!) vjimky (angl. exception). Aktivace vjimky situaci
ve skutenosti neei. V zasad jen oznamuje, e vznikla vjimena situace, s ni
si nevime iady a doplnime tuto infoimaci o kiatk infoimani text. Piogiam je
doasn pozastaven a je hledan specialni kod, ktei na vjimku ieaguje a me
vjimenou situaci vyeit (tento kod me bt ve velmi vzdalen asti piogiamu
i dokonce v jin knihovn). Pokud neni nalezen, je piogiam ukonen s vypsanim
infoimaniho textu, co je, jak ji vime, tak eeni.
Pio aktivaci vjimky budeme pouivat nasledujici kod
throw new Exception("informativntext");
Konzolov piogiamy 8
Zatim nemusime pesn iozumt smantice tohoto viazu (vimnte si vak ale-
spo, e jadiem je vznik novho objektu tidy System.Exception). Stai znate jen
vsledek, ukoneni piogiamu a (nepovinn) vypsani infoimaniho textu.
Mechanismus vjimek je bn vyuivan i ve standaidni knihovn. Vjimka je
aktivovana pi paisovani nevalidniho etzce (nap. pokud v nm neni uloeno
islo), pouiti chybnho indexu, nepipustnm petypovani, volani metody nad
null hodnotou, apod. (uvedeny jsou piklady, na n jste ji mona naiazili)
=
Nyni ji mame ve pipiaveno pio implementaci cel vstupni asti piogiamu
int rok = int.Parse(Console.ReadLine());
if (rok < 2001 || rok > 2029) {
throw new Exception("Rokmimopodporovanmeze(2001-2029)");
}
3.4.2. Zpracovn dat
Pi eeni algoiitmickch pioblm je obas mono vychazet z bnch postu-
p, ktei by pio eeni zvolil bn lovk (tj, neinfoimatik, nematematik). Ten
by (doufam) vzal kalenda pislunho ioku, zaal by ho postupn piochazet od
1. ledna. Do kolonky pivniho piacovniho dne by napsal islo 1, do diuhho z a tak
dale a do konce ioku. Jen by si musel dat pozoi, aby peskoil vechny vikendy a
pedevimsvatky (co je ielativn snadn v pipad, e voln dny jsou v kalendai
jasn oznaeny). Po skoneni by posledni zapsan islo (v poslednim piacovnim
dnu) mlo vyjadovat poet piacovnich dni.
Nyni stai algoiitmus pefoimulovat do objektov pioceduialni podoby. Zakla-
dem je objekt tidy System.DateTime iepiesentujici konkitni kalendani datum.
Objekty tidy System.DateTime sice iepiesentuji asov okamik (kdekoliv v iam-
ci dne), ale mohou iepiesentovat i kalendani dny (nap. tim, e zlomky dne budou
nulov tj. den je iepiesentovan okamikem plnoci, ji zaina).
Vhodou tto iepiesentace je skutenost, e objekt DateTime obsahuje i zaklad-
ni kalendani vlastnosti a metody. Nejdleitji vlastnosti je DayOWeek, jen
umouje zjistit den v tdnu (tj. odliit soboty a nedle). Nejdleitji metodou
je metoda void AddDays(int n), kteia viaci nov datum o dn pozdji. Tida
System.DateTime bohuel nepodpoiuje statni svatky. Hlavnim dvodem je jejich
piostoiova a asova omezenost (statni svatky plati je v jedn zemi a pedevim i v
8
tto zemi se obas mni). Pioto budeme muset navihnout dali algoiitmus, ktei
umoni otestovat zda je pislun den svatkemi nikoliv (tento algoiitmus se hodi
i v jinch piogiamech) a napiogiamovat ji tak, aby se snadno pouivala.
Objekt tidy System.DateTime iepiesentujici 1. leden poadovanho ioku lze zis-
kat pomoci (tipaiametiickho konstiuktoiu), tento objekt nasledn uloime do
piomnn den (System.DateTime je hodnotova tida).
DateTime den = new DateTime(rok, 1, 1);
V konstiuktoiu jsou pouity dva objekty tidy int zadan liteialem (jsou vdy
iovny jedn), posledni je ji uloen ve vstupni piomnn rok.
Dale si pipiavime diuhou piomnnou, kteia bude uchovavat postupn iostouci
poet piacovnich. Tato piomnna bude tidy int a nazveme ji poetPracovnDn.
Na zaatku je tato piomnna iovna nule (podle piavidla vak pouijeme explicitni
inicializaci)
int pocetPracovnchDnu = 0;
Piomnn pio ukladani objekt ji mame pipiaveny, take meme nastinit cen-
tialni ast piogiamu (vlastnost JePracovni jet neni implementovana, ale ped-
pokladame, e bizy bude)
if( den.JePracovni ) {
pocetPracovnichDnu = pocetPracovnichDnu + 1; / / zvime ita potu piac. dn
}
den = den.AddDays(1); / / pesuneme s na dali den v ioce (z.1)
if( den.JePracovni ) {
pocetPracovnichDnu = pocetPracovnichDnu + 1; / / zvime ita potu piac. dn
}
den = den.AddDays(1); / / pesuneme s na dali den v ioce (I.1)
/ / a podobn pio dalich IeI dn (Ie1 v pestupnm ioce)
Stiuktuia piogiamu je spiavna, piogiam by vak byl zbyten dlouh (1*Ie a-
dek). Samozejm je mon pouit oblibenou kombinaci Ctil-C, Ctil-V, ale i to je
dost obtin. Navic plati dali (a zasadni) piogiamatoisk piavidlo
Pravidlo 11 Programtor nepouv klvesy Ctrl+C a Ctrl+V a to ani na vlastn
kd.
Pio by nemli piogiamatoi pouivat tak uiten funkce textovch editoi (vet-
n nejlepich vvojovch piostedi). Dvodem je konzistence kodu. Pedstavte si,
Konzolov piogiamy 8
e iozkopiiujete ast kodu na nkolik dalich mist. Pak v pvodnim textu najdete
chybu i ho miin ioziite. To vak bohuel znamena, e stejnou zmnu musite
aplikovat ve vech kopiich a to konzistentn. l zde sice mete pouit kopiiovani
a vloeni, ale je to sloitji a nachyln k chybam (asto napiklad zapomenete
opiavit jednu i vice kopii).
Natsti ve vtin pipad existuje mnohem jednodui eeni ne iozkopiiovani
i iuni opakovani. V naem pipad je to pouiti cyklu. Zname ji cyklus forea,
ale v tomto pipad je vhodnji vyuit nejobecnji cyklus while.
Cyklus while
Cyklus while naleznete tm ve vech pioceduialnich jazycich, piem jeho syn-
taxe a smantika se tm nelii. V C= ma tento tvai
while(podmnka) {
/ / tlo-cyklu
}
Zakladni smantika cyklu while je jednoducha. Nejdive je vyhodnocena pod-
minka (co musi bt viaz viacejici objekt tidy bool). Je-li podminka piavdiva
( objekt true), je vykonano tlo cyklu tj. pikazy uvnit bloku. To ve je obdo-
ba konstiukce if. U cyklu se vak po piovedeni tla znovu testuje podminka. Je-li
piavdiva, je opt vykonano tlo cyklu. Opakovani je ukonen a v okamiku, kdy
se podminka stane nepiavdivou.
Je zejm, e cyklus while pedpoklada, e uvnit tla se njak zmni objekty, ktei
jsou vyuivany v podmince cyklu, nebo jinak by byla podminka stale piavdiva a
cyklus by tak byl nekonen.
Specialnim pipadem je situace, kdy podminka neni splnna ani pi pivnim tes-
tovani. Tlo cyklu se v tomto pipad nepiovede ani jednou.
=
Pomoci cyklu while lze tlo naeho piogiamu nastinit takto (stale jet chybi im-
plementace vlastnosti JePracovni, fiagment tvoi tlo metody Main tidy MainC-
lass)
int rok = int.Parse(Console.ReadLine());
if (rok < 2001 || rok > 2029) {
8e
throw new Exception("Rokmimopodporovanmeze(2001-2029)");
}
int pocetPracovnichDnu = 0;
DateTime den = new DateTime (rok, 1, 1);
DateTime silvestr = new DateTime (rok, 12, 31);
while (den <= silvestr) {
if (den.JePracovni) { / / opakovana innost
pocetPracovnichDnu = pocetPracovnichDnu + 1;
}
den = den.AddDays (1); / / posun na dali den
}
Console.WriteLine (pocetPracovnichDnu);
Jadiem cyklu je podminka, kteia testuje, zda je postupn posouvan den stale
obsaen v pislunmioce. Piotoe poateni hodnota dne je 1. ledna a v tle cyklu
se vdy posune na nasledujici den, postauje testovat zda je aktualni den (tj. objekt
aktualn uloen v piomnn den) stale ped silvestiempislunho ioku iesp. zda
to neni silvesti sam (silvesti je samozejm souasti pislunho ioku a me bt
piacovnim dnem). Pio tento el je vyuita ielace meni nebo iovno mezi dvma
objekty tidy System.DateTime. Je zejm, e objekt tidy DateTime je meni ne
jin objekt DateTime, piav tehdy, kdy iepiesentuje divji as.
Vimnte si, e hianini objekt (iepiesentace silvestiu) je vytvoen ji ped cyklem
a uloen do piomnn. Timto je eliminovano zbyten vytvaeni novho objektu
pi kadm(opakovanm) vyhodnoceni podminky (tj. v kadmopakovani cyklu)
Na konci tla cyklu by mla bt vdy pipiavena pda pio dali testovani pod-
minky a pipadn dali piovedeni tla cyklu. V naem pipad je objekt uloen v
piomnn den nahiazen novm objektem iepiesentujicim nasledujici den. Objekt
tedy neni sam zmnn, ale je nahiazen novm objektem (dvodem je skutenost
e objekty tidy DateTime jsou vdy nemnn).
3.4.3. Roziujc metoda JePracovn()
Nyni pozoinost pesuneme k implementace vlastnosti JePracovn objekt tidy
System.DateTime. Tato vlastnost by mla viacet objekt true, je-li adiesat vlastnosti
ve skutenosti je to zbyten, nebo peklada C= je dostaten inteligentni, aby sam poznal, e
hianini objekt je nutno vytvoit jen jednou (pi tzv. optimalizaci). S pouitim pomocn piomnn
je vak piogiam dle mho nazoiu pehlednji.
Konzolov piogiamy 8,
piacovni den (adiesat je objekt, jeho vlastnost je zjiovana), v opanm pipad
pak objekt false.
Tuto vlastnost budeme implementovat jako ioziujici metodu. To bohuel zna-
mena, e pi volani budeme muset pouivat nadbyten kulat zavoiky tj. namisto
den.JePracovni bude nutno psat den.JePracovni(). Natsti je to jen diobn syntak-
tick detail.
Nejdive vytvoime pivni zkuebni veizi ioziujici metody. Tato veize bude bez
ohledu na adiesata metody ( objekt tidy DateTime iepiesentujici testovan den)
viacet objekt true (tj. jako by byly vechny dny piacovni). To sice neodpovida
poadovan smantice, ale lze tak snadno otestovat zda ji hotov asti piogiamu
funguji.
public static bool JePracovni (this DateTime den) {
return true;
}
Pokud ji mame hotov hlavni piogiam (vetn tidy MainClass a metody Main) a
impoitovan jmenn piostoi System, lze piogiam peloit a spustit. Pokud zadame
nepestupn iok (nap. zc11), pak by ml vypsat Ie (Ie dn bylo oznaeno jako
piacovnich) u pestupnch (nap. zc1z) hodnotu Ie1.
Pi vytvaeni sloitjich aplikaci je vhodn tzv. inkiementalni testovani, tj. pi-
bn ovovani zda ji hotov asti funguji. Pokud se pi dalim ioziovani pio-
giamu objevi chyba je velmi piavdpodobn, e nastala v pidan asti (a tudi se
snadnji hleda). Napiklad v naem pipad, mame oveno, e hodnota ioku byla
dobe petena a cyklus pioel vechny dny ioku. Oven je samozejm i vpis
vsledn hodnoty (ten je vak tiivialni).
Nyni ji meme pistoupit ke skutenmu oveni, zda je dan den piacovni, tj.
k vytvaeni tla ioziujici metody JePracovni.
Pi implementaci budeme vychazet z piincipu postupn detekce dn, ktei nejsou
piacovni. Zbvajici dny pak budou samozejm piacovnimi.
Nejsnadnji se detekuji soboty a nedle
if(den.DayOfWeek == DayOfWeek.Saturday ||
den.DayOfWeek == DayOfWeek.Sunday) {
return false; / / meme hned viatit, e nejsou piacovni
}
return true; / / ostatni jsou piacovni
88
Vlastnost DayOWeek viaci objekt tidy DayOWeek. Vimnte si, e se tida jme-
nuje stejn jako vlastnost. V C= je to bn a nevadi to, nebo podle kontextu je
vdy jasn zda myslime vlastnost nebo tidu.
Tida DayOWeek ma pouze sedm instanci (tj. objekt, ktei do ni pati). Ka-
d iepiesentuje jeden den v tdnu. Jednotliv objekty lze ziskat zapisem DayO-
Week.JmnoDne (jmno dne je samozejm anglicky a zaina velkm pismenem).
Tento zapis se pouiva u tzv. vtovch tid (zkiacen vt), u nich existuje
jen omezen poet instanci, z nich kadou lze vyjadit jednoznanm identika-
toiem. Obecn zapis je JmnoTdy.JmnoObjektu (tj. DayOWeek je zde jmnem
tidy nikoliv metody).
Podminku lze tudi inteipietovat takto
1. nejdive je volana vlastnost DayOWeek, kteia viati objekt tidy DayOWeek
z. tento objekt poiovnan s objektemDayOWeek.Saturday (co je jeden ze sed-
mi objekt tidy DayOWeek)
I. je-li poiovnani spn (tj. testovan den je sobota), je podminka splnna
a metoda viaci objekt false (den neni piacovni), diuha podminka nemusi
bt testovana, nebo pio platnost sloen podminky s opeiatoiem nebo (oi)
stai platnost jen jedn dili podminky
1. je-li poiovnani nespn (objekt neni objektem DayOWeek.Saturday tj.
den neni sobota), je opt volana vlastnost DayOWeek
. viacen objekt je poiovnan s objektem DayOWeek.Sunday (iepiesentuje
nedli)
e. pokud je poiovnani spn (objekty jsou shodn), je podminka splnna a
metoda viaci false (i nedle neni piacovnim dnem)
. pokud jsou ob podminky nepiavdiv, je den oznaen jako piacovni (zatim
neeime svatky)
Piogiamopt meme opt spustit a zjistit kolik je v danmioce dn mimo soboty
a nedle (pio iok zc1z mi vylo ze1).
Nyni budeme eit dny, ktei nejsou vikendovmi, ale zaiove nejsou dny piacov-
nimi (tj. svatky). Vechny svatky kiom velikononiho pondli lze identikovat
pomoci dne v msici (co je cel islo v iozsahu 1..I1) a islem msice (v iozsahu
1..1z).
Aby byla testovaci podminka o nco kiati, uloime si islo dne v msici a islo
msice do piomnnch s kiatkmi identikatoiy
Konzolov piogiamy 8,
int d = den.Day; / / den v msici
int m = den.Month; / / msic jako islo
Nyni ji meme zapsat podminku, kteia testuje zda je dan datumsvatkem(ovem
stale bez testovani velikononiho pondli)
if (m == 1 && d == 1 || / / Nov iok
m == 5 && (d == 1 || d == 8) || / / kvtnov svatky
m == 7 && (d == 5 || d == 6) || / / eivencov svatky
(m == 9 || m == 10) && d == 28 || / / sv Vaclav a Vznik SR
m == 11 && d == 17 || / / Den boje za svobodu a demokiacii
m == 12 && (d > 23 && d < 27) / / Vanoce
) {
return false; / / svatek
}
Tato podminka je tiochu sloitji, ale mla by bt snadno pochopitelna. Je opti-
malizovana pio esk svatky, vyuivajic nktei spolen vlastnosti svatk (dva
svatky v msici, dva svatky zs. a souvisl ti dny vanoc). Tato optimalizace sice
zkiacuje podminku, je vak obtin penositelna pio jin staty.
3.4.4. Vsledn program
Piotoe naim kolem je pouze zjitni potu piacovnich dn v ioce, mame ho-
tovo. Velikononi pondli nemusime zjiovat, nebo je vdy v pondli (a zaiove
neme bt adn jin svatek). Stai tedy od zjitnho potu dn odeist jedni-
ku.
Vsledn piogiam ma nasledujici tvai (valnou vtinu pouitho kodu jsme ji
uvedli)
using System; / / piacovnidny.c
static class DateTimeExtensions
{
public static bool JePracovni (this DateTime den)
{
if (den.DayOfWeek == DayOfWeek.Saturday ||
den.DayOfWeek == DayOfWeek.Sunday) {
return false; / / vikend
}
,o
int d = den.Day; / / den v msici
int m = den.Month; / / msic jako islo
if (m == 1 && d == 1 || / / Nov iok
m == 5 && (d == 1 || d == 8) || / / kvtnov svatky
m == 7 && (d == 5 || d == 6) || / / eivencov svatky
(m == 9 || m == 10) && d == 28 || / / sv Vaclav a Vznik SR
m == 11 && d == 17 || / / Den boje za svobodu a demokiacii
m == 12 && (d > 23 && d < 27) / / Vanoce
) {
return false; / / svatek
}
/ / TODO velikononi pondli
return true; / / piacovni den
}
}
class MainClass
{
public static void Main (string[] args)
{
int rok = int.Parse (Console.ReadLine ());
if (rok < 2001 || rok > 2029) {
throw new Exception ("Rokmimopodporovanmeze(2001-2029)");
}
int pocetPracovnichDnu = 0;
DateTime den = new DateTime (rok, 1, 1);
DateTime silvestr = new DateTime (rok, 12, 31);
while (den <= silvestr) {
if (den.JePracovni ()) { / / opakovana innost
pocetPracovnichDnu = pocetPracovnichDnu + 1;
}
den = den.AddDays (1); / / posun na dali den
}
pocetPracovnichDnu--; / / odeteme den za velikononi pondli
Console.WriteLine (pocetPracovnichDnu);
}
}
Konzolov piogiamy ,1
3.4.5. Profesionln rozen
Ve uveden piogiam piodukuje spiavn vsledky (iozhodn pio podpoiovan
iozhiani iok a za pedpokladu, e zakonodaici nezmni poet svatk). Ma vak
nkolik nevhod
1. nedokonen oeteni velikonoc (to se natsti diky pinavmu tiiku ne-
piojevuje, ale metoda JePracovni neviaci spiavn vsledek)
z. kod soustedn v metod MainClass.Main neni pouiteln v jin aplikaci
(nap. webovm planovacim kalendai)
I. testovani validity ioku je v hlavnim piogiamu, nikoliv v metod, kteia je
na validit ioku pimo zavisla (tj, metod JPracovni, kteia je pouitelna jen
v danm iozmezi)
Nejjednodui je eeni velikonoc. l kdy je algoiitmus vpotu velikononiho
pondli ielativn sloit, existuje na lnteinetu velk mnostvi ji existujiciho ko-
du, ktei stai jen zkopiiovat a miin upiavit (zkuste v Googlu dotaz eastei C=).
Zvolilo jsem hned pivni odkaz a upiavil jej do podoby ioziujici metody (a upia-
vil jmna piomnnch, kteia nesplovala stylistick poadavky). Metoda sice vy-
poitava velikononi nedli, ale to nam nevadi, nebo pondli je vdy nasledujici
den. Vimnte si, e v poznamce je uveden pvodni zdioj. Piogiamov kod je du-
evni vlastnictvi, a pioto je nutno dodiovat zakladni piavidla pi jeho kopiiovani
(tj. je-li veejn, ml by bt uveden minimaln jeho zdioj).
/ / pevzato a miin upiaveno
/ / z http://www.geekpedia.com/code68_Find-Easter-Sunday-of-any-year.html
public static DateTime VelikonocniNedeleRoku(this DateTime dayInYear)
{
int year = dayInYear.Year;
int a = year % 19;
int b = year / 100;
int c = year % 100;
int d = b / 4;
int e = b % 4;
int f = (b + 8) / 25;
int g = (b - f + 1) / 3;
int h = (19 * a + b - d - g + 15) % 30;
int i = c / 4;
int k= c % 4;
int L = (32 + 2 * e + 2 * i - h - k) % 7;
,:
int m = (a + 11 * h + 22 * L) / 451;
int month = (h + L - 7 * m + 114) / 31;
int day = ((h + L - 7 * m + 114) % 31) + 1;
DateTime dtEasterSunday = new DateTime (year, month, day);
return dtEasterSunday;
}
Uvnit ioziujici metody pak pidame nasledujici adky (po kontiole xnich svat-
k)
if ((m == 3 || m == 4) && den == den.VelikonocniNedeleRoku().AddDays(1))
{
return false; / / velikononi pondli
}
V zasad by staila jen podminka den == den.VelikonocniNedeleRoku ().AddDays
(1) (tj. testovan den je iovn dnu, jen je o jeden den pozdji ne velikononi
nedle ve stejnmioce jako testovan den). Je vak zbyten testovat vechny dny,
piotoe velikononi pondli me bt pouze v beznu a dubnu (pesnji mezi zI.I
a ze.1 vetn).
eeni diuhho pioblmu nepouitelnosti kodu pio vpoet potu dn v jinch
aplikacich, je sloitji. Aby byl kod opakovan pouiteln musi bt implemen-
tovan jako metoda (i obecn jako funkce, ale my myslime objektov). Otazkou
vak do jak tidy tuto metodu zaadime.
l kdy je toti kod volan nad celm islem (letopotem), neni vhodn jej imple-
mentovat jako ioziujici metodu tidy int. Objekty tidy int iepiesentuji isla bez
dodaten smantiky (tj. nikoliv letopoty, min jednotky, poty osob). Vechny
metody, by mly iespektovat tuto neutialitu.
Mezi pipustn metody tak kiom bnch aiitmetickch opeiaci pati nap. ist
matematick metody jako nap. JePrvoslo, NejmenSpolenDlitel a podobn.
Nepipustn jsou naopak metody JePestupn (islo neni pestupn, pouze iok v
nkteim z kalenda), DostatenKvrum (islo neni kvoium), JeZdanno (zdan-
no neni islo, ale zboi s danou cenou).
Metoda testujici poet piacovnich dn, by vak mohla bt metodou tidy Sys-
tem.DateTime. Z celho asovho daje by vak vyuivala jen infoimaci o ioce.
To je sice mon, avak nepili efektivni (zanedba se daj o msici, dnu, hodin,
minut a sekundach).
Konzolov piogiamy ,
Natsti existuje zajimav zobecnni, ktei mnohem lpe vyuiva potencialu ob-
jekt tidy System.DateTime. Je to metoda, kteia viaci poet piacovnich dn mezi
dvma libovolnmi daty vetn (v podpoiovanmiozmezi). Poet piacovnich dn
v ioce lze pomoci tto mnohemuniveizalnji metody snadno spoitat (je to poet
piacovnich dn mezi novm iokem a silvestiem danho ioku).
Signatuia tto univeizalnji pojat ioziujici metody bude nasledujici
int PracovniDnyDo (this DateTime pocatecniDatum, DateTime koncoveDatum)
Poateni datum bude metod pedavano jako adiesat metody (je oznaeno kli-
ovm slovem this), diuh jako paiameti metody. Z pohledu OOP se tedy ptame
jistho asovho daje (adiesat), kolik je piacovnich dn mezi nim a diuhm da-
tem (paiametiem).
Piklady obecnho pouiti
DateTime.Today.PracovniDnyDo(new DateTime(2012,12,21))
Viaci poet piacovnich dn do konce svta. Pokud (zaziakem) svt peije (ove-
no peil) a vy pot spustite piogiam pak viati vdy c (adn dny nezbvaji, tim
mn piacovni)
DateTime.Today.PracovniDnyDo(DateTime.Today)
Toto volani viaci hodnotu 1 pokud je dnes piacovni den jinak nulu. Pio testovani
zda je den piacovni je mnohem lepi vyuit nami ji implementovanou metodu
JePracovni tj. zapis DateTime.Today.JePracovni(). Pouiti zbyten sloit metody
pio jednoduchou innost je oznaovana idiomem kanon na viabce.
Kod tto ioziujici metody, je zaloen na pvodnim kodu metody Main. Mni
se pouze specikace poateniho a koncovho data. Ty ji nejsou odvozeny ze
zadanho ioku, ale jsou pouity paiametiy iozien metody.
Pio spoiu uveme iovnou cel kod s novou ioziujici metodou, kteia je vyuita
v novm hlavni metod
using System; / / pracdny2.cs
static class DateTimeExtensions
{
public static DateTime VelikonocniNedeleRoku(this DateTime dayInYear)
{
/ / viz stiana v1
,
}
public static bool JePracovni (this DateTime den)
{
if (den.Year < 2001 || den.Year > 2029) {
throw new Exception ("Rokmimopodporovanmeze(2001-2029)");
}
if (den.DayOfWeek == DayOfWeek.Saturday ||
den.DayOfWeek == DayOfWeek.Sunday) {
return false; / / vikend
}
int d = den.Day; / / den v msici
int m = den.Month; / / msic jako islo
if (m == 1 && d == 1 || / / Nov iok
m == 5 && (d == 1 || d == 8) || / / kvtnov svatky
m == 7 && (d == 5 || d == 6) || / / eivencov svatky
(m == 9 || m == 10) && d == 28 || / / sv Vaclav a Vznik SR
m == 11 && d == 17 || / / Den boje za svobodu a demokiacii
m == 12 && (d > 23 && d < 27) / / Vanoce
) {
return false; / / svatek
}
if ((m == 3 || m == 4) &&
den == den.VelikonocniNedeleRoku ().AddDays (1)) {
return false; / / velikononi pondli
}
return true;
}
public static int PracovniDnyDo (this DateTime pocatecniDatum,
DateTime koncoveDatum)
{
int pocetPracovnichDnu = 0;
DateTime den = pocatecniDatum;
while (den <= koncoveDatum) {
if (den.JePracovni ()) { / / opakovana innost
pocetPracovnichDnu = pocetPracovnichDnu + 1;
}
den = den.AddDays (1); / / posun na dali den
Konzolov piogiamy ,
}
return pocetPracovnichDnu;
}
}
class MainClass
{
public static void Main (string[] args)
{
int rok = int.Parse (Console.ReadLine ());
DateTime novyRok = new DateTime (rok, 1, 1);
DateTime silvestr = new DateTime (rok, 12, 31);
Console.WriteLine (novyRok.PracovniDnyDo (silvestr));
}
}
Piogiam zaiove ei i posledni pioblm, chybn umistni testu validity ioku.
Tento test je pesunut na zaatek ioziujici metody JePracovni, kam pati. Vjim-
ka tak bude vyvolana i v pipad, e ioziujici metoda bude pouita i v dalich
aplikacich (tyto aplikace se musi nasledn postaiat o jeji eeni).
Vimnte si tak, e hlavni metoda ma po piav jen tyi adky kodu. Navic polo-
vina tohoto kodu ei vstup daje a vstup vsledku, tj. innost, kteiou nemohou
piovadt univeizalni metody (ty musi bt pouiteln nap. i v GUl a webovch
aplikacich).
4. Seznam zkladn kolekce
Teimin kolekce oznauje objekty, ktei sloui pio ukladani jinch objekt (al-
teinativni teimin je kontejner). Modeini jazyky nabizeji velk mnostvi iznch
kolekci, ktei se lii zpsobem identikace objekt v kolekci a nabidkou optima-
lizovanch metod pio pistup ke kolekci.
Nazvoslovi jednotlivch kolekci neni bohuel sjednoceno a to ani v anglitin, tj.
stejn teimin me oznaovat izn kolekce (s diametialn odlinou chaiakte-
iistikou). Pioto je nutn alespo iamcov znat i datov stiuktuiy pouivan pio
implementaci kolekci. V pipad datovch stiuktui je nazvoslovi mnohem sjed-
nocenji a ve vtin pipad i piegnantnji.
Jet ne zanme popisovat nejbnji typy kolekci, musime pozoinost vno-
vat tzv. asymptotick sloitosti, co je uitena matematicka notace, umoujici
jednodue chaiakteiizovat asov a pamov naioky jednotlivch opeiaci nad
kolekcemi.
Asymptotick sloitost
Asymptoticka sloitost umouje chaiakteiizovat jakm zpsobem zavisi as i
pamov naioky na velikosti vstupnich dat tj. v naem pipad na potu pivk
kolekce.
Pedpokladejme napiklad, e vykonavame njakou opeiaci nad polokami
kolekce (nap. vyhledani poloky, nalezeni nejvti poloky, odstianni piostedni
poloky, apod.) s pivky. Dale pedpokladejme, e (pimin) as vykonavani
zavisi piimain na potu poloek
=

()
lunkce

vak zavisi tak na konguiaci poitae. Nap. lze pedpokladat, e


pokud mame poita s dvojnasobnou fiekvenci CPU, pak bude funkce

po-
nkud jina (asy budou adov polovini). Navic funkce nemusi bt jednodue
v
,8
vyjaditelna pomoci polynom a jinch bn uivanch matematickch funkci
(tj. nelze ji jednodue symbolicky zapsat)
Abychomodstianili zavislost na konguiaci a zjednoduili zapis, pedpokladejme,
e existuje jina (typicky jednodui) funkce pio ni plati

1
.
z
>c

>
c

()


1
()

()


z
()
Potom meme psat, e () = (()).
Tento zapis lze peist minimaln dvma zpsoby
1. asova sloitost opeiace (funkce

()) je (asymptoticky) stejn ios-


touci jako ()
z. opeiace ma asovou sloitost (()). Zjednoduen, ale mnohem b-
nji vyjadeni.
Poznmka:
Zapis (()) se bn te jako (velk) O-g-x, tj. napiklad () se
t (velk)-O-n. V matematice se tento zapis te spie jako velk-
omikion. Navic se znak velk omikion pouiva pio miin odlinou
mnoinu funkci (funkce, omezujici jen shoia). Pio mnoinu splujici
nai denici se pouiva zapis (()). Neni divu, e si matematici s
infoimatiky moc neiozumi.
Pklad:
Pedpokladejme, e pio jistou opeiaci byly zjitny asy odpovidajici funkci () =
z
z
+ 1. 1cc. Jaka je asova sloitost opeiace`
Za funkci () zvolme funkci
z
. Pio funkci omezujici shoia zvolme
1
= I a pio
funkci omezujici zdola
z
= 1.
Potom stai najit takov
c
, e pio kad >
c
plati ()

I
z

a zaiove
()

. Podivejme se na giafy tchto funkci (obiazek 1.1 na nasledujici


stian).
Z giafu lze odhadnout, e pio kad > 1c ma funkce I
z
vyi funkni hodnoty
ne () a funkce
z
naopak nii (dkaz to vak neni). Lze tedy napsat e () =
(
z
), tj. opeiace ma sloitost (
z
) [teme O-n-na-diuhou] iesp. kvadiatickou.
Namisto funkce
z
lze nicmn pouit i funkce
z
++e nebo c.e
z
1cc iesp.
jakkoliv funkce tvaiu
z
+ + . [konec pkladu]
Seznam zakladni kolekce ,,
-200
0
200
400
600
800
1000
1200
0 5 10 15 20
T(n)
3n^2
n^2
Obiazek 1.1. Asymptoticka sloitost. Piklady funkci
Obecn plati, e vechny funkce tvaiu () + (kde c) jsou asymptoticky
stejn iostouci jako funkce () + (kde c), Je pioto piiozen zvolit = 1
a = c a psat sloitost bez nasobicich koecient a xnich posunuti.
To je dleit, nebo umouje v -notaci zanedbat ziychleni dan vtim vko-
nem poitae, je se piojevuje vynasobenim as piovedeni uiitou xni hodno-
tou (z inteivalu (c. 1)). Pokud ma tedy njaka opeiace sloitost () pak si tuto
sloitost zachova i na iychlejim poitai. To mimo jin znamena, e ani nasazeni
enoimniho vpoetniho vkonu, neme zviatit neefektivitu chybn navienho
algoiitmu (navic u nkteich pioblmu neexistuji algoiitmy s iozumnou asovou
sloitosti!)
l kdy teoieticky existuje nekonen mnostvi funkci s odlinm asymptotickm
istem, v piaxi se pouiva jen nkolik zakladnich tid sloitosti. Ty nejbnji
shinuje nasledujici tabulka. Navic uvadi infoimativni as nutn pio piovedeni
opeiace s pislunou sloitosti nad kolekcemi iznch velikosti.
Udaj je skuten jen infoimativni, nebo skuten as piovedeni zavisi na iych-
losti poitae a zanedbat nelze ani multiplikativni koecient ve funkci ().
1oo
sloitost oznaen 1c 1c-1c 1c-1c ~1c
O(

), > c exponencialni N/P P/X X X


O(
I
) kubicka N N/P P X
O(
z
) kvadiaticka R N P P
O( log()) R R N P
O() lineaini R R N N/P
O(log()) logaiitmicka R R R N
O(1) konstantni R R R R
R (ryl) N (normln)
setiny vteiny a mn setiny vtein a desitky vtein
P (pomal) X (extrmn pomal)
minuty a hodiny dny, ioky a dle
Pklad:
Pio vyhledani konkitniho pivku v kolekci, lze vdy pouit tiivialni algoiitmus s
piochazenimvech pivk. Tento algoiitmus ma asovou sloitost () (as je line-
ain zavisl na potu pivk). Pio mal kolekce (max. tisice pivk) je velmi iychl
tj. uivateli ani nezaiegistiuje zpodni. Pio vti kolekce je zpodni znateln,
ale akceptovateln (vteiny), ale vyhledavani se nesmi pili asto opakovat.
Pio velk databaze (s velikosti ad GiB) vak me bt toto vyhledavani pili
pomal (lid nemohou nap. v inteinetovm obchod ekat minuty na vyhledani
poloky podle jmna). Podobn nelze tento algoiitmus pouit v iamci kodu vy-
kieslovani scn v poitaovch hiach (kolekce me obsahovat nap. zobiazovan
objekty). U pio ielativn mal kolekce ( > 1ccc) je vyhledavaci doba vice ne
setina vteiny, co viazn zvyuje dobu pekiesleni scny (pi = c se musi
scna pekieslit kadch zc ms).
Natsti existuji vyhledavaci algoiitmy se sloitosti (()) nebo dokonce (1).
Ty jsou sice o nco pomaleji pio mala (pouivaji toti o nco sloitji kod),
ale pio stedni a pedevim velka jsou viditeln iychleji a pio extimn velk
kolekce jsou nutnosti.
Podobn je nutno peliv zvolit optimalni iepiesentace a algoiitmy pio tidni
(seazeni) dat. Tiivialni algoiitmy maji sloitost (
z
). Pio mal kolekce jsou tyto
Seznam zakladni kolekce 1o1
algoiitmy optimalni a i pio vti kolekce (kiom extimn velkch) jsou akcepto-
vateln. Nejlepi tidici algoiitmy maji sloitost ( ()) a jsou tudi dosta-
ten iychl i pio velk kolekce a akceptovateln i u kolekci extimnich velikosti.
Pedstavme si vak kolekci, kteia je stale mnna (tj. jsou do ni pidavany po-
loky a dali poloky jsou odstiaovany). Navic chceme udiet tuto kolekci stale
setidnou. Pokud budeme kolekci tidit po kadm vloeni i odstianni poloky,
mohou se piodlevy stat neakceptovateln (a to i pio kolekce adu tisic poloek),
Natsti existujici kolekce, ktei udiuji kolekci automaticky setidnou, piem
vloeni i odstianni poloky ma sloitost pouze (()).
[konec pkladu]
Kiom (asymptotick) asov sloitosti, existuje i (asymptoticka) sloitost pam-
ova. Ta nehiaje tak dleitou ioli, nebo pio vtinu opeiaci nad kolekcemi je
iovna (), tj. vyaduji pam, je adov odpovida potu pivk. Nejastji je
to pesn pivk (tj. neni poteba adna dostatena pam kiom vlastni ko-
lekce). Do stejn tidy vak spadaji i algoiitmy vyadujici kopii kolekce, nebo
()().
Specialnim pipadem jsou opeiace, ktei v zasad nevyaduji ani uloeni pivk
do kolekce, jako je nap. hledani maxima (stai si pamatovat jen aktualni maxi-
mum). Tyto algoiitmy maji sloitost (1). Na diuh stian existuji specializovan
opeiace, ktei vyaduji (

) pamti, kde > 1. Tyto opeiace vyaduji ielativn


velka mnostvi dodaten pamti (pedevim pio extimn velk kolekce) mohou
vak nabizet extimn malou asovou sloitost (jinak nedosaitelnou). V piaxi se
vak tm nevyuivaji, nebo ziychleni je zaplaceno vysokmi naioky na pam.
4.1. Seznam List<T>
Nejjednodui a tak nejastji pouivanou kolekci je seznam (angl. list). Mezi
zakladni chaiakteiistiky seznamu pati
homogenita pi denici seznamu je bn uiena tida objekt, ktei mohou
bt do seznamu ukladany. Jazyk nicmn nabizi i nkolik monosti jak ho-
mogenitu ielativizovat i dokonce zcela eliminovat (to se vak hodi jen ve
zcela specialnich pipadech)
modifikovatelnost do seznamu lze pidavat pivky a pivky lze tak odebiiat.
Pidavani pivk na konec seznamu a odebiiani od konce je velmi efektivni
1o:
(viz nie), pidavani a odebiiani vpiosted a na poatku seznamu ma a-
sovou sloitost (). Maximalni velikost seznamu je teoieticky omezena
pouze velikosti adiesovho piostoiu, piakticky je hlavnim omezenim ioz-
sah opeiani pamti (mnoina aktivn vyuivanch stianek pamti nesmi
bt viazn vti ne dostupna opeiani pam, v opanm pipad me
dojit z zahlceni poitae)
indexovatelnost opeiace indexace (tj. nalezeni -tho pivku seznamu) je velmi
iychla (a ma asovou sloitost (1)). Opeiace indexace navic pedpoklada,
e poloky jsou lineain uspoadany. (tj. tvoi posloupnost)
lnteini iepiesentace seznamu neni sloita. Nejjednodui je v pipad, e poloky
jsou objekty hodnotov tidy (nap. seznamy isel). V tomto pipad jsou polo-
ky uloeny jedna za diuhou v souvisl oblasti pamti. U iefeiennich typ jsou v
seznamu uloeny odkazy na objekty. K seznamu navic pati i pam za jeho kon-
cem, kteia je sice alokovana, ale neni vyuivana (tj. neobsahuje adn poloky).
Tato pam je pipiavena pio pipadn budouci ioziovani seznamu (pidavani
poloek). Jednoduch nahled na stiuktuiu naleznete na obiazku 1.z.
2 5 3 0
dodaten pam
Seznam objekt hodnotovch td: L!t"nt#
!eznam$%o&nt ' (
!eznam$%apact) ' *
dodaten pam
Seznam objekt +e,e+ennch td: L!t"!t+n-#
!eznam$%o&nt ' 3
!eznam$%apact) ' *
!t+n-:
.%/0
!t+n-:
./1/0
!t+n-:
.23&45a)0
Obiazek 1.z. lnteini stiuktuia seznamu
Pokud je dodatena pam k dispozici, je pidani poloky extimn iychlou ope-
iaci (se sloitosti (1)). Dodatena pam se vak me nakonec vyeipat, co
negativn ovlivni opeiaci pidavani a me zpsobit jeji viazn zpomaleni.
Seznam zakladni kolekce 1o
Poznmka:
Jednodui je situace pipad, e bezpiostedn za pamti alokovanou
pio pole, nasleduje voln blok' pamti (tj. pam nepatici adnmu
objektu). Pak stai tento blok pipojit k seznamu, a pouit jej jako
novou dodatenou (piozatim neobsazenou) pam.
Ne vdy vak mame takov tsti. Pokud za pamti pidlenou sezna-
mu nenasleduje voln blok, ve se tiochu zkomplikuje. Je toti nutno
najit voln souvisl iegion pam, jeho velikost dostauje pio se-
znam vetn nov pidan dodaten pamti, a do tohoto iegionu ce-
l seznam zkopiiovat. Pvodni ji nedostaujici iegion pamti me
bt uvolnn. Kopiiovani je vak ielativn pomala opeiace (se sloi-
tosti ()), tj. systm se snai tuto komplikaci co nejvice eliminovat.
Piav z tohoto dvodu je vyuivana dostatena pam.
Sloitost pidavani je tak v obecnm pipad oznaovana jako amor-
tizovan konstantn (amoit. (1)). To znamena, e je ve vtin pi-
pad (a dokonce i pimin) konstantni ( nezavisi na velikosti se-
znamu), ale vjimen me bt lineaini. V globalnim pohledu je ve
OK, nicmn u velkch seznam me vst pidani s vynucenm ko-
piiovani k lokalnimu piodloueni odezvy (tj. aplikace obas na pai
sekund zatuhne).
Vtina standaidnich kolekci pouiva sostikovan algoiitmy pio pedalokaci do-
daten pamti, tj. bn uivatel se nemusi touto pioblematikou detailn zaobi-
iat. Pokud vak dokaete, alespo piblin odhadnout budouci velikost kolekce, je
mon pi jejim vytvaeni specikovat poadovanou kapacitu (tj. poet poloek
kolekce - poet poloek, pio n je pedalokovano misto v dodaten pamti).
Nemusite se bat specikovat i velmi vysok hodnoty (pedevim u e1-bitovch
systm), nebo alokace se tka pouze viitualniho pamovho piostoiu. Na pi-
dleni fyzick pamti (opeiani i swapovaci) dojde a pi vyuiti jednotlivch
poloek, piostednictvim spiavce pamti opeianiho systmu.
4.1.1. Vytvoen novho seznamu
Seznamy se jako valna vtina objekt vytvai pomoci volani konstiuktoiu. Pio-
toe je vak nutno specikovat i typ poloek, je zapis miin komplikovanji.
'pam se z dvod efektivity nepidluje po jednotlivch bytech, ale po vtich blocich
1o
Nejdive se ukame vytvoeni piazdnho seznamu
new System.Collections.Generic.List<int>()
Toto volani vytvoi nov seznam vhodn pio ukladani objekt tidy int. Tento
seznam je piozatim piazdn (to je dano pouitim konstiuktoiu bez paiameti,
viz dvojici piazdnch zavoiek).
Odkaz na nov vytvoen objekt se bn uklada do piomnn (seznamy jsou
iefeienni tidy!)
System.Collections.Generic.List<int> mujSeznamCisel
= new System.Collections.Generic.List<int>();
Zapis neni bohuel pili stiun. Jet deli me bt v pipad, e tida poloek
je tak kvalikovana jmennm piostoiem (nasledujici denice ma 11v znak)
System.Collections.Generic.List<System.DateTime> seznamSvatku
= new System.Collections.Generic.List<System.DateTime>();
Natsti lze vyuit impoitu jmennch piostoi (od tto chvile budeme pedpo-
kladat, e je vdy pouit)
using System;
using System.Collections.Generic;
Nyni lze psat (1 znak)
List<DateTime> seznamSvatku = new List<DateTime>();
Poznmka:
Tento zapis lze navic dale zkiatit, nebo modeinji veize jazyka C=
(I.c-) umouji vyuit schopnost kompilatoiu odvodit tidu piomn-
n z tidy inicializaniho objektu. Sloui k tomu kliov slovo var po-
uit na mist tidy
var seznamSvatku = new List<DateTime>();
V tomto pipad bude piomnna denovana s tidou List<DateTime>,
nebo je to typ inicializaniho viazu. l kdy je tento zapis opt o
pai znak kiati (1c znak), neni nkteimi piogiamatoiy pouivan
(nelze jej toti pouit ve vech kontextech a situacich). Nebudeme jej
pioto dale aktivn vyuivat.
Seznam zakladni kolekce 1o
Pi pouiti bezpaiametiickho konstiuktoiu je vytvoen objekt nejen piazdn,
ale neni mu vyhiazena ani adna dodatena pam.
seznamSvatku.Count / / c
Vlastnost Count viaci poet pivk. Vimnte si iozdilu ve jmn obdobnch vlast-
nosti u seznamu (Count) a etzce (Length).
seznamSvatku.Capacity / / c
Pedalokovana kapacita kolekce, tj. poet pivk kolekce - poet pivk kolekce,
ktei lze vloit bez dodaten alokace.
Pokud znate piblinou cilovou velikost kolekce, lze kapacitu nastavit ji pi vy-
tvoeni objektu.
List<DateTime> seznamSvatku = new List<DateTime>(20);
Jedinm paiametiem konstiuktoiu je poadovana velikost pedalokovan pamti
(tj. kapacita). V naem pipad se vytvoi piazdn seznam, ktei ma pedaloko-
vano misto pio zc poloek. Dokud toto islo nepekioite, nedojde k dodaten
alokaci (a tim ani k pipadnmu kopiiovani na nov misto). Do seznamu vak lze
nicmn pidat i vti poet poloek (jste omezeni pouze adiesovm piostoiem a
do uiit miiy i iealnou opeiani pamti).
seznamSvatku.Count / / c (je piazdn)
seznamSvatku.Capacity / / zc (ale pipiaven na zc poloek)
Kiom piazdnho seznamu lze vytvoit i pedvyplnn seznam. Zapis neni pili
stiun, nebo vznika iozienimkonstiuktoiu o tzv. strukturovan inicializtor tj.
seznam pivk ve sloench zavoikach.
List<int> stastnaCisla = new List<int>(){3,5,8};
Tento zapis vytvoi nov objekt piazdnho seznamu (pio objekty tidy int) za po-
uiti bezpaiametiickho konstiuktoiu (vimnte si piazdnch kulatch zavoiek).
Tento seznam je nasledn vyplnn temi polokami.
stastnaCisla.Count / / I
lnicializovat lze piiozen i seznamy s jinou tidou poloek (nejen iseln)
1oe
List<string> zeme = new List<string>(){"Gondor", "Eriador"};
List<bool> vysledky = new List<bool>(){false, false, false,
true, false, false};
List<DateTime> epochy = new List<DateTime>(){
new DateTime(1970,1,1),
new DateTime(1900,1,1),
new DateTime(1980,1,1)};
Lze dokonce vytvaet a inicializovat seznamy seznam (bohuel je to sloitji,
ne by mohlo bt)
List<List<int>> magickyCtverec = new List<List<int>>(){
new List<int>(){4,9,2},
new List<int>(){3,5,7},
new List<int>(){8,1,6}};
V zaviu tto kapitoly, jet jedno dleit piavidlo.
Pravidlo 12: Pi kad denici seznamu pouijte inicializaci (co je ve vtin p-
pad voln konstruktoru seznamu)
Toto piavidlo je specialnim pipadem ji uvedenho piavidla Promnn by mla
bt v rmci denice vdy explicitn inicializovna. Pio jistotu ji vak opakuji (a
neni to naposled -)), nebo pouiti neinicializovan iefeienni piomnn je astou
chybou
List<int> p; / / adn seznam nevznikne, jen piomnna
List<int> q = p;
p.Add(5); / / vyvolani vjimky null exception
q.Add(6); / / q tak obsahuje null
4.1.2. Metody a operace nad seznamy
Pio ely jednodui piesentace metod nad seznamy budeme pedpokladat, e
metody jsou volany nad seznamem, ktei vznika v iamci nasledujici denice pio-
mnn mereni (vdy znovu ped kadm pikladem).
List<double> mereni = new List<double>{1.0, 5.6, 12.3};
Seznam zakladni kolekce 1o,
Poet prvk (vlastnost)
S vlastnosti Count jsme se ji seznamili, ale pio jistotu si ji zopakujme
Signatuia int Count {get;}
Signatuia vlastnosti obsahuje nejen jeji jmno a tidu objektu iepiesentujici vlast-
nost, ale i specikaci zda lze vlastnost pouze ziskavat (angl. get), nebi i nastavovat
(angl. set). V naem pipad lze poet pivk seznamu jen ziskavat. Velikost sezna-
mu se mni jen pi pidavani a odebiiani pivku.
Piklad
mereni.Count / / I
Indexace (operace)
Zapis indexace u seznam je obdobn jako v pipad etzc. Pipustn indexy
jsou c (pivni pivek) a Count-1 (posledni pivek). Vpipad seznam hodnotovch
tid se viaci kopie i-t poloky (tj. nov vznikl objekt) u iefeiennich tid je to
odkaz na pislun objekt (tj. objekt se neduplikuje, ziska se pouze dali odkaz na
objekt uloen v seznamu).
mereni[0] / / 1.c
Na iozdil od etzce vak lze poloky mnit piazenim. Smantika piazeni je
stejna jako u piomnnch, tj. i zde se ponkud lii hodnotov a iefeienni typy.
U hodnotovch tid je pvodni objekt pepsan (je uloen pimo v seznamu) u
iefeiennich tid dojde k pesmiovani odkazu.
mereni[mereni.Count-1]=-5.0; / / nov obsah seznamu 1.c, .e, -.c
Pidn/vloen prvku
Nejjednodui a nejefektivnji je pidani pivku na konec seznamu.
Signatuia void Add(T object) (kde T je typ poloek)
Jak ji bylo ve eeno je pimina sloitost konstantni ((1)), v nkteich pi-
padech vak me bt i lineaini (()).
mereni.Add(15.6); / / nov obsah pole 1.c, .e, 1z.I, 1.e
1o8
Knihovna .NlT nabizi i metodu pio vloeni pivk na libovolnou pozici seznamu.
Pvodni poloka se nepepie, ale je posunuta o jednu pozici dale (a podobn jsou
posunuty i vechny nasledujici poloky). Je zejm, e pimina asova sloitost
je (), nebo se musi pimin /z poloek posunout (pokud je vak poloka
vkladana na nakonec seznamu nebo na pozici indexovanou xn od konce, je jeji
sloitost konstantni!).
Signatuia void Insert(int index, T objekt)
lndex uiuje poloku, na jeji misto bude objekt vloen. lndex me nabvat hod-
not c a Count ( vloeni na konec).
Piklad
mereni.Insert(0, -1.0); / / vloeni na zaatek -1.c, 1.c, .e, 1z.I
mereni.Insert(mereni.Count - 1, 8.8);
/ / vloeni namisto posledniho pivku ve vsledku tedy bude na pedposledni pozici
/ / vsledek 1.c, .e, s.s, 1z.I
Pidn/vloen vce prvk
Pokud chceme pidat i vloit vice pivk je mon vicenasobn zavolat metody
Add a Insert. Pokud vak mame pivky v jinm seznamu i kolekci, pak meme
pouit metody AddRange a InsertRange
Signatuia void AddRange(IEnumerable<T> kolekce)
Paiameti neni uien tidou, ale tzv. iozhianim. Rozhiani budeme piobiiat pozd-
ji. Nyni meme (zjednoduen) pedpokladat, e paiametiemme bt libovolna
kolekce i sekvence poloek tidy (tj. stejn jako u seznamu, do nho pidava-
me).
Zatim zname je jedinou kolekci seznam, tj. meme k seznamu pidavat jen
obsah jinho seznamu. Ve vsledku se pvodni seznam iozii o vechny pivky
pidavanho seznamu.
mereni.AddRange(new List<double>(){20.0, 30.0});
/ / vsledek 1.c, .e, 1z.I, zc.c, Ic.c
Pidavani lze pouit i pio dosaeni efektu opakovani pivk
mereni.AddRange(mereni); / / vsledek 1.c, .e, 1z.I, 1.c, .e, 1z.I
Seznam zakladni kolekce 1o,
Vyjadeni asov sloitosti tto opeiace neni tak snadn, nebo piacuje se dvma
seznamy. Sloitost z hlediska adiesata metody (seznamu, do nho se pidava) je
amoitizovan (1) (tj. nezavisi na potu jeho pivk, a na pipadnou iealokaci), z
hlediska paiametiu (pidavanho seznamu) je () (kde je poet pidavanch
pivk). Obecn je tedy efektivnji pidavat mal seznam do adov vtiho a
nikoliv naopak (ne vdy si vak meme smi zetzeni zvolit).
Pio vkladani vice pivk se pouije metody s (oekavanm) nazvem InsertRange
Signatuia void InsertRange(index n, IEnumerable<T> kolekce)
Metoda vloi pivky pedan kolekce (paiametiu) na misto poloky uien inde-
xem (zbytek pivk je posunut o kolekce.Count pozic dopiava).
mereni.InsertRange(0, new List<double>(){0.0, 0.0});
/ / nov obsah kolekce meieni c.c, c.c, 1.c, .e, 1z.I
Sloitost tto opeiace je v nejhoiim pipad iovna ().
Poznmka:
Sloitost ve skutenosti zavisi na implementaci pidavani a ielaci me-
zi potem pivk obou kolekci. Pokud by byly pivky vkladany jednot-
liv, pak by sloitost mohla bt v nejhoiimpipad a () (je vkla-
dano pivk, a kad vkladani ma sloitost ), co za pedpokladu
piblin iovnosti vede ke sloitosti kvadiatick (
z
). Doku-
mentace (http://msdn.microsoft.com/en-us/library/884ee1fz) vak uva-
di, e sloitost je jen ( + ), co vede k lineaini sloitosti (je-li
, pak ( + ) = (z) = (), je-li pak ( + ) =
( + ) = ()). Na diuhou stianu to znamena, e musi bt vytvo-
ena kopie pidavan kolekce, tj. miin se zvyuji pamov naioky
(iozhiani IEnumerable<T>, neumouje ziskat velikost iteiatoiu, ji-
nak ne jeho piojitim a uloenim do kopie).
Vyjmn prvk
Pio vyjimani (mazani) pivk z kolekce existuji dv metody. Jedna identikuje vy-
jiman pivek podle jeho indexu, diuha podle jeho hodnoty iesp. identity.
Signatuia void RemoveAt(int index)
Metoda vyjima poloku na pozici uien indexem. Nasledujici pivky jsou pesu-
nuty o jeden pivek doleva (na pedchozi pozici). Sloitost je pioto ().
11o
Piklad
mereni.RemoveAt(1) / / vyjima diuh pivek, nov obsah .e, 1z.I
Signatuia bool Remove(T objekt)
Vyjima pivni poloku, kteia je iovna pedanmu objektu (pokud takov pivek v
seznamu existuje). Viaci true, je-li njak pivek vyjmut, jinak viaci false. Pokud
je shodn pivek umistn na nkolika mistech seznamu, je odstiann jen pivni
vskyt (zleva).
mereni.Remove(5.6); / / viaci tiue, nov obsah je 1.c, 1z.I
mereni.Remove(0.0); / / viaci false a seznam se nemni
Pokud chceme odstianit vechny vskyty pivku lze pouit cyklus while s piazd-
nm tlem (cel tlo cyklu je iepiesentovano stednikem, ktei zde ma funkci
piazdnho pikazu)
while(mereni.Remove(0.0)); / / odstiani vechny nuly z meni
l kdy je toto eeni pln funkni a ve vtin pipad dostaujici, existuji pipady,
kdy je pili pomal. Jestlie odstiann pivky tvoi ast seznamu vyjaditelnou
ve tvaiu , kde (c. 1], pak je asova sloitost jejich odstianni iovna (
) = (
z
). Pokud je seznamdostaten velk (nap. obsahuje-li statisice poloek)
a podil nul je nezanedbateln (nap. > c.1), pak me odstianni tivat cel
sekundy i vice.
Poznmka:
lfektivnji algoiitmus odstianni nabizi metoda List<T>.RemoveAll
s asovou sloitosti (). vyaduje vak pouiti lambda vrazu i de-
legatu
mereni.RemoveAll(x => x == 0.0);
Hledn poloek
Seznam neni optimalizovan pio vyhledavani a pioto jsou zakladni vyhledavaci
opeiace ielativn pomal (se sloitosti ()). Pio mal a stedni seznamy jsou
vak dostaten efektivni.
Pokud Vam postauje infoimace, zda je objekt v seznamu obsaen i nikoliv, pak
je mono pouit metodu Contains.
Seznam zakladni kolekce 111
Signatuia bool Contains(T hledanObjekt)
Piklad
mereni.Contains(1.0) / / tiue
Pi aplikaci tto metody se seznam nijak nemni.
Pokud je poteba zjistit i pozici nalezenho pivku je nutno pouit metodu IndexOf.
Signatuia int IndexOf(T hledanyObjekt)
Metoda viaci index pivniho vskytu hledanho objektu (pesnji objektu, jen
je hledanmu objektu ioven). Pokud neni adn objekt nalezen, je viacena hod-
nota 1 (index neme bt zapoin). Ani tato metoda nemni svho adiesata tj.
piohledavan seznam.
Piklad
mereni.IndexOf(1.0) / / c
Jak je mono snadno odvodit, lze pio zjitni pitomnosti objektu v seznamu pou-
it ob vyhledavaci metody. Napiklad v podmince konstiukce if me pouivat
metodu Contains
if(mereni.Contains(0.0)) {
/ / ieakce na pitomnost nuly v meni
}
ale lze stejn tak i metodu IndexOf
if(mereni.IndexOf(0.0) >= 0) {
/ / ieakce na pitomnost nuly v meni
}
O tom jak eeni zvolit, iozhoduji ti obecna kiitiia
strunost zpisu pednost ma kiati zapis
(objektivn) pehlednost zpisu pednost ma zapis, ktei je objektivn pe-
hlednji, tj. bude mu lpe iozumt vice piogiamatoi (vetn autoia)
efektivita pednost ma efektivnji implementace (vyadujici mn asu a pa-
mti pio piovedeni). Rychlost ani pamovou naionost nelze pimo od-
vodit z asymptotick sloitosti, ale pedevim u dat s potencialn velkm
iozsahem ji je zahodno zohlednit.
11:
Pravidlo 13: Pokud existuje vce een, pak volme to, co spluje alespo jedno z
uveden kritria (lpe vak dv) a zbvajc pli nenaruuje. Pokud mme tst,
e je nejlep ve ve te, pak je rozhodovn triviln.
Vnaempipad je zapis vyuivajici Contains zaiove kiati a pehlednji (nevy-
aduje znalost do jist miiy podiniho pouiti hodnoty -1 na mist neexistujiciho
indexu). Ob metody maji stejnou sloitost (()) a piavdpodobn ob pouivaji
velmi podobnou implementaci, tj. doba vykonavani i pouiti pamti budou ob-
dobn.
4.1.3. Prochzen seznam
Vechny ve uveden metody (kiom indexace) piacuji se seznamem jako s cel-
kem. Mnohdy je vak poteba piacovat s jednotlivmi polokami a tu bu se vemi
nebo s jejich vbiem.
Jazyk C= nabizi dva pistupy ke zpiacovani seznam po polokach
1. vyuit cykl nad seznamy cykly umouji opakovan piovadni jed-
n opeiace nad jednotlivmi polokami). Tento pistup je typick pio tzv.
pioceduialni jazyky jako je C, nebo Pascal (a do znan miiy i PHP nebo Ja-
va). Tento pistup tak umouje snadno mnit poadi poloek i poloky
hodnotovch typ.
z. vyuit LINQ funkcionl tento zpsob je elegantnji, vyaduje vak
hlubi znalosti a zkuenosti. Seznamime se s nim a pozdji. Pokud vak
ji mame zkuenosti s funkcionalnimi jazyky nebo jazykem Ruby, pak Vam
bude pipadat piiozenji. Piotoe se jedna o funkcionalni eeni, neme
pimo mnit seznam tj. pimo uloen objekty a odkazy (lze vak mnit
odkazovan objekty)
Nejjednodui piochazeni seznam (a jinch kolekci) umouje cyklus forea, se
kteim jsme se ji seznamily.
Stejn jako v pipad etzc, i u seznam piochazi cyklus postupn vemi pivky
kolekce a kopiiuje je do lokalni piomnn.
foreach(double x in mereni) {
Console.WriteLine(x);
}
LlNQ je jazykov iozieni a a knihovni iamec umoujici pouivat sostikovan dotazy a tians-
foimace v iamci jazyka C=
Seznam zakladni kolekce 11
Tento cyklus piochazi postupn vechny pivky seznamu a v kad iteiaci uklada
novou poloku do piomnn x (tato piomnna musi bt kompatibilni s tidou po-
loek seznamu, tj. shodna i implicitn petypovatelna). Piotoe se jedna o objekty
hodnotov tidy (double), je do piomnn uloena kopie objektu (isla).
l kdy se me jevit detailni popis piazovani do lokalni piomnn zbyten, neni
tomu tak. Pio piklad si uveme mal fiagment piogiamu
foreach(double x in mereni) {
x = x*2;
}
Tento fiagment by ml vechny poloky v seznamu meni zdvojnasobit. Bohuel
nefunguje, a to tim nejhoiim monm zpsobem. Pi pekladu se neohlasi chyba
ani vaiovani, a dokonce ani pi bhu nevznikne vjimka (tj. piogiam se nepeiui
s chybovm hlaenim). Piost se jen nic viditelnho nestane, tj. seznam meni
bude obsahovat pvodni hodnoty.
Dvod je jednoduch stai si jen detailn ici co se pi vykonavani cyklu dje
1. je vytvoena alokovano misto pio piomnnou x (pouze jednou, to vak v-
sledek neovlivni)
z. v pivni iteiaci je do tto piomnn zkopiiovana pivni poloka seznamu
(islo). Kopiiovan je pimo objekt, nebo objekty tidy double jsou hodno-
tov.
I. nasledn je hodnota piomnn x zdvojnasobena (nikoliv hodnota poloky
v seznamu!)
1. na zaatku diuh iteiace je do piomnn zkopiiovano diuh islo se sezna-
mu (pvodni zdvojnasoben islo je pepsano, i kdy zatim nikde nebylo
pouito, tj. okolni svt se nezmnil)
Poznmka:
U iefeiennich typ je situace jet o nco sloitji (i kdy jedno-
due odvoditelna). Pokud zmnime v tle cyklu pimo obsah lokalni
piomnn tj. odkaz, tak stejn jako u hodnotovch tid ziskame kod,
ktei nic nemni (zmnna je kopie odkazu nikoliv odkaz v seznamu).
List<string> jmena = new List<string>(){"Gon", "Mor", "Eria"};
foreach(string jmeno in jmena) {
jmeno = jmeno + "dor";
}
11
Jina situace nastane v pipad, e nad objektem odkazovanm lokal-
nim piomnou zavolame metodu, kteia tento objekt zmni. Zde se ji
nemni obsah piomnn (to jest kopie), ale objekt, na ktei odkazuje
jak lokalni piomnna tak poloka seznamu. Seznam tak po piovede-
ni cyklu obsahuje stale stejn objekty, jejich stav je vak me bt
zmnn (tj. nejedna se ji o piazdn kod).
List<List<int>> matice = new List<List<int>>();
matice.Add(new List<int>());
matice.Add(new List<int>());
/ / seznam nyni obsahuje dva piazdn podseznamy ,
foreach(List<int> podseznam in matice) {
podseznam.Add(0); / / metoda mnici stav objektu
podseznam.Add(1); / / metoda mnici stav objektu
}
/ / seznam nyni obsahuje tyt podseznamy, ty jsou vak ji naplnn
/ / c,1, c, 1
Pravidlo 14: V rmci cyklu foieach nelze zamovat poloky prozen kolek-
c (tj. nahrazovat je za jin objekty). U referenn typ je vak mono mnit stav
objekt ze seznamu odkazovan (samozejm jen jsou-li tyto objekty modikova-
teln)
Specialnim pipadem pipadem tohoto piavidla je nemonost vzajemnho pe-
souvani objekt v iamci seznamu. Pomoci cyklu forea tak nelze iealizovat algo-
iitmy, ktei vyaduji piohazovani objekt (nap. tidici algoiitmy).
Dalim omezenim cyklu forea je pesn dan smi piochazeni kolekce a ne-
monost peskakovani pozic. Piochazeny jsou vechny objekty od pivniho do po-
sledniho. Pokud napiklad chceme piochazet jen objekty na sudch pozicich, i
seznam piochazet zptn, nelze cyklus forea bohuel pouit
Pokud potebujete piohazovat poloky seznamu i jej divoejim zpsobem pio-
chazet, pak se musite uchlit k indexaci a obecnmcyklm. l kdy namnic nebiani
pouivat znam cyklus while, existuje lepi eeni cyklus for.
iesp. pesnji iozumn pouit tj. bez pouiti nepehlednho pomocnho kodu a piomnnch, i bez
(pomalho) dvojitho obiaceni seznamu pomoci metody Reverse.
Seznam zakladni kolekce 11
Cyklus for
Cyklus for jazyka C= byl pevzat z jazyka C. Ve skutenosti je to jen jin zapis
cyklu while s hlavikou, v ni se kiom podminky uvadi i inicializani a inkie-
mentani ast. V jazyce C me cyklus for nabvat zcela iznoiodch a mnohdy
ilench podob (z nich nktei dokonce nejsou v jazyce C= ani pipustn). My
se vak seznamime jen s podobou, kteia se pouiva nejastji a zce souvisi s
indexaci seznam.
Zanme od zakladniho tvaiu
for(int i = 0; i < seznam.Count; i++)
Kliovou asti cyklu for je tzv. idici piomnna. Ta se je v naem piklad po-
jmenovana i, ale me mit libovoln jmno (pokud je vak piomnna pouivana
pio indexaci, je identikatoi i tm piavidlem). Tato piomnna je ped zaatkem
cyklu vytvoena a inicializovana. Denice a inicializace je piovedena v pivni as-
ti hlaviky (ped pivnim stednikem). Na poatku ma idici piomnna hodnotu
nula, co je index pivni poloky.
Diuhou asti hlaviky cyklu je pokiaovaci podminka, je je identicka s pokiao-
vaci podminkou cyklu while. V naem pipad piobiha cyklus, dokud je hodnota
idici piomnn meni ne velikost seznamu.
Teti ast obsahuje viaz, ktei je pioveden na konci kad iteiace (po piovedeni
tla cyklu). Tento viaz musi mit postianni efekt na idici piomnnou. V naem
pipad je hodnota idici piomnn zvena o jedniku (zapis i-- je, jak ji vime,
zkiatkou za piazeni i i-1).
Myslim, e Vam je ji pibh cyklu zejm, ale pio jistotu si jej podiobn popie-
me
1. nejdive je denovana a inicializovana idici piomnna. Jeji poateni hod-
nota je c.
z. pak je testovana podminka. Je-li piavdiva, je vykonano tlo cyklu tj. pivni
iteiace (v ni je hodnota idici piomnn iovna c). Vopanmpipad cyklus
koni (tlo neni piovedeno ani jednou)
I. po piovedeni pivni iteiace je vyhodnocen viaz i++. Ten zvi hodnotu
idici piomnn na 1.
11e
1. nasleduje opt kontiola podminky. Pokud je stale piavdiva (tj. hodnota i-
dici piomnn je meni ne velikost seznamu), je podiuh vykonano tlo
cyklu. Tentokiate vak idici piomnna uchovava hodnotu 1.
. po tle cyklu je podiuh vyhodnocen iteiani viaz (i++) a hodnota pio-
mnn je opt zvena o jedniku
e. .. (dali opakovani a testovani)
. posledni iteiace cyklu je piovedena s hodnotou seznam.Count-1 (tj. s hod-
notou indexu posledniho pivku)
s. pot je je hodnota idici piomnn zvena o jedniku a nabva tak hodnoty
seznam.Count
v. nyni ji neni podminka splnna, nebo neplati, e seznam.Count ( hodnota
idici piomnn) je mni ne seznam.Count. Cyklus koni a izeni je pe-
dano na nasledujici pikaz.
Jak lze snadno odvodit, cyklus se piovede seznam.Count-kiat (tj. -kiat, kde je
poet poloek seznamu). Hodnota idici piomnn nabva postupn hodnot c,1,
z a 1, tj. hodnot index vech poloek seznamu.
Cyklus for vak umouje volit i jin dolni a hoini meze hodnot idici piomnn.
Navic i kiok me bt jin (vdy vak nenulov).
Pokud je kiok kladn ma cyklus tvai
for(int i = dolnMez; i < hornMez; i += krok)
Hodnota idici piomnn nabva nasledujicich hodnot
dolnMez, dolnMez+krok, dolnMez+zkrok, a
\
|

[
1
}
krok.
Tlo cyklu je tak piovedeno
|

[
-kiat.
Napiklad u cyklu foi(int i11, i1cc, i-I) nabva idici piomnna hodnot 11, 11,
1, zc, zI, , vs a tlo cyklu se vykona
|
1cc11
I
[
Ic-kiat.
U zapoinho kioku je iole hoini a dolni meze zamnna
for(int i = hornMez; i > dolnMez, i-=krok)
Navic na iozdil od kladnho kioku je hoini mez do zahinuta do vytvaen po-
sloupnosti isel a dolni nikoliv. Tento cyklus ma stejn poet iteiaci, ale geneio-
vana isla jsou miin odlina
hornMez, hornMezkrok, ,hornMez
\
|

[
1
}
krok.
Seznam zakladni kolekce 11,
Ve zdanliv opanm cyklu for(int i=100; i > 11; i-=3) nabva piomnna
hodnot 1cc, v, v1, ,1e, 1I.
Pokud bychom chtli pomoci indexace piojit vechny sloky seznamu od pivni
do posledni, stai pouit zakladni tvai cyklu
for(int i=0; i < mereni.Count; i++) {
Console.WriteLine( mereni[i] ); / / vypi i-tou poloku
}
Stejnho efektu lze samozejm dosahnout i pomoci cyklu forea (viz ve). Cyk-
lus forea je navic mnohem pehlednji a stiunji (a tm stejn iychl).
V cyklu for vak lze naopak jednodue mnit hodnoty poloek seznamu
for(int i=0; i < mereni.Count; i++) {
mereni[i] = 0.0; / / vynuluje vechna meni
}
Dokonce lze snadno odkazovat sousedici poloky a nasledn je zamovat
List<int> seznam = new List<int>();
...
for(int i=0; i < seznam.Count-1; i++) {
if(seznam[i+1] < seznam[i]] {
int p = seznam[i+1]; / / zamnime

a
+1
seznam[i+1] = seznam[i];
seznam[i] = p;
}
}
To bohuel nese nebezpei mn siozumitelnch a k chybam nachylnm piogia-
mm. Napiklad u naeho fiagmentu piogiamu neni na pivni pohled zejm ko-
nen efekt. Pio pln pochopeni funkce cyklu je vhodn giack znazoinni
seznamu a (pelivm) iozboi jednotlivch elementainich kiok algoiitmu (kde
vmnu meme povaovat za elementaini kiok). Velikost seznamu zvolime co
nejmeni, piem se vak idime nasledujicim piavidlem
Pravidlo 15 (linmal is keinmal) Pi testovn algoritmu je nutno zvolit takov
vstupn data, aby se kad (klov) operace provedla alespo dvakrt.
linmal ist keinmal, k si Tom nme slov.
Co se udje jen jednou, jako by se nestalo nikdy.
118
Sm-li lovk t jen jeden ivot, je to jako by neil vbec.
Milan Kundeia, Nesnesitelna lehkost byti
To v naem pipad znamena, e musime zvolit alespo tipivkov seznam (aby
se piovedli alespo dv vmny).
Potom si peliv popieme jednotliv kioky (vyhodnoceni podminek, zmny pio-
mnnch, vmny) a iozkieslime jednotliv stavy seznamu. Seznam navic na za-
atku naplnime (nahodnmi) hodnotami. Celek by se ml podobat obiazku 1.I.
3 2 1
i=0 i+1
if(seznam[i+1] < seznam[i])
2 < 3 => vmna
2 3 1
i=1 i+1
if(seznam[i+1] < seznam[i])
1 < 3 => vmna
zatek 1.iterace
zatek 2.iterace
i++
1 < 2 (i < seznam.!"nt # 1)$ %!&m'nka c(k)" *e s%)nna
i++
2 < 2 (i < seznam.!"nt # 1)$ %!&m'nka nes%)nna$ c(k)"s k!n'
i = 0 (inicia)izace)
0 < 2 (i < seznam.!"nt # 1)$ %!&m'nka c(k)" *e s%)nna
k!nen stav 2 1 3
Obiazek 1.I. Cyklus foi, iozboi piovadni
Rozboiem obiazku snadno zjistime, e
se piovede deset elementainich opeiaci (vmnu poitame jako jedinou
opeiaci). Je navic zejm, e asova asymptoticka sloitost je lineaini (pokud
se dlka seznamu zvi o jedniku, pibudou tyi opeiace)
Seznam zakladni kolekce 11,
vechny pouit indexy jsou platn (tj. neukazuji mimo seznam). To je do-
saeno miinou modikaci pokiaovaci podminky cyklu. Misto bnho i <
seznam.Count (indexy bi od pivniho do posledniho) je pouita podminka
i < seznam.Count - 1 (indexy bi od pivniho do pedposledniho). D-
vodem, je skutenost e spolu s piochazenm pivkem odkazujeme i jeho
naslednika. Pokud bychom piochazeli i posledni pivek, byl by odkazovan i
neexistujici pivek za nim!
vsledkem piovadni je pesun nejvtiho pivku na konec seznamu. Nej-
vti pivek je vdy vymnn ze svm naslednikem a piobubla tak na konec
seznamu. To neni samo o sob zajimav (nejvti pivek, lze ziskat i snadnji)
je to vak pivni kiok k setidni seznamu. Nyni toti stai aplikovat stejn
algoiitmus na seznambez posledniho pivku, co zajisti pesun diuhho nej-
vyiho pivku na pedposledni pozici, nasledn na seznam bez poslednich
dvou pivk (teti nejvyi piobubla na teti pozici od konce) a tak dale do-
kud nam nezbude dvoupivkov seznam na zaatku (zde stai jen piohodit
pivky, pokud jsou patn uspoadany).
Tento algoiitmus tidni se nazva Bubble sort (bublinkov tidni). asto
se vyuuje na kuisech piogiamovani, nebo je snadno pochopiteln. V pia-
xi je vak pili pomal, a to jak pio mal seznamy (vyaduje pili mnoho
vmn), tak pio seznamy velk (jeho asova sloitost je (
z
)). Detaily viz
http://en.wikipedia.org/wiki/Bubble_sort.
4.1.4. Selektivn vmaz
Selektivni vmaz je navenek velmi jednoduchou opeiaci odstianni vech pivk
seznamu, ktei spluji uiitou podminku.
Piklady selektivniho vmazu zname i ze ivota (omezime se samozejm jen na
data)
vmaz souboi, ktei spluji jistou podminku (nap. jsou vti ne limit, i
jsou vlastnny neopiavnnm uivatelem)
odstianni zastaialch poloek z databaze (nap. student, ktei ji spn
ukonily studium, bvalch patel z adiesae)
odstianni evidentn chybnch daj z meni (tj. daj leicich mimo
mon i pipustn meze)
1:o
Vimnte si, e opeiace selektivniho vmazu (piomazani) se dje pimo nad sezna-
mem (databazi, souboiovm systmem, apod), ktei se jejim piovedenim zmeni,
piem odstiann poloky zmizi se systmu. Tim se lii od ltiovani, kdy jsou
ze seznamu kopiiovany poloky splujici jistou podminku (nap. v e-obchod je
zobiazeno jen levnji zboi). liltiovanimse seznam(databaze, souboiov systm,
apod.) nemni a adn poloky neopoutji systm.
My budeme pio jednoduchost piomazavat pouze iseln seznamy a budeme vy-
uivat tiivialni podminky (nap. budeme chtit odstianit vechny zapoina isla).
Je zejm, e pio selektivni vmaz musime pouit cyklus for (nikoliv forea), ne-
bo se mni pimo seznam (nikoliv objekty v nm uloen).
Zkusme nejdive algoiitmus, ktei se jevi jako pimoai a nejjednodui eeni.
Piochazejme postupn seznam (za pomoci index) a nalezen kandidaty odstia-
me pomoci metody RemoveAt (zname toti jejich index)
List<int> m = new List<int>(){5, -1, 3, -2, 6};
for(int i=0; i < m.Count; i++) { / / cyklus pes indexy vech pivk
if( m[i] < 0 ) { / / podminka vmazu
m.RemoveAt(i); / / vymaeme i-t pivek
}
}
Pokud tento fiagment vloite do piogiamu (postauje do hlavni metodyMainC-
lass.Main) a doplnite o vpis vsledn podoby seznamu (za pomoci cyklu s vpi-
sem kad poloky zvla) a nasledn peloite a spustite, tak se mete zdanliv
iadovat. Piogiam by ml vypsat jen kladn poloky (zapoin byly piomazany).
Bohuel Vae iadost je pedasna (avak nepiopadejte panice)
Pravidlo 16: Pokud V algoritmus i program funguje, neznamen to bohuel jet,
e je sprvn. Naopak asto to znamen, e jste jet neodhalily veny jeho yby.
Kde je vak chyba` Zkuste miin pozmnit testovaci seznam napiklad takto (na-
misto I je I a namisto e je e)
List<int> m = new List<int>(){5, -1, -3, -2, -6};
Po peloeni a sputni nas eka nepijemn pekvapeni, piogiam vypie , I
a e. Je to podivn. Nkteia zapoina isla byla odstianna a nkteia ne. Me
se dokonce zdat, e piogiam si njak zapamatoval pvodni podobu seznamu a
zapoina isla vypisuje, piotoe byla dive kladna (to u by byla skuten eina
magie).
Seznam zakladni kolekce 1:1
Pioblmje natsti jinde. Objevit ho lze detailnimiozboiemalgoiitmu (s vyuitim
giackho zobiazeni seznam a index), viz obiazek 1.1. Pi hodnot indexu = c
se nic zajimavho nedje, islo je kladn a tak se jen pejde na nasledujici pivek
seznamu. lndex je nyni ioven 1. Diuha poloka (m[1]) je zapoina tj. je odstianna
(viz stav vpiavo od diuh ipky). Potom je znovu zven index (=z). Tento index
vak nyni ukazuje na teti poloku zkiacenho seznamu (tj. na poloku, kteia by-
la v pvodnim seznamu a tvita tj. na hodnotu z). Poloka s hodnotou I byla
peskoena, tj. nebude u nikdy odstianna. Podobna situace nastane u posledni
poloky (pedchozi poloka je odstianna, index se tak posune a za konec sezna-
mu). Pioblm je nyni jasn, diky chyb v algoiitmu nejsou odstianny vechny
zapoin poloky, ktei jsou v souvisl sekvenci zapoinch poloek na sudch
mistech (po odstianni bezpiostedn pedchazejici poloky jsou peskoeny).
5 -1 -3 -2 -6 i = 0
if( m[0] < 0 ) -- nesplnno
i++ => i=1
if (m[1] < 0 ) -- splnno
removeAt(1)
i++ => i=2
if(m[2] < 0) -- splnno
removeAt(2)
i++ => i=3
c!l"s !on#$% ne&o'
i < m()o"nt nen$ splnno
5 -1 -3 -2 -6
5 -3 -2 -6
5 -3 -2 -6
5 -3 -6
5 -3 -6
0 1 2 3 *
Obiazek 1.1. Chybn algoiitmus selektivniho vmazu
1::
eeni je navenek velmi jednoduch. lndex budeme posouvat jen tehdy, pokud
nebyla aktualni poloka odstianna (v opanm pipad se index zdanliv posou-
va diky odstianni pivku a pesunu zbvajicich poloek vpiavo). Vlastni imple-
mentace je vak sloitji, nebo posun indexu je zajiovan inkiementaci, je je
zahinuta v cyklu foi a musi bt tudi piovedena po kad iteiaci (ne jen tehdy,
kdy se nam to hodi).
Jednou z cest je naviat k cyklu while (tam meme inkiementaci idit sami). Po-
kud chceme zachovat pouiti cyklu foi, pak je zdanliv dobim eenim eliminace
nevhodn inkiementace piotiakci tj. dekiementaci.
for (int i=0; i < m.Count; i++) {
if (m [i] < 0) {
m.RemoveAt (i);
i--; / / piotiakce
}
}
Toto eeni funguje, je vak nepehledn a ponkud extiavagantni. Pi vmazu je
index nejdive snien a bezpiostedn na to zven (ve vsledku tedy neni posu-
nut, ale to neni z piogiamu zcela zejm). Navic je naiueno jedno z piogiama-
toiskch piavidel
Pravidlo 17: Hodnota dc promnn cyklu foi, by nemla bt v tle cyklu mnna.
Jakakoliv zmna idici piomnn uvnit tla cyklu, toti naiuuje piavideln (ekvi-
distantni) kiok, ktei je pio tento cyklus typick (navic nemusi bt zejm jak a
kdy je tato piavidelnost naiuena). Po naiueni nemusi navic platit zakladni vztah
o potu iteiaci, jeho platnost viazn usnaduje kontiolu spiavnosti cyklu. Navic
v nkteich jazycich neni zmna idici piomnn vbec dovolena.
Matouci chaiaktei zmny idici piomnn, lze ilustiovat na piaktickm pikla-
d. Piavideln chod cykl for se podoba chodu ozubench koleek ve stiojich.
Zmna idici piomnn je obdobou zmny potu zub bhem otaeni ozubenho
koleka. To je sice v zasad mon, viazn to vak komplikuje a znepehleduje
konstiukci.
Nezbva tedy, ne pokiaovat v hledani spiavnho eeni (pokud vbec njak
takov existuje). Zamysleme se v em tkvi piina naeho pioblmu s indexaci.
Pi odstianni pivku se jako vedleji efekt mni indexy vech nasledujicich pivk
s seznamu. Obiazn eeno, podezavame si pod sebou vtev.
Seznam zakladni kolekce 1:
Pedstavte si, e potebujete odiznout velkou (vodoiovnou) vtev, a z piostoio-
vch dvod musite na tto vtvi pi ezani sedt. Navic budete vtev ezat po
astech (napiklad o dlce jeden meti). Na algoiitmus odpovida situaci, kdy na
zaatku sedite u kmene a eete vdy mezi kmenem a Vami. U pi pivnim ezu
se tak piojevi nepijemn vedleji efekt, vyplvajici ze zmny stavu ezan vtve
(piiovnani tiochu kulha, nebo u naeho pikladu neni naiueni zcela fatalni a
pioto se mete pokouet o ezy na dalich mistech).
Jak je spiavn eeni ezaciho pioblmu` Je zejm, e stai ezat vtve z diu-
h stiany (tj. co nejdale od kmene) a navic nikoliv mezi Vami a kmenem, ale na
diuh stian. Co z toho plyne pio na piomazavaci algoiitmus` Pi vmazu je
poteba piochazet seznam v opanm smiu (od poledniho k pivnimu pivku). Pi
odstianni pivk se posun index tka jen pivk, je nasleduji za odstiaova-
nm (ty jsou vak natsti ji zpiacovany). My v dali iteiaci postupujeme vpiavo
( k niim indexm), pesnji k pivku, jen pedchazi odstiann. Jeho index se
pi odstianni samozejm nezmnil.
for (int i=m.Count-1; i >= 0; i--) {
if (m [i] < 0) {
m.RemoveAt (i);
}
}
To je mnohem lepi eeni. Je pehledn a v tle se nemni hodnota idici piomn-
n. (avak pozoi zptn cyklus neni tak tiivialni jako pim, vimnte si mezi a
ielaniho opeiatoiu v podmince!).
S timto algoiitmem meme bt spokojeni, a na jeden meni pioblm. Jeho aso-
va sloitost je (
z
). Piovadi se toti vmaz (kde (c. 1] je podil necht-
nch pivk), piem kad vmaz ma sloitost (), piotoe vyaduje pesun
pivk na uvolnn misto. To neni tak patn, ale u vtich seznam a astjiho
piomazavani to me bt pioblm.
Pokud mate dostatek pamti mete zvolit elegantni a pitom velmi iychl eeni.
Namisto smazani pivk lze pesouvat ty peivi do novho seznamu (tj. pevst
vmaz na ltiovani). Pot stai pesmiovat odkaz z pvodniho na nov a nikdo
nic nepozna. Navic lze pouit cyklus forea (pvodni seznam se nemni, jen se
nakonec zahodi)
List<int> filteredM = new List<int>(m.Count);
/ / piazdn s kapacitou dostatenou pio vechny pivky pvodniho
foreach(int item in m) {
1:
if(item >= 0){ / / negace pvodni podminky (zachovame nezapoin)
filteredM.add(item); / / pidame do novho
}
}
m = filterM; / / pesmiujeme na nov a stai zahodime
Sloitost je pouze (), ale bohuel ne vdy lze toto eeni pouit, nebo musime
bt schopni pesmiovat odkaz (nelze jej pioto napiklad vyuit pio implementaci
ioziujici metody s postiannimefektem). Navic nutnost vyuiti dostateni pamti
nemusi bt akceptovatelna.
Poznmka:
Take stale nemame to skuten dokonal (tj. iychl, nenaion a
vdy pouiteln) eeni. To samozejm existuje, musime vak vyu-
it vestavnou metodu a syntaxi tzv. lambda viaz. Lambda viazy
nam toti umouji pedat podminku jako paiameti. Seznamime se
vak s nimi a pozdji. Ale u nyni si meme ukazat to idealni eeni
m.RemoveAll( item => item < 0);
Jak snadn, mil Watsone. Zapis item => item < 0 je lambda viaz, ie-
piesentujici funkci o jedn piomnn, kteia sloui jako vymazavaci
podminka. Zavola se na kadou poloku a pokud viati true, je po-
loka nemilosidn odstianna. asova sloitost je pouze () (podle
dokumentace).
Otazka Jak se podailo dosahnout lineaini sloitosti`
4.1.5. Piazen a duplikace
Seznamy jsou modikovateln iefeienni tidy (pivni s nimi jsme se seznami-
ly). Spojeni modikovatelnosti a odkaz pinai nkolik nepijemnch pioblm,
ktei lze natsti eliminovat, ale musite o nich vdt.
Hlavni pioblm si ukame na malm (maximaln jednoduchm) piklad
List<int> a = new List<int>();
List<int> b = a; / / a odkazuje na stejn objekt jako b
b.Add(0);
/ / vpis a c
/ / vpis b c
Seznam zakladni kolekce 1:
Pokud dobe chapete, co jsou piomnn a iefeienni tidy, je ve jasn a nepioble-
matick. Piomnna a i b odkazuji na stejn objekt-seznam a tak neni pekvapiv,
e po jejich vypsani ziskame stejn vsledek (vypisujeme dvakiat tot). Pekva-
piv to me bt pouze v pipad, pokud mate pedstavu, e a i b jsou identika-
toiy objekt (tj. ikate seznam a nebo seznam b). Pi tomto (chybnm) pohledu se
pivek pidan do seznamu a zazian objevi i v seznamu b.
Bohuel i ti, ktei chapou podstatu pioblmu, mohou bt nkdy pekvapeni. Peda-
me-li napiklad seznam do metody jako paiameti, nedojde k jeho zkopiiovani, ale
je pedan pouze odkaz. Jakakoliv zmna piovedena uvnit metody nad (zdanliv
lokalnim) seznamem se piojevi i ve volajicim kodu (pestoe metoda u davno
skonila).
Obecn plati, e kdykoliv nkomu pedame seznam (mnoinu daj), tak si nem-
eme bt jisti, e nam jej nezmni (nepida pivek, i naopak njak neodstiani).
Samozejm, dokumentace me nemnnost seznamu zaiuit, ale ne vdy je tato
infoimace explicitn zminna (v opanm pipad nezbva ne doufat).
Pokud si chcete bt jisti, e se seznamnikdo nezmni, nebo pokud nechcete sloit
kontiolovat kolik piomnnch sdili jedin seznam, pak musite seznam duplikovat
(pouiva se i teimin klonovat). Pi duplikaci se vytvoi nov objekt seznamu a do
nho se zkopiiuji vechny pivky pvodniho seznamu. Oba seznamy jsou oddlen
tj. zmna v jednom se nepiojevi v diuhm (i kdy to neplati zcela absolutn, viz
nie).
Nejjednodui monosti duplikace seznamu byla ji zminna konstiuktoi s pa-
iametiem tidy List.
List<int> c = new List<int>(a);
Piomnna c odkazuje na svou vlastni kopii seznamu s vlastnimi kopiemi objekt
(objekty hodnotovch tid zde int se kopiiuji). Jakakoliv zmna vetn zmn po-
loek se tak nepiojevi v pvodnim seznamu. Vyi bezpenost a nii psychick
zatieni piogiamatoi vak neni zadaimo. Klonovani samozejm zvyuje pam-
ov naioky (kad duplikat vyaduje alokaci dali pamti) a zpomaluje piogiam
(kopiiovani ma asovou sloitost ()).
Zajimavji situace vznikne, pokud seznam obsahuje poloky modikovatelnch
iefeiennich tid. Pio piklad si uveme seznam seznam
List<List<string>> maticeSlov =
new List<List<string>>() {
1:e
new List<string>(){"Frodo", "Bilbo"}, / / 1. adek
new List<string>(){"Gandalf", "Radagast"}}; / / z. adek
List<List<string>> duplikat
= new List<List<string>>(maticeSlov); / / duplikace
/ / pidame nov adek
duplikt.Add(new List<string>(){"Aragorn","Boromir"}); / / I. adek
/ / pidame nov sloupec
duplikt[0].Add("Samved"); / / pidani poloky do 1.adku
duplikt[1].Add("Saruman"); / / pidani poloky do z.adku
duplikt[2].Add("Faramir"); / / pidani poloky do I.adku
Nyni meme vypsat jednotliv matice (nap. pomoci dvou vnoench cykl).
Matice duplikat ma nasledujici obsah (nikoliv pekvapiv)
liodo Bilbo Samvd
Gandalf Radagast Saiuman
Aiagoin Boiomii laiamii
Podoba pvodni matice vak me bt ponkud pekvapiva
liodo Bilbo Samvd
Aiagoin Radagast Saiuman
Je zejm, e pidan adek neni sdilen (pidal se jen do duplikatu), pidan slou-
pec vak sdilen je (alespo ve sv asti). Jak k tto situaci dolo`
Nejdive se podivejme na obiazek zobiazujici poateni stav ( 1. na nasledujici
stian). Piomnna odkazuje na seznam nejvyi iovn. Ten obsahuje dvojici od-
kaz na podizen seznamy (adky). Kad z podizench objekt opt obsahuje
dva odkazy na objekty etzc. Celkov jsme tedy v iamci jedn denice vytvoili
sedm objekt (ti volani konstiuktoi pomoci new a tyi etzcov liteialy) .
Nyni seznam zduplikujeme (volanim konstiuktoiu s oiiginalnim seznamem jako
paiametiem) a odkaz na duplikat uloime do piomnn duplikt.
V tto fazi tedy mame dva seznamy, ktei vak sdileji sv poloky (seznamy jsou
iefeiennimi tidami a pi kopiiovani v iamci duplikace vnjiho seznamu se ko-
piiuji odkazy). K duplikaci podseznam a samozejm ani etzc nedojde. Stav
je zobiazen na obiazku 1.e
Seznam zakladni kolekce 1:,
0 1
maticeSlov
0 1 1
string:Frodo
0
string:Bilbo
string:Gandalf
string:Radagast
Obiazek 1.. Kopiiovani objekt s vice iovnmi odkaz (poateni stav)
0 1
maticeSlov
duplikt
0 1
0 1 1
string:Frodo
0
string:Bilbo
string:Gandalf
string:Radagast
Obiazek 1.e. Kopiiovani objekt s vice iovnmi odkaz (stav po duplikaci)
1:8
Pot pidame do seznamu, je je odkazovan piomnnou duplikat (na obiazku
umistn v dolni asti), nov pivek, v podob odkazu na nov vytvoen podse-
znam (vimnte si volani konstiuktoiu pomoci new). Tento pivek se samozejm
neobjevi v oiiginalni seznamu (a neni tudi ani sdilen). Od tto chvile jsou oba
seznamy nejen oddlen, ale i odlin, viz obiazek 1..
0 1
maticeSlov
duplikt
0 1 2
0 1 1
string:Frodo
0
string:Bilbo
string:Gandalf
string:Radagast
0 1
string:Aragorn
string:Boromir
Obiazek 1.. Kopiiovani objekt s vice iovnmi odkaz (stav po pidani adku)
Nasledn postupn pistupujeme k jednotlivm polokam duplikovanho sezna-
mu. Ten obsahuje ti podseznamy, z nich dva jsou sdilen s oiiginalnim sezna-
mem a jeden je soukiom. Do kadho objektu ( podseznamu) pidame nov
pivek ( objekt tidy string). Pivni dva se pidaji do sdilenho objektu a tak se
jejich pidani nepimo piojevi v obsahu oiiginalni matice. Teti je pidan do sou-
kiom poloky a nebude tudi sdilen. Vsledn stav je zobiazen na obiazku 1.s.
Vsledn systm obsahuje 11 dilich objekt, ktei jsou alespo asten sdileny
dvma seznamy nejvyi iovn. U takto sloitch objekt (iesp. objekt jet
sloitjich) je tk denovat identitu objekt a obtin zabianit nepijemnm
postiannim efektm.
Pravidlo 18: Nepouvejte objekty, kter sdlej s ostatnmi objekty systmu st
sv modikovateln podobjekt.
piavidlo neni absolutni, existuji situace, kdy je to naopak optimalni stav, ale tyto situace jsou jasn
Seznam zakladni kolekce 1:,
0 1
maticeSlov
duplikt
0 1 2
0 1 2 1
string:Frodo
0 2
string:Bilbo
string:Samvd
string:Gandalf
string:Radagast
string: Saruman
0 1 2
string:ragorn
string:Boromir
string: Faramit
Obiazek 1.s. Kopiiovani objekt s vice iovnmi odkaz (konen stav)
Pokud chceme toto piavidlo dodiet musime bu
pouivat pouze nemodikovateln objekty (sdileni nemodikovatelnch ob-
jekt nevadi, nikdo je toti neme zmnit a tak nikdy nevznikne adn
vedleji efekt), nebo
je nutn objekty dsledn duplikovat, piem nemusi stait kopie jedn
iovn tzv. mlka kopie [angl. shallow-copy] (tj. v naempipad je to dupli-
kace pomoci konstiuktoiu). Je nutno dsledn vyuivat tzv. hlubokou kopii
(angl. deep-copy), kdy jsou kopiiovany objekty na vech iovni (s vjimkou
nemodikovatelnch).
Vytvaeni hlubokch kopii neni zcela elementaini opeiaci. Je nutno zohlednit iz-
n typy sloench objekt, nemusi to bt jen seznamy a jin kolekce. Navic odkazy
mohou bt cyklick (nap. A odkazuje na B, B odkazuje na C a C odkazuje na A).
Z tohoto dvodu nelze napsat univeizalni kod, a hlubok kopiiovani se musi eit
ad hoc.
vymezen (nap. topologick stiuktuiy)
1o
Poznmka:
Platfoima .NlT obsahuje mechanismus tzv. serializace, co je pio-
stedek uloeni objekt (vetn sloench) do pioudu byt (nap. do
souboiu) a samozejm i deseiializace, co je konstiuovani objekt
z uloench bytovch dat. Nejjednodui implementaci hlubokho
kopiiovani je tudi seiializace a nasledna deseiializace (deseiializaci
vznika nov objekt dokonal duplikat). Seiializace vak byla vy-
tvoena pio jin ely (dlouhodob ukladani objekt v souboiech a
databazich) a neni optimalizovana pio duplikace (je nap. dosti po-
mala).
Pio na konkitni a jednoduch piklad je vak hlubok kopiiovani ielativn jed-
noduch (je nutno kopiiovat jen dv iovn, etzce jsou nemnn, a mohou tak
zstat sdileny)
List<List<string>> hlubokDuplikat =
new List<List<string>>(maticeSlov.Count);
foreach(List<string> radek in maticeSlov) {
hlubokyDuplikat.Add( new List<string>(radek) ); / / duplikat adku
}
Ukol Nakieslete si giaf objekt v pamti.
Poznmka:
Pi pouiti LlNQ a lambda viaz se ve jet zjednodui
var dupl = maticeSlov.Select(
row => new List<string>(row)).ToList();
4.2. Pklady roziujcch metod seznam
Na zavi sekce vnovan seznamm si vytvoime ti ioziuji funkce. Tyto funkce
nejsou pouze instiuktivni, ale mohly by bt i uiten. Pio jednoduchost budeme
vytvaet metody, ktei piacuji jen nad seznamy celch isel. Pouit algoiitmy
vak na tid poloek (tm) nezavisi a lze je vyuit i pio metody nad seznamy
objekt jinch tid. V poznamkach na konci podsekci si navic ukaeme eeni,
kteia podpoiuji seznamy tm libovolnch objekt, vyuivajic tzv. polymorsmu.
Seznam zakladni kolekce 11
4.2.1. Nhodn permutovn prvk v seznamu
V mnoha sofwaiovch aplikaci potebujeme imitovat nahodnost. Nejsou to jen
heini automaty, ale i izn simulace i vizualizace. Knihovny .NlT poskytuji za-
kladni geneiatoi pseudonahodnch isel, ale timjejich podpoia koni. Zcela chybi
i tak zakladni opeiace jako je nahodn piomichani pivk uiitho seznamu iesp.
foimalnji nahodna peimutace pivk uspoadan mnoiny. V anglitin se nefoi-
maln pouiva teimin (random) shuing.
Pomoci nahodnho peimutovani lze modelovat napiklad iozmistni osob v mist-
nostech nebo asovou naslednost objednavek v obchod (co je objednano jako
pivni, diuh atd.).
Pio nahodn piomichani pivk v kolekcich existuje jednoduch, ale efektivni
algoiitmus oznaovan jako Durstenfeldv algoiitmus, ktei je specialnim pi-
kladem staiiho algoiitmu Fisherova-Yatesova (viz http://en.wikipedia.org/wiki/
Fisher-Yates_shuffle).
Popis tohtoto algoiitmu pevzat z anglick Wikipedie je velmi jednoduch, neni
vak zapsan v jazyce C=, ale v tzv. algoiitmickm pseudokodu, je spojuje Pascal
a bnou anglitinu
To shuffle an array a of n elements (indices 0..n-1):
for i from n 1 downto 1 do
j random integer with 0 j i
exchange a[j] and a[i]
Po pekladu do etiny dostavame (specikace cyklu v pascalsk notaci neni pe-
loena)
Prohzen prvk n-prvkovho pole a (s indexy 0..n-1):
for i from n 1 downto 1 do
j nhodn cel slo, pro n plat 0 j i
zmna a[j] a a[i]
Je zejm, e v C= iepiesentaci tohoto algoiitmu pouijeme cyklus for, nebo do-
chazi k zamn pivk a iteiace je zptna (od posledniho pivku k pivnimu). Pio
geneiovani nahodnho isla z inteivalu [c. ] pouijeme metodu Next nad objek-
tem tidy Random (v piogiamu na ni odkazuje piomnna g). Jen si musime dat
1:
pozoi na to, e volani g.Next(a, b) viaci islo v iozsahu [. ) tj. hoini mez ne-
ni zahinuta. Pioto musime hoini mez zvit o jedniku. Pio zamnu vyuijeme
klasick algoiitmus vyuivajici pomocnou piomnnou.
for (int i = a.Count - 1; i >= 1; i--) {
int j = g.Next(0, i + 1); / / nahodn islo z inteivalu [c, i]
/ / zamna a[i] a a[j]
int p = a[i];
a[i] = a[j];
a[j] = p;
}
Abychom vak mohli algoiitmus otestovat, musime jej nejdive zahinout do ioz-
iujici metody (metoda Shue nad objektem tidy List<int>). Piotoe budeme
potebovat i vpis (piomichanho) seznamu doplnime jet jednoduchou iozi-
ujici metodu pio vpis seznamu do konzole (metodu oznaime identikatoiem
Print).
using System; / / shue.cs
using System.Collections.Generic;
static class ListExtensions {
static Random g = new Random(); / / staticka inicializace geneiatoiu
public static void Shuffle(this List<int> a) {
for (int i = a.Count - 1; i >= 1; i--) {
int j = g.Next(0, i + 1); / / nahodn islo z inteivalu [c, i]
/ / zamna a[i] a a[j]
int p = a[i];
a[i] = a[j];
a[j] = p;
}
}
public static void Print(this List<int> a) {
for (int i=0; i < a.Count; i++) { / / pio kad index seznamu
Console.Write(a[i]); / / vypi pivek
if (i < a.Count - 1) { / / neni-li pedposledni
Console.Write(","); / / vypi oddlova
}
}
Console.WriteLine(); / / a nakonec odadkuj
Seznam zakladni kolekce 1
}
}
class MainClass {
public static void Main(string[] args) {
/ / testovaci seznam
List<int> test = new List<int>(){1,2,3,4};
for (int i=0; i<48; i++) { / / 1s-kiat
test.Shuffle(); / / piomichej
test.Print(); / / a vypi
}
}
}
Nejzajimavji asti plnho piogiamu je denice piomnn g odkazujici objekt
pio geneiovani nahodnch isel. Pivotn jsem denici umistil na zaatek meto-
dy Shue. Pio kad volani piomichavaci metody se tak vytvaela nova instance
tidy Random. To nesniuje efektivitu piogiamu, nebo vytvoeni novho gene-
iatoiu je iychl a nevyaduje adn zvlatni piostedky. Piogiam fungoval, ml
vak jeden nepijemn nedostatek, obsah seznamu se pili nepiomichaval. N-
ktei kombinace se tm piavideln opakovaly a jin se naopak vbec neobjevily.
Dvodem tohoto podivnho (i kdy nikoliv zcela neoekavanho) chovani je me-
chanismus inicializace geneiatoiu. Ten toti vyaduje nastaveni jedinen poa-
teni hodnoty a v bnm poitai existuje pouze jedin univeizalni zdioj unikat-
nich isel hodiny iealnho asu. Tento zdioj neni zcela idealni, nebo se mni jen
ielativn pomalu, v adu setin sekundy. Pokud bhem tto zdanliv velmi kiatk
doby vytvoime vice geneiatoi, pak jsou vechny nastaveny stejn a poskytu-
ji stejnou posloupnost nahodnch isel. Tato situace nastala i zde, nebo dobu
piovedeni metody Shue lze vyjadit v mikiosekundach. Pivky se tudi sice pio-
michavaly, ale pokad za pouiti ti stejnch vmn. Neni divu, e se jednotliv
peimutace zaaly opakovat.
Jak jsem tento pioblm (a jeho eeni) odhalil` Pomohly mi m dlouholet zkue-
nosti, ktei vak piavdpodobn nemate. Co vak mete udlat u dnes, je pio-
studovani dokumentace. Dokumentace imy Microso neni obecn pili kvalitni,
ale tento pioblm natsti zmiuje
e default seed value is derived from the system clo and has nite resolution.
As a result, dierent Random objects that are created in close succession by a call
to the default constructor will have identical default seed values and, therefore, will
1
produce identical sets of random numbers. is problem can be avoided by using
a single Random object to generate all random numbers. ( zdioj MSDN, Random
Constructor pio .NlT 1., http://msdn.microsoft.com/en-us/library/h343ddh9.aspx).
eeni je tudi jasn, vyuiti jedinho objektu tidy Random pio vechna volani
piomichavaci metody. Zde je vyuit statick (tidni) datov len uvnit pomocn
tidy ListExtensions, ktei je inicializovan jen jednou a to ped pivnim volanim
ioziujici metody. Statickm datovm lenm budeme vnovat pozoinost poz-
dji, zde si je meme pedstavit jako piomnn, ktei existuji celou dobu vyko-
navani piogiamu (a jsou tudi jen jednou inicializovany) a ktei jsou dostupn
jen v iamci metod dan tidy (vetn metod statickch a tudi i ioziujicich).
Ostatni asti piogiamu by Vam mly bt zejm. Pio vpis seznamu (ioziujici
metoda Print) je vyuit cyklus for, nebo zpiacovani posledniho pivku se od ostat-
nich miin lii, nebo za poslednim pivkem nemusi bt vypsan oddlova (zde je
to aika a mezeia). V cyklu forea nelze jednodue zjistit, zda je piochazen pi-
vek posledni i nikoliv.
Poznmka:
Jak jsemzminil na zaatku tto sekce, musime jet piodiskutovat po-
uitelnost naich ioziujicich metod pio seznamy, jejich polokami
jsou jin tidy. Nae implementace pedepisuje, e adiesatem obou
metod (Shue a Print) je seznam isel tidy int. Pio jin seznamy je
tak nelze pouit. Pokud se vak pokusime vytvoit obdobn metody
pio jin tidy poloek, snadno zjistime, e jsou tm identick. Lii
se jen v zamn identikatoiu tidy poloek v hlavikach metody a v
denici pomocn piomnn v kodu zamny. Jako piklad si meme
uvst veizi pio seznamy etzc
public static void Shuffle(this List<string> a) { / / 1. zmna
for (int i = a.Count - 1; i >= 1; i--) {
int j = g.Next(0, i + 1); / / nahodn islo z inteivalu [c, i]
string p = a[i]; / / 2. zmna
a[i] = a[j];
a[j] = p;
}
}
public static void Print(this List<string> a) { / / 3. zmna
for (int i=0; i < a.Count; i++) { / / pio kad index seznamu
Console.Write(a[i]); / / vypi pivek
Seznam zakladni kolekce 1
if (i < a.Count - 1) { / / neni-li pedposledni
Console.Write(","); / / vypi oddlova
}
}
Console.WriteLine(); / / a nakonec odadkuj
}
Modeini jazyky, k nim C= pati, pioto podpoiuji i tzv. polymorfn
metody. Polymoifni metody jsou schopny pevzit a zpiacovat objek-
ty vech tid, jejich iozhiani podpoiuje vekei metody a opeiace,
ktei jsou nad nimi v tle metody volany. V pipad naich iozio-
vacich metod to mohou bt seznamy s libovolnmi polokami, nebo
v metod Shue neni nad objekty poloek volana adna metoda a
v metod Print je to pouze metoda ToString, je je dostupna u vech
objekt v systmu.
Jazyk C= podpoiuje dva typy polymoismu. Tzv. stati polymor-
smus je zastoupen geneiickmi metodami. Statick polymoismus
ei iozdily mezi tidami ji v dob pekladu. Ve skutenosti dla auto-
maticky tot, co jsme ve piovadli iun. Pio kadou tidu poloek
vytvoi automaticky novou veizi metody, v ni nahiadi obecn jm-
no tidy za jmno skuten. Nasledujici fiagment piogiamu ukazuje
geneiickou veizi metody Shue. Ta se od bn metody lii uvedenim
jmen tzv. geneiickch typ v lomench zavoikach (zde je pouit jedi-
n geneiick typ oznaen identikatoiem T). Tyto typy neoznauji
konkitni tidy, jsou pouze jejich zastupci. Ve vsledn specializova-
n veizi metody budou nahiazeny identikatoiem skuten tidy (tj.
nap. tidou int nebo string). Zastupn jmno je pouito jak v oznae-
ni tidy paiameti, tak i v denici piomnn (je zejm, e piomnna
musi mit stejn typ jako poloky seznamu).
public static void Shuffle<T>(this List<T> a) {
for (int i = a.Count - 1; i >= 1; i--) {
int j = g.Next(0, i + 1); / / nahodn islo z inteivalu [c, i]
T p = a[i];
a[i] = a[j];
a[j] = p;
}
}
1e
Diuh typ polymoismu je oznaovan jako dynami. Pi pouiti
tohoto typu polymoismu, se o skutenm tid objekt iozhodne a
za bhu. Aby dynamick polymoismus fungoval, musi existovat in-
kluzivni ielace mezi tidami (tj. uiita tida je podtidou jin tidy) a
iozhodnuti o tom jaka veize metody se pouije musi bt piovedeno
a v okamiku jejiho volani. V objektovch jazycich se vyuiva me-
chanism ddinosti, iozhiani a pozdni vazby, kteim se budeme v-
novat pozdji. Piozatim si ukaeme, jak by vypadala pln polymoifni
veize metody Print (tentokiat s vyuitim dynamickho polymois-
mu). ldentikatoi IList oznauje iozhiani, ktei spluji vechny se-
znamy bez ohledu na typ poloek (a nejen seznamy, ale i dali podob-
n kolekce). Ty vechny lze pouit jako paiameti metody.
public static void Print(this IList a) {
for (int i=0; i < a.Count; i++) { / / pio kad index seznamu
Console.Write(a[i]); / / vypi pivek
if (i < a.Count - 1) { / / neni-li pedposledni
Console.Write(","); / / vypi oddlova
}
}
Console.WriteLine(); / / a nakonec odadkuj
}
Metodu Print by bylo mono polymoifn zapsat i pomoci statickho
polymoismu. To vak ji necham na Vas.
4.2.2. Test setdn seznamu
Seznam budeme oznaovat jako setidn (iesp. seazen) pokud plati
a)
cz


+1
(seznam iostouci nebo s konstantnim pibhem)
b)
cz


+1
(seznam klesajici nebo s konstantnim pibhem)
Specialnim pipadem jsou piazdn a jednopivkov seznamy, ktei meme pova-
ovat za setidn. Dokonce i dvoupivkov seznamy jsou vdy setidn (spluji
vdy bu podminku (a) nebo (b)).
Algoiitmus pio seznamy s vice ne dvma pivky je jednoduch a piiozen. Po-
iovnate pivni dva pivky a zjistite, ktei z nich je vti. Tim zjistite, jak smi
(iostouci i klesajici) by ml mit zbytek seznamu. Tento smi budete ovovat
Seznam zakladni kolekce 1,
i pio nasledujici (pekivajici se) dvojice pivk (diuh s tetim, teti s tvitm,
atd.). Tj. je-li
c
<
1
, pak musi pio vechny ostatni pivky platit


+1
(ios-
touci seznam), naopak je-li
c
> , pak musi platit


+1
(klesajici seznam).
Bohuel me nastat i situace, kdy
1
=
z
. Pak nememe iozhodnout o pi-
bhu seznamu (seznam me bt iostouci, klesajici, konstantni a samozejm i
nesetidn).
Tuto situaci lze eit dvma zpsoby
1. hledanim pivni odlin dvojice, kteia nam uii pibh, dale v seznamu. Po-
kud neni adna takova dvojice nalezena, ma seznam konstantni pibh (a
tudi je setidn). V opanm pipad je nutno ovit zda vechny nasle-
dujici dvojice dodiuji stejn pibh. (evolun een )
z. iozienim mnoiny stav o stav konstantni a pizpsobenim ovovacich
piavidel (revolun een )
Vhodou diuhho eeni je sjednoceni pistupu pio vechny pivky (neni nutno
hledat pivni neshodnou dvojici). Navic podminky ovujici zachovani stavu jsou
jen miin sloitji
1. Pokud je pibh pio pivnich pivk konstantni, pak v pipad, e

<
+1
zmnime stav pibhu na iostouci, pio

>
+1
na klesajici. Jinak se stav
nemni, nebo seznam ma stale konstantni pibh.
z. Je-li pedchozi pibh po pivcich iostouci, pak musi platit


+1
(stav
se nemni). Vopanmpipad je seznamnesetidn a metoda me skon-
it (ostatni pivky u neni poteba kontiolovat)
I. Podobn je-li pedchozi pibh po pivcich klesajici, pak musi platit

+1
(stav se nemni). V opanm pipad je seznam nesetidn a metoda
me skonit (ostatni pivky u neni poteba kontiolovat).
Na poatku (dokud jet neni zpiacovan adn pivek), by ml bt stav nastaven
na konstantni (neme pedjimat ani iostouci ani klesajici pibh).
Pokud piogiam spn zkontioluje vechny pivky, pak plati, e je setidn. V
opanm pipad by metoda skonila pedasn pi nalezeni pivk s opanm
pibhem.
Zakladni funkce algoiitmu je piesentovana na obiazku 1.v na nasledujici stian.
ipky (nad seznamem) znazoiuji aktualni pibh, ielani opeiatoiy (pod sezna-
mem pak zjitnou ielaci). Znazoinny jsou ti typick piklady (iostouci, klesa-
18
jici, nesetidn). tvitou monosti je seznam s jedinou opakovanou hodnotou
(konstantni pibh).
1 1 2 3 3
3 3 3 3 2
1 1 2 4 3

x
=

zjitn relace
prbh (po teston!"
= = = #
zjitn relace
prbh (po poronn!"
set$!%n&
set$!%n&
zjitn relace
prbh (po poronn!"
neset$!%n&
=
'
Obiazek 1.v. Test setidni seznamu (typy pibh)
Tim konime algoiitmick iozboi a meme pejit k iepiesentaci dat i kodu.
Piomnna udiujici pibn stav (pibh) me nabvat ti hodnot. Neme
tudi uchovavat hodnoty tidy bool (existuji jen dva objekty tto tidy). Stavy
vak lze iepiesentovat piostednictvim jinch tid
int: nap. pomoci hodnot c (konstantni pibh), 1 (iostouci pibh) a -1 (klesa-
jici pibh), ielativn intuitivni a efektivni, nachyln k chybam, nebo do
piomnn lze vloit i jin celoiseln hodnoty.
string: nap. pomoci etzc konstantni, iostouci a klesajici. Neefektivni (vi-
ce ne zcbyt na objekt), siln nachyln k chybam (mete vloit jakkoliv
etzec, z nich mnoh se mohou jevit jako iozumn nap. ioste). lntui-
tivni jsou navic jen pio echy (a i pio n jen omezen).
Seznam zakladni kolekce 1,
Ostatni nam znam tidy pinaeji stejn pioblmy (ar, double), nebo jsou s-
manticky zcela nepouiteln (System.Datetime).
Natsti nam jazyk C= nabizi vhodnji eeni piostednictvim tzv. vtov tdy
(vtovho typu)
Vty
Vty jsou specializovan tidy, ktei maji pesn denovan poet monch in-
stanci. Tento poet je ve vtin pipad velmi mal, maximaln desitky. Uivatel
me vytvaet vlastni vtov tidy, piem specikuje vechny potencialni ob-
jekty dan tidy vtem jejich symbolickch jmen (identikatoi).
enum Barva {
Modra,
Cervena,
Bila
}
Timto zapisem (denici) vznikne nova vtova tida, kteia me mit ti izn in-
stance (piozatimse vak adna instance nevytvoi). Kada instance ma symbolick
jmno, ktei musi bt v iamci vtu unikatni.
lnstance vtov tidy si mete vytvoit kdekoliv v piogiamu pomoci zapisu
JmnoTdy.JmnoObjektu, nap. Barva.Modr.
lnstance vtovch typ se pouivaji jako symboly, ktei nemaji adnou vnitni
stiuktuiu a nepodpoiuji adn metody, vlastnosti a opeiace kiom vzajemnho
poiovnani (testu iovnosti).
Objekt Barva.Modr tak napiklad nelze inteipietovat jako popis baivy (nap. uve-
denimjeji pozice v baievnmpiostoiu RGB), ani jako etzec pti znak (tj. otazka,
jakm znakem symbol zaina nema adn smysl). Baivy nelze samozejm sitat
i nasobit ani zjiovat, jaka z nich je vti i meni.
Jedinou spiavnou inteipietaci, je chapani objektu jako jedinen entity, kteiou
lze jednodue a jednoznan odliit od vech ostatnich objekt vtu. Tj. v naem
pipad je modia baivou, o ktei nic nevime, ale dokaeme ji jednoznan odliit
od baivy bil a eiven (jin baivy v naem modelu nejsou).
Nasledujici fiagment piogiamu ukazuje vechny opeiace, ktei lze bn s objek-
tem vtovho typu piovadt
1o
Barva b = Barva.Modra; / / vytvoeni a uloeni v piomnn
...
if(b == Barva.Modra) { / / test iovnosti identity
/ / zde bude kod zavisl na hodnot piomnn vt. typu
}
Console.WriteLine( b.ToString() ); / / vpis symbolickho jmna
Vpis instance vtu (iesp. jeho symbolick iepiesentace) by se navic ml vyui-
vat jen pio ely ladni (tj. jen ve fazi vvoje piogiamu a jen pio piogiamatoiy).
Symbolick oznaeni vtovch objekt je toti stejn jako jmna piomnnch i
tid pouze inteinim oznaenim a pio koncov uivatele musi bt tiansfoimovano
do popisnch etzc (nejlpe v jazyce uivatele), i jet lpe do jin (netextov)
iepiesentace (zde napiklad obaivenim vizualniho pivku na modiou baivu).
Poznmka:
Vtov tidy (typy) jsou bohuel v C= pouivany i k jinm elm,
ne k zavadni mnoin jednoznanch symbol. Navic se navenek
piojevuje i jejich inteini iepiesentace pomoci celoiselnch konstant.
Vsledkemje situace, kdy lze snadno napsat syntakticky spiavn kod,
ktei je vak vice ne pochybn (tj. nelze jej iozumn inteipietovat)
Barva b = (Barva)42; / / ` nedenovana baiva
Barva b1; / / implicitn symbol s iepiesentaci c (nejasteji pivni uveden) zde Modia
Barva b2 = Barva.Bila;
if (b1 < b2) {...}
/ / piavdiva podminka, ale jen z dvod vnitni iepiesentace
b2 = b1 + 1; / / bz je ceivena, ale pio`
b2 = b1 * 10;
/ / ` nesmyslna opeiace, jejim vsledkem je nedenovana baiva
Nkdy se vak celoiselna iepiesentace hodi. Tyto pipady je vak
nutno stiiktn odliovat od vyuita vtovch tid jako mnoin sym-
bol! Syntakticky je to stejna konstiukce, ale smanticky je to nco
pln jinho.
Seznam zakladni kolekce 11
Vtov typ jako mnoina sel se symboliou representaci
enum Hodnoceni {
Negativni = -1, / / hodnoty symbol jsou explicitn uvedeny
Neutrlni = 0,
Pozitivni = 1;
}
Hodnoceni h; / / implicitn c tj. neutialni
if(h >= Hodnoceni.Neutralni) / / alespo neutialni
Hodnoceni h2 = -h; / / opan hodnoceni
h++; / / zlepeni hodnoceni o stupe
/ / ale to neni zcela koei, pio Pozitivni neni denovano!
U vt tohoto typu je vhodn explicitn denovat iepiesentovan
iseln hodnoty. Pokud se neuvedou, pak je pivni poloka iepiesen-
tovan nulou a ostatni maji iepiesentaci o jedniku vyi ne pedcho-
zi poloka (a u je dana explicitn i nikoliv). A na zcela vjimen
pipady by mly bt pouit iseln hodnoty v iamci vtu jedinen.
Vtov typ jako mnoina bitov pznak
Bn objekty i hodnoty nemohou nikdy zaujimat mn ne byte
pamti. Repiesentace objekt vtovch typ (shodna s iepiesentaci
isel tidy int) zaujima dokonce byty tyi.
Pokud se vak v iepiesentaci symbolickch konstant omezime pou-
ze na hodnoty obsahujici v binaini (dvojkov) iepiesentaci jedinou
jedniku (tj. mocniny dvou), je mono uloit vice tchto hodnot do
vicebytov inteini iepiesentace. Objekt vtovho typu pak ji ne-
iepiesentuje jedinou hodnotu, ale mnoinu hodnot (z nich kada je
navic iepiesentovana symbolickm jmnem).
Pio manipulaci s jednotlivmi hodnotami je nutno vyuit tzv. bito-
vch opeiaci tj. logickch opeiaci, ktei se piovadji mezi jednotli-
vmi bity iepiesentace isla. Maximalni poet iepiesentovatelnch
hodnot je dan potem bit tto iepiesentace, implicitn je to Iz hod-
not ( poet bit ve 1 bytech). V nasledujicim pipad je to z hodnot
(len lviopsk unie).
1:
[Flag]
enum EUMembers {
Austria = 0x00000001, / / 1
Belgium = 0x00000002, / / z
Bulgaria = 0x00000004, / / 1
Cyprus = 0x00000008, / / s
Czechia = 0x00000010, / / 1e
Denmark = 0x00000020, / / Iz
Estonia = 0x00000040, / / e1
...
Sweden = 0x04000000, / / e1csse1
UK = 0x08000000 / / 1I1z1zs
}
EUMembers visegrad_group =
EUMembers.Czechia | EUMembers.Poland |
EUMembers.Slovakia | EUMembers.Hungary;
EUMembers euro_zone =
EUMembers.Austria | EUMembers.Belgium |
... | EUMembers.Spain;
/ / pidani pivku
euro_zone |= EUMembers.Estonia;
/ / zkiatka za euiozone euiozone lUMembeis.lstonia,
/ / vyjmuti pivku
euro_zone &= ~EUMembers.Greece;
/ / pinik mnoin
EUMembers euro_visegrad = visegrad_group & euro_zone;
/ / testovani pislunosti
if( EUMembers.Czechia & euro_zone ) {
...
}
Console.WriteLine( visegrad_group.ToString() );
/ / vypie seznam jmen stat oddlen svislitkem
Vimnte si pouiti zapisu [Flag] ped hlavikou vtovho typu. Je
to piklad tzv. atributu, pomoci nho lze dodat dodaten infoima-
Seznam zakladni kolekce 1
ce (metadata) ke tidam (a tak napiklad i metodam). Tento atiibut
je uloen do vslednho bytovho kodu a me bt vyuivan pio-
giamem i exteinimi nastioji. Atiibut Flag je zde vyuivan metodou
ToString, kteia pi jeho uvedeni spiavn inteipietuje sloen hodnoty
(pi absenci piznaku by vypisovala jen nepehledna isla).
Konverze z etzce a globln operace s vtovm typem
Zakladni opeiace s vtovm typem lze piovadt pimo s objektem
vtovho typu (petypovani na celoiselnou hodnotu a pevod na
etzec). Pio dali opeiace je vak nutno vyuit tidni metody tidy
System.Enum (nikoliv tedy tidni metody jednotlivch vt!). Ti-
da System.Enum nema adn vlastni instance-objekty, poskytuje vak
pomocn (statick) metody pio instance vech vt a je foimaln
pedkem v hieiaichii ddinosti pio vechny vty (ddinosti se bu-
deme zabvat a pozdji)
using System;
enum Vlak {
Os,
R,
Ex
}
Vlak vlak = Enum.Parse(typeof(Vlak), Console.Readline());
/ / opeiatoi typeof viaci objekt iepiesentujici tidu,
/ / je je jeho aigumentem
foreach(Vlak vlak in Enum.GetValues(typeof(Vlak))){
Console.WriteLine( vlak ); / / iteiace pes vechny instance vtu
}
foreach(string jmenaTypuVlaku in Enum.GetNames(typeof(Vlak))){
/ / iteiace pes etzcov iepiesentace
}
=
Nyni se viatime k naemu piogiamu. Nejdive vytvoime kostiu piogiamu s ti-
dami a metodami (zatim bez vlastniho kodu).
using System;
using System.Collections.Generic;
1
enum Prubeh {
Klesajici,
Konstantni,
Rostouci
}
static class ListUtil {
public static bool JeSetriden (this List<int> seznam) {
/ / zde bude kod ioziujici metody
return true;
}
}
class MainClass {
public static void Main (string[] args) {
/ / zde bude testovaci kod
}
}
Kod ioziujici metody vychazi z algoiitmu uvedenho na zaatku podsekce (sti.
1Ie). Jadiem je cyklus piochazejici vechny pivky seznamu. Zvolen je cyklus for,
nebo umouje souasn pistup ke dvma pivkm(u nas jsou to pivky

a
+1
).
V zasad lze pouit i cyklus forea a pamatovat si pedchozi pivek (nevhodou
vak je nutnost specialniho zpiacovani pivniho pivku a piazdnho seznamu).
Prubeh prubeh = Prubeh.Konstantni;
for (int i=0; i < seznam.Count-1; i++) {
if (prubeh == Prubeh.Konstantni) {
if (seznam[i] < seznam[i + 1]) {
prubeh = Prubeh.Rostouci;
} else {
if (seznam[i] > seznam[i + 1]) {
prubeh = Prubeh.Klesajici;
}
/ / jinak zstava pibh nezmnn
}
} else { / / nekonstantni pibh
if (prubeh == Prubeh.Klesajici && seznam[i] < seznam[i + 1]
||
Seznam zakladni kolekce 1
prubeh == Prubeh.Rostouci && seznam[i] > seznam[i + 1])
return false;
}
}
return true; / / je setidn
Kod metody zaina nastavenim poateniho pibhu (na zaatku neni znam sku-
ten pibh, pioto je zvolen neutialni tj. konstantni ). Cyklus piochazi vechny
pivky kiom posledniho (posledni pouit index je seznam.Count-2). Pokud by
byl piochazen i posledni pivek, dolo by k peteeni indexu pi pistupu k nasle-
dujicimu ( + 1) pivku.
Nejdive je een pipad, kdy je piozatimni pibh konstantni. Pak je jsou ti mo-
nosti (pioto je nutn v tto vtvi pouit dva vnoen cykly if, jedno if umouje
vyeit pouze dv monosti)

<
+1
pibh se mni na iostouci

>
+1
pibh se mni na klesajici
jinak (tj.

=
+1
) pibh se nemni (tj. neni teba vykonat
nic, pioto chybi ast else ve vnoenm if )
Pokud je piozatimni pibh nekonstantni (ast else vnjiho podminnho via-
zu), pak testujeme, zda jej nenaiui dali pivek (s indexem i-1). Naiueni me
nastat pouze ve dvou pipadech
=

<
+1
nebo
=

>
+1
Pokud tato situace nastane, je ioziujici metoda ukonena s vsledkem false (se-
znam neni setidn).
V opanm pipad se nic nedje (opt chybi ast else) a piogiam pokiauje dali
iteiaci (tj. testovanim daliho pivku).
Vokamiku, kdy jsou spn (tj. bez pedasnho ukoneni) zkontiolovany vech-
ny pivky, je cyklus ukonen a metoda viaci (a po skoneni cyklu!) hodnotu true.
Algoiitmus je ielativn jednoduch, miin matouci vak me bt sple navzajem
vnoench podminek. V oiientaci Vam me pomoci diagiam aktivit (nastupce
dive pouivanch vvojovch diagiam).
Algoiitmus neni zcela tiivialni a pioto musi bt dsledn otestovan. Testovaci kod
umistn do metody MainClass.Main obsahuje pt testovacich seznam.
1e
prubeh=Rostouci
prubeh=Kl esaj i ci
seznam je neusporadany
test naruseni prubehu test predchozi ho prubehu
[ prubeh = Rost ouci && x[ i ] > x[ i +1]
| | prubeh = Kl esaj i ci && x[ i ] < x[ i +1]
[ j i nak]
[ prubeh! =Konst ant ni ]
[ x[ i ] =x[ i +1] ]
[ x[ i ] >x[ i +1] ]
[ x[ i ] >=x[ i +1] ]
[ x[ i ] <x[ i +1] ]
[ prubeh=Konst ant n ]
Visual Paradigm for UML Community Edition [not for commercial use]
Obiazek 1.1c. Logika vtveni v tle cyklu (test setidnosti)
Seznam zakladni kolekce 1,
List<int> t1 = new List<int>(){1, 1, 3, 3, 5, 8};
List<int> t2 = new List<int>(){1, 1, 3, 5, 3, 8};
List<int> t3 = new List<int>(){1, 0};
List<int> t4 = new List<int>(){1, 0, 1};
List<int> t5 = new List<int>(){0, 0, 0, 0};
Console.WriteLine(t1.JeSetriden());
Console.WriteLine(!t2.JeSetriden());
Console.WriteLine(t3.JeSetriden());
Console.WriteLine(!t4.JeSetriden());
Console.WriteLine(t5.JeSetriden());
Seznam t1 je iostouci (a tudi setidn). Seznam t2 je nesetidn (je pevan
iostouci, ale po islu nasleduje I). Seznam t3 je klesajici ( setidn), na iozdil
od seznamu t4 (ten je nejdive klesajici pak vak ioste). Seznam t5 obsahuje jen
nulov pivky, je tudi setidn (konstantni pibh).
Pi testovani vypisujeme pimo vsledek volani metody, pokud oekavame, e
bude ioven true (tj. pozitivni). Pokud vak oekavame vsledek negativni (false)
vypieme jeho negaci. Na vstupu by se tedy ml objevit ptkiat etzec Tiue.
Ve uvedena implementace viaci pio testovan seznamy spiavn vsledky, to
vak bohuel stopiocentn nezaiuuje, e je spiavna. Nelze toti vylouit, e pio
jin (netestovan) etzec metoda sele. Piotoe jsme vak otestovali vechny ty-
py pibhu, je tato piavdpodobnost velmi mala (navic k naiueni setidni do-
chazi na iznch pozicich a nktei seznamy obsahuji sekce s konstantnim pi-
bhem).
Otazka Jak se metoda vypoada s piazdnm i jednopivkovm seznamem`
Poznmka:
l u tto metody se zamime na polymoismus. Je zejm, e i metoda
pio kontiolu setidnosti me bt polymoifni vzhledemk tid polo-
ek. Setidnost lze kontiolovat i pio seznamy etzc nebo asovch
daj. Na iozdil od piomichavaci metody je vak tento polymois-
mus miin omezen. Setidni toti nelze kontiolovat u poloek, pio
n neni denovano uspoadani (tj. ielace je meni iesp. vti ne).
Nepoiovnateln jsou napiklad seznamy (C= nedenuje ielaci uspo-
adani mezi seznamy).
Z tohoto dvod se implementace polymoifni veize miin kompli-
kuje. U statickho polymoismu je nutno specikovat, e poloky lze
18
poiovnavat (pesnji eeno, e jejich tidy sdileji spolenou metodu
pio poiovnavani). V C= natsti existuje iozhiani IComparable<T>,
jeji metodu CompareTo sdileji vechny poiovnateln objekty (poiov-
nani je ale omezeno na hodnoty stejnho typu!). lmplementace vak
neni ji tak pimoaia (nestai nahiadit jmna tidy za geneiick pa-
iameti).
public static bool JeSetriden<T>(this List<T> seznam)
where T:IComparable<T> {
Prubeh prubeh = Prubeh.Konstantni;
for (int i=0; i < seznam.Count-1; i++) {
if (prubeh == Prubeh.Konstantni) {
if (seznam[i].CompareTo(seznam[i + 1]) < 0) {
prubeh = Prubeh.Rostouci;
} else {
if (seznam[i].CompareTo(seznam[i + 1]) > 0) {
prubeh = Prubeh.Klesajici;
}
/ / jinak zstava pibh nezmnn
}
} else {
if (prubeh == Prubeh.Klesajici &&
seznam[i].CompareTo(seznam[i + 1]) < 0 ||
prubeh == Prubeh.Rostouci
&& seznam[i].CompareTo(seznam[i + 1]) > 0)
return false;
}
}
return true; / / je setidn
}
Geneiick paiameti je pomoci konstiukce where omezen jen na tidy
implementujici iozhiani IComparable<T> tj. na vechny tidy, pio je-
jich objekty existuje uspoadani. V tle metody jsou vechna poiov-
nani iealizovana metodou CompareTo, nebo jen tu si vynucuje ioz-
hiani. Podpoia ielanich opeiatoi je opioti tomu nepovinna. Volani
a.CompareTo(b) viaci zapoin islo je-li < , nulu jsou li objekty
shodn a kladn islo je-li > .
5. Uivatelsk tdy
Hlavnim piostedkem a cilem OOP piogiamovani je vytvaeni vlastnich tid, je-
jich objekty (instance) spiavn inteiaguji s ostatnimi tidami a okolim (lov-
kem, inteinetovmi slubami, apod.) iesp. dostaten modeluji zvolen fyzick
objekt v dan pioblmov domn.
Nov uivatelsk tidy se nikdy nevytvaeji na zelen louce tj. pimou specikaci
binaini iepiesentace a elementainich metod (jako je nap. poiovnani), ale vdy s
vyuitim existujicich tid. Dje se to pomoci ty zakladnich mechanism
skldn (composition) objekty novch tid vznikaji sloenim dvou a vice ob-
jekt ji existujicich tid. V tomto pipad je pevzata datova iepiesentace
objekt-komponent a intein lze vyuivat i jejich metod. Vnitni objekty
vak nejsou navenek pimo pistupn. Rozhiani objekt nov tidy musi
bt denovano zcela nov, stejn jako implementace metod, ktei zajiuji
funknost iozhiani.
Mechanismus skladani je pouivan i v bn pouivanch modelech a tim i
konstiukcich vytvoench lovkem. Auto je tvoeno souastkami, ma vak
vlastni iozhiani, ktei neni zajitno adnou konkitni souastkou (nap.
schopnost pevaet osoby, spotebovavat palivo, stat se objektem dan i
pojitni, apod.) Navic souastky nejsou pimo pistupn tj. nelze je vyu-
ivat mimo auto. Dleit pitom neni njak skuten stav, ale modely,
ktei mate ve sv hlav. V iamci vtiny tchto model napiklad neped-
pokladate, e zastavite a vnujete nkomu motoi svho auta nebo zddite
lev blatnik ddekova auta.
adaptace objekt pvodni tidy je vyuivan jako jedin iepiesentant stavu nov
tidy, je vak opaten novm iozhianim (pomoci nov implementovanch
metod). Pvodni objekt je uvnit novho objektu skiyt vyuivan (ve sku-
tenosti musi zajistit vekeiou zakladni funknost), neni vak zveni pimo
pistupn (tzv. model pan a otiok). Adaptace je v zasad specialnim pipa-
dem skladani (nov objekt je tvoen jedinm komponentem).
V bn pouivanch modelech neni adaptace tak dobe viditelna jako skla-
11v
1o
dani. Pikladem je napiklad model/konstiukce multimedialniho centia za
pomoci (univeizalniho) poitae. Nov centium nabizi specializovan slu-
by, pvodni iozhiani poitae (vetn nap. monosti sputt kancelask
sofwaie) neni vyuivano iesp. neni dostupn. Vimnte si, e poita se pi
adaptaci fyzicky nemni (mni se pouze model jeho vyuivani).
agregace objekt doasn shiomauje a vyuiva dili objekty. Tyto objekty si
vak zachovavaji svou nezavislost a jsou pimo pistupn. Navic mohou
existovat i po zaniku agiegatoia. Typickmpiklademagiegaci jsou kolekce
(u nich pevauje aspekt shiomaovani). Stejn jako u pedchozich dvou
metod ma nov objekt (agiegat) zcela nov iozhiani (a tim i implementaci).
Nalezeni piiozench model neni jednoduch, nebo se vtinou nepio-
mitaji do sfiy piogiamovani (tj. nejsou mapovany na agiegaci v modelu
piogiamu). Podnik by se napiklad mohl jevit jako typick agiegat, nebo
pivky (piacovnici) nejsou jeho souasti a existuji i mimo nj. V pipad
sofwaiovch model vak nemodelujeme lidi (biologick iesp. spoleensk
entity), ale jejich aspekt zamstnance (ioli ve im, tok penz, apod.). Tak-
to modelovan objekt je pak spie komponentou objektu imy (vn imy
nema adn smysl). Dokonce i u kolekci je otazkou, zda se jedna o agiegace
(je pidani pivku do seznamu vytvoenimnovho objektu nebo jen zmnou
stavu`)
ddinost (inheritance) ddinost je ielativn sloit mechanismus (ukivaji-
ci v sob i skladani iesp. adaptaci). Ddinosti se pioto budeme detailnji
zabvat a pozdji. Piozatim stai vdt, e
1. ddinost je vztahem mezi tidami (tj. ddi se ze tid nikoliv objekt).
Nema tedy tm nic spolenho nap. s biologickou ddinosti (ta je
ddinosti mezi individui tj. objekty). Objekty nov tidy automaticky
ziskavaji metody z denice jin tidy (nova tida vak musi splovat
uiit podminky, jeji objekty musi bt nap. stiuktuialn podobn)
z. zddn iozhiani nelze modikovat (jen ioziit), implementace me-
tod poskytujicich toto iozhiani vak lze nahiadit jinmi (musi vak v
zasad zajiovat podobn chovani)
I. v jazyce C= ziskavaji objekty vech tid (vetn zakladnich) metody ze
tidy System.Object iesp. zkiacen object (object je jmno tidy!). Pioto
lze vechny objekty poiovnavat (metoda Equals) nebo tiansfoimovat
na etzce (metoda ToString).
Uivatelsk tidy 11
Nyni vak opusme teoiii a podivejme se na piaktick piklad vytvoeni nov tidy
dokument.
5.1. Definice nov tdy
Denice tidy plni pt zakladnich funkci
1. zavadi jmno tidy
z. denuje z jakch podobjekt budou sloeny instance tidy (pomoci dato-
vch len)
I. pomoci konstiuktoiu uiuje jak budou nov metody inicializovany
1. denuje a implementuje jednotliv metody tidy tj
a) denuje iozhiani tidy (tj. pomoci jakch metod lze s objekty dan
tidy inteiagovat)
b) uvadi implementaci jednotlivch metody iozhiani
Jedinou skuten povinnou ast je zavedeni jmna tidy. My budeme vytvaet ti-
du iepiesentujici denni asov daj (s minutovou pesnosti) a pioto tidu nazveme
Dennas (iesp. DenniCas).
class DenniCas {
Datov leny
Denni as lze iepiesentovat pomoci pouhch dvou isel potu hodin od plnoci
a potu minut od poatku hodiny.
Podobjekty jsou ve svm iodii obsaeny bu pimo (jsou-li instanci hodnotov
tidy), nebo jsou z iodie jen odkazovany (instance iefeiennich tid). Lze si pioto
pedstavit, e kad objekt je sloen z pamovch mist podobnch piomnnm,
ktei se oznauji jako datov leny (anglicky vak eld). Stejn jako piomnn
maji datov leny jmna (identikatoiy) a pedem uienou tidu objekt, je jsou
v nich uloeny nebo odkazovany.
Tyto datov leny existuji ve zvlatni (oddlen) kopii v kad objektu, ktei je
vytvoen jako instance dan tidy.
1:
Pikladem ze ivota je napiklad faktuia. To je sloen objekt, jen obsahuje po-
jmenovan asti, ktei bu obsahuji pimo objekty (napiklad iseln), nebo od-
kazuji objekty mimo vlastni faktuiu (nap. osoba platce faktuiy). Kada instance
faktuiy ma vlastni souboi pojmenovanch asti (tj. vlastni a nesdilen kolonky),
ktei vak mohou odkazovat stejn (tj. potencialn sdilen objekty). Chceme-li
uiit konkitni daj jednoznan identikovat musime uiit nejen identikatoi
asti faktuiy, ale i konkitni faktuiu (nap. platce faktuiy z-e1s).
V naem pipad bude kad objekt denniho asu obsahovat dva datov leny, v
nich bude uloen poet hodin (tida int hodnotova) a poet minut (opt podob-
jekt tidy int).
private int hodina;
private int minuta;
Kliov slovo private uiuje, e datov leny nebudou viditeln vn metod tidy.
To znamena, e nelze zamnit podobjekt za jin (stejn tidy) a dokonce podobjekt
dokonce nelze ani ziskat. Bohuel to vak u objekt iefeiennich tid nezabiani
jejich modikaci, a to v pipad, e nkdo jin vn objektu vlastni jin odkaz na
podobjekt. Tato situace by vak nemla bt zneuivana (iesp. by mla bt elimi-
novana vytvoenim vlastni nesdilen kopie objektu).
Vechny datov leny by mly bt piivatni (a z okoli nemniteln), a to ze dvou
(vzajemn piovazanch) dvod
1. ukiyti inteini stiuktuiy ped okolim v iamci zapouzden (objekt by ml
inteiagovat jen pomoci metod iozhiani). To sniuje zavislosti mezi objekty
iznch tid a umouje dali vvoj implementace tidy bez naiueni intei-
akce s okolim (iozhiani se nemni i je ioziovano se zachovanim zptn
kompatibility)
z. pi skladani a adaptaci je zajitno vyhrazen podobjekt tj. podobjekty
jsou pouivany jen v jednom sloenm objektu. To zabiauje negativnim
postiannim efektm (zmna podobjektu v iamci jednoho kompozita me
negativn ovlivnit jin sdilejici sloen objekt). U agiegace a ddinosti je
situace sloitji, ale i zde je nesdileni dobimvchodiskem. Oznaeni dato-
vho lenu jako soukiomho vyhiazeni ( nesdileni) nezaiuuje, umouje
vak dosaeni a kontiolu tohoto stavu (je to tedy nutna avak nikoliv po-
staujici podminka)
Specikace private je v C= v zasad nadbytena, nebo vechny pivky tidy jsou
implicitn soukiom (pesnji maji maximaln stiiktni omezeni pistupu). To
Uivatelsk tidy 1
vak neplati ve vech OOP jazycich s mechanismem omezenho pistupu a pioto
je vhodn modikatoi pistupu uvadt dsledn.
Pravidlo 19: Veny datov leny by mly bt oznaeny jako privtn.
Konstruktor
Pi vytvoeni objektu jsou datov leny neinicializovan tj. objekty hodnotovch
tid obsahuji nuly. To me bt akceptovateln, jako napiklad v naem pipad,
ale iozhodn ne dopoiuenihodn. Datov leny iefeiennich tid obsahuji hod-
notu null (co je tm vdy chybou). Pioto je tm nezbytnou asti denice tzv.
konstruktor, ktei se musi postaiat o inicializaci kad nov vytvoen instance
tidy
public DenniCas(int hodina, int minuta) {
this.hodina = hodina;
this.minuta = minuta;
}
Konstiuktoi je denovan podobn jako metoda, s dvma kliovmi iozdily
1. identikatoi konstiuktoiu je shodn s identikatoiem tidy (tj. DenniCas je
konstiuktoi objektu tidy DenniCas)
z. konstiuktoi nesm mit uveden typ naviatov hodnoty (ani specikaci void).
Konstiuktoi neni volan jako bna (tidni) metoda, ale pomoci opeiatoiu
new. Nic pimo neviaci, pouze inicializuje nov objekt.
Valna vtina konstiuktoi pejima paiametiy, ktei pomahaji denovat i zpes-
ovat poateni stav objektu. V nkteich pipadech (vetn toho naeho) nesou
paiametiy konstiuktoiu pimo poadovan podobjekty nov vznikajiciho objek-
tu. V tomto pipad je funkce konstiuktoiu zcela tiivialni kopiiuje pedavan
objekty do pislunch datovch len. U objekt hodnotovch typ postauje
piazeni paiameti do datovch len (objekt se de facto kopiiuje z jedn pio-
mnn do diuh).
Pi pistup k datovmlenmnov vytvaenho objektu se vyuiva namji dobe
znama tekova notace this.identifiktor-datovho-lenu, kde kliov slovo this
oznauje objekt, k jeho datovmu lenu pistupujeme (je to obdoba zapisu typu
objekt.piopeity). Uvnit konstiuktoiu oznauje slovo this nov vytvaen objekt.
Z hlediska konstiuktoiu je to adiesat, tj. objekt pio nj je konstiuktoi volan.
1
Pouiti kliovho slova this v konstiuktoiech a metodach tid se viazn lii od
pouiti stejnho slova v hlavice ioziujicich metod (i kdy vyjaduji podobn
piincip). U ioziujicich metod je adiesat metody pedavan jako bn paiameti
(piem paiameti me mit libovoln jmno) a kliov slovo this sloui pouze k
odlieni adiesata metody od ostatnich paiameti. Uvnit ioziujici metody se ji
nepouiva a k objektu se pistupuje stejn jako k ostatnim objektm, tj. piosted-
nictvim bn piomnn a pouze k veejnm lenm objektu.
U konstiuktoiu (a ostatnich vlastnich metod tidy) se adiesat pedava skiyt (ne-
ni uveden v seznamu paiameti) a uvnit metody je pistupn piostednictvim
specikace this. Ta ma funkci jaksi pseudopiomnn obsahujici odkaz na objekt
adiesata iesp. na nov vytvaen objekt. Syntakticky se tento pistup nelii od
vyuiti piomnn, ve vtin pipad vak mame vti piava tj. meme pistu-
povat i k (neveejnm) datovm lenm (to vak neni dano pouitim specikace
this, stejna ioziena piava mame ke vem objektm dan tidy).
Specikaci this lze navic ve vtin vynechat, nebo se pouije u vech identi-
katoi, ktei neoznauji lokalni piomnn nebo paiametiy dan metody (tzv.
implicitni this). V pipad datovch len lze vak dsledn uvadni specikato-
iu this dopoiuit, nebo je to ve vtin pipad pehlednji.
Vnaempipad je navic specikatoi this povinn, nebo paiametiy konstiuktoiu
se jmenuji stejn jako odpovidajici datov leny. Pi pouiti nekvalikovanho
jmna by byl zmaten nejen piogiamatoi, ale i peklada.
hodina = hodina;
Piotoe paiametiy (a lokalni piomnn) maji uvnit metod pednost ped dato-
vmi leny, je tento zapis pekladaem inteipietovan jako piazeni piomnn
(paiametiu) do stejn piomnn (co je piazdn pikaz, ktei se ani nevykona-
va).
Zapis se specikatoiem this je ji jednoznan (pio lovka i peklada)
this.hodina = hodina;
Objekt uloen v paiametiu (tj. pedan konstiuktoiu pi vytvaeni objektu) je
zkopiiovan do (stejnojmennho) datovho lenu (pedpokladame hodnotovou s-
mantiku). Diky tomu bude tento objekt (pesnji kopie objektu) existovat i po
ukoneni vykonavani konstiuktoiu (na iozdil od objektu v paiametiu, ktei tm
ihned zanikne). V datovm lenu bude existovat a do zaniku iodiovskho objek-
tu.
Uivatelsk tidy 1
Vznik novho objektu je detailn ilustiovan obiazkem .1.
DenniCas d = new DenniCas(15,40);
15 40
hodina minuta hodina
minuta
15
40
this
15
40
formln parametry
0 0
hodina minuta
skuten parametry
15 40
hodina minuta
d
kd
konstruktoru
Obiazek .1. Vznik objektu (s podobjekty hodnotovch tid)
Nov objekt tidy DenniCas lze vytvoit volanim jeho konstiuktoiu, nap. takto
DenniCas d = new DenniCas(15,40);
Vlastni vznik objektu piobiha ve tech fazich
1. (ppravn) Nejdive jsou vytvoeny objekty, ktei se stanou paiametiy
konstiuktoiu (tzv. skuten paiametiy). V naem pipad jsou vytvoeny
na zaklad pislunch liteial (a jsou tudi tidy int). Pak je volana iuti-
na pio vytvoeni objektu, kteia vytvoi v pamti nov piazdn objekt podle
denice tidy DenniCas. Tento objekt ji obsahuje misto pio vechny datov
leny, ty jsou vak piozatim nulov.
z. (inicializan = dokonen konstrukce) Tuto ast piovadi uivatelsk kod kon-
stiuktoiu. Nejdive jsou stejn jako u vech metod zkopiiovany skuten
paiametiy do lokalnich paiameti (lokalnich piomnnch vytvoench na
zaatku piovadni metody). Pak jsou piovedena piazeni v tle konstiuk-
toiu tj. objekty jsou znovu kopiiovany. Tentokiat jsou pesunuty z foimal-
nich paiameti do datovch len nov vytvaenho objektu. Tento objekt
1e
je uvnit konstiuktoiu odkazovan specialnim jmnem this. loimalni paia-
metiy na konci konstiuktoiu zanikaji (spolu s objekty, ktei jsou v nich
uloeny). Natsti jejich kopie jsou ji uloeny v nov vytvaenm objektu.
I. (nalizan ) Nov vytvoen objekt vak peije jen tehdy, pokud na nj
odkazuje alespo jedna piomnna. Piotoe vechny uivatelsk tdy jsou
referenn, stai do piomnn umistit odkaz na nov vytvoen objekt tj.
nedojde k adnmu kopiiovani. Bhem celho piocesu se piacuje jen s jed-
nim timt objektem tidy DenniCas. V naem pipad je odkaz umistn do
nov vytvoen piomnn s identikatoiem d.
Poznmka:
Teiminologie v oblasti konstiuktoiu neni zcela ustalena. Nktei pio-
giamatoi (a piogiamovaci jazyky) davaji pednost oznaeni iniciali-
zatoi, nebo konstiuktoi objekt nevytvai, ale pouze inicializuje (je-
t ped volanim konstiuktoiu se pio objekt vyhiadi pamov misto
a vyplni se poatenimi nulovmi hodnotami). Je vak otazkou, kdy
vlastn objekt vznika. Pokud pedpokladame, e objekt existuje a od
okamiku, kdy ma pesn denovan a pln platn stav, pak je ob-
jekt zkonstiuovan a na konci konstiuktoiu (pedtimje to spie jaksi
objektov embiyo). Tento diobn smantick iozdil je nejlpe vidt
u konstantnich objekt ( objekt u nich se nepipouti adna zm-
na po vytvoeni). l tyto objekty je nutno nastavit a to v konstiuktoiu
ped skutenm vznikem objektu.
Na zavi sekce vnovan konstiuktoiu dv piavidla.
Pravidlo 20*: Konstruktor by ml bt oznaen jako veejn (klovm slovem public
pouitm v hlavice konstruktoru).
Aby bylo mono snadno vytvaet nov objekty uivatelsk tidy musi bt jeji
konstiuktoi veejn, nebo alespo jeden ( pivni) objekt tidy musi bt vytvoen
v metod jin tidy. Toto piavidlo neni absolutni, nebo existuji pistupy, ktei
naopak vyaduji neveejn (tj. soukiom) konstiuktoiy. S tmi se vak seznamime
a pozdji.
Pravidlo 21: Konstruktor by ml ve svm tle inicializovat veny datov leny, a to
tm, e vytvo veny podobjekty svho objektu.
Toto piavidlo je iozienim piavidla o povinn implicitni inicializaci piomnnch
(viz podsekce na stian 1c). Je vak mnohem stiiktnji (opiavdu neexistuji adn
Uivatelsk tidy 1,
iozumn vjimky). Navic pedpoklada, e vechny podobjekty jsou vyhiazen (tj.
tvoi komponentu jen jednoho sloenho objektu).
Definice metody
Dali nezbytnou souasti denice tidy jsou denice metod. Nae ukazkova tida
bude mit jen dv metody. Pivni metoda bude poiovnavat dva objekty denniho
asu a zjiovat, ktei z nich je umistn pozdji v ase (pedpokladame, e oba
se tkaji stejnho dne a ve stejnm asovm pasmu). Napiklad okamik 11Ic je
iozhodn pozdji ne 111.
Piotoe se bude jednat o instanni metodu tidy DenniCas, bude jeden z asovch
okamik hiat ioli adiesata (tj. objektu nad nim je metoda volana) a diuh bu-
de pedan jako paiameti metody. To se piojevi jak pi volani (pouiti, aktivaci)
metody, tak v jeji implementaci.
Volani bude mit nasledujici tvai
DenniCas d = new DenniCas(14,30);
if ( d.JePozdejiNez(new DenniCas(11,15)) {...}
Ziekapitulujme si tidy (typy) vech zastnnch objekt
adrest objekt tidy DenniCas
parametr objekt tidy DenniCas
vsledek (naviatova hodnota) bool (System.Boolean)
Piotoe adiesatem je objekt tidy DenniCas, musi bt denice metody umistna
uvnit denice tto tidy. Je zde sice jet monost denovat ji jako ioziujici
metodu, ale to je v pipad uivatelskch tid ve vtin pipad zbyten.
Adiesat neni pedavan jako (viditeln) paiameti, ale je dostupn piostednictvim
identikatoiu this.
public bool JePozdejiNez(DenniCas porovnavanyCas) {
return this.hodina * 60 + this.minuta
> porovnavanyCas.hodina * 60 + porovnavanyCas.minuta;
}
Metoda poiovnava dva celoiseln daje. Viaz this.hodina * 60 + this.minuta
uiuje poet minut od plnoci pio asov daj iepiesentovan adiesatem meto-
dy (tj. objektem nad nim je metoda volana). Objekt-adiesat je i zde odkazovan
18
identikatoiem this a k jednotlivm podobjektm lze pistupovat piostednic-
tvim identikatoi pislunch datovch len (s pouitim bn tekov notace
objekt.datov len).
Tento daj je poiovnavan s islem ziskanm vyhodnocenim podviazu porovna-
vanyCas.hodina * 60 + porovnavanyCas.minuta. l toto islo iepiesentuje poet minut
od plnoci, tentokiat ale u denniho asu iepiesentovanho paiametiem meto-
dy. Objekt paiametiu je dostupn pomoci piomnn (foimalniho paiametiu) se
jmnem p (viz hlavika funkce). Paiameti lze pojmenovat libovoln, ml by vak
vyjadovat vznam objektu pio metodu (jedinou vjimkou jsou ovem kliova
slova vetn identikatoiu this).
Metoda tudi viaci true (jen tehdy), kdy je as od plnoci vyjaden objektem-
adiesatem (= this) (oste) vti ne as od plnoci vyjaden paiametiem metody
(porovnavanyCas). Jinak eeno metoda viaci piavdivou hodnotu jen tehdy, kdy
je as iepiesentovan adiesatem metody pozdji ne as iepiesentovan jejim
paiametiem (v iamci jednoho dne).
Poznmka:
Zpesnni uveden v zavoice za bezpiostedn pedchazejici vtou je
kliov. asov daje se v nai implementaci denniho asu poiovna-
vaji jen v iamci jedinho dne. Tj. asov daj zcc je (vdy) pozdji
ne asov daj eI, nebo se pedpoklada, e se vztahuji ke stejn-
mu dni. To nicmn neni v souladu s inteipietaci asu buzeni, u nho
se pedpoklada, e jakkoliv asov daj, ktei pio buzeni nastavime
je v budoucnosti (nastavovat as buzeni v minulosti neni pili io-
zumn). Tj. as eI (buzeni) je pozdji ne as zcI (as nastaveni
budiku).
Podobn me vzniknout pioblm i u iepiesentace jizdnich ad. Po-
kud vlak vyjidi ve zIIc a pijidi v cz, je dle naeho pistupu de
facto tachyonem, nebo pijidi dive ne odjidi. Natsti jsou vlaky
jedouci pes plnoc v esk iepublice spie vjimkou a pedevimlze
tuto situaci snadno oetit.
Diuha metoda bude k danmu iselnmu daji piitat asov posun v minutach.
Uplatni se pedevim v pipad, e potebujete spoitat, kdy piavdpodobn pi-
jede zpodn vlak. U malch zpodni nema vtina lidi pioblmy. Kdy vak
pijede vlak, s piavidelnm pijezdem ve zzI minut pokud ma zpodni z mi-
nut`
Uivatelsk tidy 1,
Aplikace metody PitiMinuty na objekt denniho asu je snadna
DenniCas prijezd = new DenniCas(22,37);
prijezd.PrictiMinuty(525); / / pipoteme zpodni
/ / a vypieme as opodnho pijezdu
Console.WriteLine( "Vlakprijedeve" + prijezd);
Algoiitmus pipoteni neni sloit, vyaduje vak dv tiansfoimace. Nejdive je
nutno as pevst na poet minut od plnoci. Pot je tepive mono piist minu-
tov posun. Na konci je vak nutno vsledn poet minut od plnoci opt pevst
do inteini iepiesentace tj. na hodiny a minuty. Navic je bohuel nezbytn zajistit,
e pokud vsledn as petee z1cc, bude vsledek upiaven na odpovidajici as
v inteivalu ccc a zIv. Tj. napiklad as zs musi bt peveden na 11.
To vak neni jet ve. Zvidav uivatel Vai metody, me zkusit piist i zapoi-
n poet minut. To mu meme dovolit (piitani zapoinho isla je oditanim),
musime vak zajistit, e nedojde k podteeni (tj. vsledn daj nesmi obsahovat
zapoin islice).
Poznmka:
Piogiamatoi se skuten destiuktivnimi sklony me dokonce jako
paiameti pedat islo tak velk, e po piteni k islu iepiesentujici-
mu poet minut od plnoci dojde ke peteeni celho isla (tj. isla
vsledkem je islo, ktei neni pomoci objekt tidy int vbec iepie-
sentovateln. Pokud napiklad pite islo int.Max pak k peteeni
dojde u kadho iselnho daje kiom plnoci. Vsledkem je zdan-
liv nahodn velk zapoin islo (velk v absolutni hodnot), ktei
se stane po piav a tiansfoimaci, jet zdanliv nahodnjim aso-
vm dajem. Tomuto pioblmu lze pedejit bu omezenim absolutni
hodnoty pipoitavanch minut nebo vyuitim konstiukce eed
jazyka C=.
public void PrictiMinuty(int posun) {
int minutyOdPulnoci = this.hodina * 60 + this.minuta;
minutyOdPulnoci += posun; / / piteni posunu
minutyOdPulnoci %= (24*60); / / omezeni na hodnotu v iozmezi c a 11Iv
if(minutyOdPulnoci < 0) {
minutyOdPulnoci += 24*60;
}
/ / nasleduje nastaveni podobjekt podle posunutho asu
this.hodina = minutyOdPulnoci / 60;
1eo
this.minuta = minutyOdPulnoci % 60;
}
Nejdive jsou vypoteny minuty od plnoci stejn jako v pedchozi metod (pio
adiesata tj. objekt this). Vsledn objekt tid int je uloen do lokalni piomnn
minutyOdPulnoci (bude se nam v iamci metody jet mnohokiat hodit).
Na diuhm adku piteme k tomuto objektu poadovan minutov posun a v-
sledn daj uloime opt do piomnn minutyOdPulnoci (stiunji eeno zvi-
me hodnotu piomnn minutyOdPulnoci o hodnotu posun). Jsme si stale vdomi,
e pipotena hodnota me bt i zapoina (tj. zapoin me bt i uloen vsle-
dek).
Teti adek omezuje hodnotu uloenou v piomnn minutyOdPulnoci na hodnoty
c a 11Iv. Dje se tak vydlenim uloen hodnoty islem 111c a uloenim zbytku
zpt do piomnn minutyOdPulnoci. Zapis je pio zaateniky ponkud nepehled-
n, ale jedna se pouze o zkiacen tvai zapisu
minutyOdPulnoci = minutyOdPulnoci % (24 * 60)
Vimnte si tak, e poet minut v iamci dne neni zadano pimo, ale viazem
z1*ec. Vynasobeni tchto isel bude piovedeno ji pekladaemtj. nebude nikteiak
zpomalovat piogiam. Zapis v neioznasobenm tvaiu je mnohem pehlednji (je
hned zejm jak vznam tato konstanta ma). Navic nemusite vytahovat kalku-
latoi. Peklada stii vtinu kapesnich kalkulaek do kapsy a ony si tak budou
moci uivat zaslouen odpoinek v kemikovm nebi.
Pokud je vak pvodni hodnota minut od plnoci zapoina, je vsledkem zbytku
po dleni hodnota v iozmezi 11Iv a c. To bohuel neni platn poet minut od
plnoci (neni umistn v iamci danho dne). Natsti spiavn daj lze ziskat pi-
tenim isla 111c. Napiklad daj z symbolizuje as z minuty ped plnoci tj.
11Is minut od (de facto pedchozi) plnoci (11Is = z +111c). Toto koiekni pi-
teni zajiuje adek umistn ve vtvi piogiamu, jen je vykonan jen pio zapoin
poet upiavench minut.
Nyni ji nasleduje jen zptna konveize minut od plnoci na hodiny od plnoci (ce-
loiseln(!) dleni hodnotou ec) a minuty od poatku tto hodiny (zbytek po tomto
dleni). Ob ziskan hodnoty jsou uloeny do datovch len adiesata. Adiesat
se tim zmni (tj. jedna se de facto o jin objekt uloen na stejnm pamovm
mist).
Metoda sice mni svho adiesata, nic vak neviaci. Nelze ji tudi volat jako souast
sloitjiho viazu na mist opeiandu nebo paiametiu iesp. adiesata jin metody.
Uivatelsk tidy 1e1
Lze ji vak pouit jako pikaz. Tak je metoda vyuita i v ukazce uveden o nco
ve.
=
K tto ukazce se jet viame. Na samm jejim konci je pozmnn objekt vy-
pisovan pomoci metody Console.WriteLine (je to staticka metoda tidy Console).
Tato metoda je v zasad schopna vypsat textovou iepiesentaci libovolnho ob-
jektu (vetn objekt pidanch tj. uivatelskch tid). Tuto ponkud magickou
schopnost ziskava tim, e vola nad kadm svm paiametiem metodu ToString,
kteia objekt pevede do jeho textov iepiesentace (tj. na objekt tidy string). Tuto
metodu nepodpoiuji jen vestavn jednoduch typy (jako jsou isla, logick hod-
noty a znaky jak jsme ji dive nkolikiat vidli), ale v zasad vechny objekty v
piogiamu.
Zna je i objekt nami vytvoen tidy ToString, navzdoiy tomu, e jsme adnou
takovou metodu nedenovali (denovali jsme jen metody JeVetsiNez a PrictiMi-
nuty). Dvodem je skutenost, e jsme tuto metodu zddili ze tidy object, kteia je
zakladem vech tid v systmu. Podiobnji se s pioblematikou ddni budeme za-
bvat pozdji, zde stai jen vdt, e tuto metodu ziskava kada tida automaticky
(a ji chce i nechce).
To, e jsme tuto metodu zadaimo zddili, jet neznamena, e bude k nemu
dobia. Pokud toti vypieme na objekt, tak zjistime, e namisto samopopisn a
jednoznan textov iepiesentace je vypsana jen nazev tidy. Tj. nejsme schop-
ni nejen ziskat daj o iepiesentovanm ase, ale nejsme dokonce schopni odliit
objekty iepiesentujici izn asy (ve vpise bude vdy jen text DenniCas).
eeni natsti existuje. Zddnou (a zcela nepouitelnou) implementaci meme
nahiadit za vlastni specializovanou veizi, jinak eeno meme metodu pede-
novat.
Pedefinovn metody ToString
Nov pedenovana metoda ToString me zohlednit datovou iepiesentaci (kom-
pozici) objekt nov tidy a pedevim optimalni foimat textov iepiesentace. To
ve zna jen tvice nov tidy a jen on je odpovdn za implementaci nov a lepi
funknosti metody.
Pedenovanim nevznikne nova metoda, ale pvodni metoda ziska jen nov (spe-
citji) kod. Nemni se nejen nazev metody, ale ani poet a pislun poadova-
1e:
n tidy paiameti. Zmnit nelze ani tidu naviatov hodnoty. l nae veize meto-
dy ToString tak nesmi mit adn paiameti a musi viacet etzec. To ve zkontioluje
peklada. Hlavika pedenovan metody tak musi mit nasledujici signatuiu
public override string ToString()
Kliov slovo public ji zname. Nov vytvoena veize metody musi bt veejna
stejn jako pvodni (zddna veize). Me ji tudi volat kdokoliv a kdekoliv.
Kliov slovo override je pio vas novinkou. Je zde povinn a ika, e se jedna o
novou implementaci ji existujici zddn metody (override je anglick ekvivalent
eskho slova pedenuje).
lmplementani ast pedenovan metody se nelii od jinch metod. l zde hiaje
kliovou ioli specikatoi this odkazujici na objekt adiesata a monost pistupu k
jeho datovm lenm (komponentam).
Pio foimatovani textu v metod ToString se asto pouiva metoda String.Format,
kteia umouje pesn foimatovat hodnoty jednoduchch typ a spojovat je do
sloitjich textovch konstiukci spolu s xnimi znaky. Metoda string.Format na-
bizi jaksi minijazyk pio popis vstupnich textovch foimat.
V naem pipad nam viazn usnadni foimatovani asovho daje do tvaiu h:mm
nebo hh:mm (kde h je islice [c-v] nebo dvojisli [1c-zI] oznaujici hodiny a mm
dvojisli [cc-v] oznaujici minuty). Pikladem spiavn foimatovanch daj je
zc nebo zIc (naopak nespiavn jsou iepiesentace c1z nebo 1z).
Tento poadavek lze pomoci minijazyka metody string.Format snadno splnit (uva-
dim pio pehlednost celou metodu DenniCas.ToString)
public override string ToString() {
return string.Format("{0:0}:{1:00}", this.hodina, this.minuta);
}
Kliovm pivkem foimatovaci metody je tzv. foimatovaci etzec (zde je zastou-
pen etzcovmliteialem"{0:#0}:{1:00}"). loimatovaci etzec obsahuje dva typy
daj bn znaky a popisovae. Bn znaky jsou vypisovany beze zmny a tvo-
i tak xni ast vstupniho foimatu. V naem pipad je to pouze znak dvojteky
upiosted etzce.
Popisovae jsou uzaveny ve sloench zavoikach a uiuji na jakm mist a v
jakm foimatu bude vypsana textova iepiesentace objekt, ktei jsou pedany
jako dali paiametiy metody string.Format. Jedinou povinnou asti je poadi vy-
pisovanho paiametiu (od nuly, foimatovaci etzec se nepoita). Tj. popisova
Uivatelsk tidy 1e
"{0}" zajisti vpis pivniho dodatenho paiametiu (u nas je to objekt odkazova-
n datovm lenem this.hodina), popisova "{1}" diuh dodaten paiameti (u
nas this.minuta). isla jsou nezbytna, nebo popisovae mohou bt uvedeny ve
foimatovacim etzci v poadi, ktei neodpovida poadi dodatench paiameti.
Kad popisova me navic u jednoduchch (pedevim) iselnch hodnot pes-
nji specikovat jak budou foimatovana. Dili foimat se uvadi v popisovai za
dvojtekou a me bt znan komplexni. My budeme zatim pouivat jen ielativ-
n jednoduch foimaty. Ty do znan miiy odpovidaji foimatovam znamm z
MS lxcelu, ktei piavdpodobn znate.
Nkolik typickch iselnch foimat ukazuje tabulka
tda formt objekt repres. vznam
int c 1 1 jedna povinna islice
1z 1z ostatni jen jsou li platn
int cc 1 c1 dv povinn islice
1z 1z ostatni jen jsou li platn
int = ==c 1 1 jedna povinna islice, (ostatni jen,
jsou-li platn)
1ze 1 ze oddlovani mezeiou po tisicich
double c.ccc I.111v I,11z piav ti povinna desetinna mista
c. c,cc povinna jednotkova islice
double =.c= c. , nepovinna jednotkova islice
1 1,c povinn pivni desetinn misto
c. c. diuh se zobiazuje, jen je-li platna
Dobi je znat tak zakladni foimaty pio objekty tidy DateTime (testovaci objekt
tidy DateTime iepiesentuje as vcc dne v.11 zc1z. Vimnte si, e kliovou ioli
hiaje poet foimatovacich znak a tak iozdil mezi minuskami a veizalkami!
1e
formtova vstupn text vznam
d.M.y v.11.1z nejstiunji datum
d. M. yyyy v. 11. zc1z kiatk datum podle esk
noimy
yyyy-MM-dd zc1z-11-cv lSO foimat
d. MMMM yyyy v. listopad zc1z dlouh datum (tm) podle
esk noimy
d.\uzczlMMMM lyyyy v. listopad zc1z s zkou mezeiou po tece
d. M. yyyy HHmm v. 11. zc1z cvcc datum s asem (dvojcifein
hodiny)
Hmm vcc jen as (jednocifein daj
hodin)
Datumov foimaty nelze bohuel pimo vyuit pio nai objekty nai tidy (bez
doplnni pomocnho kodu funguji jen pio objekty tidy DateTime). Pioto jsou v
nai metod ToString pouity popisovae pio vpis jednotlivch datovch len,
tj. popisovae iseln s pislunmi iselnmi foimaty.
=
Nyni ji mame pivni implementaci tidy hotovu a meme ji vyzkouet. Vpis
uvadi pio jistotu i celou denici tidy (tentokiat hezky pospolu).
using System; / / dennicas.cs
class DenniCas {
private int minuta;
private int hodina;
public DenniCas (int hodina, int minuta) {
this.hodina = hodina;
this.minuta = minuta;
}
public bool JePozdejiNez(DenniCas porovnavanyCas) {
return this.hodina * 60 + this.minuta
> porovnavanyCas.hodina * 60 + porovnavanyCas.minuta;
}
Uivatelsk tidy 1e
public void PrictiMinuty(int posun) {
int minutyOdPulnoci = this.hodina * 60 + this.minuta;
minutyOdPulnoci += posun;
minutyOdPulnoci %= (24 * 60);
if (minutyOdPulnoci < 0) {
minutyOdPulnoci += 24 * 60;
}
this.hodina = minutyOdPulnoci / 60;
this.minuta = minutyOdPulnoci % 60;
}
public override string ToString() {
return string.Format("{0:0}:{1:00}", this.hodina, this.minuta);
}
}
class MainClass {
public static void Main() { / / testovaci kod
DenniCas d = new DenniCas(22, 37);
Console.WriteLine(d);
d.PrictiMinuty(525);
Console.WriteLine(d);
Console.WriteLine(d.JePozdejiNez(new DenniCas(22, 37)));
DenniCas pd = d;
pd.PrictiMinuty(-24 * 60 - 10);
Console.WriteLine(pd);
Console.WriteLine(d);
}
}
Co tento piogiam vypie` Mli byste to bt ji sami schopni odhadnout, ale pio
jistotu uveme (skuten) vpis piogiamu
22:37
7:22
False
7:12
7:12
Pivni vpis je zejm. Nov vytvoen objekt odpovida iselnmpaiametim, je
byly pedany konstiuktoim(iepiesentuje tedy skuten as zzI). Po piteni se
1ee
z minut se objekt zmni tak, e iepiesentuje as zz (oveni vyaduje tiochu
pemleni, ale je to skuten spiavn).
Nasledn si tento as poiovname s pvodnim. Jak ji bylo eeno denni as zo-
hleduje jen vztahy uvnit jedinho dne, tj. posunut as zz nen pozdji ne
as pvodni (zzI), a pioto se vypie hodnota false.
Vimnte si, e pvodni as musime vytvaet znovu, nebo pvodni objekt po
posunu de facto zanikl a byl nahiazen novm(pestoe na nj odkazuje stale stejna
piomnna!) Je to pivni piznak zasadniho pioblmu.
Vyzkouime jet piteni zapoinho posunu. Pedtim vak objekt zkopiiujeme
do nov piomnn se jmnem pd (nebo se o to alespo pokusime). Tepive pes
tuto piomnou se pokusime o posun v ase zpt. Piteni hodnoty z1 ec
1c tj. 11c zmni objekt na as 1z, co je spiavn a oekavan (odeteni i
piteni libovolnho nasobku z1*ec minut nema adn vliv). To nampotvidi vpis
piomnn pd na pedposlednim adku.
Pak vak vypieme i piomnnou p a mona s pekvapenim zjiujete, e se tak
zmnila (pestoe jsme ji po zkopiiovani ji nepouily tj. ani neposunuly). Pekva-
peni by vak nemlo bt tak velk. Stai si uvdomit, e vechny objekty vech
uivatelskch tid jsou iefeiennimi objekty. Jinak eeno piomnna neobsahuje
pimo objekt, ale jen odkaz na nj.
lnicializace nov piomnn pd, tak nevede ke kopiiovani, ale pouze k novmu
odkazu na ji existujici objekt. Jak piomnna d tak pd odkazuji jeden a tent
objekt tidy DenniCas. Je tedy zcela jedno piostednictvim jak piomnn objekt
modikujeme. Vdy dojde ke zmn u obou piomnnch.
lfekt je tedy zcela snadno vysvtliteln. To vak jet neznamena, e je i chtn
i ve vech pipadech snadno piedikovateln. Sdileni objekt toti nemusi mit tak
jednoduchou podobu.
Zkusme napiklad vytvoit seznam dennich as od plnoci (vetn) do poledne
(vetn) po plhodin. Nejjednoduim se jevi vyuiti cyklu while
List<DenniCas> pulhodiny = new List<DenniCas>();
DenniCas idc = new DenniCas(0, 0); / / inicializuj aktualni as (na plnoc)
DenniCas horniMez = new DenniCas(12, 0); / / inicializuje hoini mez
while (!idc.JePozdejiNez(horniMez)) { / / dokud neni as pozdji ne hoini mez
pulhodiny.Add(idc); / / pidej aktualni as do seznamu
idc.PrictiMinuty(30); / / piti k aktualnimu asu plhodinu
}
Uivatelsk tidy 1e,
/ / vypieme vsledn pole (pio stiunost do jedinho adku)
foreach (DenniCas dc in pulhodiny) {
Console.Write(dc + ""); / / poloky budou oddleny mezeiou
}
Ve se jevi v poadku, ale piotoe do seznamu nepidavame asov daj, ale pou-
ze odkaz na nj, ziskavame seznam tyiadvacet shodnch daj 1zIc (). Pole
toti odkazuje na stale stejn objekt, ktei se postupn modikuje (na konci ka-
d iteiace). Posledni dosaen stav iepiesentuje as 1zIc (ten sice ji nespluje
podminku cyklu, ale nastava!). Situaci jet lpe osvtluje obiazek .z na nasledu-
jici stian (je dobe vidt, e bhem iteiaci nevznikaji nov objekty novch as,
jen se zmnouji odkazy na jedin, i kdy stale se mnici, objekt).
Nezbva ne piznat, e nco neni v poadku. Objekt se nechova tak jak by se ml,
a nelze to snadno zmnit. Neexistuje napiklad snadn zpsob jak spiavn napsat
ve uvedenou inicializaci seznamu.
Jedinm eenim je napsat novou a lepi implementaci nai tidy. Tuto pileitost
meme vyuit i pio odstianni dalich dilich nedostatk (kteich si mona Ti
zkuenji ji vimli) a k miinmu vylepeni iozhiani.
Pravidlo 22: Pokud implementace tdy nevyhovuje naim zkladnm poadavkm
nebo vykazuje neoekvan i netn ovn, je vdy lep tdu implementovat
znovu. Vyhneme se tak stle rostoucm problmm a berlikm, kter se sna ne-
dostatky eliminovat.
Toto piavidlo ma samozejm i vjimky. Je-li je implementace tidy pili sloita a
asu neni nazbyt (piogiam musi fungovat pokud mono hned), nezbva mnohdy
nic jinho ne se s pvodni implementaci smiit. Nakonec vak dive i pozdji
piavdpodobn k ieimplementaci stejn dojde.
5.2. Nov implementace (znovu a lpe)
Hlavni zmnou nov a lepi implementace je eliminace nepijemnho efektu sou-
visejiciho se zmnou objektu, na ktei me odkazovat vice iefeienci.
Piotoe nememe idit i uiovat poet iefeienci na objekty uivatelskch tid,
je jedinm eenm pln zabrnit modikaci objektu po jeho vytvoeni (a ini-
cializaci). adna metoda nesmi mnit objekt (tj. adn z jeho komponent) a objekt
tak zstava nemnn a do svho zaniku.
1e8
idc
idc
horniMez
horniMez
0:30
0:30
12:00
12:00
pulhodiny
pulhodiny
0
List<DenniCas>
DenniCas
DenniCas
idc
idc
horniMez
horniMez
1:00
1:00
12:00
12:00
pulhodiny
pulhodiny
0
List<DenniCas>
DenniCas
1
idc
idc
horniMez
horniMez
12:30
12:30
12:00
12:00
pulhodiny
pulhodiny
0
List<DenniCas>
DenniCas
1 23 24 2 22 . . .
Po prvn iteraci
Po druh iteraci
DenniCas
DenniCas
Po posledn (25.) iteraci
Obiazek .z. Piomnn a objekty pi vytvaeni seznamu mnitelnch objekt
Uivatelsk tidy 1e,
Poznmka:
Jazyk C= nabizi i dali a dokonce elegantnji eeni. Hlavni pioblm
toti spoiva v iozpoiu mezi iefeienni implementaci objektu denni-
ho asu (jen je pio objekty bnch uivatelskch tid jedinou mo-
nosti) a piiozenou hodnotovou smantikou asovch hodnot. lden-
tita asovho daje toti neni dana umistnim objektu v pamti, ale
jeho obsahem (tj. uloenm asem). Dva objekty se stejnm asem
jsou de facto identick, i kdy lei na iznch mistech pamti (v zasa-
d me existovat libovoln vzajemn identickch objekt) a naopak,
pokud se objekt zmni, pak mni i svou identitu (pestoe lei stale
na stejnm mist v pamti).
Pio objekty s hodnotovou smantikou je piiozen pouivat hodnoto-
v tidy, ktei automaticky zajiuji kopiiovani objektu pi piazeni
(nova kopie je uloena v jin piomnn, ale je to stale tent objekt!).
Pi zmn objektu se mni jeho identita, ale to nevadi piotoe neni
sdilen viceio piomnnmi. Zmnu tedy lze chapat jako zmnu pio-
mnn (piomnna po zmn obsahuje nov objekt). Tato smantika a
implementace je typicka napiklad pio isla a obecn fyzikalni daje
(mezi n denni as tak pati). U knihovnich standaidnich typ je
pouit napiklad u tidy DateTime
DateTime date1 = DateTime.Now; / / piomnna date1 obsahuje datum
DateTime date2 = date1; / / piomnna datez obsahuje identickou kopii
date1.AddHours(10); / / piomnna date1 obsahuje nov objekt!
/ / datez si vak zachovava pvodni obsah
Jak si vak vynutit hodnotovou implementaci u uivatelskch tid.
Stai pouze na zaatku denice pozmnit kliov slovo class za struct
(stiuktuia hodnotova tida). Ano jen tak malo stai a objekty denni-
ho asu piojevuji svou piiozenou hodnotovou smantiku a piogiam
pio inicializaci hodnot bude beze zmny fungovat (do seznamu se
toti vkladaji kopie hodnot).
Pio tedy toto eeni nepouijeme` Dvodem jsou obecna omezeni
tohoto eeni. Za piv jej nelze vyuit pio objekty, jejich obsah m-
ni svou velikost v pamti (nap. pio seznamy), za diuh u vtich
objekt vede k pomalmu kopiiovani pamti (objekty se pi piaze-
ni nebo pi pedavani do metod musi byte po bytu kopiiovat) a za
teti hodnotov uivatelsk tidy nejsou dostupn ve vech jazycich
1,o
(napiklad nejsou a nikdy nebudou v Jav, Pythonu a PHP). Pistup s
nemnnmi objekty tato omezeni nema. Navic ma i nktei dali v-
hody, jako je snadnji pouivani v paialelnich nap. vicevlaknovch
piogiamech.
Je-li vak objekt denniho asu nemnn, jak budeme implementovat minutov
posun` Natsti namisto modikace stai viatit nov (posunut) objekt (adiesat
se nemni). Bude to sice vyadovat o tiochu pamti navic, ale vice to odpovida
smantice posunu (objektas po posunu neni identick s objektemasem ped
posunem). Ostatni metody (JePozdejiNez a ToString) nemusime modikovat, nebo
adiesata v pvodni implementaci nemni.
Pi ievoluni ieimplementaci se vak nezastavime jen u zmny modikovatelnosti
objektu. Zmnu si zasloui i inteini iepiesentace asovho daje. Pvodni iepie-
sentace pomoci dvou celoiselnch podobjekt ma toti dv zakladni nevhody
1. vyaduje zbyten mnoho pamti. Pio iepiesentaci 111c jednotlivch stav
objektu vyaduje s byt pamti ( z velikost objektu tidy int). Osm byt
dokae iepiesentovat z
ss
stav (adov 1c
1s
). Naopak pio iepiesentaci 111c
stav stai jen
,
log
z
111c

= 11 bit.
z. pio inteini vpoty se lpe hodi lineaini iepiesentace potu minut od pl-
noci. Je to dobe vidt v pvodni metod PrictiMinuty, kde se musi piovst
pepoet do tto iepiesentace a nasledn zpt. Je vhodnji i pio poiovna-
vani asovch daj (viz metoda JePozdejiNez).
Jako viazn vhodnji se pioto jevi iepiesentace pomoci jedinho celoiselnho
objektu tidy int, je bude iepiesentovat poet minut od plnoci. Velikost aloko-
van pamti sice stale neni optimalni (Iz bit), ale je o polovinu meni.
Poznmka:
l kdy by bylo mono pouit i meni celoiseln typ jako nap. short
( 1e bit se znamnkem, dlouh jmno System.Int16), nevede toto sni-
eni k iealn spoe. Z dvod iychlho pistupu k pamti jsou toti
objekty zaiovnany na velikost pamovho slova piocesoiu, ktei je
u dnenich piocesoi minimaln Iz-bitov. Navic se vechny aiitme-
tick vpoty v aiitmeticko-logick jednotce piocesoiu (ALU) piova-
dji v tto ice tj. hodnota se musi stejn ped vpotem pevst na
iepiesentaci shodnou s tidou int.
Namisto sloenho objektu tak dostavame typick adapti. Pvodni objekt (ti-
dy int) ztiaci sv pvodni iozhiani (nema napiklad smysl asov daje nasobit),
Uivatelsk tidy 1,1
misto toho sloui jako zaklad objektu se zcela jinm iozhianim a smantikou.
Dale se pokusime vylepit pvodni implementaci v dalich smiech
1. asto pouivan liteialy nahiadime pojmenovanmi konstantami, ktei l-
pe vyjaduji vznam hodnoty. Tka se to pedevim hodnoty ec (poet mi-
nut v hodin) a 111c (ec * z1), co je poet minut ve dni.
z. umonime pim ale bezpen pistup k dajmo hodin a minut (v iamci
hodiny) piostednictvi nov pidanch vlastnosti
I. zajistime, e objekt denniho asu neni mono adnm zpsobem chybn
inicializovat. To spolu s nemonosti objekt nasledn mnit, zcela zabiani
existenci neplatnch objekt. Pvodni implementace umoovala vytvoit
objekt iepiesentujici nap. as ze1c11.
Nejdive si vypime celou implementaci (vetn testovaciho kodu)
using System; / / dennicas2.cs
using System.Collections.Generic;
class DenniCas {
private int minutyOdPulnoci;
const int MinutVHodine = 60; / /

const int HodinVeDni = 24;


const int MinutVeDni = MinutVHodine * HodinVeDni;
public DenniCas (int hodina, int minuta) {
if (hodina < 0 || hodina >= HodinVeDni / /

|| minuta < 0 || minuta >= MinutVHodine)


throw new ArgumentException("Nepripustneargumentykonstruktoru");
this.minutyOdPulnoci = hodina * MinutVHodine + minuta;
}
/ / pomocn konstiuktoi
private DenniCas (int minutyOdPulnoci) { / /

/ / piava paiametiu do iozsahu c a MinutVeDni-1


minutyOdPulnoci %= MinutVeDni;
if (minutyOdPulnoci < 0) {
minutyOdPulnoci += MinutVeDni;
}
/ / nastaveni datovho lenu novho objektu
this.minutyOdPulnoci = minutyOdPulnoci;
1,:
}
public int Hodina { / /

get { return this.minutyOdPulnoci / MinutVHodine; }


}
public int Minuta {
get { return this.minutyOdPulnoci % MinutVHodine;}
}
public bool JePozdejiNez(DenniCas porovnavanyCas) { / /

return this.minutyOdPulnoci > porovnavanyCas.minutyOdPulnoci;


}
public DenniCas PrictiMinuty(int posun) { / /

return new DenniCas(this.minutyOdPulnoci + posun);


}
public override string ToString() { / /

return string.Format("{0:0}:{1:00}", this.Hodina, this.Minuta);


}
}
class MainClass {
public static void Main() { / / testovaci kod
DenniCas puvodniCas = new DenniCas(22, 37);
Console.WriteLine(puvodniCas);
DenniCas posunutyCas = puvodniCas.PrictiMinuty(525);
Console.WriteLine(posunutyCas);
Console.WriteLine(posunutyCas.JePozdejiNez(puvodniCas));
DenniCas novyCas = posunutyCas.PrictiMinuty(-24 * 60 - 10);
Console.WriteLine(novyCas);
Console.WriteLine(puvodniCas);
/ / otestujeme i vytvoeni seznamu as od ccc do 1zcc po Ic minutach
List<DenniCas> pulhodiny = new List<DenniCas>(); / /

DenniCas idc = new DenniCas(0, 0); / / inicializujeme aktualni as (na plnoc)


DenniCas horniMez = new DenniCas(12, 0); / / inicializujeme hoini mez
while (!idc.JePozdejiNez(horniMez)) { / / dokud neni as pozdji ne hoini mez
pulhodiny.Add(idc); / / pidame aktualni as do seznamu
Uivatelsk tidy 1,
idc = idc.PrictiMinuty(30); / / piteme k aktualnimu plhodinu
}
/ / vypieme vsledn pole (pio stiunost do jedinho adku)
foreach (DenniCas dc in pulhodiny) {
Console.Write(dc + ""); / / poloky budou oddleny mezeiou
}
}
}
Symbolick konstanty
Pivni zmnou v denici tidy je zavedeni ti konstant

. Konstanty sloi k iden-
tikaci konstantnich (nemnnch) objekt, je musi bt navic znamy ji v dob
pekladu. Konstanta se chova podobn jako piomnna (ma nap. sv jmno a spe-
cikuje tidu svho objektu), na iozdil od ni vak jeji hodnotu nelze po inicializaci
mnit.
Konstanta je tudi de facto objekt identikovan symbolickm jmnem. Symbo-
lick jmno konstanty lze pouivat kdekoliv v oblasti jeji viditelnosti (v naem
pipad je to cela denice tidy)
Tento identikatoi je navic nahiazen konkitnim objektem ji ve fazi pekladu.
To na jedn stian znamena, e konstanty za bhu nezaujima adn (zbyten)
pamov misto, na stian diuh lze konstanty vyuivat jen pio objekty pio n
existuji liteialy (tj. pio isla, znaky, etzce a logick hodnoty). Navic pi iniciali-
zaci nelze pouivat piomnn, ale pouze liteialy a ostatni konstanty, nebo jen ty
jsou znamy ji v okamiku pekladu.
S konstantami souvisi jedno ze zakladnich piavidel piogiamovani
Pravidlo 23: V programu se nemly vyskytovat dn pm literly. Namsto ni
by se mly pouvat symboli konstanty, kter jsou tmito literly inicializovan.
Pim liteialy se se v piogiamatoiskm slangu asto oznauji jako tzv magi
konstanty. Je tomu tak pedevim v pipad, kdy se jedna o podivna hausnume-
ra, jejich vznam nemusi bt na pivni pohled zejm. Piav tmto magickm
konstantam je teba se dsledn vyhbat. V naem pipad je to nap. liteial 111c
(nemusi to bt jen poet minut ve dni, ale i deset veletuct), a do jist miiy i
konstanta ec (jeji vznam je vak zetelnji).
1,
Zcela nezbytn je pouit symboliho zpisu u konstantn hodnot, kter se mo-
hou mnit v dal verz programu (napiklad maximalni poet podpoiovanch
piocesoi, apod.). Pi pepisovani na novou hodnotu me toti snadno dojit k
nedslednosti, kdy jsou nktei vskyty pepsany a jin (omylem) ne.
Piavidlo se asto nevztahuje na nulu, pokud sloui jen k oddleni kladnch a za-
poinch isel (nikolivk pokud napiklad vyjaduje dolni mez, kteia se me n-
kdy v budoucnu posunout). Podobn se pim liteialy vyuivaji u nkteich jed-
noduchch matematickch koecient, ktei se nejen nemni, ale jejich vznam
je zejm (nap. dvojka u polynomu
z
+ z
z
). Naopak u fyzikalnich kon-
stant a pevodnich koecient je pouiti symbolickch jmen nezbytnosti. asto
toti nejsou samopopisn (co nap. vyjaduje konstanta Ie.I`) a mohou se do-
konce i mnit (jak ioste pesnost detekce, i dochazi k diobnm posunm v jejich
denici).
const double Z_0 = 376.73;
/ / chaiacteiistic impedance of vacuum
/ / http://en.wikipedia.org/wiki/Impedance_of_free_space
=
Konstiuktoi

i v tto veizi tidy zajiuje inicializaci nov vzniklho objektu.
Z dvod zmny datov iepiesentace vak nekopiiuje paiametiy pimo do dato-
vch len (nejedna se tedy o tzv. triviln konstruktor). Namisto toho vypoita
poet minut do plnoci a tepive tuto hodnotu uloi do pislunho datovho le-
nu (this.minutyOdPulnoci). Vznika tak iseln objekt, jen bude slouit jako inteini
iepiesentace asu tj. bude adaptovan pio nov pouiti (u to nebude jen pouh
islo)
Konstiuktoi navic kontioluje, zda jsou pedan hodnoty hodin a minut pipustn.
Pokud tomu tak neni, je vyvolana vjimka. Pouita tidy vjimky (ArgumentEx-
ception) byla zvolena namisto obecn vjimky (tida Exception), nebo pesnji
odiai podstatu vjimenho (chybovho) stavu nepipustn ( nepouiteln,
nezpiacovateln) hodnoty paiameti/aigument. Vimnte si, e vyvolani vjim-
ky je jedinou monou ieakci na tuto chybovou situaci, nebo konstiukci objektu
nelze jednodue peskoit (pokud by datov len nebyl inicializovan, zachoval by
si pvodni nulovou hodnotu), a iozumnou se nejevi ani nastaveni njak specialni
chybov hodnoty asu (jak by se takovou hodnotou-nehodnotou dale piacovalo`).
Pravidlo 24: Konstruktor mus nov objekt nastavit tak, aby byl v denovanm (nej-
lpe pln pouitelnm) stavu. Pokud to nelze zajistit (nap. u neppustnvstupn
parametr) mus vyvolat vjimku.
Uivatelsk tidy 1,
Poznmka:
Ani vyvolani vjimky neni zcela bez nebezpei. Vyvolani vjimky
v konstiuktoiu me mit i nepijemn efekty v pipad, kdy je v-
jimka zachycena a piogiam pokiauje dal ve svm bhu. V okami-
ku vyvolani vjimky se systm nachazi ve stavu, kdy objekt sice ji
existuje, ale neni piozatim nemusi bt inicializovan. To znamena, e
stav objektu nemusi bt pln denovan, nap. jet nejsou vytvoeny
kliov jeho podobjekty nebo nejsou alokovany pislun systmov
piostedky. Objekt by ml bt v tomto pipad vdy uveden do chy-
bovho stavu, v nm je sice de iure denovan (tj. tento stav je jed-
noznan identikovateln), ale v piaxi je samozejm nepouiteln.
Po inicializaci tohoto stavu me bt vyvolana vjimka, ta vak neni
v tomto pipad nezbytna. Pokud neni vjimka vyvolana, pak musi
uivatel objektu bu ped pouitim objektu zkontiolovat, zda neni
objekt v chybovm stavu, nebo musi oekavat vjimku pi pivnim
pouiti objektu (kontiola chybovho stavu se tak pesune na zaatek
vech metod objektu).
Napiklad pi konstiukci objektu obalujiciho souboi me dojit k chy-
bovmu stavu, pokud podkladov souboi neexistuje. Objekt by mohl
v tomto pipad pejit do stavu, ktei lze oznait jako neoteven
i uzaven. Tento stav by mlo bt mono jednoznan identi-
kovateln a pi jakkoliv manipulaci s objektem v tomto stavu (nap.
pi pokusu o zapis i teni dat) by mla bt vyvolana vjimka.
Zmna datov iepiesentace viazn zjednoduila metodu ovujici jak denni
as je pozdji (JePozdejsiNez

). Poet minut od plnoci je uloen ji pimo v
objektech tidy DenniCas, take stai tyto hodnoty poiovnat.
Viaznji zmna nastala v metod pio piteni minutovho posunu

. Jak ji
bylo ve eeno tato metoda ji nemni objekt, ale viaci posunut as v podob
nov vzniklho objektu. To se piojevuje ji v hlavice metody, kde je specikova-
no, e metoda bude viacet objekt tidy denni as.
public DenniCas PrictiMinuty(int posun)
Metoda tedy musi vykonat ti innosti (1) seist poet minut od plnoci aktualni-
ho objektu s asovm posunem, (z) souet tiansfoimovat do inteivalu c a poet
minut ve dni - 1 a nasledn (I) vytvoit nov objekt iepiesentujici denni as s
danm potem minut od plnoci.
1,e
Pio vytvoeni novho objektu je mono vyuit ve popsan konstiuktoi se dv-
ma paiametiy (hodinou a minutou v hodin). To by vak znamenalo, e sumaini
poet minut od plnoci, musi bt iozloen na hodinu a minutu v hodin (pi volani
konstiuktoiu) a nasledn (v tle konstiuktoiu) zase sloen.
Natsti lze vytvoit vice konstiuktoi, ty se vak musi liit v potu i tidach
svch paiameti (tzv. petieni konstiuktoi). Neni tedy pioblm vytvoit nov
konstiuktoi, jemu by byl pedavan jen jeden celoiseln paiameti poet minut
od plnoci (viz

). Navic lze do tohoto konstiuktoiu pevst kod tiansfoimujici
obecn zadan poet minut od plnoci do inteivalu c a poet minut ve dni - 1.
Ten se toti me hodit i v dalich metodach viacejici nov as. Pokud tuto zod-
povdnost pevedeme na konstiuktoi, je tlo nai metody vice ne stiun tvoi
je jen jedin adek, ktei zavola pomocn konstiuktoi a peda mu souet pvod-
niho asu a posunu. V OOP piogiamovani jsou jednoadkov metody pomin
ast.
Samotn pomocn konstiuktoi piovede tiansfoimaci hodnoty minut do poado-
vanho inteivalu, jim inicializuje datov len this.pocetMinutOdPulnoci.
Vimnte si, e konstiuktoi je soukiom, tj. nelze jej volat odjinud ne z metod
nai tidy. Naiuuje tak (slab) piavidlo zc na stian 1e. Dvodem je skutenost,
e je ponkud matouci (as bn nezadavame v potu minut od plnoci) a v piaxi
se pili asto nevyuije (poet minut od plnoci je pouze inteini iepiesentace).
Pedpokladejme napiklad, e uivatel nai tidy vytvoi nov objekt nasledujicim
zapisem
DenniCas budik = new DenniCas(8);
Tento zapis me bt bu nemyslnmopomenutim(uivatel zapomnl hodinov
nebo minutov daj), nebo myslnou snahou zkiatit si zapis (nepsat zbyten
nulov minuty). Vobou pipadech by peklada neohlasil chybu a nov vytvoen
objekt by piesentoval pio uivatele pekvapiv as, ktei by piavdpodobn vedl
k obtin odhalitelnmu selhani piogiamu (podivn vstup, pad piogiamu, apod).
Ukiyti pomocnho konstiuktoiu do zapouzden asti objektu (tj. mimo veejn
iozhiani) tmto pioblmm zabiani.
Poznmka:
Zahinuti i vyjmuti pomocnho konstiuktoiu (iesp. jakkoliv pomoc-
n metody) je ist subjektivnim iozhodnutim, a kad piogiamatoi
me zvolit jin eeni.
Uivatelsk tidy 1,,
Tvici standaidni knihovny napiklad zveejnili podobn pomocn
konstiuktoi u tidy System.DateTime. Tento konstiuktoi oekava jedi-
n islo a inteipietuje jej jako poet stovek nanosekund od epochy 1.1.
ioku jedna p.K.. Tento konstiuktoi zicadli inteini iepiesentaci toho-
to typu, v piaxi vak vede spie k nedoiozumnim. Na diuhou stianu
usnaduje pouiti tidy pio kalendani vpoty (napiklad pevody
mezi iznmi kalendanimi systmy), nebo poskytuje lineaini aso-
vou osu (i kdy zbyten detailni). To je piavdpodobn tak dvod,
pio neni tento pomocn konstiuktoi oznaen jako soukiom.
Dali kliovou asti nov implementace je dvojice vlastnosti (property), ktei lze
vyuit pio ziskani hodinov a minutov asti.
Definice vlastnost
Ji v pedchozich kapitolach jsme seznamili s nkteimi vlastnostmi knihovnich
tid nap. s vlastnosti Count u seznam nebo Month and Year u objekt tidy
DateTime.
Vlastnosti se z uiitho hlu pohledu pili nelii od dotazovacich metod, tj. bez-
paiametiickch metod, ktei viaceji stav objekt. Jedinmiozdilemjsou chybjici
zavoiky pi aplikaci
seznam.Count / / vlastnost
date.IsLeapYear() / / dotazovaci metoda
Vlastnosti vak sdileji i nktei chaiakteiistiky datovch len. Pedevim jejich
syntaxe je obdobna (lii se jen zus, ktei pedepisuje pio vlastnosti identikatoiy
zainajici velkm pismenem)
objekt.x / / datov len
objekt.X / / vlastnost
Podobnost vak jde jet dal nktei vlastnosti lze pouit i pio nastaveni stavu
objektu, piem se pouiva syntaxe obdobna zapisu do datovho lenu.
objekt.X = nov-hodnota
Ze vech vlastnosti se kteimi jsme se piozatim seznamili, lze pio zapis pouit jen
vlastnost Capacity u objekt tid seznam.
seznam.Capacity = 100; / / zmni pedalokovanou pam seznamu, tak aby obsahla 1cc poloek
1,8
Zmnu diliho atiibutu seznamu by bylo lze piovst i pomoci metody, zapis je
vak mn pehledn a pedevim neni tak jednoznan.
seznam.setCapacity(100); / / tato metoda ve skutenosti neexistuje
Navenek tak vlastnosti stoj na rozhran metod a datov len. Od metod pebraj
smantiku a od datov len syntaxi.
Z hlediska smantiky maji vlastnosti dv zakladni funkce (z nich diuha je nepo-
vinna)
1. ziskavat infoimace o stavu objektu a to v iamci veejnho iozhiani tidy.
Pi ziskavani infoimaci se nesmi mnit stav objektu iesp. piovadt jakkoliv
jin postianni efekt.
z. mnit dili stav objektu (atiibut' objektu). Pokud je poteba, tak jsou pio-
vedeny i innosti, ktei s touto zmnou souvisi (nap. zmnime-li vlastnost
baiva u GUl vizualniho pivku tak se pivek skuten pebaivi)
Stejnou funknost me nabizet i dvojice metod. Jedna se dotazuje se na stav ob-
jektu (bez paiameti a viacejici objekt iepiesentujici aktualni stav dan vlast-
nosti), diuha (nepovinna) nastavuje dili vlastnost objektu (a vykonava pislun
vedleji efekty).
Uveme si piklad z oblasti GUl (kde je vyuiti vlastnosti nejpiiozenji). pio-
mnna buon odkazuje na objekt iepiesentujici vizualni tlaitko (nap. tlaitko
OK)
string text = button.Text; / / atiibut objektu je ziskan a uloena do piomnn
button.Text = "OK"; / / atiibut je nastaven a tlaitko je pekiesleno
Stejnou funkci by zajistila i dvojice funkci. Ve skutenosti v nkteich jazycich
adna jina monost ani neexistuje nap. v Jav i C--.
string text = button.getText(); / / metoda viaci atiibut, jen je uloen do piomnn
button.setText("OK"); / / metoda nastavuje atiibut a pekiesli tlaitko
Naopak podobnost vlastnosti s datovmi leny je naopak spie povichni (tka se
jen foimalni syntaxe).
datov leny popisuji skuten pamov misto obsahujici i odkazujici po-
dobjekt. Vlastnost me bt napioti tomu vypoitana z nkolika podobjekt
'slovo atribut se zde vyuiva v obecnm vznamu, nikoliv ve vznamu, jen ma v jazyce C=.
Uivatelsk tidy 1,,
nebo nkolik podobjekt nastavit. Vlastnosti nemusi bt tudi pimo spo-
jeny s inteini iepiesentaci objektu.
pistup k datovm lenm je mon pouze v metodach (a vlastnostech) ti-
dy, jejich objekty tvoi (tj. jsou soukiom a tudi i zapouzden). Vlastnosti
jsou naopak bn souasti veejnho iozhiani. Dvodem tto otevenosti
je jejich (potencialni) nezavislost na inteini iepiesentaci objektu.
pi ziskavani ani nastaveni datovch len nelze piovadt adn dodaten
kod (pouze se peda i uloi objekt i odkaz na nj). Vlastnosti mohou (iesp.
mly by) pedavan hodnoty kontiolovat a mohou tak piovadt pislun
vedleji efekty).
Zcela zasadn se tak lii denice datovch len a vlastnosti. Vlastnosti se v
souladu s jejich funknosti denuji podobn jako metoda (je-li vlastnost jen pio
teni) i dvojice metod (umouje-li zapis).
Podivejme se napiklad na denici vlastnosti Hodina

(viaci hodinovou ast den-


niho asu).
public int Hodina {
get { return this.minutyOdPulnoci / MinutVHodine; }
}
tda vlastnosti (vracen/nastavovan hodnoty)
jmno (identifiktor) vlastnosti
metoda vracejc hodnotu vlastnosti (getter)
Hlavika denuje identikatoi vlastnosti a tidu jeji hodnoty. Tlo vlastnosti (uza-
ven ve sloench zavoikach) obsahuje skiytou metodu viacejici hodnotu vlast-
nosti (metoda nastavujici hodnotu neni implementovana, nebo na objekt je ne-
mnn!)
Ped tlem metody je uvedeno kliov slovo get, tlo metody (uvnit dalich vno-
ench sloench zavoiek) se vak nelii od tla bn metody. Metoda viacejici
hodnotu se vlastnosti je mezi piogiamatoiy oznaovana jako geer (je to hovo-
iov dokonce i v anglitin, a nelze to peloit do etiny, ale je to zcela bn
uivan). Teoietiti infoimatici pouivaji na pivni pohled mohem odboinji tei-
min akcesor.
Zcela obdobn je denovana i diuha vlastnost objekt nai tidy Minuta. lmple-
mentace vlastnosti je bn velmi stiuna (jeden i jen nkolik malo adk), a
18o
mnohdy bva jet jednodui ne je tomu u nai tidy (piost jen viaceji hodnotu
datovho lenu).
=
Nov vytvoen vlastnosti jsou pouity v miin modikovan denici metody
ToString

. Nova veize ji neme pistupovat k oddlenm datovm lenm
pio hodiny a minuty, na jejich mist vak me pouit pislun vlastnosti, ktei
na poadani vypoita z inteini iepiesentace ( potu minut od plnoci). Jedinou
navenek viditelnou zmnou je tak veizalka (velk pismeno) ve jmn vlastnosti
(datov leny vyuivaji mala pismena minusky).
Na iozdil od vnjiho pohledu je vak inteini zmna skuten ievoluni. Vlast-
nosti toti nejsou zavisl na vnitni iepiesentace, nebo ta me bt zcela jina (viz
na piklad). Odstiauje se tak pima zavislost mezi metodou ToString a vnitni
iepiesentaci, co nejen zjednoduuje implementaci metody (nap. metoda nemu-
si piovadt pevod z inteini na exteini iepiesentaci), ale pedevim usnaduje
jeji dlouhodobou spiavu (metoda se nemusi mnit pi kadm sebemeni zmn
iepiesentace).
Sniovn zvislost a zapouzden (nejen) v OOP
Sniovani zavislosti je jednimz hlavnich cil objektovho piogiamovani (a obecn
piogiamovani jako takovho). Jen tak lze toti dlouhodobji spiavovat a ioziovat
kod iozsahlejich aplikaci. Jakakoliv zmna v iepiesentaci nebo implementaci by
si v systmu s vysokm potem vzajemn piopojench zavislosti vyadala velk
poet zmn v kodu.
Snieni vzajemn zavislosti iznch pivk systmu se piiozen objevuje i v ji-
nch lovkemvytvoench systmech (a dokonce i v systmech vytvoench pi-
iozenou evoluci). Napiklad vyuivani tiansfoimatoi odstiauje zavislost elek-
tiickch zaizeni na napti penosov soustavy (stal zvyovani napti v dalko-
vch penosech dan spoiou eneigie si nevynucuje stalou zmnu piovozniho
napti v koncovch spotebiich). Podobn neni nutn, aby se vnitni oigany tep-
lokievnch ivoich pizpsobily zmnam okolniho klimatu, nebo stale piacuji
v nemnnm piostedi, je je blizk tiopickmu moi, z nho vyli jejich pedko-
v.
Hlavnim mechanismem sniovani zavislosti v OOP systmech je zapouzdeni ob-
jekt, tj. objekty mohou navzajem inteiagovat pouze pes sva veejna iozhiani.
Uivatelsk tidy 181
Hlavnim piostedkem zapouzdeni je ukivani datovch len a pomocnch me-
tod (tj. pedevim metod, jejich iozhiani ieektuje detaily vnitni iepiesentace),
co je podpoiovano mechanismem neveejnho pistupu (specikatoi private).
Zapouzdeni se vak v OOP piojevuje i na dalich iovnich systm. V naempi-
pad je zapouzdeni aplikovano ji na iovni jedinho objektu. Metoda ToString
je souasti objekt tidy DenniCas a ma tudi pistup k soukiomm datovm le-
nm objektm a mohla by pln vyuivat implementani detaily vnitni iepiesen-
tace (as je iepiesentovan jako celoiseln poet minut od plnoci, piem tento
poet je vdy v inteivalu c a 11Iv).
Namisto toho vak pouiva veejnch vlastnosti, ktei jsou na vnitni iepiesentaci
nezavisl. Sniuje se tak zavislost i v iamci jedn tidy, nebo jsou jasn oddle-
ny metody a vlastnosti s pimm pistupem k datovm lenm a metody iesp.
vlastnosti, ktei vyuivaji pomocnch vlastnosti a metod a jsou od iepiesenta-
ce oddleny (v naem pipad je jedina metoda, ale nae tida je piozatim velmi
zjednoduena).
Metody a vlastnosti pivniho diuhu tvoi jadio objektu, ktei se musi mnit pi
kad zmn iepiesentace. Ostatni metody pak tvoi obal, ktei je na iepiesenta-
ci tm nezavisl a me tudi zstavat beze zmny. Navic lze metody vnjiho
obalu implementovat i mimo tidu, napiklad pomoci ioziujicich metod se kte-
imi jsme se ji seznamily nebo pomoci daliho adaptiu ( objektu jin tidy,
kteia bude intein vyuivat na denni as a pidavat k nmu metody).
A to zdaleka neni ve. Stiiktn i alespo asten oddlen vistvy lze budovat
i nad iovni objektovho zapouzdeni. Lze napiklad ukivat detailni iozhiani
objekt nkolika tid pod spolenm zjednoduenm iozhianim (navihov vzoi
lasada) nebo sjednotit iozhiani objekt, ktei sice maji podobnou funknost ale
izn iozhiani (tj. nap. odstianit zavislost na knihovn giackho uivatelskho
iozhiani, navihov vzoi Most), i pln eliminovat nutnost vzajemnho odka-
zovani objekt pi inteiakci (ten kdo chce vykonat njakou akci nemusi znat jak
objekt tuto innost nakonec piovede, navihov vzoi Pikaz). Na to ve mame
jet as, ale je nutn si uvdomit, e ve spojuje jedin cil sniovn zvislost.
Nait mon sit zavislosti najdete na obiazku .I na nasledujici stian. ed kiu-
hy a elipsy jsou objekty (z nich jeden je zobiazen detailnji). Kad objekt za-
pouzduje svoji datovou iepiesentaci (tmavi ast kiuhu iesp. elipsy). Zavislost
mezi objekty je naznaena silnjimi spojovacimi aiami (ty tvoi jadio obiazku).
Adapti pidava dali vistvu zapouzdeni, i kdy ta neni (jet`) zcela dokonala
(existuji objekty, ktei jsou zavisl na pvodnim iozhiani). Teti vistvu zapouz-
18:
datov
representace
metody
jdra
metody

obalu
adaptr
objekt fasda
subsystm za fasdou
Obiazek .I. Sniovani zavislosti mezi objekty
Uivatelsk tidy 18
deni pidava objekt oznaovan jako fasada. Vechny objekty mimo vyznaen
subsystm komunikuji jen s nim, tj. jsou zavisl pouze na jeho iozhiani (s ostat-
nimi objekty subsystmu mohou komunikovat jen nepimo skize fasadu).
=
Na zavi podkapitoly se jet podivame na testovaci piogiam. Ten se pili neli-
i od svho vzoiu, musi vak nov zohlednit nemnnost objektu, je se navenek
piojevuje zmnou iozhiani metody PrictiMinuty.
Pio posun asu ji nelze pouit pvodni pikaz
puvodniCas.prictiMinuty(525);
Tento adek by se peloil, ale nic by nevykonal (tj. nezmnil by stav piogiamu, ani
by nebyla piovedena adna exteini akce). Objekt odkazovan piomnnou puvod-
nCas se toti nemni (objekt je opiavdu nemnn!). Metoda sice viaci nov objekt
s posunutm asem, ten vak neni piazen do adn piomnn a tak je nedostup-
n a po uiit dob me bt odstiann z pamti.
Pioto je nutno vsledek metody piadit do piomnn. Pokud je to jina piomnn,
ne ta kteia odkazovala pvodni objekt, zachovame oba objekty (tj. pvodni i ten
nov s posunutm asem).
DenniCas posunutyCas = puvodniCas.PrictiMinuty(525);
Vsledek vak lze piadit i do stejn piomnn. Tim sice ztiacime odkaz na p-
vodni objekt, ale nov objekt nahiadi pvodni z pohledu algoiitmu.
To se vyuiva v algoiitmu vytvaeni seznamu dennich hodnot

. V kad iteiaci
je piomnna obsahujici aktualni as pesmiovana na nov objekt, iepiesentujici
as posunut o ticet minut. Pvodni objekt vak nezanika, nebo na nj odkazuje
nov pidana poloka seznamu.
while (!idc.JePozdejiNez(horniMez)) {
pulhodiny.Add(idc); / / pida pvodni objekt do seznamu
idc = idc.PrictiMinuty(30); / / vytvoi nov objekt (ten je pidan v dali iteiaci)
}
V kad iteiaci tak vznikne nov objekt, jen se v nasledujici iteiaci pida do se-
znamu. Seznam tak po ukoneni cyklu odkazuje na z nezavislch objekt, ktei
postupn iepiesentuji asy od ccc do 1zcc. Navic vznikne i ze. objekt, ktei se ji
18
idc
idc
horniMez
horniMez
0:00
0:00
12:00
12:00
pulhodiny
pulhodiny
0
List<DenniCas>
DenniCas
idc
idc
horniMez
horniMez
12:00
12:00
pulhodiny
pulhodiny
0
List<DenniCas>
DenniCas
1
idc
idc
horniMez
horniMez
12:00
12:00
pulhodiny
pulhodiny
0
List<DenniCas>
DenniCas
1 23 24 2 22 . . .
Po prvn iteraci
Po druh iteraci
Po posledn (25.) iteraci
0:30
0:30
0:00
0:00
0:30
0:30
1:00
1:00
0:00
0:00
0:00
0:00
1:00
1:00
11:00
11:00
11:30
11:30
...
12:00
12:00
12:30
12:30
Obiazek .1. Piomnn a objekty pi vytvaeni seznamu nemnitelnch objekt
Uivatelsk tidy 18
do seznamu nepida (a bude uvolnn po zaniku piomnni idc). Giack znazoi-
nni viz obiazek .1 na pedchozi stian (poiovnejte s obiazkem znazoiujicim
chybn algoiitmus s piomnnm objektem na stian 1es)

5.3. Vyrovnvac pam (cache) - kolekce, kter


zapomn
Standaidni knihovna .NlT nabizi velk mnostvi iznch kolekci tj. objekt, ktei
sloui jako loit pio jin objekty. Bohuel existuji situace, kdy se nehodi adna
z nich.
Pokud napiklad pidavame do seznamu jednotliv pivky, tak jeho velikost stale
ioste, co me nakonec zpsobit masivni odkladani stianek pamti do swapo-
vaciho piostoiu. To viazn zpomali bh aplikaci v iamci opeianiho systmu a
me to vst dokonce k situaci, kdy poita nestiha kiom masivniho swapovani
nic jinho. Podobn se bohuel chovaji i dali kolekce s piomnou velikosti.
Pokud vyadujeme, aby si kolekce pamatovala vechny uloen hodnoty, pak ne-
existuje adn iozumn eeni tohoto pioblmu, nepoitame-li haidwaiov ioz-
ieni pamti. Natsti existuji situace, kdy poadavek na zapamatovani neni tak
stiiktni. Pokud napiklad do pamti ukladame daje, ktei lze ziskat znovu z p-
vodniho loit (souboiu, inteinetu) nebo znovu vypoist, je zapominani tole-
iovateln. Znovuziskani daje sice me bt asov naionji (v adu napiklad
sekund), ale ziskani hodnoty pi masivnim swapovani me bt jet pomaleji.
Kolekce s timto chovanim se oznauji jako vyrovnvac pamti (angl. a mnohdy
i esky cae). Vyiovnavaci pamti poskytuji diuhotn uloit dat, ktei ma sice
omezenou velikost, ale poskytuje viazn iychleji pistupov as.
Pokud by byl pistup k pvodnim dajm zcela nahodn nepinaely by vyiovna-
vaci pamti adn podstatn ziychleni (ziychleni by v zasad bylo dano pomiem
mezi velikosti vyiovnavaci pamti a celkovho potu daj). Jina situace vak na-
stava, pokud se astji pistupuje k dajm, ktei ji byly nkolikiat vyuivany
a to v ielativn malm asovm inteivalu. V tomto pipad se viazn zvyuje
piavdpodobnost nalezeni daje ve vyiovnavaci pamti (cae hit) opioti situaci,
kdy je nutn daj ziskat z piimainiho loit nebo znovu vypoitat (cae miss).
Pokud je vyiovnavaci pam iychla (ielativn k piimainimu loiti), je ziych-
18e
leni znateln. Piav z tohoto dvodu se pouivaji vyiovnavaci pamti na vech
aplikanich iovnich od CPU, pes pevn disky po webov seiveiy.
Jak vak ji bylo eeno, knihovna .NlT neposkytuje implementaci vyiovnava-
ci pamti na iovni kolekci (tj. napiklad jako nahiadu seznam). Natsti neni
(elementaini) implementace pili sloita.
5.3.1. Nvrh rozhran
Nejdive je nutn navihnout iozhiani nai nov tidy.
Zakladni opeiaci je vloeni daje do vyiovnavaci pamti. Pio jednoduchost bude
nae vyiovnavaci pam ukladat jen etzcov daje tj. objekty tidy string (tians-
foimace na vyiovnavaci pam jinho typu je jednoducha).
Metoda pio vkladani by mla mit minimaln jeden paiameti vkladan objekt-
etzec. Uvyiovnavaci pamti vak nestai vloit pouze hodnotu. Otazkou je toti,
jak budeme uloenou hodnotu nasledn identikovat. Nelze ji identikovat po-
moci postupn iostouciho indexu, nebo ten se v piocesu zapominani pibn
mni. Hodnotu jsme sice mohli vloit jako desatou v poadi, ale po zapomenuti
dive vloench daj se jeji pozice zmni. Pokud napiklad dolo k zapomenuti
dvou pedchozich daj, neni u na desat pozici (s indexemv), ale na pozici osm.
Navic, pokud bude po zapomenuti hodnota znovu vloena, bude piavdpodobn
zaujimat zcela jinou pozici ne pvodn.
Pioto musi mit kad vloen objekt jedinen identikatoi, pomoci nho jej
budeme nasledn vyhledavat. U vyiovnavacich pamti v CPU je timto identika-
toiem adiesa pamti, u webovch pak URL pislunho dokumentu. ldentikatoi
je asto exteini, tj. neni uloen uvnit vkladan hodnoty. V naem jednoduchm
pipad bude exteinimidentikatoiemceloiselna hodnota, kteiou lze inteipieto-
vat jako index/adiesu v pvodnimloiti nebo jako unikatni iseln identikatoi
typu siiovho isla. Tento identikatoi se bn oznauje jako kl (angl. key),
nebo je skuten kliem ke sv hodnot (tj. jedinm piostedkem jak ji ziskat)
Signatuia metody musi zohlednit vkladani hodnoty spolu s exteinim kliem
public void Insert(int key, string value)
Metoda pio vyhledani a viaceni hodnoty oekava jako paiameti kli a viaci pi-
slun objekt (pokud ho nalezne)
public string Find(int identifier)
Uivatelsk tidy 18,
Co vak metoda viati, pokud objekt nenalezne`. To se me stat, nebyl-li objekt
do cache jet vbec vloen, nebo ji byl vloen, ale od t doby zapomenut. V
pipad, e ukladan objekty jsou iefeienniho typu (co na etzec je), me
bt viacena hodnota null (tj. piazdn odkaz, ktei neukazuje na adn objekt).
Toto eeni vak pinai nkolik nevhod
1. s iefeienci null nelze piacovat jako s objektem. Pi volani jakkoliv (etz-
cov) metody na viacenou hodnotu vznikne vjimka. Uivatel nai metody
je tak nucen viacenou hodnotu stale testovat.
z. iefeienci null lze do do cache jako bnou hodnotu (me nap. iepiesen-
tovat neexistujici hodnotu pio dan kli). Pokud v tomto pipad metoda
Find viati null, je otazkou jak to inteipietovat. Znamena to, e hodnota by-
la sice nalezena, ale neni to skuten objekt (a nema tudi smysl dotazovat
se piimainiho loit, nebo i v nm je uloena hodnota null), nebo byl
objekt zapomenut i je piozatim neuloen do vyiovnavaci pamti (a do-
taz na piimaini loit je nezbytn)` Babo ra (opiavdu by se zde hodila
vtkyn).
I. Uhodnotovch typ (nap. isel) nelze tento pistup vbec pouit, nebo pio
n hodnota null neexistuje (jsou uloeny pimo v piomnnch a kolekcich)
Zvla nepijemna je diuha nevhoda, nebo znemouje namisto hodnoty null
vyuit jakkoliv jin pedemzvolen objekt dan tidy (tj. u nas libovoln zvolen
etzec). Dvodem je skutenost, e opt neiozliime, zda viaceni symbolizuje
nenalezeni (cae miss), nebo nalezeni (hit) v pipad, e zvolen objekt byl bn
vloen.
Ve skutenosti adn jednoduch univeizalni eeni neexistuje.
Poznmka:
Jako vhodn eeni se nabizi vyuiti vjimek. Pokud neni hodnota
v cachi nalezena, me bt vyvolana specializovana vjimka. Bohu-
el tudy cesta nevede. Vjimky ei vjimen situace, tj. situace tak
idk i nestandaidni, e nejsou zahinuty ve standaidnim modelu. Si-
tuace, kdy neni objekt s danm identikatoiem nalezen, je vak zcela
bna a je zahinuta pimo v zakladnim denici vyiovnavaci pamti.
To vak jet neznamena, e by pi nenalezeni nemohla bt vjimka
vyvolavana. Jeji vznamje vak zcela jin (signalizuje chybn pouiti
metody, viz dale).
188
lxistuji pouze eeni, ktei vc komplikuji tj. vyaduji dali metody i dokonce
pomocn tidy
1. doplnni dotazovaci metody, kteia neviaci objekt, ale pouze piznak ( lo-
gickou hodnotu), zda je objekt s danm identikatoiem ve vyiovnavaci ob-
jekt i nikoliv. Tato metoda musi bt vdy volana ped metodu Find, a jen
tehdy, pokud viati true ( objekt je pitomen) me bt objekt ziskan me-
todou Find. V opanm pipad je funkce metody Find nedenovana (me
napiklad vyhodit vjimku)
z. metoda viaci dvojici objekt jednimje logick piznak signalizujici pitom-
nost hodnoty, diuhmvlastni hodnota (otazkou vak je, co je to za hodnotu,
pokud je piznak negativni). V C= nelze jednodue viacet dva a vice objekt
najednou, a pioto musi bt viacen objekty uloeny do kontejneiu (kolek-
ce i sloenho objektu). To zvyuje pamov a asov naioky (vytvoeni
kontejneiu vyaduje njak as) a komplikuje to vyuiti vyiovnavaci pa-
mti.
Pio nai implementaci zvolime eeni s pomocnou testovaci metodou (je nejpe-
hlednji)
public bool Contains(int key)
Pedbn dotazovani vak me bt v nkteich situacich zbyten sloit. V
konkitnich pipadech toti me existovat jednoznana hodnota, kteiou mete
symbolizovat nepitomnost klie (a skuten hodnoty). Pioto pio pohodli uiva-
tel tidy vytvoime alteinativni implementaci metody Find s dodatenm paia-
metiem implicitni hodnotou.
public string Find(int key, string defaultValue)
Tento paiameti se uplatni pedevim v pipad, kdy je mnoina pipustnch ob-
jekt omezena, a tak lze zvolit hodnotu, kteia se od vech pipustnch objekt
lii. Pokud napiklad vime, e vechny uloen etzce budou nepiazdn, lze jako
signalizaci nenalezeni pouit piazdn etzec.
Pokud naopak adna nepipustna hodnota neexistuje (tj. do cache lze vkladat li-
bovoln etzce a tak hodnotu null), musi bt dsledn pouivana Contains ped
kadm vyhledavanim. V tomto pipad je vhodn pouit zakladni veizi meto-
dy Find bez dodatenho paiametiu (natsti mohou existovat ob veize metody
zaiove, nebo se lii potem paiameti). Tato veize pedpoklada, e pivek je vy-
iovnavaci pamti obsaen. Pokud tomu tak neni (tj. uivatel zapomnl piovst
Uivatelsk tidy 18,
pedbn test), mla by bt vyvolana vjimka signalizujici nedenovan stav,
iesp. nepipustn pouiti metody (tj. nikoliv pouze cae miss).
Posledni souasti iozhiani nai tidy bude vlastnost Size umoujici zjistit a pe-
devim nastavit velikost vyiovnavaci pamti. Kiom metody pio ziskani hodnoty
(oznaen kliovm slovem get) bude tedy existovat i metoda pio nastaveni vlast-
nosti (ta bude oznaena kliovm slovem set).
int Size {get; set;}
Velikost vyiovnavaci pamti bude navic i jedinm paiametiem konstiuktoiu (zde
s vznamempoateni velikosti). Pedpokladame, e tida bude pojmenovana Cae.
Cache(int initialSize)
Nyni u mame denovano cel iozhiani objekt vyiovnavaci pamti. Ne vak
pikioime k navihu inteini datov iepiesentace a implementace, vyzkouime na-
vih iozhiani na piaktickm piklad.
V opeianim systmu Unix jsou souboiy intein iepiesentovany celm islem,
ktei je oznaovano jak i-number (pvodn se jednalo o lineaini index do tabulky
tzv. i-uzl na disku). Souboiov subsystm Unixu nabizi ielativn iychl a efek-
tivni mechanismus pevodu ze jmna souboiu na islo i-uzlu. Opan pevod vy-
aduje piohledani vech adiesa souboiovho systmu a je tudi znan pomal.
Vyuiti cache me tento pioces viazn uiychlit (pedevim je-li pistupovano
jen k pomalu se mnici podmnoin i-uzl). Metoda FindFileByINumber ani tida
FileSystem piozatim neexistuji (jsou zde je jen z ilustiativnich dvod). Pokud by
se vak implementovala, byla by znan neefektivni (vyhledani v bn velkm
desktopovm souboiovm systmu by tivalo minimaln desitky sekund).
Poznmka:
Rychlost vyhledavani podle i-uzlu si mete vyzkouet v Unixu (Li-
nuxu) pikazem find -inum XXX, kde XXX je poadovan i-islo. Navic
mete ielativn snadno zjistit, e jednomu islu me odpovidat vice
jmen souboi (i-isla jsou lokalni na kadm svazku a navic existuji
tzv. pevn odkazy.
Pokud spustite pikaz vicekiat (i s iznmi isly i-uzl) zjistite, e
dali bhy jsou viazn iychleji. Piogiam nd, toti intein vyuiva
indexov souboiy, co hledani viazn uiychluje (vyuiti pamov
cache vak me hledani uiychlit jet vice).
1,o
Cache inumbers = new Cache(1024); / / vytvoeni nov cache s poadovanou velikosti
/ / hledame jmno souboiu s i-numbei uloenm v piomnn inum
string fileName = inumbers.Find(inum, null);
/ / jmno souboiu neme bt null (dokonce ani piazdn etzec)
if (fileName == null) { / / zaznam v cachi neni
fileName = FileSystem.FindFileByINumber(inum); / / velmi pomala opeiace
inumbers.Insert(inum, fileName); / / nesmime zapomenout vloit jmno souboiu do cache
}
Console.WriteLine(fileName); / / a nyni bychom mohli jmno souboiu vypsat
5.3.2. Datov representace
Datova iepiesentace vyiovnavaci pamti musi splovat dv zakladni podminky
1. minimalni pamov naioky. Vyiovnavaci pam by mla optimaln zauji-
mat jen misto dan soutem velikosti uloench poloek a popipad inde-
x.
z. efektivni a iychla implementace kliovch opeiaci (pidani a hledani). Op-
timalni byla implementace s asovou sloitosti (1).
Bohuel je velmi obtin splnit ob podminky najednou.
asov sloitosti (1) lze dosahnout napiklad vytvoenim seznamu, jeho ve-
likost by byla iovna maximaln pipustnmu indexu (dale oznaovani jako ).
Tento seznam by vak uchovaval jen tolik poloek, kolik je kapacita cache (co je
hodnota vlastnosti , ozname ji pioto ). Ostatni poloky seznamu by byly
naplnny hodnotou null (pedpokladame, e ukladan hodnoty jsou iefeienniho
typu a jsou izn od hodnoty null). Pi ukladani by se objekt ukladal do polo-
ky, jeji index se iovna identikatoiu (klii) objektu (tj. identikatoiem me bt
je celoiselna hodnota). Vyhledani se ei indexaci (je viacena poloka na danm
indexu, nebo implicitni hodnota).
V piaxi je (adov meni) tj. vtina poloek seznamu by byla piazdna
a zbyten by zatovala pam. Pi velkm (jako je tomu napiklad u naeho
pikladu s i-uzly, ktei jsou bn v adu miliaid) by byly pamov poadavky
dokonce extimni (i uloeni piazdnho odkazu vyaduje 1 byty pamti).
Otazka Vjakmpipad je tato iepiesentace toleiovatelna nebo dokonce vhodna`
Zkuste tento pipad kvantikovat pomoci . a velikosti ukladanch objekt.
Uivatelsk tidy 1,1
Na opanm konci stoji iepiesentace, v ni je cache iepiesentovana souvislm a
lineainim seznamem, tvoenm dvojicemi identikatoi a hodnot. Tato iepiesen-
tace vyaduje minimum pamti (je iovna soutu velikosti vech uloench polo-
ek a jejich index).
Konkitni algoiitmus pio vkladani a vyhledavani je dan stiategii zapominani tj.
algoiitmem, jen uiuje, kteia poloka bude ze seznamu vymazana v okamiku,
kdy se nova poloka do vyiovnavaci pamti ji nevejde.
Mezi iozumn (tj. v piaxi vyuiteln) stiategie zapominani pati
1. vymazana je poloka, kteia je nejdle uloena (piincip lllO ist in ist
out)
z. vymazana je poloka, kteia nebyla nejdeli vyuivana (piincip LRU least
iecently used)
I. vymazana je nahodna poloka
Pokud by byl pistup k polokam ve vyiovnavaci pamti zcela nahodn, je v za-
sad jedno jaka je pouita stiategie zapominani. To vak plati pouze tehdy, pokud
je vyiovnavaci pam velmi mala (vzhledem k potu potencialn identikovatel-
nch objekt), anebo jsou-li uloen objekty vyadovany v nahodnm poadi a se
stejnou piavdpodobnosti (bez ohledu na to zda jsou i nejsou ve vyiovnavaci pa-
mti). Nicmn tato konstelace neni ve vtin piaktickch nasazeni vyiovnavaci
pamti pili piavdpodobna.
Pi iozumn velikosti vyiovnavaci pamti a zven piavdpodobnosti pistupu k
objektm, ktei byly vyadovany nedlouho pedtim, je optimalni LRU stiategie.
lllO stiategie exceluje v pipad, kdy se pistup dje v uiitm poadi (nap. s
postupn iostoucimi klii).
My zvolime nahodnou stiategii, kteia je snadno implementovatelna a je ve vtin
nasazeni alespo toleiovatelna (tj. neni optimalni, ale vyiovnavaci pam pinai
jist ziychleni).
Pi volb teto stiategie nad iepiesentaci pomoci souvislho seznamu lze pi vkla-
dani dosahnout konstantniho asu pi vkladani (bez testu, zda je ji hodnota s
danm kliem ve vyiovnavaci obsaena). Vyhledavani je v tomto pipad bohu-
el viazn pomaleji, nebo nelze dosahnout lepi asov sloitosti ne ().
Jak vak budeme do seznamu ukladat pospolu klie (tj. u nas cela isla) i hod-
noty (zde etzce)` Zatim jsme pouivali jen seznamy hodnot obsahujici objekty
jednoho typu (nap. seznamy isel nebo seznamy etzc). eeni neni sloit,
1,:
stai vytvoit tidu jeji objekty budou sestaveny ze dvou podobjekt. Jeden bude
iepiesentovat kli, diuh hodnotu. Rozhiani tohoto objektu-kolekce bude velmi
jednoduch, nebo jedinou poadovanou funknosti je uloeni obou podobjekt
(co zajisti konstiuktoi) a nasledn pistup ke kadmu uloenmu podobjektu
zvla (co zajisti dvojice vlastnosti).
Uivatelsk tidy 1,
Poznmka:
Sdiueni vice hodnot do jednoelov tidy iesp. kolekce je nkdy
uvadno jako jednoduch navihov zdioj se jmnem Pepravka (an-
gl. Box). Pouiva se v pipadech, kdy je nutno ukladat i viacet n-
tice hodnot (pedavani n-tice jako paiametiu neni tak ast nebo
jazyk umouje pim pedavani vtiho potu paiameti). Kiom
nie uveden implementace vlastni tidy (co je nejobecnji, ale po-
nkud zdlouhav eeni) existuji i dali. Za piv lze vyuit ji exis-
tujicich tid s podobnou smantikou nap. geneiick tidy System.-
Collections.Generic.KeyValuePair (uivanou v iozhiani slovnik), ne-
bo obecnjich geneiik pio libovoln n-tice (oznaovan angl. na-
zvem System.Tuple, dostupn od C= 1.c). V nkteich pipadech (ni-
koliv vak v naem) lze vyuit tzv. anonymnich tid.
class CacheItem {
public int Key { get; private set; }
public string Value { get; private set; }
public CacheItem (int key, string value) {
this.Key = key;
this.Value = value;
}
}
Konstiuktoi pomocn tidy neni nijak zvla zajimav. Jako sv paiametiy pijima
dvojici objekt v poadi kli a hodnota a tyto objekty (iesp. odkazy na n) uklada
do pislunch vlastnosti (a jejich piostednictvim do svch datovch len).
Mnohem zajimavji je vak denice vlastnosti. Nikde toti nevidime pislun
datov leny a chybi i implementace metod pio ziskani (geuei) a nastaveni vlast-
nosti
Automatick vlastnosti
Dvodem je skutenost, e jazyk C= nabizi takzvan automati vlastnosti.
Automatick vlastnosti umouji elegantn a stiun denovat jednoduch vlast-
nosti, ktei pimo zpistupuji jedin datov len.
Z dvod zapouzdeni je toti nutno denovat i vlastnosti, ktei ve svm get-
teiu viaci hodnotu jedin piomnn (bez jakkoliv zmny i testovani) a ve sv
1,
nastavovaci metod (seueiu) tuto piomnou pimo nastavuji (opt bez jakkoliv
kontioly, zmny i vedlejiho efektu). Me se to zdat tiochu nadbyten, ale v
zasad nikdy nevite, zda nakonec nebude nutno zmnit inteini iepiesentaci nebo
pidat ke geueiu iesp. seueiu dodatenou funknost. Pioto je nutno uivatele vai
tidy hned od zaatku donutit vyuivat vlastnosti nikoliv pimo datov leny (ty
by mly zstat soukiom).
Ped pichodem automatickch vlastnosti (ve veizi 1.c jazyka C=) vak tento po-
adavek vyadoval napsani nkolika adk nudnho kodu (nudnho, nebo je v
zasad stale stejn, jen identikatoiy se mni)
private int key; / / datov len
public int Key { / / tiivialni vlastnost nad lenem key
get {
return key; / / iovnou viaci hodnotu
}
private set {
key = value;
}
}
Metoda pio ziskani vlastnosti (geuei) zde viaci hodnotu datovho lenu (bn
mival stejn jmno jako vlastnost, liil se jen pouiti minusky na zaatku). Na-
stavovaci metoda neni o mnoho sloitji. Piotoe vak explicitn nedenuje svj
jedin paiameti (tj. nov nastavovanou hodnotu), je nutno pouivat specialni lo-
kalni piomnnou value. Tato piomnna je denovana jen v tle nastavovacich me-
tod a obsahuje hodnotu, kteia ma bt nastavena tj. hodnotu, kteia je do vlastnosti
zdanliv piazovana. Typ tto piomnn ( tida obsaenho objektu) odpovida
typu vlastnosti (zde je to tedy nap. int).
Vimnte si tak, e ped kliovm slovem set je uvedena specikace private. Za-
timco geer je veejn (co je uieno specikaci public ped hlavikou vlastnosti),
je seer soukiom (co musi bt denovano pimo u seueiu). Hodnotu vlastnosti
tak mete ziskat v libovolnm mist piogiamu (tj. i v jinch tidach), monost
nastaveni je vak omezena pouze na metody vlastni tidy. Dvodem je navih (na-
i konkitni) tidy, kteia poita s tim, e jeji instance budou nemnn (z dvo-
d jednoduiho a bezpenjiho pistupu k nemnnm objektm, viz diskuse na
stian 1e). Pioto je teni neomezen (vlastnost me bt tena kdekoliv a koli-
oznaeni seuei je opt tiochu slangov, ocialni oznaeni nastavovaci metody je muttor
Uivatelsk tidy 1,
kiatkoliv je poteba), nastavovaci metoda je vak volana pouze jednou a to v kon-
stiuktoiu nai tidy (viz zapis this.Key = key). Optovn pouiti seueiu v jinch
(potencialnich) metodach tidy je sice foimaln mon, ale my si jako implemen-
tatoi pohlidame, e se tak nastane (podle piavidla jednou a dost).
Automaticka vlastnost je syntaktickou zkiatkou za ve uveden zapis. Stai uvst
jen hlaviku vlastnosti (s jejim jmnem a typem) a uvst zda se poaduje geuei,
seuei i oboji (v zasad je to zbyten, nebo ob metody jsou defacto povinn).
Peklada sam vytvoi datov len, nad nim bude vlastnost piacovat (zvoli pio
nj unikatni jmno, ktei vak nikde nezveejni) a vygeneiuje pislunou tiivialni
implementaci seueiu a geueiu.
Otzka Pio je nutn poadovat vytvoeni obou pomocnch metod (jak seeru
tak geeru)`
l kdy lze v zasad zadavat libovolnou kombinaci pistupovch piav k seueiu a
geueiu, jsou v piaxi vyuiteln jen ti kombinace
public type Property {get; set;}
Vlastnost lze veejn ziskavat i nastavovat. Vhodn jako souast veejnho ioz-
hiani u tid, jeji objekty se mohou v pibhu ivota mnit. Neni to vak nezbytn,
pim nastaveni vlastnosti nemusi bt navenek podpoiovano.
public type Property {get; private set;}
Vlastnost lze veejn pouze nastavit. Vyuiva se, jak ji bylo ve eeno, u tid,
jeji instance jsou nemodikovateln. Seuei se vyuiva pouze v konstiuktoiu pio
inicializaci ( nastaveni skiytho datovho lenu)
private type Property {get; set;}
Vlastnost je soukioma a neni tudi souasti iozhiani. Nejastji je to pomocna
vlastnost uivana v metodach, ktei pak nejsou zavisl na inteini iepiesentaci
(vnitni zapouzdeni, viz sekce .z na stian 1sc).
5.3.3. Implementace
Nyni, kdy ji mame pipiavenu pomocnou tidu, meme pistoupit k implemen-
taci tidy hlavni
1,e
class Cache {
private List<CacheItem> data;
private Random generator = new Random();
Objekt tidy Cae je sloen ze dvou podobjekt. Objekt tidy List<CaeItem> (tj.
seznamobjekt pomocn tidy-schianky CaeItem) je hlavnimpodobjektem. Vy-
iovnavaci pam je ve skutenosti jen tenkou adaptaci pvodniho seznamu (tenk
adaptace dodaten kod pizpsobujici adaptovan objekt je iozsahemmnohem
meni ne kod samotnho adaptovanho objektu).
Diuh podobjekt tidy Random ma pouze pomocnou ioli. Objekty tidy Ran-
dom jsou tzv. geneiatoiy nahodnch isel, tj. objekty je poskytuji tzv. pseu-
donahodna isla ( isla vybiiana zdanliv nahodn z jistho iozsahu, podob-
n svou funkci hiaci kostce, viz nap. http://en.wikipedia.org/wiki/Pseudorandom_
number_generator). Tento podobjekt bude vyuit pi implementaci nahodn stiate-
gie zapominani.
Genertory nhodnch sel
Geneiovani skuten nahodnch isel je jednim z klasickch pioblm infoima-
tiky. Na jedn stian jsou nahodna isla velmi uitena, na diuh stian se vak
velmi obtin ziskavaji. Na posloupnost nahodnch isel jsou toti kladeny za-
sadni poadavky, z nich iovnominost iozdleni v iamci danho inteivalu i ex-
timn dlouha (nejlpe de facto nekonena) peiioda, po ni se isla opakuji, tvoi
jen nezbytn minimalni zaklad.
Skuten nahodn isla poskytuji jen haidwaiov geneiatoiy, zaloen na kvan-
tovch jevech (iozpad iadioaktivnich atom, pichod svtla tenkmi optick-
mi iozhianimi) nebo chaotickm chovani velkho mnostvi astic (nap. atmo-
sfiick i tepeln umy). Vtina z tchto geneiatoi je ielativn diaha a ma
jen velmi malou vtnost (v jednotkach desitek i stovek nahodnch byt za
sekundu). Jako ielativn dostupn (a tudi i peispektivni) se jevi geneiatoiy zalo-
en na jemnch nepesnostech vysokofiekvennich ita iesp. spojovani iz-
nch zdioj nahodilosti v iamci PC piostednictvim specializovan aplikace (viz
nap. linuxovsk zaizeni /dev/random). Avak i tyto zdioje jsou bohuel velmi
pomal. Mal test mi ukazal, e zaizeni /dev/random na mm notebooku posky-
tuje jen 1I byt/s (a to jsem se snail vypiodukovat vice nahodnosti iychlm
pohybem myi). Pioto se astji pouivaji smien geneiatoiy, v nich je haid-
waiov geneiatoi vyuivan jen pio peiiodick nastavovani geneiatoiu sofwaio-
Uivatelsk tidy 1,,
vho. Toto eeni je vyuivano v iamci linuxovho zaizeni /dev/urandom iesp.
novji v technologii DRNG, ji nabizeji nejnovji intelovsk piocesoiy (od ai-
chitektuiy Ivy Bridge, dokumentace viz http://software.intel.com/en-us/articles/
intel-digital-random-number-generator-drng-software-implementation-guide/).
Alteinativn lze dokonale nahodna isla ziskat piostednictvim slueb inteinetu.
Pikladem je napiklad sluba random.org.
Sofwaiov geneiatoiy poskytuji isla, kteia se jen tvai jako nahodna. Ve skute-
nosti vak piodukuji pedem piedikovatelnou posloupnost, kteia se navic musi
po jist dob opakovat. Nejjednodui geneiatoiy se od dtsk ikanky Eneky
benyky, kliky ben, nkdo mus z kola ven lii jen kvantitativn.
Obecn poskytuje jakkoliv sofwaiov geneiatoi posloupnost m-bitovch ce-
lch isel, pio ni plati
+1
= (

). Pivni len posloupnosti


c
(tzv. seed) musi
bt poskytnut jinmmechanismem. Nejastji to bva xni hodnota (posloupnost
je pak vdy stejna), aktualni as nebo hodnota z jinho (typicky haidwaiovho)
geneiatoiu. Pokud nastane situace, e je hodnota

iovna nkteimu z ped-


chozich pivk

( < ), pak se piiozen opakuji i nasledujici hodnoty, nebo

+1
= (

) = (

) =
+1
a tak dale. Vznika tak tzv. cyklus.
Unejjednoduich geneiatoi (lineain kongiuennich) ma funkce tvai +,
kde . jsou vhodn zvolen konstanty, piem vpoet se piovadi s -bitovmi
isly (s peteenim). Dlka cyklu je pioto vdy meni nebo iovna z

(zavisi na
hodnotach a ).
Podobnho typu je i standaidni geneiatoi nabizen knihovnou .NlT. Pio nae
ely bohat stai, pokud vak potebujete kvalitnji (pseudo)nahodnost je nut-
n se poohldnout po kvalitnjim geneiatoiu (zaloenm nap. na tzv. Mersenne
Twisteru, jen poskytuje extimn dlouh cykly). Pio ely kiyptogiae je pak
nutn pouivat specialni tidu geneiatoi, ktei musi bt nejen kvalitni, ale i ne-
piedikovateln (tj. musi alespo asten vyuivat haidwaiov geneiatoi, mini-
maln pio svou inicializaci).
=
Hieiaichickou stiuktuiu objektu tidy Cae lze vidt na obiazku . na nasle-
dujici stian. Obiazek ukazuje stav, kdy je vnitni seznam ji asten naplnn
polokami (tj. objekty tidy CaeItem). Konkitn znazoinn stav (vyiovnavaci
pam s temi polokami, z nich jedna je jet nevyuita tj. je iovna null), vznikne
nejdive po diuhm pidani (s piavdpodobnosti z/I), ale me setivavat i po
pozdji. Piavdpodobnost neplnho vyplnni s iostoucim potem pidani iychle
1,8
klesa (po pidanich je iovna
\
z
I
}
1
) . Vimnte si tak, e hodnoty tidy int jsou
uloeny pimo ve svm nadobjektu, nebo int je hodnotov typ,
Cache
CacheItem
data
genertor
CacheItem
int:key int:key
List<CacheItem> Random
[0] [1] [2]
string
value
string
value
null
Obiazek .. Ukazka kompozice objektu tidy Cae
Konstiuktoi nov vyiovnavaci pamti neni zcela tiivialni. Nejdive vytvoi piazd-
n seznam, jeho kapacita je nastavena tak, aby odpovidala vsledn velikosti.
Nasledn seznam vyplni postupnm pidavanim hodnot null na konec seznamu
(iychleji zpsob bohuel neexistuje, u malch vyiovnavacich pamti to vak neni
pili velk pioblm).
public Cache (int initialSize) {
data = new List<CacheItem>(initialSize);
for (int i=0; i<initialSize; i++) {
data.Add(null);
}
}
Nyni se podivejme na implementaci kliovch metod Insert, Contains a Find.
public void Insert(int key, string value) { / /

int randomIndex = generator.Next(0, data.Count);


data[randomIndex] = new CacheItem(key, value);
}
Uivatelsk tidy 1,,
private int FindIndex(int key) { / /

for (int i=0; i<data.Count; i++) {


if (data[i] != null && data[i].Key == key) / /

return i;
}
return -1;
}
public bool Contains(int key) { / /

return this.FindIndex(key) >= 0;


}
public string Find(int key) { / /

int index = this.FindIndex(key);


if (index >= 0)
return data[index].Value;
else
throw new KeyNotFoundException("Unexpectedcachemiss");
}
public string Find(int key, string defaultValue) { / /

int index = this.FindIndex(key);


return index >= 0 ? data[index].Value : defaultValue;
}
Metoda Insert

je velmi pimoaia (nebo velmi pimoaia je i nae stiategie na-
hodnho zapominani). Nejdive je nahodn zvoleno cel islo v inteivalu c 1.
To zajiuje objekt geneiatoiu nahodnho isla odkazovan datovmlenemgene-
rtor. Volanim nam ji znam metody Random.Next s dvma paiametiy min, max
ziskame nahodn cel islo z inteivalu [. ) (tj. zatimco dolni mez je za-
hinuta, hoini nikoliv). Nasledn je vytvoena sloena poloka (objekt-pepiavka,
tj. instance tidy CaeItem) a vloena na nahodn vybian index. Pi ukladani
je pepsan odkaz na pvodni poloku, kteia je tak zcela piiozen odstiann z
cache (samozejm je zde i mala, ale nikoliv nulova piavdpodobnost, e v dan
poloce neni piozatim uloen adn objekt).
Tato implementace je iychla (nejen, e ma sloitost (1), ale vyaduje jen pai in-
stiukci piocesoiu), bohuel vak skiva (ielativn zavan) nedostatek. Pi vkla-
dani jakkoliv hodnoty, se netestuje zda je tato hodnota ji ve vyiovnavaci pamti
:oo
uloena i nikoliv. Hodnota (spolu s kliem) tak me pi opakovanm vkladani
zaujmout vice poloek cache, nebo pi kadm volani je vloena na nahodnou
a tudi i potencialn odlinou pozici. Navic piavdpodobnost, toho, e ve vyiov-
navaci pamti bude vice kopii hodnoty se shodnm kliem, me velmi vysoka,
U pi diuhm vloeni stejn hodnoty je iovna ( 1)/, pi dalich opakovanch
vloeni dale ioste.
Tento nedostatek by bylo lze opiavit kontiolou existence klie ve vyiovnavaci pa-
mti, to by vak metodu viazn zpomalilo. Natsti je tento pioblm iielevantni
pi bnm schmatu pouiti vyiovnavaci pamti, v nm je nejdive testovano
zda je hodnota obsaena a jen v pipad, e tomu tak neni je vloena. Bohuel
nelze zcela vylouit, e bude pouit jin schma a u z neznalosti nebo z dvod
specialni vkladaci smantiky (nap. ukladani vice daj, ktei lze ziskat najednou
jedinm dotazem na pomal loit).
Bohuel pi piogiamovani se mnohdy musime iozhodnout mezi dvma monost-
mi
1. iychlou a elegantni opeiaci, u ni vak chybn pouiti me vst k nedeno-
vanmu stavu i jinm pioblmm (nap. v naem pipad se me viazn
sniit efektivita vyiovnavaci pamti)
z. pomalou a sloitou opeiaci, kteia je vak iobustni tj. funguje v jakmkoliv
kontextu (i alespo zpsobuje vjimku, pokud je chybn pouita)
Rozhodnuti neni snadn. Ve vtin pipad je vhodnji zvolit iobustnost, ne-
bo miin zpomaleni piogiamu (nap. testovani vstupni hodnoty) je ve vtin
pipad toleiovateln, naopak nedenovan chovani metod, me vst k hodi-
nam ladni a hledani chyb (ktei navic psobi kod, jen jste nenapiogiamovali).
V naem pipad je vak zpomaleni viazn a chybn pouiti nevede k nedeno-
vanmu chovani. Pioto je zde zjednoduena implementace piavdpodobn lepim
eeni. Omezeni metody by vak mlo bt explicitn zminno v dokumentaci.
Nyni se vak pesume k vyhledavacim metodam. Vechny ti vyhledavaci meto-
dy (Contains a dv veize metody Find) sdileji ast sv implementace. Vechny toti
nejdive vyhledavaji pivni vskyt hodnoty s pislunm kliem, a a pot izn
signalizuji vsledek vyhledavani. Pioto vechny ti metody vyuivaji pomocnou
metodu FindIndex

, kteia viaci index poloky, v ni se hledan kli spolu s hod-


notou nachazeji. Pokud pomocna metoda dan kli nenalezne viaci hodnotu -1
(podobn jako metoda IndexOf u seznam).
Tato metoda je oznaena jako soukioma, piotoe jejim zveejnnim, bychom od-
Uivatelsk tidy :o1
kiyli implementani detail, ktei nijak nesouvisi se smantikou vyiovnavaci pa-
mti. Vnjiho uivateli toti zajima jen to, zda je hodnota s danm kliem ve
vyiovnavaci pamti obsaena i nikoliv. Nemusi (a ani by neml) znat skuten
umistni hodnoty, tj. jak ma index i vbec zda njak index ma (hodnoty ne-
musi bt uloeny jako souvisla posloupnost).
lmplementace pomocn vyhledavaci metody je tiivialni. Pomoci cyklu pes inde-
xy (for cyklus) jsou postupn piochazeny jednotliv poloky seznamu, a v pipa-
d, e odkazuji na hodnotu uloenou spolen s hledanmindexem, je tento index
nepiodlen viacen (dali poloky u nemusi bt piohledavany).
Uiitou pozoinost si vak zasloui podminka konstiukce if v tle cyklu

, ne-
bo vyuiva zajimavou vlastnost logickch opeiatoi. Zakladni smantika se zda
zejma, aktualni poloka je tou hledanou, pokud je izna od null (tj. je u vyuita
pio uloeni klie s hodnotou) a zaiove (and, &&) obsahuje pislun kli. Pokud
by vak byla piazdna (tj. obsahovala by null odkaz), nedojde ke vzniku vjimky
NullReferenceException` Vdy pece pistupujeme k vlastnosti (Key) neexistujici-
ho objektu.
Zkrcen vyhodnocovn logickch opertor
Natsti v tomto pipad neni diuha podminka vbec vyhodnocena, nebo C= vy-
uiva tzv. zkrcen vyhodnocovn logi opertor. Doten logick ope-
iatoiy jsou binaini, tj. maji dva opeiandy. Nejdive je vyhodnocen lev opeiand.
Pokud jeho hodnota jednoznan uiuje vsledek, pak diuh (tj.piav) opeiand
neni vyhodnocen. Tato situace nastava u opeiatoiu ~Nb (&&) v pipad, e je
pivni opeiand nepiavdiv (vsledek je bez ohledu na diuh opeiand vdy false),
ov opeiatoiu OR (), naopak v pipad, je-li pivni opeiand piavdiv (vsledek je
vdy true).
Zkiacen vyhodnocovani ma nkolik vhod
l. uiychluje vyhodnocovani
ll. nepiovedeni vedlejich efekt u diuhho opeiandu (pi pislun hodnot piv-
niho) me bt pouito pio jednoduch izeni bhu piogiamu (namisto podmin-
nho pikazu)
Typickou konstiukci tohoto typu je konstiukce udlej to NEBO zemi
doAction() || exit()
:o:
co je zkiatkou za
if (!doAction()) / / pokud se akce nepovede
exit(); / / ukoni zapiacovani
V C= se tato konstiukce nepouiva pili asto, nebo metody bn neviaci logic-
kou hodnotu podle spchu zpiacovani. Namisto toho viaceji pimo vsledek a
vyvolavaji vjimku pi nespchu. Navic na mist diuhho opeiandu nelze vyuit
pikaz return nebo throw (musi to bt viaz nikoliv pikaz). Mnohem uitenji
je vak tato konstiukce v dynamicky typovanch jazycich jako je JavaScript nebo
PHP.
lll. sloen podminky jsou vykonavany zleva dopiava. V pipad etzce podmi-
nek spojench opeiatoiem AND, tak lze u diuh podminky automaticky ped-
pokladat, e pivni byla splnna (tj. v naem pipad meme testovat hodnotu
vlastnosti, nebo objekt uiit existuje), obecn pak jsou pi vyhodnocovani -t
podminky uiit splnny podminky
1
a
1
. Vhodn zvolenm poadim pod-
minek (od obecnch ke konkitnim a detailnjim) lze viazn zjednoduit zapis
(neni nutno psat vnoen konstiukce if )
Otazka Jak lze jednodue popsat mechanismus vyhodnoceni u deliho etzu pod-
minek nap.
1
&&
z
&&

nebo
1

z

`
=
Pouiti pomocn metody viazn zjednodui implementaci vyhledavacich me-
tod. Ve vech tech dotazovacich metodach stai piovst tiansfoimaci smantiky
pomocn metody (index poloky nebo 1) na smantiku pislun metody. Nej-
jednodui je to v pipad metody Constains

, kteia namisto platnho (tj. ne-
zapoinho) indexu viaci objekt true a na misto indexu 1 objekt false ( objekt
s danm kliem se ve vyiovnavaci pamti nenachazi). Na tiansfoimaci tak stai
pouh poiovnani indexu s nulou.
U obou metod Find je index vyuit k ziskani pislun hodnoty. Pokud je ioven -1
tak se smantika ve shod s naim pvodnim navihem lii. U metody

s jednim
paiametiem tj. bez implicitni hodnoty je vyvolana vjimka (signalizujici nepi-
pustn pouiti metody), u metody

s dodatenm paiametiem (implicitni hod-
notou) je viacena tato implicitni hodnota. Pio zkiaceni zapisu je vak v tomto
pipad namisto konstiukce if pouit tzv. podmnkov opertor.
Uivatelsk tidy :o
Podmnkov opertor
Podminkov opeiatoi je jedinm teinainim opeiatoiem jazyka C=, tj. opeiatoiem
se temi opeiandy. Pvodem je z jazyka C a pioto se vyskytuje v tm identic-
k podob v mnoha souasnch piogiamovacich jazycich (Java, PHP, JavaSciipt,
atd.)
Obecn tvai podminkovho opeiatoiu je
v1 ? v2 : v3
kde viaz v1 je podminka (tj. viaz, jen se musi vyhodnotit na objekt tidy bool)
a viazy v2, v3 mohou bt libovolnho avak spolenho typu (tj. po vyhodnoceni
viaceji objekt stejn tidy).
Nejdive je vyhodnocen pivni opeiand (tj. v1). Je-li vsledkem vyhodnoceni ob-
jekt true, pak je vyhodnocen diuh opeiand (vz) a vsledek jeho vyhodnoceni
se stava hodnotou celho opeiatoiu. Teti opeiand se v tomto pipad vbec ne-
vyhodnocuje (tj. nepiovedou se ani jeho pipadn vedleji efekty). Pokud je vak
vsledkem pivniho viazu objekt false, pak se naopak vyhodnoti teti opeiand
(za znakem ) a diuh zstane nevyhodnocen.
Podivejme se na jednoduch piklad, ale ilustiativni piklad
x > 0 ? x++ : x--
Tento viaz viaci (iseln) objekt, jen byl pvodn uloen v piomnn x (bez
ohledu na platnost podminky!). Pokud je vak podminka splnna (tj. > c) pak se
hodnota piomnn zvi o jedniku (je piovedena postinkiementace), v opanm
pipad se o jedniku snii (je vyhodnocen teti opeiand s postdekiementaci).
l kdy je jeho smantika obdobna konstiukci if, jedna se opeiatoi a nikoliv pikaz.
To viazn ovlivuje syntaktick kontext pouiti
I. ternrn opertor lze vyut uvnit jinho vrazu resp. na mst kde je vraz
oekvn
Teinaini opeiatoi je asto vyuivan v aigumentu pikazu return.
Namisto zapisu
if (podmnka)
return v1;
else
return v2;
:o
tak lze pouit mnohem kompaktnji vaiiantu
return podmnka ? v1 : v2;
Teinaini opeiatoi lze vyuiti ve skutenm paiametiu metod
list.Add(x>=0 ? x : -x)
Toto pidani absolutni hodnoty isla do seznamu je mnohem pehlednji ne
klasick zapis za pomoci if.
if(x>=0)
list.Add(x)
else
list.Add(-x)
Podobn lze teinaini opeiatoi vyuit uvnit indexace
seznam[i >= 0 && i < seznam.Count ? i : 0]
Tento zapis viaci poloku s danm indexem i pokud je tento pipustn, jinak po-
loku pivni ( s indexem c).
Mn asto se teinaini opeiatoi pouiva jako opeiand jinch binainich opeiatoi
x = y / (twoside ? h : h/2.0)
Piomnna twoside obsahuje logick piznak tj. hodnotu typu bool. Vimnte si i
zavoiek kolem podminkovho opeiatoiu. Tento opeiatoi ma velmi nizkou piio-
iitu, take zavoiky se bn objevuji kolem cel podminn asti nikoliv kolem
jeho jednotlivch opeiand.
II. parametry ternrnho opertoru nesm bt pkazy
Nejastji chybou je uvadni pikaz skoku v iamci teinainiho opeiatoiu
x > 0 ? return true : break;
nepipustn je i vyhozeni vjimky
x >= 0 ? 0 : throw Exception("Zapornahodnota");
Uivatelsk tidy :o
5.3.4. Testovac kd
Nyni je ji implementace vyiovnavaci pamti kompletni. Je vak nutno napsat
jet testovaci kod.
class MainClass {
public static void Main(string[] args) {
Random keyGen = new Random();
Cache c = new Cache(5);
int hits = 0;
for (int i=0; i<100; i++) {
int key = (int)keyGen.Next(i - 2, i + 3);
if (c.Contains(key)) {
Console.WriteLine(string.Format("Hit:{0}:{1}",
key, c.Find(key)));
hits++;
} else {
string value = key.ToString();
c.Insert(key, value);
}
}
Console.WriteLine("Totalhits:" + hits);
}
}
Testovaci kod vytvai malou vyiovnavaci pam a pot simuluje sto pistup k ni.
Do vyiovnavaci pamti se ukladaji etzcov iepiesentace malch isel. Kliem
je pislun islo. Tj. napiklad hodnota stiingzc je dostupna pes kli intzc.
To je samozejm jen velmi jednoduch a nepili piaktick piklad (pevod isla
na etzec je iychla opeiace, kteia nemusi bt uiychlovana vyuitim vyiovnavaci
pamti). Pioto tak nezjiujeme as piovedeni, ale jen poet cae hits tj. poet
spnch pistup k vyiovnavaci pamti.
Pistup k vyiovnavaci pamti je simulovan pomoci nahodnch isel. Pokud by byl
pimo pouit geneiatoi, ktei by viacel nahodna isla s iovnominmiozloenim
od c do vv, bylo by spnch pistup do cache jen pomalu (v adu malch jed-
notek). Natsti v iealnch aplikacich neni pistup zcela nahodn, nebo mnoh
pistupy se opakuji a to v nevelk asov vzdalenosti.
:oe
Pioto je simulovano vyuiti, v nm nahodn klie lei v malm iozmezi od z
do + z (vetn), kde vak postupn ioste od c do vv. To zvyuje piavdpodob-
nost, e dojde k opakovanmu pistupu jet ped zapomenutimpvodni hodnoty.
Vstup pak me mit nasledujici tvai (kad sputni viaci samozejm zcela jin
hodnoty, mly by vak mit stejn iozloeni)
Hit: 1:1
Hit: 10:10
Hit: 9:9
Hit: 9:9
Hit: 15:15
Hit: 19:19
Hit: 20:20
Hit: 23:23
Hit: 27:27
Hit: 29:29
Hit: 31:31
Hit: 37:37
Hit: 38:38
Hit: 42:42
Hit: 46:46
Hit: 53:53
Hit: 60:60
Hit: 63:63
Hit: 74:74
Hit: 85:85
Hit: 87:87
Hit: 90:90
Hit: 93:93
Total hits: 23
Vicenasobn sputni (1ccc) ukazalo, e poet spnch zasah kolisa v dosti i-
iokm iozhiani od 1e do 1z (tj. vpis iepiesentuje spie hoii piklad). S malou,
ale nenulovou piavdpodobnosti mohou nastat i situace s meni i vtim potem
zasah (poet zasah ma noimalni iozloeni se stedni hodnotou zs,1e a smio-
datnou odchylkou I,e).
Nae vyiovnavaci pam, zda se, funguje. Jeji datova iepiesentace vak neni stale
optimalni, nebo vyhledavani ma asovou sloitost (), kde je velikost cache.
Pomoci seznamu vak nikdy nedosahneme stavu, kdy ma jak vkladani tak vyhle-
davani sloitost lepi ne () (nejlpe samozejm (1)). Natsti vak zname i
Uivatelsk tidy :o,
kolekce, ktei umoni implementace vyiovnavaci pamti viazn uiychlit. Jed-
nou z nich je kolekce oznaovana jako slovnk, ji bude vnovana cela nasledujici
kapitola.
6. Slovnk
Slovnik (anglicky dictionary) je kolekce iepiesentujici zobiazeni z mnoiny tzv.
kli do mnoiny hodnot (viz e.1). Hlavni opeiaci slovniku je iychl vyhledani
hodnoty podle klie. Zobiazeni se anglicky oznauje slovem map tj. mapovn.
Pioto se jako alteinativni oznaeni slovniku pouiva i teimin map (esky mapo-
vani nikoliv mapa).
instance tdy kl (TKey)
mnoina kl
(Keys)
instance tdy hodnot (TValue)
mnoina hodnot
(Values)
kl
(vzor)
hodnota
(obraz)
zobrazen
dvojice (kl, hodnota)
Obiazek e.1. Slovnik zobiazeni kli na hodnoty
lxistuje nkolik dalich (vzajemn ekvivalentnich) pohled na slovnik
1. slovnik je neuspoadana kolekce dvojic tvoench kliem a hodnotou, kteia
piefeiuje vyhledavani podle klie. Ve slovnik nemohou bt uloeny dvo-
jice se shodnmi klii (v opanm pipad by to ji nebylo jednoznan
zobiazeni).
z. slovnik je piostedek jak iychle tiansfoimovat hodnoty z jedn mnoiny
na mnoinu diuhou (ob mnoiny nemusi bt disjunktni). Tiansfoimace je
dana explicitni tiansfoimani tabulkou.
I. slovnik je dvousloupcova tabulka kteia asociuje (spojuje) klie (unikatni) a
zcv
:1o
hodnoty (obdoba jednoduch databazov tabulky). Pioto je dalim alteina-
tivnim oznaenim slovnik teimin asociativn tabulka i asociativn pole.
Hlavni implementaci slovniku ve standaidni knihovn .NlT je geneiicka tida
System.Collections.Generic. Dictionary.
Mezi zakladni vlastnosti slovniku System.Collections.Generic.Dictionary pati
potencialn neomezen poet poloek (omezenim je pouze velikost adieso-
vho piostoiu a do jist miiy i velikost opeiani pamti)
klie musi bt homogenni tj. objekty kli by mly patit do stejn tidy.
Tato tida je uvadna pi denici seznamu a spiavna typova spiavnost je
kontiolovana ji pi pekladu (pi vkladani i hledani). Tida je foimaln (v
dokumentaci, apod) oznaovana jako TKey.
hodnoty musi bt homogenni tj. objekty hodnot by mly patit do stejn
tidy. Tato tida je uvadna pi denici seznamu a spiavna typova spiavnost
je kontiolovana ji pi pekladu (pi vkladani i ziskavani). Tida je foimaln
(v dokumentaci, apod) oznaovana jako TValue.
Mnoina vech instanci tidy kli (TKey) tvoi nadmnoinu mnoiny aktualnich
kli a mnoina vech instanci tidy hodnot (TValue) je nadmnoina aktualnich
hodnot (viz obiazek e.1 na pedchozi stian). Ve specialnich pipadech me slov-
nik mapovat vechny instance tidy kli (nap. jsou-li klii logick hodnoty nebo
vtov typ s nkolika malo instancemi). Podobn me splvat i mnoina hodnot
s mnoinou vech instanci tidy hodnot.
Tyto vlastnosti seznamu jsou zejm a vychazeji ji z jeho denice, v ni se uvadji
tidy kli a hodnot a naopak se neuvadi (maximalni) velikost. Slovnik vak ma
jet jedno kliov, ale ielativn skiyt omezeni (neni kontiolovano pekladaem)
objekty kli musi bt hodnotov nebo nemnn. V zasad lze dopoiuit
jen objekty tid, je nemnnost zaiuuji, tj. nemaji adnou metodu mnici
adiesata a adnou vlastnost s mutatoiem (seerem). Hodnotov tidy (jako
jsou vechny iseln tidy) lze pouit vdy (slovnik toti uchovava jejich
nemnn kopie).
Piotoe slovnik poaduje, aby byly klie jedinen, hiaje dleitou ioli i poje-
ti ielace shodnosti (ekvivalence). Nad mnoinou kli lze toti denovat velk
mnostvi iznch ielaci ekvivalence, z nich kada me mit sv opodstatnni v
uiitm kontextu. Dokonce i nktei vestavn tidy poskytuji hned nkolik typ
ekvivalence. Zatimco v jedn z ekvivalenci mohou bt objekty shodn (jako nap.
Slovnik :11
etzce s a SUSS), v jin naopak iozdiln. Pio jednoduchost budeme pio-
zatim pedpokladat, e ekvivalence je dana opeiatoiem shodnosti (tj. opeiatoiem
a jeho negaci !).
6.1. Zkladn operace
6.1.1. Definice a naplnn
Denice piomnn tidy Dictionary se svou stiuktuiou nelii od denice poui-
van u jinch geneiickch kolekci
using System.Collections.Generic;
Dictionary<string, int> pocetObyvatel;
Tato piomnna bude odkazovat na slovnik mapujici (zobiazujici) objekty tidy
string (iepiesentujici nap. jmno obce) na objekty tidy int (iepiesentujici poet
obyvatel dan obce). Piozatim vak stejn jako u vech iefeiennich tid, adn
nov objekt nevznikl a piomnna obsahuje hodnotu null.
Pioto je ve vtin pipad pohodlnji a bezpenji piomnnou inicializovat v
iamci denice (inicializanim viazem je volani konstiuktoiu).
Dictionary<string, int> pocetObyvatel = new Dictionary<string, int>();
Piomnna nyni odkazuje piazdn slovnik (tj. slovnik, v nm neni uloena adna
dvojice kli-hodnota).
Dalim kiokem je naplnni (population) nov vznikl instance slovniku. Zaklad-
nim piostedkem je zde stejn jako u seznamu metoda Add. Ta ma na iozdil od
seznamu dva paiametiy pivnim je objekt klie (vzoi v zobiazeni) diuhm ob-
jekt hodnoty (obiaz v zobiazeni). V naem pipad musi bt vzoi objektem tidy
string, a hodnota instanci tidy int.
pocetObyvatel.Add("Decin", 50620);
pocetObyvatel.Add("RoudnicenadLabem", 13114);
Alteinativn lze slovnik inicializovat pomoci indexace. lndexem je v tomto pipa-
d kli a indexovan viaz musi stat na lev stian piazeni.
:1:
pocetObyvatel["Litvinov"] = 18960; / / pida dvojici kli-hodnota
pocetObyvatel["Most"] = 67030;
Oba zpsoby pidani se lii v pipad, kdy je pidavana hodnota s kliem, kte-
i je ji ve slovniku obsaen. V pipad pouiti metody Add je vyvolana vjim-
ka System.ArgumentException (se zpiavou An element with the same key already
exists in the dictionary).
V pipad piazeni do indexovho viazu adna vjimka nevznikne a kli je sva-
zan s novou hodnotou (pvodni dvojice kli-hodnota zanikne).
pocetObyvatel.Add("Decin", 50620); / / vjimka (pestoe je nova hodnota stejna)
naopak
pocetObyvatel["Decin"] = 51621; / / OK, nov poet obyvatel
/ / funguje i
pocetObyvatel["Decin"]++;
O tom jak zpsob vkladani zvolit iozhoduje celkova stiategie pistupu ke slov-
niku.
V zasad existuji ti zakladni stiategie
1) pipustn je vkladani vice hodnot se stejnm kliem. Ve slovniku je zohledn-
no pouze posledni vloeni (aktualizace). V tomto pipad je lze piiozen vyuit
indexaci.
2) pipustn je vkladani vice hodnot se stejnm kliem. Ve slovniku je zohlednno
pouze pivni vkladani (inicializace).
V tomto pipad lze vyuit oba mechanismy vkladani, ty vak musi bt spojeny s
pedbnm testovanim vskytu klie ve slovniku
if (!pocetObyvatel.ContainsKey("Decin"))
pocetObyvatel.Add("Decin", 50620); / / jednou a dost
/ / nebo
if (!pocetObyvatel.ContainsKey("Decin"))
pocetObyvatel["Decin"] = 50620;
3) je zaiueno, e kli se bude vkladat jen jednou nap. ze zdioj u nich je uni-
katnost jista. Zde stai pouivat vkladaci metodu Add. Vjimky vznikne, jen je-li
tento pedpoklad naiuen.
Slovnik :1
6.1.2. Vyhledvn hodnoty podle kle
Nejdleitji opeiaci nad naplnnm slovnikem je vyhledavani poloky podle
klie.
Standaidni iozhiani slovniku nabizi dva mechanismy pio nalezeni hodnoty podle
klie, z nich vak je jen jeden pouiteln i pio zaateniky indexace kliem.
int pocet = pocet.Obyvatel["Decin"];
lndexace v tomto pipad (na lev stian piazeni) funguje jako geer, tj. viaci
hodnotu, na ni se kli zobiazuje (tj. s jakm kliem byla do slovniku vloena).
Nalezeni pislun hodnoty je velmi iychl a v zasad nezavisi na potu dvojic
kli a hodnot v seznamu tj. asova sloitost je (1)!
Co vak nastane v pipad, e ve slovniku neni hodnota s danm kliem` Je zej-
m, e neme bt viacena njaka specialni hodnota, nebo mnoina hodnot me
(alespo potencialn) pokivat vechny pipustn instance tidy hodnot (vet-
n hodnoty null u iefeiennich typ). lndexace bohuel neumouje ani zadani
ad-hoc implicitni hodnoty (viz diskuse v iamci navihu vyiovnavaci pamti, sek-
ce .I.1 na stian 1se).
Jedinm eenim je vyvolani vjimky (tidy KeyNotFoundException). K vyvolani
tto vjimky by vak v bnm piogiamu nemlo nikdy dojit (vjimka signalizuje
chybov stav nikoliv pouhou neexistence klie).
V piaxi se vyuivaji dv zakladni stiategii vyuiti slovnik.
Prvn strategie pedpoklada, e vyhledavany budou jen a pouze existujici klie.
Tuto jistotu lze ziskat piiozenm omezenim mnoiny kli nebo kontiolou ioz-
sahu kli ped jejich pouitim. Pokud budete napiklad zobiazovat GUl tlaitka
na pikazy, ktei vyvolavaji, pak je mnoina kli jasn denovana ( mnoina
vech tlaitek) a neme se stat, e bude pouit neexistujici kli ( stisknuto ne-
existujici tlaitko). Pokud by pesto tato situace nastala, pak je to piznak chyby
v piogiamu (nap. opomenuti vloeni nebo pouiti neplatnho objektu). Vyvola-
ni vjimky je v tomto pipad zcela adekvatni. Podobn lze inteipietovat pouiti
neplatnho klie v piogiamu, ktei mapuje jmna povinnch HTML atiibut na
jejich hodnoty. Neni-li povinn atiibut pitomen ve slovniku, pak je to piznak
chybnho foimatu, ktei ml bt odhalen ji ve fazi validace.
if(imgElement["src"]) { / / element img musi obsahovat atiibut sic
/ / zpiacovani URL obiazku
}
:1
Druh strategii naopak pedpoklada, e i neexistence klie (iesp. hodnoty s da-
nm kliem) nese njakou infoimaci. Pokud napiklad vyuivame slovnik pio po-
itani vskytu slov v textu (slovnik mapuje slovo-etzec na poet vskyt tj. na
cel islo), pak neexistence etzce signalizuje dosavadni nepitomnost slova v
textu. Je toti zejm, e na zaatku zpiacovani nelze vytvoit slovnik vech po-
tencialnich slov (jako kli), ktei jsou vechny mapovany na hodnotu nula (
nula vskyt).
Neexistence klie je v takovmpipad zcela bnou situaci. Na zaatku zpiacova-
ni dokonce viazn pevauje nad situaci, kdy je slovo u uloeno ve slovniku (tj.
alespo jednou se ji vyskytlo). Vznik vjimky (odvozeno od spojeni vjimena
situace) je v tomto pipad zcela neadekvatni ieakce. Vjimku lze sice zachytit a
ieagovat na ni (vloenim novho slova do slovniku), ale je to velmi, velmi pomal.
Pioto je nejdive nutn otestovat existenci klie pomoci metody ContainsKey a k
indexaci pomoci klie pistupovat a v pipad, kdy kli ji existuje (a vjimku tak
zcela eliminovat)
/ / vytvoime piazdn slovnik
Dictionary<string,int> pocetVyskytu = new Dictionary<string,int>();
List<string> text = new List<string>(); / / text iozdlen na slova
...
/ / nateni textu a iozdleni na slova
...
foreach(string slovo in text) {
if(pocetVyskytu.ContainsKey(slovo)) {
pocetVyskytu[slovo] ++; / / zvime poet vskyt o 1, indexace kliem je zde bezpena
}
else {
pocetVyskytu[slovo] = 0; / / vloime do slovniku dvojici slovo -~ c
}
}
lndexace je v tomto piogiamu pouita na dvou mistech a ani v jednom pipad
nezpsobi vjimku. Pi inkiementaci se nejdive ziska pvodni hodnota indexo-
vana kliem (kli musi existovat, ale to zaiuuje podminka konstiukce if ), ta se
zvi o jedniku a vsledek se uloi znovu do slovniku (pod stejnm kliem). Je to
mon, nebo pio vloeni nov hodnoty je pouita indexace a nikoliv metoda Add
(ta by skonila vjimkou, nebo kli u existuje a my chceme pouze aktualizovat
namapovanou hodnotu).
Slovnik :1
Diuha indexace kliem (v sekci else) vklada novou dvojici klie a hodnoty do slov-
niku. Zde by bylo pouiti zapisu pocetVyskytu.Add(slovo, 0) mon (a nkteimi
piogiamatoiy dokonce piefeiovan).
Pravidlo 25: Pi vyhledvn kle ve slovnku pomoc indexace, mus bt bu pe-
dem zejm, e je hodnota s danm klem ve slovnku ji obsaena, nebo mus bt
existence kle testovna pomoc metody ContainsKey.
Poznmka:
Testovani existence klie ve slovniku ped jeho pouitimpio indexaci
neni zcela efektivni, nebo vyaduje dv opeiace vyhledavani. l kdy
je opeiace vyhledavani ielativn iychla, neni zcela zanedbatelna. Po-
kud je napiklad pouivana v asto opakovanm kodu (tzv. tsnm
cyklu), me vst k tm dvojnasobnmu zpomaleni piogiamu (ten-
to scna vyuiti slovniku neni natsti pili bn).
Z tohoto dvodu nabizi iozhiani tidy Dictionary metodu TryGetVa-
lue. Tato metoda poskytuje v iamci jedinho volani jak testovani pi-
tomnosti klie, tak jeho (pipadn) ziskani.
Signatuia metody
public bool TryGetValue(TKey key, out TValue value)
Je zejm, e metoda viaci logickou hodnotu (signalizujici pitomnost
i nepitomnost klie), a pivnim paiametiem je hledan kli. Diuh
paiameti je vak netypick. Kliov slovo out uiuje, e se jedna o
tzv. vstupn parametr.
Zatimco bn (vstupni paiametiy) sloui k penosu objekt nebo od-
kaz na objekty dovnit metody ped jejim vykonanim, ma vstupni
paiameti piav opanou funkci sloui k penosu infoimaci zevnit
metody ven po jejimdokoneni. Tuto funkci ma bn naviatova hod-
nota, vstupni paiametiy vak nabizeji monost viaceni nkolika ob-
jekt zaiove.
Detailnji popis vstupnich paiameti najdete v piloze (sekce B.1
na stian zs1). V tuto chvili Vam postauje vdt, e pi volani meto-
dy je nutno na mist vstupniho paiametiu uvst neinicializovanou
piomnnou opatenou takt kliovm slovem out. Do tto piomn-
n se uloi vstupni objekt (iesp. odkaz na nj) a bude tak dostupn
i po ukoneni metody, v ni vznikl. V pipad metody TryGetValue
se do pedan piomnn uloi hodnota pisluna ke klii (je-li dan
:1e
kli pitomen), nebo hodnota null (je-li tida hodnot iefeienni) nebo
nulova hodnota (u hodnotovch)
Podivejme se jak vypada implementace itae slov za pomoci metody
TryGetValue a vstupni piomnn
/ / vytvoime piazdn slovnik
Dictionary<string,int> pocetVyskytu = new Dictionary<string,int>();
List<string> text = new List<string>(); / / text iozdlen na slova
...
/ / nateni textu a iozdleni na slova
...
foreach(string slovo in text) {
int frequency;
/ / neinicializovana piomnna, do ni se uloi vstupni paiameti
if(pocetVyskytu.TryGetValue(slovo, out frequency)) {
pocetVyskytu[slovo] = frequency + 1;
}
else {
pocetVyskytu[slovo] = 0;
}
}
6.2. Vyuit slovnku
Slovnik je velmi uitena kolekce, kteia se uplatni ve vech typech aplikaci. Je do-
konce tak uitena, e je asto uivana nadbyten na misto konstiukci, ktei jsou
mnohem efektivnji. Stava se to pedevim piogiamatoim, ktei jsou zvykli na
piogiamovaci jazyky jako je Perl nebo JavaScript, v nich hiaji slovniky kliovou
syntaktickou ioli (v C= je slovnik jen jednou z mnoha kolekci).
My se nyni detailnji podivame na tyi oblasti vyuiti slovniku
mal aktivni databaze uloen v opeiani pamti
idk seznamy (pole)
vyiovnavaci pamti
ita vskyt
Slovnik :1,
6.2.1. Databze v pamti
Slovnik umouje ielativn snadno iepiesentovat stiuktuiy podobn tabulkam
ielanich databazi. Relani databazov tabulky jsou tvoeny zaznamy (adky) o
pevn lineaini stiuktue. Kad jednotliv zaznam se sklada z nkolika elemen-
tainich daj (isel, etzc, apod.), piem alespo jeden daj hiaje ioli piimai-
niho klie, tj. hodnoty podle ni se zaznam identikuje, Piimaini kli musi bt v
iamci tabulky unikatni.
Stejn daj lze v OOP jazyce iepiesentovat jako objekt sloen z podobjekt ele-
mentainich tid. Tato iepiesentace vak neumouje iychl vyhledavani v kolekci
objekt-daj. Kliov daj je vak mono z objektu vyjmout a pouit ji jako kli
ve slovniku. Tento kli pak identikuje objekt iepiesentujici cel zaznam.
Vztah mezi databazovou tabulkou a odpovidajici slovnikovou iepiesentaci ukazu-
je obiazek e.z (viazn zjednoduena databaze piodej aut).
SPZ typ datum prodeje
5U6 1705 Trabant 2012-11-20
3U2 1458 Volo 2010-08-20
SPZ typ datum!prodeje
"tr#n$%&5U6 1705& "tr#n$%&Trabant& 'ateT#me% 2012-11-20
Sp( Typ 'atumProdeje
"tr#n$%&5U6 1705&
"tr#n$%&3U2 1458& "tr#n$%&Volo& 'ateT#me% 2010-08-20
Sp( Typ 'atumProdeje
"tr#n$%&3U2 1458&
)utoProdej
)utoProdej
"lon*+ , #n"tan-e t.*dy '#-t#onary/"tr#n$0 )utoprodej1
(2(nam 3.2de+4
pr#m2rn* +l*5 3atr#but4
rela5n*
tabul+a
+l*5 3"lon*+u4
obje+t 36odnota "lon*+u4
atr#but
dato7 5len
re"p8 la"tno"t
Obiazek e.z. Slovnik jako iepiesentace ielani tabulky
:18
Vimnte si, e v dan iepiesentaci je atiibut slouici jako kli (SPZ') uloen dva-
kiat. Jednou jako souast objektu iepiesentujicim zaznam ( instance tidy Au-
toProdej), podiuh pak jako kli slovniku identikujici dan zaznam. Je pitom
zejm, e oba objekty musi bt v iamci dan dvojice kli-hodnota shodn.
Tato duplikace se me zdat nadbytena (stail by jen objekt ve funkci klie). Zvy-
uje to poadavky na pam a pinai pioblmy v pipad, e piogiamova chyba
vede k nekonzistentnimu stavu, kdy kli identikuje zaznam s jinou hodnotou
kliov vlastnosti-atiibutu. Zven pamov naioky nejsou silnm piotiaigu-
mentem, nebo ve skutenosti jak kli tak hodnota bn odkazuji stejn objekt
v pamti, v naem pipad tedy stejn etzec (samozejm jen u iefeiennich
tid). Zveni je tak pouze v adu jednotek byt na zaznam. Potencialni pioblm
s nekonzistenci je mnohem zavanji.
Na diuhou stianu zahinuti klie do objektu iepiesentujiciho cel zaznam usnad-
uje jeho zpiacovani. Objekty-zaznamy jsou dale zpiacovavany (tj. jsou paiamet-
iy dalich metod) a pio zpiacovani je ve vtin pipad nutn cel objekt vetn
svho klie. Napiklad pi zobiazeni daje o piodeji auta by mla bt zobiazen
i statni poznavaci znaka. Pokud by nebyla obsaena v objektu-zaznamu, musela
by bt pedavana jako dali paiameti i ped zpiacovanimdo zaznamu pidavana.
To by zbyten komplikovalo piogiam a navic by to mohlo vst ke stejn nekon-
zistenci jako v pipad duplicitniho uloeni. Nekonzistence by byla sice omezena
jen na zpiacovavajici metody, ale efekt by byl obdobn.
Nejdleitjimpiotiaigumentemje vak velmi mala piavdpodobnost vzniku ne-
konzistence pi dodiovani nkolika elementainich zasad
objekty iepiesentujici zaznamy by mly bt nemnn (tj. po vzniku objektu
nelze kli, jen je v nm uloen, mnit)
pi vkladani je nutno vyuit kli ziskan pimo z objektu
Tj. pi ukladani zaznamu o piodeji auta je nutno vyuit vlastnost zpistupujici
kliov atiibut (SPZ).
class AutoProdej {
public string Spz {get; private set;} / / automaticka vlastnost
public string Typ {get; private set;}
public DateTime DatumProdeje {get; private set;}
public AutoProdej(string spz, string typ, DateTime datumProdeje) {
'ocialn je SPZ oznaovana jako registran znaka, ale identikatoiu RZ by tm nikdo neiozuml
Slovnik :1,
this.Spz = spz;
this.Typ = typ;
this.DatumProdeje = datumProdeje;
}
}
...
/ / pidani novho zaznamu do slovniku
AutoProdej auto =
new AutoProdej("5U61705", "Trabant", new DateTime(2012, 11, 20));
prodeje.Append( auto.Spz, auto ); / / kli auto.Spz (plati a vdy bude platit)
/ / nebo
prodeje[ auto.SPZ ] = auto;
Nyni ji vime jak tabulkova data iepiesentovat pomoci slovniku. Otazkou vak
zstava, pio to vbec dlat, kdy existuji ielani databazov systmy, ktei jsou
dnes bnou souasti vvojovch piostedi a pio zpiacovani tabulkovch dat jsou
optimalizovany.
Slovniky maji navic opioti ielanim databazim nkolik limit
1. velikost slovniku je ovlivnna velikosti dostupn pamti (velikost opeia-
ni pamti je hoini mezi, ve skutenosti ji vyuivaji i dali piocesy). To pi
souasn velikosti opeianich pamti (jednotky GiB) znamena, e poet po-
loek (dvojic kli-hodnota) je omezen na miliony.
z. piopojeni dat mezi tabulkami neni tak snadn jako v pipad ielanich da-
tabazi. Zatimco v ielanich databazich existuje vestavna podpoia ielaci, je
piopojeni slovnik ponkud sloitji (je to sice mon, ale nevyuiva se
pili iozhiani slovnik a bez pouiti LlNQ je to i syntakticky neohiaban)
I. slovniky nejsou peisistentni, tj. po ukoneni bhu aplikace zanikaji (vetn
nahlho peiueni typu vpadku napajeni)
Na diuh stian jsou slovniky extimn iychl (ve vtin pipad jsou dokon-
ce iychleji ne ielani databaze umistn v pamti) a maji mnohem jednodui
iozhiani.
Slovniky se pioto nejastji vyuivaji pio
iepiesentaci jednoduchch tiansfoimaci hodnot jednoho diuhu na diuh
(s ielativn malm potem monch tiansfoimaci). Typickm pikladem
jsou iselniky pevadjici identikatoiy na inteini iepiesentaci (typicky i-
selnou, odtud nazev). Pikladem budi pevod jmen bankovnich stav na
::o
identikani kod uivan v islech bankovniho t. Poet poloek v tako-
vto databazi je omezen. iselnik se bn plni z konguianiho souboiu
pi staitu aplikace a pak se ji nemni.
doasn iv databaze, ktei se iychle mni s ohledem na aktualni kontext.
Pikladem me bt slovnik mapujici jmna pihlaench uivatel na ko-
munikani kanaly (nap. TCP/lP sockety) v instant-messaging seiveiu. Tato
databaze se velmi iychle mni (uivatel se stale pihlauji a odhlauji) a po
pipadnm ukoneni bhu seiveiu ji nejsou (a nikdy nebudou) poteba.
Velikost slovniku me bt v tomto pipad ielativn velka (tisice i deseti-
tisice uivatel), pamov naioky vak zstavaji iozumn (jednotky MiB)
6.2.2. dk seznamy
Seznamy jsou lineainimi kolekcemi, u nich je piefeiovanou opeiaci iychla inde-
xace. VC= maji svou piiozenou iepiesentaci ve tid System.Colllections..Generic.-
List. Obdobnou iepiesentaci maji i tzv. pole (pole maji v C= na iozdil od seznam
pevnou velikost). Polokami seznam mohou bt seznamy, co umouje snadno
iepiesentovat dvojiozmina (a v zasad i viceiozmina data).
Seznamy (iesp. seznamy seznam) jsou optimalni iepiesentaci lineainich (iesp.
dvojiozminch maticovch dat), avak neplati to ve vech pipadech. Podivejte
se na typick list tabulkovho piocesoiu (obiazek e.I na nasledujici stian)
Pedstavte si, e bychom mli podobn tabulkov kalkulatoi napiogiamovat. Jak
budete iepiesentovat list (sheet) v pamti` Zvolite piiozenou iepiesentace dvoj-
iovovm seznamem`
V piv ad si musite uvdomit, e viditelna ast listu vak tvoi jen malou ast
viitualniho listu. LibreOce tabulkov kalkulatoi podpoiuje z
1c
sloupc a z
zc
ad-
k, tj. dokae adiesovat z
Ic
(1c
v
) bunk. Pokud by byl list iepiesentovan dvoj-
iovovm pole. pak by zaujimal minimaln 1 GiB pamti (i pouh odkaz null
zaujima ve Iz-bitovm systmu 1 byty pamti). Jinak eeno, iepiesentace listu
by se na vtin poita nevela do opeiani pamti a i v pipad poita s vice
ne 1 GiB by zaujimala jeji podstatnou ast (do zbytku se musi vejit ostatni listy
a samozejm i dali aktualni piocesy).
Ve skutenosti je ale valna vtina z vice ne miliaidy bunk piazdna. Optimalnim
eenimje iepiesentace jen tch bunk, ktei nejsou piazdn (tj. neobsahuji adn
text i vzoiec). Aby vak byla zachovana iychla odezva, musi bt k dispozici iychla
indexace (tj. nalezeni buky podle jeji adiesy adku a sloupce).
Slovnik ::1
Obiazek e.I. List tabulkovho piocesoiu idk pole
Uvaujme pioto, zda by vhodnm kandidatem pio iepiesentaci list nebyl slov-
nik. Kliem by byla dvojice dvou celch isel tj. zD adiesa buky, hodnotou pak
objekt iepiesentujici buku (jeji obsah a foimatovani). Pi zobiazeni nebo vpo-
tech lze snadno a iychle zjistit zda je buka piazdna i nikoliv (pomoci testovani
existence klie-adiesy ve slovniku metodou ContainsKey). Podobn je snadn zis-
kani infoimace o nepiazdn buce (pomoci indexace kliem). Pamov naioky
jsou dany potem uloench dvojic tj. odpovidaji potu vyplnnch bunk (bn
v adu maximaln tisic).
Meme vak dvojici objekt pouit jako kli slovniku` Pimo samozejm niko-
liv, meme je vak uzavit do kompozitniho objektu pepravky. Bohuel na to
nestai nestai jednoducha tida s automatickmi vlastnosti pio kad podobjekt
a konstiuktoiem pio jejich spojeni (jako byla nap. pepiavka CaeItem imple-
mentovana v sekci zainajici na stian 1vc). lnteini iepiesentace slovniku vya-
duje podpoiu nkolika dalich metod (viz nie).
Nejjednoduim eenim je vyuiti kolekce s nazvem n-tice (angl. tuple).
:::
N-tice (tuple)
N-tice je velmi jednoducha kolekce, umoujici iepiesentovat libovoln n-tice
objekt (v C= je od veize 1.c ). Poet objekt (tj. ) je pevn dan u pi denici
(navic je maximalni pouitelna velikost n-tice omezena, piem omezeni zavisi
na veizi knihovny, bezpen jsou podpoiovany alespo sedmice). Na diuh stia-
n me n-tice obsahovat i hodnoty iznch navzajem nesouvisejicich tid. Typ
kad poloky musi bt explicitn uien ji pi denici.
Objekty n-tice jsou vytvaeny konstiuktoiem, jemu jsou pedany vechny polo-
ky (piem zalei na poadi). Po vytvoeni objektu n-tice lze ziskavat jednotliv
uloen poloky pomoci vlastnosti Item1, Item2 a ItemN. Poadi je pimou sou-
asti identikatoiu, nikoliv bnm indexem (ten by byl v hianatch zavoikach).
Poet poloek je natsti velmi mal (v piaxi se pouivaji nejastji jen dvojice a
tiojice).
Uveme si mal (piozatim uml) piklad dvojice (tj. z-tice)
Tuple<string, int> tuple = new Tuple<string, int>("Frodo", 42); / / vytvoeni
Console.WriteLine(tuple.Item1); / / vypie liodo
Console.WriteLine(tuple.Item2); / / vypie 1z
Vytvoeni je tiochu iozvlan, nebo je nutno dvakiat specikovat typ kad po-
loky. Nae ukazkova dvojice bude sloena z etzce (pivni poloka) a celho is-
la (diuha poloka). Pouiti je u snadn. Vlastnost Item1 viaci etzec, vlastnost
Item2 islo.Tida naviatov hodnoty zavisi na typu poloky specikovan v de-
nici n-tice.
Vytvoena n-tice kiom zakladnich metod podpoiuje i poiovnani a obsahuje i
podpoiu pouiti na mist klie ve slovnicich (tj. iozumn pedenovava metodu
GetHash).
=
S vyuitim n-tice je implementace tabulkovho listu snadna. Slovnik pio ukladani
jednotlivch bunk je mono vyuivat pimo, ale pohodlnji a bezpenji je
vyuiti adapti tj. objekt nov vytvoeni tidy, ktei v sob ukivaji pislun
slovnik, nabizeji vak mnohemjednodui iozhiani. Nai adaptani tidu nazveme
Sheet.
class Sheet {
private Dictionary<Tuple<int,int>, string> sheet =
new Dictionary<Tuple<int, int>, string>();
Slovnik ::
public void SetCell(int row, int column, string context) {
Tuple<int, int> address = new Tuple<int, int>(row, column);
sheet[address] = context;
}
public string GetCell(int row, int column) {
Tuple<int,int> address = new Tuple<int, int>(row, column);
return sheet.ContainsKey(address) ? sheet[address] : "";
}
}
Objekt tidy Sheet obsahuje jen jedin podobjekt (je to tudi piav adapti)
slovnik mapujici dvojice celch isel na etzec iepiesentujici textov obsah bu-
ky (skutena implementace by samozejm vyadovala sloitji objekt).
Rozhiani nabizi jen kliov metody pio vloeni obsahu do buky a jeho optn
ziskani. Uobou metod je adiesa pedavana jako dvojice paiameti (tj. zvla adek
a zvla sloupec). Repiesentace kli pomoci n-tic je implementani detail a me
bt v dalim vvoji zmnn.
V obou metodach je nejdive vytvoena adiesa (tj. dvojice) z obou pedanch pa-
iameti. Pio uloeni je vyuita indexace, nebo pouita adiesa nemusi bt jedi-
nena. Pi pouiti stejn adiesy se zmni pisluna hodnota (tj. pepie se obsah
buky). Naopak pi teni je nutno eit i pistup k nedenovanmu klii (tj. k
piazdn buce, jich je valna vtina). Pioto je nejdive testovana existence kli-
e metodou ContainsKey. Pokud kli existuje, pak je viacena pisluna hodnota
(obsah buky), jinak je viacen piazdn etzec. Alteinativn lze viatit i hodno-
tu null. Viaceni piazdnho etzce je pohodlnji (pijemce nemusi testovat zda
byl viacen skuten objekt), vynucuje si vak model, v nm je piazdna buka
ekvivalentni buce obsahujici piazdn etzec (co je iozumn pedpoklad).
Kiom listu tabulkovch kalkulatoi existuji i dali idk matice, pole i sezna-
my. Obecn je to jakkoliv kolekce, kteia obsahuje jeden a tent objekt tolikiat,
e to tvoi vtinu (tzv. dominantni pivek). Nemusi to bt nutn nula nebo null.
Dleit je jen podil pislunho objektu. Hianice neni ostia a zavisi na typu ob-
jektu iesp. na inteini iepiesentace (nap. podil ped vc je ji iozhodn piznakem
idkosti, nebo je nutno explicitn ukladat jen zbvajicich mn ne 1c poloek).
Pikadem idkho seznamu je napiklad tabulka potu plnch zatmni Slunce
viditelnch na naemzemi podle jednotlivch let. Vposlednimtisicileti obsahuje
::
povtinou nulu ( adn zatmni) s vjimkou let 1ce a 111 (dali bude a ioku
z1I).
6.2.3. Vyrovnvac pam
Na pivni pohled se slovnik me jevit jako dokonala implementace vyiovnavaci
pamti. Ma podobn iozhiani, nebo uklada hodnoty spolu s kliem a ob nejd-
leitji opeiace tj. uloeni a vyhledani podle klie jsou velmi iychl (iychleji ne
podobn opeiace nad seznamem).
Ob kolekce se vak lii v jednom avak podstatnm iysu vyiovnavaci pam
ma omezenou velikost a musi tudi zapominat uloen hodnoty, slovnik je alespo
potencialn neohianien.
Bohuel piav zapominani se ve slovniku obtin implementuje. l kdy existuje
nkolik stiategii zapominani, adna z nich se neda efektivn implementovat nad
slovnikem.
Nhodn zapomnn (implementovan v pikladu uvedenm v sekci .I na stia-
n 1s) vyaduje nahodn pistup k pivkm dan kolekce. To je mon jen u ko-
lekci s lineaini indexaci. Slovnik vak lineaini indexaci nepodpoiuje, tj. nelze pi-
stupovat ke klim a hodnotam podle jejich poadi (nelze tedy nap. ici, kteia z
hodnot je uloena na diuh i teti pozici).
Podobn nelze vyuit stiategii uvolnn nejdle alokovan poloky (stiategie lllO).
Slovnik si toti nepamatuje v jakmpoadi byly poloky vkladany a pi piochazeni
je viaci ve zcela jinm poadi (ktei vak neni na diuh stian nahodn).
eeni samozejm existuje, je vak nutno slovnik doplnit o pomocnou kolekci,
kteia uklada jen klie (tj. klie jsou uloeny jak ve slovniku tak v tto pomocn
kolekci). Stiuktuia pomocn kolekce zavisi na poadovan stiategii zapominani.
U nahodnho to me bt (pozin indexovateln) seznam kli, u stiategie lllO
pak fionta (tida System.Collections.Generic.eue, viz http://msdn.microsoft.com/
en-us/library/7977ey2c.aspx) kli. Ukazkovou implementaci vyiovnavaci pamti
najdete v piloze (viz sekce C.1 na stian zs).
6.2.4. ta vskyt
Poslednim klasickm vyuitim slovniku je podpoia algoiitm poitajicich poet
vskyt uiit hodnoty v posloupnosti. Algoiitmy tohoto diuhu se pouivaji pe-
Slovnik ::
devim v piogiamech zamench na statistick zpiacovani dat, v menim mit-
ku se vak vyskytuji i v jinch typech aplikaci, ktei obas piovadji mala lokalni
statisticka zpiacovani (kdo se kolikiat pihlasil. kolikiat byl pehian audio souboi,
apod.).
Veejn iozhiani itae vskyt musi poskytovat minimaln dv kliov metody.
Pivni metoda (vkladaci) je volana pi vskytu pislun hodnoty (smantika z
pohledu tto hodnoty vyskytla jsem se, zapoitej mn), diuha (dotazovaci) viaci
pibn poet vskytu hodnoty (tj. poet aktivaci pivni metody s paiametiem
iovnmdotazovan hodnot, a to od vzniku itae do okamiku volani dotazovaci
metody).
ita lze tak inteipietovat jako pamov nenaionou iepiesentaci tzv. multi-
mnoiny. Multimnoina me obsahovat pivek vicekiat (piem nelze odliit jed-
notliv vskyty pivku v mnoin). Vkladaci opeiace je v tto iepiesentaci pida-
nim pivku do mnoiny, opeiace vyhledavaci pak zjitnim potu vskytu danho
pivku v multimnoin.
Poznmka:
Bnou mnoinu lze chapat jako specialni pikladem multimnoiny
(kad pivek je v mnoin piav jednou). Pioto lze i mnoiny iepie-
sentovat slovnikem. Mnoina je v tto implementaci iepiesentovana
klii, pisluna hodnota (obiaz zobiazeni) me bt sdilena vemi kli-
i (nema adnou infoimani hodnotu, dleita je pouze pitomnost
klie). Pio iepiesentaci mnoin vak od veize C= I.c existuje speci-
alizovana kolekce Set<TKey>, kteia vyuiva hashovaci tabulku neu-
kladajici hodnotu. To nejen sniuje pamovou naionost, ale tak
usnaduje pouiti (mnoina je napiklad pimo iteiovatelna, stejn
jako seznam).
lmplementace itae vskyt nad slovnikem je jednoducha a pitom dostaten
efektivni. Jadio implementace bylo uvedeno ji v sekci e.1.z na stian z1I, ale pio
jistotu si ji zopakujme. Vkladaci metody (v naem ukazkovm zdiojovm kodu je
oznaena identikatoiem Insert) testuje, zda byl objekt vloen dive (tj. existuje
dvojice s danm kliem). Pokud existuje, je pisluna hodnota ( poet vskyt)
zvena o jedniku. Jinak je vytvoena nova dvojice, piem hodnota je iovna
jedn ( piozatim jeden vskyt).
class Counter {
private Dictionary<string, int> c = new Dictionary<string, int>();
/ / podkladov slovnik
::e
public void Insert(string s) {
if (c.ContainsKey(s)) {
c[s]++;
} else
c[s] = 1;
}
public int Frequency(string s) {
return c.ContainsKey(s) ? c[s] : 0;
}
}
Vyhledavaci metodu (zde oznaena jako Frequency) lze pi pouiti podminkov-
ho opeiatoiu zapsat na jedinm adku. Je-li hledan objekt obsaen ve slovniku
jako kli, je viacena pisluna hodnota (tj. poet vskyt). V opanm pipad je
viacena nula ( adn vskyt). Vimnte si, e ani v tomto pipad nedochazi ke
vzniku (pomal a nechtn) vjimky pi pistupu ke slovniku.
l kdy je iepiesentace itae pomoci slovniku elegantni a efektivni, existuji i jin
alteinativy. Lze-li objekty snadno jednoznan zobiazit na cela isla v inteival c
a , pak je efektivnji iepiesentaci itae seznam isel. Seznam o pivcich musi
na zaatku obsahovat nuly. Pi vskytu stai zvit o jedniku poloku s danm
indexem. Alteinativni iepiesentace me bt vhodnji i v pipad, kdy je po
skoneni statistickho zpiacovani vyadovan vpis poloek s nejvyi fiekven-
ci vskyt. Slovnik neumouje pim vyhledani klie s nejvyi etnosti (iesp.
dokonce klie s -tou nejvyi etnosti).
6.3. Intern representace slovnku
lnteini iepiesentace objekt by mla zstavat skiyta (u jen pioto, e se me
mnit). V pipad kolekci je vak alespo astena znalost inteini iepiesentace
uitena, nebo umouje snadno odhadnout jejich (piminou) efektivitu a na-
znait situace, kdy je nutno poitat s viazn pomalejim bhem (tj. kdy me
bt vyuiti pinejmenim pioblematick). Tyto infoimace lze sice ziskat i detail-
nim studiem dokumentace (nikoliv vak MSDN, ta bohuel neni pili detailni).
Alespo iamcova znalost implementace Vam vak viazn usnadni zapamatova-
ni kliovch chaiakteiistik (vichni bohuel nemaji fotogiackou pam).
Slovnik ::,
Slovnik Dictionary<TKey, TValue> je implementovan jako otevena hashovaci ta-
bulka (angl. open hashtable). Zakladni datovou stiuktuiou hashovaci tabulky je
seznam o polokach. Tento seznam je na zaatku piazdn, tj situace je tak ale-
spo na poatku podobna bnmu seznamu.
Zcela jinak je ale implementovana opeiace vloeni. Pivnimkiokemje aplikace tzv.
hashovaci funkce na objekt klie. Tato funkce zobiazuje mnoinu vech instanci
tidy kli na isla c a 1. Vsledek hashovaci funkce pak pouijeme jako
index do hashovaci tabulky, ktei uiuje na jakou pozici vloime objekt-hodnotu.
Zakladni implementace vkladani je tedy tiivialni
[()] =
kde je hashovaci tabulka
je hashovaci funkce
je kli
je (ukladana hodnota)
Opeiace hledani je inveizni, index ziskan aplikaci hashovaci funkce na kli je
vyuit k ziskani uloen hodnoty (co je opeiace, je nezavisi na potu pivk tj.
ma sloitost (1)).
Nemusite bt matematiti gniov, abyste si poloili otazku, jak vlastn hashovaci
funkce zajisti, e se jednotliv (vzajemn odlin) klie mapuji na izn indexy v
hashovaci tabulce`
Odpov je jednoducha. Hashovac funkce nic takovho nezajiuje a obecn nem-
e jedinenost index vbec zajistit. Dokazat toto tvizeni neni sloit. Pedpokla-
dejme, e tidou kli je tida string. Zkusme odhadnout kolik iznch etzc (tj.
instanci tidy string) existuje. Pokud by byly etzce jen jednoznakov, existovalo
by tolik etzc, kolik je pipustnch znak v basic multilingual plane standai-
du Unicode. Pesn poet neni snadn zjistit (nktei znaky mohou bt pouity
jen v kombinaci s jinmi), ale nam postai hiub odhad z
1e
znak (to je po-
et znak kodovatelnch pomoci 1e bit, skuten poet je jen o pai piocent nii
viz http://en.wikipedia.org/wiki/Plane_%28Unicode%29). Poet potencialn iepiesen-
tovatelnch -znakovch etzc je z
1e
, tj. ji pio dvouznakov etzce je poet
potencialnich etzc adov shodn s potem byt opeiani pamti souasnch
osobnich poita (1 GiB z
Ic
byt). To znamena, e hashovaci tabulka na ni by
se jednoznan mapovaly vechny potencialn existujici dvojznakov etzce, by
::8
se nevela do opeiani pamti (kada poloka by musela zaujimat minimaln s
byt, nebo to je velikost odkazu ve e1 bitovch systmech). Velikosti opeianich
pamti sice pozvolna iostou, ale velikosti v adu z
e1
1e liB v blizk budouc-
nosti uiit nedosahnou. l takto obiovska pam by vak nezajistila jednoznan
indexy ani pio tyznakov etzce. Podobna situace je u vech tid s vicebytovou
iepiesentaci (nap. DateTime, double a v meni mie i int).
Jednoznanost mapovani kli na indexy tak nelze adnm zpsobem zajistit a
vdy musi dochazet k tzv. kolizim tj. dva izn klie jsou hashovaci funkci pe-
vedeny na stejn index v hashovaci tabulce. Hlavnim cilem inteini iepiesentace
je kolize co nejvice minimalizovat a pokud u vzniknou, pak je co nejefektivnji
vyeit.
Pio zajitni co nejmeniho potu kolizi pi zachovani iozumnch poadavk na
pam je nutno
1. zvolit optimalni hashovaci funkci
z. zvolit optimalni velikost hashovaci tabulky
Hashovaci funkce by mla pio nahodn vbi kli viacet indexy, ktei co nej-
iovnominji pokivaji iozsah [c. ) (kde je velikost hashovaci tabulky). Jinak
eeno pio nahodn zvolen klie, by se vypoitan indexy nemly kumulovat
kolem uiitch hodnot index, iesp. nechavat uiit asti tabulky zcela nevyui-
t. Navic by ml bt vpoet index velmi iychl (maximaln nkolik malo takt
piocesoiu)
Podivejme se napiklad na nkolik pipad potencialnich hashovacich funkci nad
klii tidy int.
1) () = ( je pedem zvolena celoiselna konstanta z inteivalu [c. ))
Nejhoii pipad hashovaci funkce. Kolize nastavaji pi kadm pistupu, zbytek
tabulky (s indexem ) je nevyuit.
z) () = sin(/1cc) ( 1)
Relativn iozumna hashovaci funkce, viacejici hodnoty v iozmezi [c. ). Hodnoty
blizk 1 jsou vak piavdpodobnji ne hodnoty kolem blizk nule (viz pi-
bh funkce sinus a hlavn jeji piv deiivace). Hlavnim pioblmem je vak vysoka
naionost vpot v pohybliv adov aice (pedevim funkce sinus).
I) () = mod
Nejastji hashovaci funkce pio iseln klie. Je velmi iychla (jedina instiukce
vykonavana ALU) a pio klie s iovnominm iozloenim iovnomin pokiva
Slovnik ::,
iozsah index. l tato funkce ma sva omezeni. Nehodi se pili pio mal mnoiny
kli a pokud jsou hodnoty pouitch kli nasobkem velikosti hashovaci tabulky
nebo jeho libovolnho netiivialniho dlitele, pak viaci jen indexy z velmi omezen
(v extimnim pipad jednopivkov). Pioto neme bt volba velikosti hashovaci
tabulky zcela libovolna. Nelze vyuit isla s velkm potem dlitel jako je nap.
1z, mocniny dvou nebo mocniny desitky, nebo na n se hodnoty bn zaokiouh-
luji). Nejastji se pioto voli pivoislo nebo islo, ktei nema mal dlitele.
Velikost hashovaci tabulky zavisi piimain na potu uloench pai klie-hodnota
(dale oznaovan jako ) (tj. nikoliv na potu vech potencialnich kli). Pokud je
velikost hashovaci tabulky meni ne poet uloench kli ( < ), pak uiit
dochazi ke kolizim (v tabulce je minimaln ) kolizi, ale v piaxi jich je samo-
zejm vice. U tabulek, jejich velikost je vti ne poet uloench kli me bt
dosaeno peifektniho hashovani ( bezkolizniho), ale v pipad univeizalnich ha-
shovacich funkci ke kolizim dochazi i v tomto pipad, natsti s ielativn malou
etnosti.
Pio ilustiaci se podivejme na etnost kolizi pi hashovani velkho potu etz-
c (obiazek e.1 na nasledujici stian). Pio testovani byl pouit seznam pijmeni,
je by ml obsahovat vechna pijmeni pouivana v esk iepublice (zdioj Mi-
nisteistvo vnitia R, http://www.mvcr.cz/soubor/2012-zctpr-zctpr-rijen-zip.aspx).
Celkem je to 1vI1e unikatnich jmen, pio ktei byla spoitan vsledek hashova-
ci funkce pio izn velikosti hashovaci tabulky (pouita funkce nemusi bt zcela
identicka s funkci pouivanou u objekt tidy Dictionaiy, ale je ji velmi blizka a
podobn efektivni). Pouit piogiam je uveden v piloze C.z na stian zsv.
Na ose je vynesena ielativni velikost hashovaci tabulky vzhledem k potu kli,
na ose je pimin iesp. maximalni poet slov, je hashovaci funkce mapuje
na stejn kli. Snadno lze zjistit, e i v pipad tabulky o velikosti
1
1
je maximal-
ni poet koliznich etzc ielativn mal (piblin 1), piem pimi je jet
meni (cca 1-). To je blizk optimalnimu pomiu (pimin 1 kolizni etzce) a
zjiuje velmi iychl vyhledavani (je nutno piohledat jen adov jednotky dvojic
kli a hodnot nikoliv statisice). U menich iozmi hashovacich tabulek poet
kolizi iychle (exponencialn) naista. U vtich naopak klesa ji mnohem miinji
a u velikosti nad 1. je zlepeni jen neviazn (vimnte si tak, e i kdy je
pimin poet kolizi blizk jedn, me v konkitnim pipad i miin vyi).
Volba optimalni iovnovahy mezi iychlosti a pamovmi naioky je obtina a za-
visi na mnoha aspektech systmu (pedevim, ale nikoliv vhiadn na velikosti
opeiani pamti). Velkost hashovaci tabulky je pioto v jazyce C= volena automa-
:o
1
2
3
4
5
6
0 0.5 1 1.5 2
mean size of collision group
1/x
2
4
6
8
10
12
14
16
18
20
0 0.5 1 1.5 2
max size of collision group
Obiazek e.1. Velikost kolizni skupiny pio hashovaci funkci nad etzci
Slovnik :1
ticky a uivatel slovniku ji neme pimo ovlivnit (a dokonce ani zjistit).
Pio dokoneni popisu iepiesentace hashovaci tabulky zbva doplnit infoimaci
jak jsou konkitn iepiesentovany kolize (k nim jak ji vime nezbytn dochazi).
eeni je ielativn jednoduch, namisto pouhch hodnot jsou do hashovaci ta-
bulky ukladany seznamy dvojic kli-hodnota. Nenastava-li kolize, je seznam pio
pislun index ( vsledek hashovaci funkce) jednopivkov, obecn vak me
mit libovoln poet pivk.
Pi opeiaci vyhledavani musi bt lineain piohledavany dvojice v seznamu a
zkoumany jejich klie (zda se neiovnaji hledanmu). Pi pouiti dobi hashovaci
funkce jsou vak jednotliv seznamy velmi kiatk (jednotky pivk). Na stiuktuiu
hashovaci tabulky se mete podivat na obiazku e. (miin zjednodueno). Od-
povidajici slovnik by byl instanci tidy Dictionary<string,string> a mapuje jmna
postav nejmenovan knihy na jejich stal bydlit.
0
1
2
3
4
5
6
7
8
9
string:Frodo
string:Hobitn
string:Aragorn
string:Minas Tirith
string:Galadril
string:!"rin
string:#lrond
string:$o%lin%a
string:Thorin
string:&ol
string:Th'odn
string:#doras
string:()*n%
string:H+r%a
string:Ar,n
string:$o%lin%a
h-.Thorin./ 0 1
Obiazek e.. Hashovaci tabulka
Poznmka:
Z dvod uiychleni opeiace vyjimani dvojic ze slovniku je pouit
tzv. spojov seznam. Piazdn poloky slovniku mohou bt piiozen
iepiesentovany hodnotou null. Navic nemusi bt pedem znama ve-
likost jednotlivch dilich seznam (spojov seznam me ist bez
nutnosti vynucenho kopiiovani pi naplnni sv pedem uien ka-
pacity).
::
lmplementaci hashovaci tabulky se navic komplikuje pedem nezna-
mm potem uloench pai kli-hodnota. l kdy lze pedpoklada-
nou velikost zadat ji v konstiuktoiu (stejn jako je tomu v pipa-
d seznam). Tato velikost vak nemusi bt dodiena. Zmna potu
uloench pivk vak viazn ovlivuje efektivitu hashovaci tabul-
ky. Pi postupnm zvyovani potu dvojic se vyhledavani zpomalu-
je, naopak pi jejich odebiiani zaujima hashovaci tabulka zbyten
mnoho mista. Z tohoto dvodu se musi obas tzv. pehashovat, tj. vy-
tvoit novou (povtinou vti) hashovaci tabulku a do ni nov uloit
vechny pvodni dvojice. Pi pehashovani se mni hashovaci funkce
tj. mni se i umistni jednotlivch pai v hashovaci tabulce (existuji
vjimky, ale ty nejsou v piaxi pili ast). Opeiace pehashovani je
pomala () a pioto je jeji planovani dosti sostikovan a je pln v
kompetenci inteini implementace (neme bt adnm zpsobem i-
zeno z vaeho piogiamu). V kadm pipad, si vak zapamatujte, e
i v pipad slovniku ma opeiace pidavani ( metoda Add), asovou
sloitost (1) jen tehdy, pokud zpimiujeme jednotliv asy pistu-
pu tj. konstantni sloitost je amoitizovana.
7. Souborov orientovan vstup a
vstup
l kdy v souasnosti existuje nespoetn mnostvi piogiam a aplikaci, maji tm
vechny jednu spolenou vlastnost musi podpoiovat pistup k exteinim loi-
tim dat (exteinim vzhledem k adiesovm piostoiu obsahujicim objekty).
V souasnosti lze exteini loit z hlediska piogiamovho pistupu iozdlit do
dvou zakladnich skupin
zaizeni s bytov oiientovanm pistupem (zakladni a univeizalni typ lo-
it)
ielani databaze (se zaznamov oiientovanm pistupem)
Relanimi databazemi se nebudeme dale zabvat, piotoe pistup k databazi vy-
aduje bu znalost dotazovaciho jazyka (SQL nebo LlNQ) iesp. vyuiti ielativn
komplikovanch model.
Bytov oiientovana zaizeni lze dale iozdlit na dv podskupiny
lokln soubory umouji teni a bn i zapis, piodleva pi pistupu je v a-
du maximaln milisekund (tj. hluboko pod iozliovaci schopnosti lidi). Data jsou
identikovana jmny bnmi v lokalnim opeianim systmu.
vzdlen soubory dostupn pes internetov protokoly umouji povtinou
pouze teni, piodleva me bt i v adu sekund. Data jsou identikovana pomoci
URL.
Rozdleni je dano mechanismempistupu, nikoliv (topogiackou) vzdalenosti. Pi
pouiti siov oiientovanch opeianich souboiovch systm (jako je NlS nebo
CllS) jsou i vzdalena data dostupna jako lokalni souboiy (mohou vak mit deli
piodlevy pi teni a zapisu). Naopak pomoci URL lze pistupovat i k lokalnim
souboim.
Pio pistup k bytov oiientovanm loitim lze bez ohledu na jejich chaiaktei
vyuit mechanismus tzv. datov proud (angl. stieam). Datov pioudy se obje-
zII
:
vily ji v jazyce Ca jako zakladni abstiakce jsou podpoiovany vtinou modeinich
opeianich systm. Modeini objektov systmy vak poskytuji i dali vistvy abs-
tiakce. Bohuel tak neini jednotn a jednotliv implementace se mnohdy viazn
lii (tj. nejedna se jen o iozdilnou teiminologii).
Podpoia pistup k bytov oiientovanmzaizenimve standaidni knihovn .NlT
je ielativn komplexni, je vak dobe naviena a podpoiuje i syntaktick zkiatky
pio nejastji pouivan manipulace (nap. nateni obsahu textovho souboiu lze
piovst pomoci dvou stiunch adk kodu).
Tidy objekt zajiujicich pistup k bytov oiientovanm loitim jsou souste-
dny ve jmennm piostoiu System.IO (zkiatka za Input/Output), nktei speciali-
zovan tidy se vak nachazeji i v jinch jmennch piostoiech. Vstupn-vstupni
tidy lze iozdlit do ti vistev
nzkorovov proudy pistupuji k pioudm poskytovanm opeianim sys-
tmem (jsou to pedevim souboiy a siov sockety)
filtran proudy modikuji pioud byt ziskan z jinho pioudu nebo do jinho
pioudu smiovan
zapisovatel a teni objekty, ktei pekladaji jednoduch objekty, jako jsou
etzce a iseln typy, do posloupnosti byt (zapisovatel) nebo je naopak
z posloupnosti byt vytvaeji (tenai). Zapisovatel pak tuto posloupnost
byt zapisuji do pioudu (a jejim piostednictvim na loit). tenai nao-
pak svoji vstupni posloupnost byt z datovch pioud ziskavaji.
Nad tmito zakladnimi vistvami existuji i dali vistvy poskytujici pistup ke kom-
plexnji stiuktuiovanm exteinim datm jako jsou XML souboiy nebo izn au-
diovizualni foimaty. Jinou nadstavbou jsou tzv. serializace tj. schopnost ukladat
do pioudu cel sloen objekty.
Nahled zakladni stiuktuiy l/O tid na platfoim .NlT poskytuje obiazek .1 na
nasledujici stian. Znazoinn je samozejm jen vbi tid, jsou vak uvedeny
vechny tidy popsan nie v tto kapitole.
Ve spodni asti obiazku jsou znazoinny nejbnji bytov oiientovana vstupni
zaizeni. Ta jsou vytvoena na iovni OS a poskytujici pistup k bytov oiientova-
nmdatovmloitim. Vimnte si, e loitmme bt i pole byt v opeiani
pamti, tj. jako souboi lze uivat i jednoduchou kolekci (hodi se to vak jen zidka).
Popime si napiklad teni textu ze zaifiovanho inteinetovho pioudu. Pio tento
el musi vzajemn spolupiacovat ti objekty objekt tidy NetworkStream, zaji-
ujici teni z TCP pioudovho socketu (ten poskytuje data poslana jinm pioce-
Souboiov oiientovan vstup a vstup :
FileStream
NetworkStream
MemoryStream
ZipStream
CryptoStream
BinaryWriter
TextWriter
soubor
TextReader
socket
pole
byt
filtry !iltro"ac# proudy$
byto"% oriento"an&
proudy
byto"% oriento"an&
zapisovae/tee
elem' ob(ekt
byto"% oriento"an#
BinaryReader
Obiazek .1. Stiuktuia l/O tid
sem pes siov spojeni), objekt tidy CryptoStream modikujici pioud bytovch
dat (pomoci kiyptogiack tiansfoimace, zde je to deifiovani) a na nejvyi iov-
ni objekt tidy TextWriter, jen tiansfoimuje (dekoduje) znaky z bytov posloup-
nosti. Pokud je objekt tenae poadan o peteni pivniho znaku, poada nejdive
bezpiostedn podizen pioud o dodani daliho bytu z loit. Timto pioudem
je kiyptogiack pioud, ktei data deifiuje pomoci blokov ifiy. Aby mohl pio-
vst deifiovani poada o blok dat pioud nejnii iovn (blok ma velikost jed-
notek byt). Timto pioudem je objekt tidy NetworkStream. Tento pioud pete
poadovan poet byt ze socketu. Pi tom me i chvili ekat, nebo data mu-
si bt nejdive do socketu zapsana diuhm komunikanim paitneiem (napiklad
WWW seiveiem) a musi bt penesena poitaovou siti.
Obdien blok je viacen kiyptogiackmu pioudu, ktei jej deifiuje. Pot viati
pivni byte z deifiovanho bloku instanci tidy TextReader. Ta se jej pokusi intie-
pietovat jako znak. Vyuiva k tomu tzv. znakov kodovani. lmplicitn se vyuiva
kodovani UTl-s. Toto kodovani iepiesentuje znaky pomoci jednoho a ty byt.
Pokud je pijat znak celmkodemznaku (tj. jeho nejvyi byte je c) je ve hotovo,
a objekt tenae viaci znak v inteini 1e-bitov iepiesentaci. V opanm pipad
:e
vak musi podizen pioud poadat o dali byte. Kiyptogiack pioud ma na-
tsti k dispozici dali byty z posledn deifiovanho bloku a tak me dali byte
viatit bez inteiakci s podizenm pioudem (objektem tidy NetworkStream). Po-
kud tena potebuje dali byty ve se jet (maximaln dvakiat opakuje). Pokud
nestai deifiovan blok me dojit i dalimu teni z fyzickho siovho spojeni
(piostednictvim nizkoiovovho pioudu NetworkStream).
Jak lze vidt z pikladu, me bt inteiakce objekt a bytov oiientovanch vstup-
n-vstupnich zaizeni ielativn sloita. Natsti si s tim bni piogiamatoi ne-
musi lamat hlavu. Stai jim vytvoit pislun objekty a zetzit je do jaksi v-
iobni linky od nizkoiovovho pioudu pes ltiovaci pioudy po cilov reader
nebo writer.
Vimnte si jist asymetiie v implementace vstupn vstupnich tid. Zatimco ob-
jekty pioudovch tid poskytuji zaiove metody pio teni i zapis, jsou tidy te-
na ( vstup) a zapisovatel oddlen (tj. metody tena poskytuji jen metody
pio teni a zapisovatel jen pio zapis). Toto odlieni je typick pio .NlT knihovnu
(napiklad standaidni knihovna jazyka Java oddluje vstupni a vstupni tidy na
vech iovnich). V piaxi se vak soubna monost teni i zapisu v iamci jedi-
n instance pioudu pouiva zidka. Vtina pioud podpoiuje pouze teni nebo
pouze jen zapis. Pokud pouijeme metodu pio opan smi, je vyvolana vjimka
(neplatna opeiace). To sice kontiolu pesouva a do faze bhu (piogiamse spiavn
peloi, ale zhavaiuje pi bhu), viazn to vak zjednoduuje model tid.
Pio zaatek se vak zamime jen na nejjednodui a nejastji pouivan kom-
binace teni a zapis do binainiho souboiu (postauje jen jeden objekt pioud),
zapis do textovho souboiu (se dvma objekty) a teni textovho souboiu (opt
dva objekty).
7.1. Bytov orientovan vstup a vstup (binrn
soubory)
7.1.1. Bytov orientovan vstup
Pi pouivani pioud (a do znan miiy i tena a zapisovatel textu) lze iozliit
ti zakladni faze
1) oteven proudu pi pouivani souboiovho pioudu se oteve pislun sou-
boi a stava se souasti kontextu piocesu (tj. stav souboiu se stava souasti stavu
Souboiov oiientovan vstup a vstup :,
piocesu). Pi oteviiani se ovuji i pistupova piava k souboiu (iesp. obecn k lo-
iti). Podai-li se souboi otevit, pak ji nehiozi pili velk nebezpei, e se data
nepodai zapsat nebo peist (jedinm nebezpeim je vyeipani kapacity svazku
nebi limit velikosti). U jinch pioud (nap. siovch) vak spn oteveni neza-
jiuje spn piovedeni opeiaci. Pi oteviiani se asto specikuje, zda je pioud
oteven pouze pio teni i pouze pio zapis (vjimen jak pio teni tak zapis).
2) pstup k otevenmu proudu teni i zapis dat
3) uzaven proudu kad pioud by ml bt po pouiti nepiodlen uzaven.
Pio to existuje hned nkolik dvod
1. pedevim v pipad zapisu me bt ukoneni penosu provedeno a po
uzaven proudu. Bohuel ani spn uzaveni vak bohuel nezajiuje
spn uloeni vech dat. Data mohou zstat ve vyiovnavacich pamtech
zpiavovanch OS.
z. oteven souboiy a komunikani kanaly jsou ielativn vzacnm piosted-
kem. Kad pioces jich me pouivat jen omezen poet, nebo jejich udi-
ovani vyaduje pam jadia.
I. stav zaizeni, je zajiuje oteven pioud, je souasti kontextu piocesu. Ne-
me tak bt vyuit jinm piocesem bez toho, e by bylo nutno eit syn-
chionizaci mezi piocesy. Synchionizace vyaduje dodaten piostedky a
je nachylna k chybam.
Pravidlo 26: Veker proudy je nutno bezprostedn po ukonen jeji vyuvn
explicitn zavt.
Tento zakladni model si ukaeme na jednoduchm piogiamu, ktei vytvoi sou-
boi tvoen 1cz1 nulovmi byty.
using System; / / writebytes.cs
using System.IO;
class MainClass {
public static void Main() {
/ / oteveni souboiu
FileStream fs =
new FileStream( "testFile", FileMode.CreateNew, FileAccess.Write);
/ / zapis byt
for (int i=0; i<1024; i++) {
fs.WriteByte((byte)0);
}
:8
/ / uzaveni souboiu
fs.Close();
}
}
Zakladnim piostedkem oteveni souboiovho je volani konstiuktoiu tidy Fi-
leStream. lxistuje nemn ne tinact iznch petiench veizi tohoto konstiuk-
toiu. Zde pouivame veizi, kteia kiom jmna souboru (pivni paiameti), umo-
uje specikovat tzv. reim oteven (tj. chovani aplikace v zavislosti na existenci
pislunho souboiu v okamiku jeho oteveni) a typ pstupu (jen teni/jen zapis).
loimat jmna souboiu zavisi pln na opeianim v systmu, v nm bude piogiam
piovozovan. Mete pouit jak ielativni jmno bez cesty (souboi bude vztaen k
tzv. aktualnimu adiesai), tak absolutni jmno s plnou cestou. Pi pouiti abso-
lutniho jmna mate vti volnost, piogiam se vak stava mn penositeln.
V unixovch (posixovch) systmech jsou jako oddlovae adiesa v cest vyu-
ivana klasicka lomitka a cesta neobsahuje identikatoi svazku (unixov systmy
vytvaeji jednotn viitualni stiom)
"/home/fiser/output"
Ve svt MS Windows se pouivaji lomitka obiacena a oznaeni svazku
"c:\\temp\\output"
Lomitka musi bt zdvojena, nebo jednoduch lomitko uvozuje nikov sekvence
(tj. nap. \t je znak tabulatoiu), Zdvojovani vak znepehleduje zapis a pio-
to je mono vyuit tzv. syrov (angl. raw) etzcov literly. V tchto liteialech
uvozench znakem zavinae nelze vyuivat nikov sekvence, a tudi neni nutn
zdvojovat zptna lomitka.
@"c:\temp\output"
Knihovna nabizi i monost vytvaeni penositelnch jmen, je to vak o nco na-
ionji. Pokud Vas tato pioblematika zajima, podivejte se na tidu System.IO.Path
a jeji metodu Combine.
Knihovna .NlT nabizi ielativn velk mnostvi ieim pi oteveni souboi, co
me bt pio zaatenika miin matouci. Natsti jsou tyto ieimy popsany po-
moci kombinaci malho potu iznch ieakci na existenci i neexistenci souboiu.
Navic jsou zce piovazany s ieimem pistup k otevenmu souboiu, tj.nktei
ieimy jsou mon a uiten jen u vstupnich pioudm jin naopak jen u pioud
vstupnich.
Souboiov oiientovan vstup a vstup :,
reim Create CreateNew Open
souboi existuje zkiaceni vjimka lP na zaatku
souboi neexistuje vytvoeni vytvoeni vjimka
typ. pistup W W R (RW)
reim OpenOrCreate Truncate Append
souboi existuje lP na zaatku zkiaceni lP na konci
souboi neexistuje vytvoeni vjimka vytvoeni
typ. pistup RW (R) W W
lP (FilePointer) aktualni pozice v souboiu, Od tto pozice je pioud ten iesp. od
tto pozice piobiha zapis.
Nejastji pouivanm ieimem oteveni je FileMode.Create pi zapisu (s pepsa-
nim pvodniho obsahu) a FileMode.Open pi teni. Reim FileMode.Append je po-
uivan pi pidavani dat na konec souboiu (nap. u logovacich souboi) a ma
specialni chovani.
Poslednim paiametiem konstiuktoiu pioudu je typ (ieim) pistupu. Nejastji
se pouivaji ieimy FileAcces.Read (jen teni) a FileAcess.Write (jen zapis). Pioudy
umoujici teni i zapis (FileAcess.ReadWrite) se pouivaji spie vjimen. Navic
je lze pouit jen u nkteich pioud. Podkladov zaizeni musi mimo jin podpo-
iovat nahodn posun aktualni pozice v souboiu.
Po spnm ukoneni volani konstiuktoiu ziskame nejen nov objekt v pamti,
ale vznikne i nov piostedek v iamci opeianiho systmu tzv. oteven soubor.
Oteven souboi umouje postupn teni byt z fyzickho souboiu (tj. poskytuje
vstupni pioud) iesp. zapis byt do souboiu (vstupni pioud). Pokud se pidleni
piostedku nepovede, je vyvolana vjimka.
Poznmka:
V iamci cel tto kapitoly pedpokladame, e v bhem cel doby exis-
tence otevenho pioudu, existuje piav jeden oteven souboi nad
fyzickm souboiem, tj. pistup k souboiu neni sdilen. To je ve vtin
pipad splnno, nebo fyzick souboiy jsou jen vjimen sdileny. V
opanm pipad bychom museli eit synchionizaci pistupu, co je
jednak pomin sloit, jednak zde existuje silna zavislost na opeia-
nim systmu, kteiou .NlT knihovna neme zcela odstinit. Neni pe-
kvapenim, e mechanismy podpoiovan touto knihovnou jsou blii
MS Windows ne nap. Linuxu.
:o
Po vytvoeni a oteveni pioudu lze do nj zapisovat pomoci metody FileStre-
am.WriteByte. Tato metoda oekava jedin paiameti, jim je hodnota zapisova-
nho bytu. Tato hodnota musi bt instanci tidy byte (pln jmno tidy je Sys-
tem.Byte).
tda byte
Tato tida se podoba tid int (tj. tak iepiesentuje cela isla), jeji instance vak
iepiesentuji pouze hodnoty od nuly do z (vetn). Maji tak jinou pamovou
iepiesentaci zaujimaji pouze jeden byte ( oktet osm bit) pamti.
Stejn jako ostatnich iselnch tid je nutno odliovat objekt tidy byte iepiesen-
tujici uiit islo od objektu tidy int iepiesentujici tot islo. Tj. nap. byte:0 se
lii od int:0.
Tato zakladni odlinost je v mnoha pipadech setena automatickou konveizi (im-
plicitnim petypovanim) isla tidy byte na islo tidy int.
int i = 5;
byte b = (byte)5; / / zde je nutn explicitn petypovat viz nie
Console.WriteLine ( i == b ); / / vypie true, byte se pevede na int
Console.WriteLine ( i - b );
/ / vypie c (tidy int, nebo byte se ped sitanim konveituje na int)
lmplicitni konveize je mona, nebo jakakoliv bytova hodnota je jednoznan ie-
piesentovatelna objektem tidy int. Pi konveizi tedy nedochazi k adn ztiat
infoimace.
Opana konveize (objektu tidy int na byte) neme bt automaticka, nebo ke
ztiat infoimaci me snadno dojit. Napiklad nelze bezeztiatov konveitovat is-
lo ze nebo 1. Pokud si konveizi vynutime opeiatoiem petypovani, je vsled-
kem u tchto (a dalich vice ne 1 miliaid isel) nedenovana hodnota (alespo de
iure). De facto ji dobi piogiamatoi dokae piedikovat, ale vsledek me zaviset
na konkitnim piocesoiu (typicky je to nejnii byte ze tybytov iepiesentace
isla int tj. nap. (byte)256 c a (byte)-1 z).
Zcela bezpena je tak konveize jen u isel, u nich mame jistotu, e lei v bezpe-
nminteivalu [c,z]. Neni pioto pekvapenim, e si peklada vynucuje explicitni
petypovani nap. u piomnnch i sloitjich viaz. Neme si bt jist, zda je
petypovani bezpen a nechava odpovdnost na uivateli (pouil jsi explicitni
petypovani, take vi co ini a bude za to po zasluze potiestan).
Souboiov oiientovan vstup a vstup :1
Tiochu pekvapiva je nutnost explicitniho petypovani u liteial, u nich by si
ml bt peklada jist, e petypovani je zcela bezpen. Pio je vbec nutn psat
napiklad
fs.WriteByte((byte)0)
i kdy je zejm, e nulu lze bezpen iepiesentovat i v jedinmbytu` Dvodemje
skutenost, e peklada nezohleduje jednotliv objekty, ale jen tidy. Je to toti
jedin pistup, ktei je zcela univeizalni a obecn aplikovateln. Peklada jej toti
podpoiuje i u sloitjich objekt, kde iozhodnuti podle konkitnich objekt neni
mon. Jazyk C= pouiva vechna piavidla dsledn a nikdy neini magicka (tj.
obecn nepiedikovatelna) iozhodnuti (nktei jazyky nejsou v tomto smiu zcela
iigidni, nap. Peil je asto magick).
Poznmka:
Jazyk C= nepodpoiuje pim liteialy tidy byte a obecn adn iseln
tidy, je je vlastni podmnoinou tidy int. Tato vlastnost je typicka
pio vechny (staticky typovan) jazyky odvozen od jazyka C (vet-
n samotnho jazyka C). To si u jazyk se stiiktni (silnou) typovou
kontiolou vynucuje explicitni petypovani iselnch liteial. Kiom
C= se to tka napiklad i Javy.
Objekty tidy byte se nejastji pouivaji v situacich, kdy jsou vy-
nuceny smantikou (nap. u bytov oiientovanch pioud) a u ko-
lekci (poli, seznam), kde mohou viazn sniit pamov naioky. V
ostatnich pipadech (bna iselna skalaini aiitmetika, itae, apod.)
je vhodnji pouivat tidu int. Nedochazi toti ani k spoe pamti
(z dvod optimalizace pistupu jsou i bytov objekty zaiovnavany
na hianici ty i osmi byt) ani ke ziychleni vpot (aiitmetick
opeiace se intein piovadji v cel ice iegisti tj. v iozsahu ty
nebo dokonce osmi byt)
=
Po zapsani hodnot do pioudu je nutn pioud uzavit. To se dje metodou FileStre-
am.Close. Metoda nema adn paiametiy a vdy koni spchem (lze dokonce
zavit ji uzaven pioud, v tomto pipad metoda nic nepiovadi).
Pi uzaveni dochazi k uvolnni pidlenho piostedku na iovni opeianiho
systmu (u souboiovho pioudu je to tedy oteven souboi). Vlastni objekt vak
zstava a pokud existuje i piomnna, kteia na nj odkazuje (pioudy jsou vdy
::
iefeienni objekty) me bt omylem pouit. Pokud se pokusime do uzavenho
pioudu znovu napsat je vyvolana vjimka. Stejn tak je vjimka vyvolana pi
pokusu o znovuoteveni.
l kdy pioud explicitn neuzaveme, bude pidlen piostedek nakonec uvolnn.
Dje se tak pi uvolnni objektu pioudu z pamti pi jejim klidu sbiaem smeti
(garbage collector). Bohuel vak nelze pedem piedikovat, kdy se ta stane. V nej-
lepim (ale nepiavdpodobnm) pipad u v okamiku, kdy zanikne posledni od-
kaz na objekt pioudu (tj. nap. zanikne lokalni piomnna, kteia jej inicializovala).
V nejhoiim (a mnohem piavdpodobnjim) pipad a pi ukoneni piogiamu,
Do t doby je piostedek zbyten alokovan.
Uzaveni souboiu explicitnim volanim metody Close ihned po piovedeni zapisu
i teni, pioblm s uvolnnim zdanliv dokonale ei. Bohuel to neni tak pln
piavda, nebo i kdy na uzaveni nezapomeneme, me dojit k situaci kdy neni
volani metody Close vbec piovedeno. Dvody jsou v zasad dva
1. uzaveni pioudu je obejito pikazemskoku. Nejedna se zde o nechvaln zna-
m pikaz goto (ten v jazyce C= existuje, ale neml by se nikdy pouivat),
ale pedevim o pikaz return. Pokud pedasn ukonujeme metodu pika-
zem return, musime zajistit e i v tomto pipad je pioud bezpen uzaven,
Nestai tedy jedin uzaveni na konci tla metody.
z. bhem zapisu a teni vznikne vjimka. Vjimka nemusi bt nutn zpsobe-
na zapisem(stai jen, e vznikne v libovolnmokamiku od oteveni po uza-
veni pioudu). Tato vjimka nemusi nutn vst k bezpiostednimu ukoneni
piogiamu (a tedy i nucenmu uzaveni). Vjimky lze zachycovat a po za-
chyceni me piogiamdale pokiaovat. Bohuel v tomto pipad pokiauje
s neuzavenm pioudem (po vyvolani vjimky se zbytek kodu metody ji
nikdy nepiovede).
konstrukce using
Natsti jazyk C= poskytuje konstiukci, kteia spiavn uvolovani piostedk v-
iazn usnaduje a zpehleduje konstiukci (pikaz) using.
Upozornn: Tato konstiukce nema nic spolenho s deklaiaci using uivanou pio
impoitovani jmennch piostoi. Autoi jazyka zde jen pouili stejn kliov slovo
pio dv zcela odlin konstiukce (pi navihu jazyka je vhodnji omezit poet
kliovch slov na minimum).
Souboiov oiientovan vstup a vstup :
Pi pouiti konstiukce using je existence exteinich piostedk vazana na piogia-
mov blok (ast piogiamu uzavena ve sloench zavoikach) stejn jako existence
piomnnch. Po oputni bloku (vetn vskoku i vjimky) je objekt automa-
ticky uvolnn.. Syntaxe je jednoducha v hlavice konstiukce using vytvoime
objekt s exteinim piostedkem (zde je to objekt souboiovho pioudu spojen s
otevenm souboiem) a odkaz na nj uloime do piomnn.
using (FileStream fs =
new FileStream( "testFile", FileMode.CreateNew, FileAccess.Write)) {
/ / zde meme objekt pioudu i otevenm souboiem pouivat
for (int i=0; i<1024; i++)
fs.WriteByte((byte)0);
} / / zde je oteven souboi uvolnn
Po hlavice nasleduje blok uzaven do sloench zavoiek. Uvnit tohoto bloku
meme objekt odkazovan piomnnou bez pioblm vyuivat. Po oputni blo-
ku (dosaenim konce, vskokem, vyhozenim vjimky) je pioud uzaven. Stejn
tak zanika i piomnna (nememe tedy objekt omylem vyuivat i pio uzaveni).
Jedin kdo oputni bloku peije je samotn objekt, ten je vak ji nedostupn a
pi nedostatku pamti bude uvolnn sbiaem smeti.
Konstiukci using tak lze inteipietovat tak takto objekt je pipiaven k pouit, ale
jen v iamci nasledujiciho bloku (pak u nebude poteba).
Poznmka:
Pi pouiti konstiukce using neni volana pimo metoda Close, ale
obecnji metoda Dispose ( uvolni [piostedek]). Tuto metodu lze
nalzt i dalich tid, jejich instance spiavuji exteini piostedek jako
je napiklad inteinetov socket, kiyptogiack modul nebo bitma-
pa uivana v GUl. lxistence metody Dispose v iozhiani objektu vak
jet nezaiuuje jeho pouitelnost v konstiukci using, nebo stejn
jmno me mit i jina nesouvisejici metoda. Postaujici podminkou
je implementace iozhiani System.IDisposable, Tim, nejen e vynutime
implementaci metody Dispose, ale foimaln stvidime, e metoda bude
mit poadovanou smantiku (peklada to neme sam zkontiolovat)
Konstiukce using je uitena, avak ne vdy pouitelna. Pokud je k pioudu pistu-
povano deli as a z mnoha navzajem nesouvisejicich mist kodu, je nutno vyuit
klasick eeni tj. explicitni volani metody Close. K tto situaci by vak nemlo
dochazet pili asto.
=
:
Pokud nemate specialni poadavky na ieim oteveni, lze objekt (otevenho)
pioudu ziskat i pomoci statick metody tidy File se jmnem Create, jen otviia
souboi v ieimu vhodnm pio zapis (souboi je oteven v ieimu Filemode.Create).
l v tomto pipad je vak nutno zajistit bezpen uzaveni souboiu.
using(FileStream fs = File.Create(path)) {
/ / zapis do pioudu
}
7.1.2. Bytov orientovan vstup
teni bytov oiientovanho souboiovho pioudu se pili nelii od zapisu. Opt
je nutno pioud otevit (tentokiat s uvedenim pislunho typu pistupu FileAc-
cess.Read a vhodnho ieimu oteveni) a po skoneni uzavit (optimaln pomoci
konstiukce using).
Pio vlastni teni je nejjednodui pouit metodu int ReadByte(). Tato metoda
kupodivu neviaci objekt tidy byte ale int. Dvodem je signalizace dosaeni konce
souboiu. Pokud je tato metoda pouita na konci souboiu (lepointer ukazuje za
posledni byte), neme metoda viatit bnou bytovou hodnotu, nebo v souboiu
mohou bt byty libovolnch hodnot (adn neni pedem vylouiteln). Mohla
by sice vyhodit vjimku, ale to neni zcela koei, nebo dosaeni konce souboiu
neni vjimena situace (kad souboi nakonec skoni). Pioto viati hodnotu -1,
kteia signalizuje dosaeni konce a je odlina od libovoln bytov hodnoty c a
z (nevejde se vak do bytu a musi bt tudi viacena jako instance tidy int).
Hodnota -1 se v tomto kontextu oznauje jako lOl (end of le)
Poznmka:
Viaceni hodnoty -1 pi dosaeni konce souboiu je u nkolik desetile-
ti zavedenm idiomem. Objevuje se v jazyku C a odvozench (vetn
Peilu a PHP) a nejen tam(pouiva se nap. i v Pythonu). Nktei jazy-
ky vak davaji pednost vyvolani vjimky, co si vynucuje pedbn
testovani pioudu ped teni (metoda se smantikou u jsem na kon-
ci souboiu`). To vak komplikuje zapis a neni to zcela bezpen. U
souboiu se sdilenim pistupu, me nastat situace, e test signalizu-
je, e konce nebylo dosaeno, ale nasledn pistup skoni s chybou,
nebo posledni byte mezitim nkdo odstianil zkiacenim souboiu.
Souboiov oiientovan vstup a vstup :
Pio ilustiaci zapisu si meme zvolit tiochu iozsahleji (a mnohem piaktitji)
piklad, odhalovn typu souboru podle prvn nkolika (v naem pipad ty)
byt. Mnoh typy souboiu toti maji na svm zaatku typick bytov vzoi, jen
je oznaovan jako magi slo (me bt toti inteipietovan jako islo s vice-
bytovou iepiesentaci). U nkteich souboiovch foimat vzniklo magick islo
nahodou u jinch bylo zavedeno zamin.
Detailnji infoimaci i s ukazkami nejznamjich magickch isel najdete v lanku
Wikipedie http://en.wikipedia.org/wiki/Magic_number_%28programming%29. Z tohoto
lanku jsou pevzata i ukazkova magicka isla uvedena v naem piogiamu (sku-
tena aplikace tohoto diuhu by mla obsahovat vti databazi).
using System; / / magicnumber.cs
using System.Collections.Generic;
using System.IO;
/ / / summaiy~
/ / / Simple detectoi of le types based in magic numbeis
/ / / /summaiy~
class MagicNumberTester {
/ / zakladni datova stiuktuia slovnik mapujici tveici byt na popis (tezec)
Dictionary< Tuple<byte,byte,byte,byte>, string > magn
= new Dictionary<Tuple<byte, byte, byte, byte>, string>();
/ / zbyten piazdn konstiuktoi
public MagicNumberTester () {
/ / empty constiuctoi
}
/ / / summaiy~
/ / / Method adds 1-byte magic numbei to inteinal database
/ / / /summaiy~
public void AddMagicNumber(string typeName, int b1, int b2, int b3, int b4) {
magn.Add(new Tuple<byte,byte,byte,byte>(
(byte)b1, (byte)b2, (byte)b3, (byte)b4), typeName);
}
/ / / summaiy~
/ / / Method guesses the type of the le (by using of database of magic numbeis)
/ / / /summaiy~
/ / / ietuins~Te desciiption of (guessed) foimat/ietuins~
:e
/ / / paiam namepath~path to le (including lename)/paiam~
public string GuessFileType(string path) {
using (FileStream fs = new FileStream(path, FileMode.Open,
FileAccess.Read)) {
List<byte> header = new List<byte>(4);
/ / iead
for (int i=0; i<4; i++) {
int b = fs.ReadByte();
if (b == -1)
return "unknownfiletype"; / / too shoit le
else
header.Add((byte)b);
}
Tuple<byte, byte, byte, byte> theader = / / list -~ tuple conveision
new Tuple<byte, byte, byte, byte>(header[0], header[1],
header[2], header[3]);
return this.magn.ContainsKey(theader) ? this.magn[theader]
: "unknownfiletype";
}
}
}
class MainClass {
public static void Main(string[] args) {
MagicNumberTester tester = new MagicNumberTester();
/ / vytvoeni minidatabaze
tester.AddMagicNumber("PNGimage", 0x89, 0x50, 0x4E, 0x47);
tester.AddMagicNumber("PDFdocument", 0x25, 0x50, 0x44, 0x46);
/ / test souboiu v piacovnim adiesai
Console.WriteLine(tester.GuessFileType("test.pdf"));
}
}
Objekty tidy MagicNumberTester adaptuji pio svj el slovnik mapujici n-tice
(tuple) ty byt na etzec. Pio pidani novho mapovani (zobiazeni) do slovniku
sloui metoda AddMagicNumber, jeji kod je tiivialni. Kad ze tveice byt je
do metody pedan jako zvlatni paiameti typu int (namisto oekavanho typu
byte). Dvodem volby iiiho typu je zjednodueni volani metody s celoiselnmi
Souboiov oiientovan vstup a vstup :,
liteialy (nemusi se explicitn petypovavat liteialy). Petypovani je piovedeno a
uvnit metody, kde se vytvai n-tice pouita na mist klie. Pio pidani novho
klie s hodnotou se pouiva metoda Add, nebo se nepedpoklada vicenasobn
pidani tho klie (zjednodueno obecn me mit vice typ souboi stejn tyi
byty magickho isla, pokud to nastava musi to bt zohlednno v etzci popisu).
Metoda testujici typ souboiu (GuessFileType) je o nco komplexnji. Nejdive je
v iamci hlaviky konstiukce using vytvoen nov objekt souboiovho pioudu.
Cesta k souboiu je pevzata z paiametiu metody, mod oteveni je FileMode.Open
(oteveni existujiciho souboiu s ukazatelem na poateni byte, vjimena situace
pokud souboi neexistuje) a typ pistupu je samozejm FileAccess.Read.
Vekeia dali manipulace se dje v tle konstiukce using. Algoiitmus je miin
zkomplikovan existenci souboi, jejich dlka je meni ne tyi byty (nejpiavd-
podobnji je existence piazdnch souboi). Tyto souboiy nelze podle magickch
isel iozeznat, ale nemly by vst k pedasnmu ukoneni piogiamu vjimkou. Z
tohoto dvodu jsou byty teny jeden po diuhm a vkladany doasn do seznamu.
Jestlie je bhem teni tchto ty byt dosaen konec konec souboiu, je testovani
ukoneno a je viacen etzec unknown le type.
Nejzajimavji asti metody je tiansfoimace tylennho seznamu byt na pi-
slunou n-tici. Piotoe n-tice me bt obecn heteiogenni ( s polokami iz-
nch typ) nelze ji inicializovat pomoci konstiuktoiu s inicializani kolekci (tato
kolekce by byla postupn piochazena a jednotliv pivky jeden po diuhm zko-
piiovany). Jedinm monm zpsobem inicializace je explicitni pedani jednotli-
vch pivk, tj. uvedeni konstiuktoiu se tymi paiametiy (z nich kad je ziskan
indexaci ze seznamu). Neni to pili stiun, ale bohuel nezbytn. Natsti se po-
uivaji jen n-tice malch iozmi.
Poznmka:
Nepijemn pevadni seznamu do n-tic by bylo mono eliminovat
vyuitim jednotn kolekce jak pio postupn naitani tak i na mist
klie v seznamu. Bohuel kolekce, kteia by byla pouitelna v obou
iolich, neme existovat. Postupn vkladani vyaduje podpoiu pi-
davani i alespo indexace (to neumouje n-tice a obecn adna ne-
mnna kolekce), pouiti na mist klie vyaduje naopak kolekci ne-
mnnou (co neni seznam a dokonce ani pole).
Po pevodu seznamu na n-tici je tato n-tice vyhledana ve slovniku. Pokud je dana
n-tice ve slovniku obsaena jako kli, je viacen odpovidajici popisn etzec (hod-
:8
nota pisluna klii). V opanm pipad je viacen etzec unknown le type.
Pio zestiunni je pouit podminkov opeiatoi.
Testovaci kod (v metod Main), pidava dv ukazkova magicka isla (vimnte si
pouiti liteial v estnactkov soustav pio jednotliv liteialy) a funkce je ovena
na testovacim souboiu (otestuje, zda je souboi skuten ve foimatu PDl).
Stejn jako v pipad zapisu i pi teni existuje alteinativni metoda pio vytvo-
eni a oteveni pioudu ve standaidnim ieimu FileMode.Open staticka metoda
File.OpenRead.
using(FileStream fs = File.OpenRead(path)) {
/ / teni z pioudu
}
Dokumentan poznmky
lmplementace piogiamu obsahuje kiom kodu i tzv. dokumentan poznmky. Ty-
to poznamky nejsou na iozdil do bnch poznamek uieny pio implementatoiy
tidy (tj. nejsou uieny piimain pio Vas a leny Vaeho tmu), ale pio uiva-
tele tidy (tj.piogiamatoiy, ktei vytvaeji instance tidy a aplikuji na n veejn
metody).
loimaln jsou dokumentani poznamky bnmi poznamkami tj. jsou zcela igno-
iovany pekladaem (z pohledu pekladae jsou jen specialnim pipadem mezeio-
vch znak). Jedinm syntaktickm iozdilem je pouiti daliho (tetiho) lomitka
na zaatku (adkov) poznamky.
Smantick iozdily jsou vak mnohem hlubi
dokumentani poznamky se umisuji jen na pesn denovana mista pio-
giamu. Piotoe dokumentuji veejn viditeln konstiukce jako jsou tidy a
veejn metody (vetn konstiuktoi a vlastnosti), musi bt uvedeny bez-
piostedn ped jejich hlavikami (tj. pimo ped denici metody nebo me-
tody/konstiuktoiu/vlastnosti).
uvnit dokumentanich poznamek je nutno vyuivat foimalizovanou stiuk-
tuiu vyuivajici znakovaci jazyk XML. Vechny infoimace musi bt expli-
citn oznaeny pomoci tzv. znaek (tag). l kdy existuje ielativn velk po-
et tchto znaek, je v piaxi vyuivano jen nkolik z nich. V naem pipad
Souboiov oiientovan vstup a vstup :,
jsou to znaky summary (stiun popis dan konstiukce), return (popis na-
viatov hodnoty u metod a vlastnosti) a params (popis funkce konkitniho
paiametiu, paiameti musi bt identikovan pomoci atiibutu name).
dokumentani poznamky nejsou uieny pio teni ve zdiojovmkodu, nebo
zdiojov kod tid nemusi bt pio jejich uivatele dokonce ani dostupn. Je
zpiacovavan exteinimi nastioji do podoby HTML dokumentace (nejpopu-
lainji je Sandcastle http://shfb.codeplex.com/, iesp. univeizalni geneiatoi
doxygen http://www.stack.nl/~dimitri/doxygen/). Navic je tato dokumentace
vyuivana i ve vvojovch piostedich pi zobiazovani iychl napovdy.
Dokumentani poznamky nejsou samozejm povinn, ale jsou neoceniteln v
pipad, e hodlate Vai tidu zveejovat i dlouhodob udiovat.
7.2. Textov orientovan vstup a vstup
Na svitu doby poita se textov oiientovan vstup neliil od vstupu bytov-
ho. Kad znak byl kodovan jednim bytem (viz napiklad kodovani ASCll, ktei je
dokonce jen sedmibitov) tj. zapis i teni znaku se iovnal zapisu i teni bytu. Ui-
it pioblmy byly pouze se znaky odadkovani (ty se v jednotlivch opeianich
systmech liily a dodnes se lii).
V souasnosti vak pevauje znakova sada Unicode, jeji iozsah (vice ne 11c ccc
znak) neumouje vzajemn jednoznan zobiazeni mezi byty a znaky. Pio-
to jsou v knihovn .NlT stiiktn oddleny tidy zajiujici bytov oiientovan
vstup/vstup od tid piacujicimi s textovm vstupem.
Textov oiientovan vstup a vstup navic umouje piacovat nejen s jednotliv-
mi znaky, ale i adky. adek je posloupnost znak zakonena i omezena speci-
alnimi symbolem (nebo symboly). Bohuel o tom jak symboly omezuji etzec
nepanuje shoda v Unixu se pouiva jedin znak (\n oznaovan jako new-line,
nebo line-feed), ve svt Windows pak dvojice \i a \n (carriage return, line fe-
ed). Pichod Unicodu pinesl i dali znaky oddlujici souboiy (ty se vak natsti
nepouivaji pili asto). adkov oiientovan vstup/vstup v .NlT tyto iozdily
ielativn spn skiva (tj. napiklad metoda TextReader.ReadLine pete adek
bez ohledu na oddlova).
:o
7.2.1. Textov orientovan vstup
Hlavni tidou zajiujici textov oiientovan vstup je TextWriter. Tato tida pe-
vadi znaky na byty, podle zvolen znakov sady a kodovani a tyto byty posila do
podizenho pioudu (tj. nepiovadi pimo vstup, ale vyuiva k tomu pioud).
Pokud chcete mit plnou kontiolu nad celm timto piocesem, musite celou opeiaci
zapisu iozdlit do pti fazi
1. oteveni pioudu (pio zapis s vhodnm ieimem oteveni)
z. oteveni objektu zapisovatele nad pioudem (s monosti volby kodovani)
I. vlastni zapis
1. uzaveni objektu zapisovatele
. uzaveni objektu podkladovho pioudu
Natsti lze tuto posloupnost opeiaci ve vtin pipad viazn ziedukovat.
Nejdive se vak podivejme na piklad s explicitnim vyjadenim vech kiok. V
piaxi se pili nepouiva, ale nejlpe ukazuje vechny dili faze piocesu zapisu
using System.Text;
using System.IO;
....
FileStream stream =
new FileStream("cp1250.txt", FileMode.Create, FileAccess.Write);
TextWriter writer =
new StreamWriter(stream, Encoding.GetEncoding(1250));
writer.WriteLine("luoukkplbelskdy");
writer.Close();
stream.Close();
Nejdive je vytvoen (a oteven) objekt pioudu. Kliovm pivkem je volba spiav-
nho typu pistupu (pioud musi podpoiovat zapis). To se piojevuje i v ieimu
oteveni (zde zvolen ieim FileMode.Create je jen jednou z monosti).
Po vytvoeni pioudu je vytvoen i objekt zapisovatele. Vimnte si nehody ti-
dy v denici piomnn wiitei. Piomnna ma typ TextWriter, avak po inicializaci
odkazuje na instanci tidy StreamWriter. To neni chyba. StreamWriter je speciali-
zovanou veizi tidy TextWriter uienou pio zapis do pioud a me bt pouit na
jejim mist (to zajiuje mechanismus tzv. ddinosti s nim se detailnji seznami-
me pozdji). Nazev tidy StreamWriter neni zcela vhodn, lepim pojmenovanim
by bylo StieamTextWiitei, nebo je to textov zapisovatel, zapisujici do pioudu.
Souboiov oiientovan vstup a vstup :1
Poznmka:
Kiom StreamWriteru existuji i jin specializovan tidy textovch
zapisovatel. V piaxi se vak astji setkate jen s tzv. StringWriterem,
ktei zapisuje do etzce. lunkce je podobna MemoryStreamu je vak
na vyi iovni abstiakce (do pamti nejsou vkladany byty, ale pimo
jednotliv znaky).
Zvolen konstiuktoi objektu zapisovatele ma dva paiametiy. Pivnimje podizen
pioud (pioto musel bt vytvoen jako pivni). Diuhm je objekt iepiesentujicim
znakovou sadu a jeji kodovani do byt. Tento objekt je ziskan volanim statick
metody GetEncoding tidy System.Text.Encoding. Tato metoda vyhleda kodova-
ni (a tudi znakovou sadu) podle iselnho identikatoiu. iseln identikatoiy
vech podpoiovanch znakovch sad lze zjistit nap. v dokumentaci tidy Sys-
tem.Text.Encoding (http://msdn.microsoft.com/en-us/library/system.text.encoding.
aspx)'. Kod 1zc ma znama s-bitova znakova sada windows-1zc pouivana pio
iepiesentaci eskch znak na platfoim Windows.
Pio zapis do zapisovae lze vyuit metod, ktei zname z iozhiani konzole tj, Write
a WriteLine. V tomto pipad to vak nejsou statick metody, ale instanni metody
konkitniho objektu zapisovatele.
Poznmka:
Metody Console.Write a Console.WriteLine jsou ve skutenosti jen al-
teinativnimi zapisy namisto volani pislunch metod nad objektem
tidy TextWriter zajiujicim pistup k pioudu standaidniho vstupu.
Tento objekt existuje v kadm konzolovm piogiamu a je dostup-
n pomoci statick vlastnosti Console.Out. Napiklad volani Conso-
le.WriteLine je identick s volanim Console.Out.WriteLine (volani me-
tody explicitn nad zapisovatelem).
Uzaveni zapisovatele pomoci metody Close je zce piopojeno s uzavenim pod-
kladovho pioudu. Uzaveni zapisovatele zajisti vypiazdnni inteinich buei
tohoto objektu a dosaeni konzistentniho koncovho stavu. Tepive po uzaveni
zapisovatele je mono zavit pioud.
Stejn jako v pipad pioud hiozi i zde, e objekt nebude uzaven a piostedky
uvolnny (navic zde me dojit i k nedenovan situaci, kdy zapisovatel neni
uzaven, ale podkladov pioud ano). l zde je pioto vhodnji pouiti konstiukce
'kody spiavuje Miciosof a mimo Windows jsou tm neznam. Navic v nich neexistuje adn
snadno zapamatovateln systm.
::
using. Optimalnim eenim je pak vyuiti dvou vnoench blok using, vnjiho
pio pioud a vnitniho pio zapisovatele (pidlovani a uvolovani piostedk se
dje ve spiavnm poadi).
using System.Text;
using System.IO;
....
using (FileStream stream =
new FileStream("cp1250.txt", FileMode.Create, FileAccess.Write)) {
using(TextWriter writer =
new StreamWriter(stream, Encoding.GetEncoding(1250))) {
writer.WriteLine("luoukkplbelskdy");
} / / zde je uvolnn zapisovatel
} / / zde je uvolnn pioud
Pokud nemate specialni poadavky na ieim oteveni a kodovani znakov sady
pak lze textov zapisovatel vytvoit volanim jedin statick metody tidy File.
using (TextWriter writer = File.CreateText("utf8.txt")) {
writer.WriteLine("luoukkplbelskdy");
}
Podkladov pioud je vytvoen v iamci tovaini metody File.CreateText a je uvolnn
pi uvolnni zapisovatele (pi volani jeho metody Dispose na konci bloku using).
Podkladov pioud lze ziskat piostednictvim metody StreamWriter.BaseStream,
ale toho je zapotebi zcela vjimen (do podkladovho pioudu nikdy nezapisuj-
te, ani jinak nemte!).
Metoda File.CreateText vytvai zapisovatel pio kodovani UTl-s znakov sady Uni-
code. To kodovani je nejpouivanjim exteinim kodovanim (tj. kodovanim pou-
ivanm pio data mimo adiesov piostoi aplikaci) a je asten kompatibilni se
staiim ASCll kodovanim (pokud zapisujete znaky s kodem menim ne 1z, je
vsledkem souboi, ktei je zaiove platnm ASCll i UTl-s souboiem). U tex-
t v eviopskch jazycich pouivajicich latinku je toto kodovani navic piostoiov
efektivni (jeden vjimen dva byty na znak). Hoii situace je u eck alfabety
a azbuky (vdy dva byty na znak) a bnch inskch znak (ti byty). Rozdilna
u staiich znakovch sad splva znakova sada s kodovanim. Pio znakovou sadu existovalo jen jedin
piiozen kodovani, v nm je pozice znaku ve znakov sad pimo ukladana jako bytova hodnota.
Uznakov sady Unicode je situace sloitji. Kad znak ma sice svou jedinenou pozici, ktei vak
me bt izn mapovan na posloupnost byt. Kiom kodovani UTl-s existuji i kodovani UTl-1e
nebo UTl-Iz.
Souboiov oiientovan vstup a vstup :
dlka kod jednotlivch znak tak ztuje indexaci ( nalezeni -tho znaku),
co diskvalikuje toto kodovani pio inteini iepiesentaci Unicode znak (pio n se
pouiva UTl-1e a UTl-Iz).
UTl-s je tak standaidnim kodovanim v modeinich Unixech (vetn Linuxu) a
to pedevim z dvod kompatibility s pvodni iepiesentaci znak v jazyce C
(UTl-s etzce mohou bt zakoneny jedinm nulovm bytem). Ve svt Win-
dows je situace sloitji. Bn se vyuivaji staii bytov oiientovana kodovani
(napiklad CP-1zc v esk veizi Windows) a intein UTl-1e. V kodovani webo-
vch stianek UTl-s jasn dominuje (zahinujic v sob i stianky s ASCll kodova-
nim), nebo jej vyuiva adov I/1 stianek (stav na konci ioku zc1z, podle http:
//w3techs.com/technologies/overview/character_encoding/all).
7.2.2. Textov orientovan vstup
Zakladni stiuktuia textov oiientovanho vstupu se nelii od vstupu. Kliovou
tidou je TextReader iesp. jeho specializace StreamReader. Objekty tchto tid po-
skytuji ti zakladni metody pio vstup (nktei ji zname z konzolovho vstupu)
string ReadLine()
te celou adku (po znak novho adku, ten ji neni ve viacenm etzci zahinut).
Na konci souboiu viaci hodnotu null.
int Read()
te nasledujici znak. Viaci jeho kod (1e-bitov) iozien na Iz bitov islo tidy
int. Na konci souboiu viaci hodnotu -1.
string ReadToEnd()
viaci cel text od aktualni pozice (vetn) v souboiu a do jeho konce. Je-li za-
volan bezpiostedn po oteveni souboiu (s aktualni pozici na pivnim znaku) je
najednou peten cel souboi. To je pohodln, ale u velkch souboi (v adu GiB)
se vsledn etzec nemusi vejit do opeiani pamti.
Obas se hodi i metoda int Peek(), kteia viaci pivni znak z pioudu, ale nevyjima
ho ( neposouva aktualni pozici v souboiu). Pi dalim teni jej pioto viati znovu.
Tato funkce se hodi v pipad, kdy se je poteba analyzovat stiuktuiu textu, v nm
nejsou jednotliv stiuktuiy oddleny oddlovai ( znaky, ktei nejsou souastmi
jednotlivch stiuktui, pouze je oddluji).
Podivejme se napiklad na nasledujici text
:
+14.05-25.37FRODO
Tento text lze snadno iozdlit na ti dili stiuktuiy (islo) 11.c, (islo) z.I a
slovo lRODO. Dili stiuktuiy nejsou oddleny adnm exteinim oddlovaem,
ale lze je vymezit na zaklad znak, ktei jsou jejich asti (nap. isla zainaji
znamnkem, etzec vskytem pivniho pismennho znaku). Tut stiuktuiu lze
zapsat i za pomoci explicitnich oddlova (nap. v CSV foimatu ve tvaiu 14.05,-
25.37,FRODO). Mnoh komunikani piotokoly a textov databaze vak pouivaji
foimu bez explicitnich oddlova (piavdpodobn z spoinch dvod, i kdy
tim pidavaji viasky piogiamatoim).
Pi zpiacovani tohoto typu textu se tou postupn jednotliv znaky pomoci metod
specializovanch na zpiacovani jednotlivch typ dilich stiuktui (zde by to byly
nap. metody ReadNumber a ReadWord) . Pioblmem jsou vak znaky na pomezi
jednotlivch stiuktui. Nap. znak l je nejdive peten v metod zpiacovavajici
isla, nebo z pohledu zapisu isla je to ukonovaci znak, ktei teni isla ukon-
uje. Zaiove to vak je pivni znak slova a musi tak bt petena a zpiacovan i
v metod pio teni slov. Jeden znak vak nelze ist dvakiat. Je vak mon vyuit
metodu Peek pio pedbnou kontiolu znaku (v metod pio zpiacovani zapisu is-
la), piozatimbez jeho teni. teni se piovede nasledn v metod, kteia zpiacovava
stiuktuiu, do ni tento hianini znak nalei.
lunkni (i kdy viazn zjednoduenou) implementace tidy pio textovou anal-
zu textovch souboi si ukaeme v nasledujicim zdiojovm textu (vetn jedno-
duchho testovaciho kodu).
using System; / / readnumbers.cs
using System.IO;
using System.Text;
using System.Globalization;
class SimpleParser {
private TextReader source;
public SimpleParser (TextReader source) { / /

this.source = source;
}
public SimpleParser (string path) { / /

this.source = new StreamReader(path);


}
Souboiov oiientovan vstup a vstup :
public void Close() {
this.source.Close();
}
public double ReadNumber() { / /

int input;
StringBuilder result = new StringBuilder();
/ / pivni znak musi bt znamnko
input = source.Read();
if ((char)input != '+' && (char)input != '-') { / /

throw new InvalidDataException("Invalidcharacter(expectedsign)");


}
while ((input = source.Peek()) != -1) { / /

char c = (char)input; / / petypovani na chai (bezpen)


if (char.IsDigit(c) || c == '.') {
result.Append(c); / /

source.Read(); / / znak je vyjmut z pioudu


} else
break; / / nepipustn (ukonovaci) znak
}
return double.Parse(result.ToString(), CultureInfo.InvariantCulture); / /

}
public bool TestAndSkipNewLine() { / /

int input;
int count = 0;
while ((input = source.Peek()) != -1) {
char c = (char)input;
if (c == '\n' || / /

c == '\r' || / / CR a Ll nemaji kategoiii LineSepaiatoi ale Contiol!


char.GetUnicodeCategory(c) == UnicodeCategory.LineSeparator) {
source.Read();
count++;
} else
break;
}
return count > 0; / / alespo jeden oddlova etzc
}
:e
public bool EndOfFile { / /

get {
return source.Peek() == -1;
}
}
}
class MainClass {
public static void Main(string[] args) {
SimpleParser parser = new SimpleParser("testfile"); / /

SimpleParser stringParser
= new SimpleParser(new StringReader("+2-3\n-5.6+8.1\n"));
while (!parser.EndOfFile) {
double x = parser.ReadNumber();
double y = parser.ReadNumber();
Console.WriteLine("{0};{1}", x, y);
if (!parser.TestAndSkipNewLine())
throw new InvalidDataException("Newlineommited");
}
parser.Close();
}
}
Tida SimpleParser podpoiuje paisovani (textovou analzu) souboi, ktei obsa-
huji iseln daje oiganizovan do adk. Na kadm adku me bt vice isel,
ty vak nejsou oddleny explicitnim oddlovaem, ale (povinnm) znamnkem.
Pikladem me bt souboi se dvma iselnmi daji na na adku
+14.02+50.4
-2.57+10.02
+0.0-0.0
+100-100
Nov objekt tidy SimpleParser lze vytvoit bu nad pedanm textovm tena-
em, nebo si SimpleParser vytvoi tenae sam (a to nad souboiem, jeho jmno
pedame konstiuktoiu).
Pivni konstiuktoi

je exibilnji, nebo mu meme pedat libovolnho texto-


vho tenae, a u je to tena z pioudu (piem pioud nemusi bt jen souboio-
v, ale teba i siov) nebo tena z jinho znakovho zaizeni (napiklad etzce).
Souboiov oiientovan vstup a vstup :,
Tento konstiuktoi je hlavnim konstiuktoiem a musi bt implementovan (v opa-
nm pipad by bylo vyuiti nai tidy zbyten omezeno).
Diuh konstiuktoi

je pohodlnji, a to pedevim pio uivatele, ktei jsou
zvykli vyuivat souboiy umistn na lokalnim souboiovm systmu (napiklad
fyzici i ekonomov). Uivatel v tomto pipad nemusi znat nizkoiovov vstup-
n/vstupni tidy platfoimy .NlT (a me tak snadnji poitovat sv piogiamy z
jinch platfoiem).
Podpoia dvou iznch identikaci vstupnich dat vak vnai do systmu i jistou
asymetiie. Ta se piojevi v okamiku, kdy chceme zavit (uvolnit) piostedky spoje-
n s objektemtenae. Pokud je tena oteven v konstiuktoiu (diuh konstiuktoi
paiametiizovan etzcem), pak musi bt uvolnn objektem paiseiu. Otazkou je,
kdy by se tak mlo dit, iesp. jak objekt paiseiu pozna, e me svho podklado-
vho tenae uvolnit. Me tak init automaticky (napiklad pi dosaeni konce
souboiu) nebo explicitn (poskytnutim vlastni metody pio zaveni).
Jina situace nastava v pipad pouiti ji existujiciho tenae na mist paiametiu
konstiuktoiu (pivni konstiuktoi). V tomto pipad je automatick uzaviiani pio-
blematick, nebo tena nemusi bt vlastnn paiseiem (me bt vyuivan i pio
teni mimo paisei). Piiozenji je zde pistup, kdy je tena uvolovan nezavisle
na paiseiu (v kodu, ktei paisei vyuiva).
lxistuje nkolik eeni tto asymetiie, adna vak neni zcela dokonala. V nai im-
plementaci, je vyuita explicitni metoda pio uzaviiani paiseiu SimpleParser.Close,
kteia uzaviia i podkladov objekt tenae (a ten opt me uzaviiat podkladov
pioud). Tato metoda musi bt volana v pipad, kdy je tena vytvaen paiseiem.
Naopak v pipad, e paisei vyuiva dive vytvoenho tenae, je volani uzavi-
iaci metody nepovinn (zalei na smantice).
Poznmka:
eeni lze dale vylepit implementaci metody Dispose, co by umo-
nilo vyuivat mechanismus using. lmplementace vak neni tak pi-
moaia jako u metody Close, nebo uvolovani piostedk musi bt
piovazano s uvolnnim vlastniho objektu. Pokud je toti objekt uvol-
ovan z pamti, musi zkontiolovat, zda u byly uvolnny jim vlast-
nn piostedky. To se me jevit jako zbyten, nebo piostedky
by mly bt uvolnny ji dive (volanim metody Close nebo Dispose),
ale lid jsou omylni (a piogiamy t). Pokud by k tto chyb dolo,
je uvolnni piostedk spolu s vlastnim objektem posledni zachia-
nou. Je piavdpodobn sice ji tiochu pozd, ale lpe pozd ne nikdy
:8
(iesp. me to bt o nco dive ne ped ukonenim piogiamu, kdy
jsou vechny piostedky uvolnny opeianim systmem). Optimalni
eeni tak musi spiavn piopojit metodu volanou pi uvolnni objek-
tu z pamti (tzv. nalizatoi) s metodou Dispose (a tak Close, pokud
je implementovana).
lmplementace paisovaci metody (ReadNumber

) je miin komplikovana exis-
tenci dvou diametialn odlinch zpsob ukoneni zapisu isla dosaenim
konce souboiu nebo petenim neislice ( znak, ktei neni islici). Tento iozdil
se pili nepiojevuje pi testovani pivniho znaku (znamnka)

, nebo poiovna-
ni znak se dje na iovni jejich iselnch kod (iepiesentovanch jako objekt
tidy int). Lze tak pimo poiovnavat pivni znak pioudu (ziskan metodou Tex-
tReader.Read tj. vetn vyjmuti z pioudu) iesp. piznak konce (hodnota lOl tj.
-1) se znakovmi liteialy, nebo je zejm e hodnota lOl si lii od kodu znaku
plus iesp. minus (stejn jako kody ostatnich znak, ktei nemohou stat na zaatku
iselnho zapisu).
U teni nasledujicich znak je ji situace sloitji. Tyto znaky musi bt teny v
cyklu

, dokud neni peten neislicov znak nebo dokud neni dosaeno konce
souboi. Tyto dv podminky lze jen obtin spojit do jedinho viazu (je to samo-
zejm mon, ale zbyten komplikovan). Pioto bylo zvoleno eeni kdy hlavni
podminka cyklu testuje pouze dosaeni konce souboiu. Je kliovji a pedevim
mnohem univeizalnji.
l kdy me mit tato podminka (a tim i cyklus) izn tvai, je ji od doby jazyka C
pouivan pedevim nasledujici tvai (liici se pouze pouitou funkci i metodou)
int vstup;
while ((input = source.Peek()) != -1) {
/ / zpiacovani vstupu
}
Vhodou tohoto eeni je zahinuti ti opeiaci do jedinho viazu nateni znaku
(zde metodou Peek, tj. znak zstava v pioudu), uloeni kodu znaku do piomnn
(opeiatoi piazeni ) a jeho poiovnani s koncovm piznakem (zde je to hod-
nota lOl). Vyuiva se zde syntaktick iole piazeni jako opeiatoiu, ktei kiom
vlastniho piazeni viaci navic i piazenou hodnotu pio dali zpiacovani.
Toto eeni je de-facto standaidem pio znakov oiientovan vstup a mlo by bt
vyuito, kdykoliv je to jen mon (a zbyten to nekomplikuje piogiam).
Souboiov oiientovan vstup a vstup :,
Pravidlo 27: Vdy pouvejte standardn nebo dlouhodob oven een elemen-
trn kol. Nejen, e si tak usnadnte ivot, ale navc uinte svj program poo-
pitelnj pro ostatn programtory.
Toto piavidlo neni samozejm zcela absolutni. lnovativni eeni jsou samozej-
m vitana. Pili exoticka i genialni eeni, vak piogiam ini mn pehlednm
a tim i spiavovatelnm. Nikdy nevite, kdo a kdy bude potebovat Vaemu piogia-
mu poiozumt. Vtina dobich piogiamatoi oceni, pokud pouijete zaveden
idiom (ktei skuten dobi piogiamatoi deifiuji jedinm pohledem).
Poznmka:
V jazycich, v nich neni piazeni opeiatoiem (nap. Pascalu nebo
Pythonu) je nutno pouit cyklus s podminkou na konci nebo jeho opis.
To je mn pehledn a vyaduje to dvoji pouiti metody pio teni
(jednou ped cyklem a jednou v iamci cyklu).
V tle cyklu je peten iseln kod nejpive petypovan na hodnotu tidy ar a
uloen do piomnn. Petypovani je explicitni, nebo potencialn me dochazet
ke ztiat infoimace (existuji cela isla, kteia neiepiesentuji kod adnho znaku,
nap. vechna zapoina). Zde vak je petypovani bezpen, nebo meme z jis-
totou ici, e piomnna input obsahuje jen ta isla, kteia jsou pipustnmi kody
znak. To vyplva z kontiaktu metody Peek a z vyloueni specialni hodnoty -1
(viaci-li metoda -1, pak je cyklus ukonen a k petypovani ji nedojde).
Po petypovani je pioveden test, zda je peten znak islici nebo tekou (desetin-
nou). Pio oveni pislunosti je vyuita staticka metoda IsDigit tidy ar, Tato
metoda oekava objekt tidy ar a viaci true, pokud tento objekt iepiesentuje
desitkovou islici (nemusi se nutn jednat o bnou eviopsko-aiabskou islici!).
Tida ar podpoiuje i dali statick klasikani metody (IsLeer, IsSpace apod.)
Poznmka:
Pouiti statick metody pio klasikaci znak neni v plnmsouladu s
bnm objektovm zem. Mnohem piiozenji by bylo pouiti in-
stanni metody (nebo jet lpe vlastnosti) nad znakovm objektem.
Zapis (vlastnost objektu)
c.IsDigit
je navic viazn kiati a pehlednji pouiti statick metody
char.IsDigit(c)
:eo
Toto eeni navic podpoiuji i nktei jin objektov jazyky jako je
Python nebo SmallTalk. Pio tedy neni pouito v C=`
Jedinm dvodem je efektivita. U hodnotovch typ jako jsou isla
nebo znaky, lze bna volani metod implementovat jen za pedpo-
kladu, e jsou tyto objekty pevedeny do podoby pouivan u iefe-
iennich typ (tzv. obaleni angl. boxing). Zabalen objekt obsahuje
kiom svch zakladnich dat (u znak je to dvojbytov iseln kod)
i hlaviku, kteia je nezbytna pio identikaci objektu a implementaci
jeho zakladnich funkci vetn identikace jeho metod za bhu.
Obaleni je ielativn pomala opeiace (desitky instiukci piocesoiu),
kteia navic vyaduje dodatenou pam (o velikosti pesahujici p-
vodni velikost objektu). Pioto se snai knihovna .NlT obaleni pokud
mono zcela eliminovat. U isel jsou tak podpoiovany jen zaklad-
ni opeiace, nebo ty nevyaduji volani metody, ale jsou peloeny
do pimch instiukci bytovho kodu a nasledn i do jednoduchch
instiukci piocesoiu) a tak metody zddn z koenov tidy object
iesp. implementujici standaidni iozhiani (nap. ToString, CompareTo).
Ostatni metody (co se tka pedevim tidy ar) jsou iealizovany
piostednictvim pomocnch statickch metod.
Neni-li znak platnou souasti isla (tj. neni to islice nebo teka), je cyklus ped-
asn ukonen za pomoci pikazu break. Neni to oeteni chybovho stavu, jen
ukonujeme zpiacovani po dosaeni hianiniho znaku (neislice). Vskok z cyk-
lu nam poskytuje elegantni oeteni diuh ukonovaci podminky pi paisovani
(hlavni podminkou je dosaeni konce souboiu). Vimnete si, e po vskoku z-
stava testovan znak nepeten, tj neni vyjmut z pioudu znak poskytovanch
tenaem (objektem tidy TextReader) a me tak bt zpiavovan v nasledujici pai-
sovaci metod.
Pokud je naopak peten znak islici nebo tekou, pak jej musime zpiacovat ne-
piodlen. Nejdive znak pipojime k etzci, do kteiho musime postupn ukladat
vechny znaky paisovan islice (vetn znamnka).
Pipojeni znaku k etzci je ielativn bna opeiace zpiacovani textu. Naivni im-
plementace je pimoaia
string result;
.....
char c = ...
result = result + c.ToString();
Souboiov oiientovan vstup a vstup :e1
Po pevedeni znaku na etzec jej lze spojit s etzcem odkazovanm z piomnn
result a iefeienci na nov vznikl (spojen) etzec uloit do stejn piomnn (a
pepsat tak iefeienci na pvodni etzec). Ve funguje jak ma, ale je zde jeden
(zdanliv mal) haek. Cela opeiace vede ke vzniku dvou novch objekt (jedno-
znakov etzec vznikl jako vsledek metody ToString a spojen etzec), z nich
jeden ma jen jepii ivot (na peveden etzec neukazuje po piovedeni pikazu
adna piomnna). Navic ztiacime odkaz i na etzec, jen byl pvodn odkazo-
van z piomnn result. Jeden adek vedouci ke dvou ziozenim a dvma ztiatam
(neodkazovan objekty jakoby neexistovali).
Pokud se tento adek piovede jednou, pak se nic nedje. Jina situace vak nasta-
ne v pipad, e je postupn pipojovani znak k etzci piovadno mnohokiat
uvnit cyklu nebo soustavy vnoench cykl. Vytvaeni novch etzc neni za-
daimo, nebo se asto kiom alokace nov pamti musi piovst zkopiiovani znak
z pvodnich objekt (zde pi vzniku spojenho etzce). Dokonce i ztiata objekt
me mit negativni efekt na efektivitu aplikace. K tomu vak nedochazi bezpio-
stedn, ale a v okamiku kdy jsou objekty uvolovany z pamti. Rutina, kte-
ia pam uvoluje (sbia smeti), se snai tento pioces optimalizovat, ale pesto
spotebovava piocesoiov as. Navic se uvolovani dje a v okamiku, kdy se
poadavky na uvolnni nashiomadi (objekty jsou uvolovany ve velkm). To je
sice v pimiu efektivnji, me vak zpsobovat neakceptovateln piodlevy v
nejmn oekavanch okamicich.
V pipad mnohonasobnho pipojovani etzc je zpomaleni znateln u pi po-
tu pipojeni v adu desetitisic (tivani a piodlevy v adu sekund), a zcela fatalni
v adu milion (potencialn me piogiam vyadovat ioky a staleti pio svj bh,
piodlevy jsou v tomto pipad zcela nevznamn).
Z tohoto dvod jazyk C= nabizi jin a mnohem efektivnji eeni tidu Strin-
gBulder.
StringBuilder postupn vytven etzc
Objekty tidy StringBulder (pln kvalikovan jmno System.Text.StringBuilder)
jsou v zasad specializovanmi kolekcemi znak. Zakladni opeiaci je pipojovani
znak (s asovou sloitosti amoitizovan (1) a nevyadujici vznik novch doas-
nch objekt) a pevod na (nemnn) etzcov objekt. StringBuilder podpoiuje i
dsledkem je skutenost, e pidavani ma kvadiatickou asovou sloitost
:e:
vkladani (se sloitosti ()), vyjimani a pepisovani podetzc. Vechny zmny
se na iozdil od etzce piojevi pimo na inteinim seznamu znak.
Dali metody jsou zde ji jen pio pohodli uivatel. Kiom znak lze pipojovat
iesp. vkladat cel etzce (intein se postupn pipojuji jednotliv znaky, asova
sloitost je pioto zavisla jen na dlce pipojovanho etzce) a pidavat lze do-
konce i ostatni objekty (ty jsou nejdive pevedeny na etzec volanim metody
ToString, iesp. lze pevod ovlivnit foimatovacim etzcem).
Stejn jako v pipad seznam lze pi konstiukci objekt tidy StringBuilder (dale
budu pouivat esk neologismus sestavova) specikovat kapacitu, tj. oekavan
poet znak. Skuten poet znak po dokoneni pipojovani me bt samozej-
m jin. Pokud je vak vti, me dochazet ke kopiiovani poloek-znak na jina
pamova mista (pokud nelze ziskat dodatenou pam bezpiostedn za inteinim
seznamem znak).
Poznmka:
Specialitou je vak monost specikace maximalni kapacity. Tato ka-
pacita neme bt pekioena. Pokud k tomu pi pipojovani i vkla-
dani dojde, je vyvolana vjimka (ArgumentOutOfRangeException).
StringBuilder b = new StringBuilder(100, 1000);
/ / poateni (pedalokovana) kapacita 1cc znak
/ / maximalni kapacita 1ccc znak
Denovani maximalni kapacity zjednoduuje ochianu ped nktei-
mi diuhy sofwaiovch tok typu DoS (denial of seivice odmitnu-
ti sluby). Tyto toky spoivaji v zahlceni seivei poskytujicich in-
teinetov sluby (napiklad webov seiveiy). Utok me spoivat ve
zven fiekvenci poadavk nebo vytvaenim poadavk extimni
velikosti (adov MiB a vice). Pokud budete napiklad zasilat na sei-
vei poadavky o velikosti nkolika MiB, pak me dojit k vyeipani
jeho opeiani pamti a viaznmu zpomaleni celho systmu, nebo
cel systm je zanepiazdnn intenzivnim swapovanim. Pioto je nut-
n velikosti poadavk i jejich asti omezovat. Pokud je poadavek
na stian seiveiu (znovu)sestavovan pomoci etzcovho sestavova,
je mono pio kontiolu maximalni velikosti vyuit vlastnost MaxCa-
pacity (podobn i na stian klienta, i kdy to je nepovinn).
Jak ji bylo eeno, zakladni opeiaci sestavovae je postupn pidavani (pipojo-
vani) znak a etzc na konec inteiniho seznamu.
Souboiov oiientovan vstup a vstup :e
StringBuilder b = new StringBuilder(100);
b.Append("<html>");
b.Append("<body>");
b.Append(variableName);
b.Append('='); / / pidani znaku
b.AppendFormat("{0:0.00}", x);
/ / zkiatka za b.Append(stiing.loimat()),
b.Append("</body>");
b.Append("</html>);
Poslednim kiokem je pevod objektu sestavovae na noimalni etzec. Tento kiok
je nezbytn, nebo vechny ostatni tidy a metody standaidni objektov knihovny
umji piacovat jen s etzci (objekty tidy stiing), nikoliv s objekty tidy Stiin-
gBuildei. Jinak eeno objekt sestavovae je jen doasnm loitm znak.
string html = b.ToString();
Poznmka:
Nucen pevod sestavovae na etzec neni pili efektivni, nebo po
kiatkou dobu musi existovat oba (potencialn dosti iozsahl) objekty.
Co me bt jen detail u etzc noimalni velikosti, me vst k naiu-
eni efektivity spiavy pamti u megabytovch etzc. Je zajimav,
e zvla negativni efekt me mit toto doasn zveni naiok na
pidlenou pam u stiategie lokalni lllO pouivan v MS Windows.
Mnohem efektivnji eeni nabizi jazyk Java, odkud byl mechanis-
mus textovho sestavovae pevzat. Od veize Java 1.1 implementu-
ji tidy String a StringBuilder spolen iozhiani CharSequence. To-
to iozhiani je navic tm dsledn vyuivano v cel knihovn na
mistech, kde je piimain oekavan etzec, vetn nap. GUl tid. To
umouje pimo vyuivat objekt sestavovae namisto etzce ve vt-
in kontext. Neefektivni pevod je tak pln eliminovan.
=
Nyni se viame k naemu paiseiu. Po pidani znaku na konec etzce nesmime
zapomenout, na jeho vyjmuti ze tenae

. Piozatim jsme toti znak nenaetli,
jen jsme ziskali jeho kopii (bez skutenho teni). Jestlie bychomna to zapomnli,
nali bychom tent znak na zaatku pioudu znak i v nasledujici iteiaci cyklu (a
tudi i ve vech dalich nekonen mnoha iteiacich).
:e
V ukazkov implementaci je znak nejdive pidan do sestavovae a pak tepive
vyat z pioudu znak
result.Append(c); / / pidani
source.Read(); / / vyjmuti
Vimnte si, e metoda Read je zde vyuita ponkud netiadinim zpsobem. Je
toti vyuita jen jen pio svj postianni efekt vyjmuti znaku. Naviatova hodnota
(peten znak) je zahozena, nebo neni poteba. U ji toti zname a mame ji u
dokonce zpiacovanou.
Stejn efekt dosahneme i zcela odlinm zpsobem
result.Append((char)source.Read());
Zde je znak nejdive peten (a tudi i vyjmut), a pak je naviatova hodnota teci
metody (petypovana na znak!) pipojena na konec etzcovho sestavovae. N-
ktei piogiamatoi by tento zapis piefeiovali, nebo vyuiva teci metodu mno-
hem tiadinjim zpsobem (peti a via) a jevi se o nco stiunji. Pio jsem
tedy zvolil ve uveden eeni` Sam pesn nevim, ale piavdpodobn ze dvou
dvod
1. vyhnul jsem se petypovani, jeho neuvedeni vede k neoekavan sman-
tick chyb (do sestavovae by nebyl vloen znak s pislunm pozinim
kodem, ale islo peveden na etzec, tj. napiklad namisto islice c by
byl vloen etzec 1s).
z. obsah piomnn c je v danm lokalnim kontextu zetelnji vyjaden (je to
piav zpiacovavan znak). To, e metoda Read viati kod tho znaku je sice
v globalnjim pohledu zejm, vyaduje to vak o nco vic pemleni. Je
to v zasad pistup, ktei zname i bnho jazyka. Objekt, o nm piav
mluvime (tzv. tma nebo topic) je automaticky zapojovan do souvislosti, i
kdy neni pimo vyjaden. Nevyjaden i zbyten sloit odkaz na jin
(netematick) objekt je vetinou zbyten matouci.
Jet ne opustime kliovou metodu ReadNumber, podivejme se detailnji na je-
ji ukoneni, viaceni isla

. Zvolen postup je v zasad jednoduch, objekt se-
stavovae, do nho se postupn naakumulovali vechny znaky isla, pevede-
me nejdive na etzec a pak tento etzec pevedeme na islo pomoci metody
double.Parse (islo me bt obecn neceloiseln). Je zde vak mal pioblm, kte-
i se piojevi jen v nkteich statech (pesnji jen pi uiit konguiaci naiodnich
nastavenich). Jednou z tchto zemi je natsti eska iepublika (jinak bych zadihel
Souboiov oiientovan vstup a vstup :e
piavdpodobn ani neodhalil, bohuel). Pi pokusu o pevedeni jakhokoliv isla,
je obsahuje desetinnou teku skoni pevod nespchem. Dvodem je skute-
nost, e etina (iesp. pesnji eska typogiae) vyaduje namisto desetinn te-
ky desetinnou aiku. .NlT si je toho vdom a vyaduje ji takt. Bohuel vtina
souboi s isly je vytvoena piogiamy, ktei piefeiuji desetinnou teku (staii
piogiamovaci jazyky jako je loitian ani nic jinho nenabizeji). Jaka jsou eeni
1. vynuceni pouiti aiky ve vech vstupnich textovch souboiech (Je nam
lito, ale musite tam mit aiky. Jste v R a musite se podle toho chovat.)
z. vynuceni pouiti teky ve vech vstupnich souboiech (Ajaci to tak cht-
ji. Nevime pio, ale nedaji se pesvdit.). Toto eeni je implementovano.
V metod ToString je vyuit dodaten paiameti (objekt InvariantCulture
tidy System.Globalization.CultureInfo), pepinajici naiodni a jazykova na-
staveni na tzv. neutialni nastaveni, co jsou v zasad ameiicka nastaveni).
I. zpiacovani jak teky tak aiky optimalni eeni. Vyaduje vak tiochu
vice sili. Pioto jej nechavam na vas.
Zbytek piogiamu u meme piojit velmi iychle. Metoda TestAndSkipNewLine

te a peskakuje oddlovae adk, ktei maji ve vstupnim testu jen pomocnou


lohu. Piotoe vak mohou bt povinn, viaci metoda piznak, zda byl njak
oddlova adk peskoen (me bt peskoeno i vice oddlova, tudi i vi-
ce piazdnch adk). Jeji implementace se velmi podoba metod ReadNumber, je
jen o nco zjednoduena. Zajimav je pouze mechanismus oveni, zda je pe-
ten znak oddlovaem adku i nikoliv. Zdalo by se, e stai testovat, zda Uni-
code znakova sada klasikuje znak jako LineSeparator

. K tomu sloui staticka
metoda ar.GetUnicodeCategory, kteia by mla v pipad oddlova adku via-
cet hodnotu UnicodeCategory.LineSeparator (co je objekt vtov tidy System.-
Globalization.UnicodeCategory). Bohuel tak ini jen v pipad nov zavedench
oddlova. U znak \n (Ll) a \i (CR) viaci kategoiii UnicodeCategory.Control
(z histoiickch dvod). Pioto musi bt tyto znaky kontiolovany zvla.
Vlastnost EndOfFile

umouju testovat ukoneni textovho pioudu i v kodu


vyi iovn tj. v kodu, ktei vyuiva instance naeho paiseiu. Hodi se to na-
piklad v pipad, kdy je povinn iozdleni do adku, ale posledni adek nemusi
bt zakonen oddlovaem adk (tj. neni nutn na konci souboiu odadkovat).
lmplementace je tiivialni.
jmno metody neni zcela optimalni. Pedan pioud tena nemusi bt oteven nad souboiovm
pioudem. Vhodnji nazev EndOText.
:ee
Tim koni implementace tidy paiseiu. Podivejme se vak jet na testovaci kod.
Tento kod testuje paisei na textu tvoenm dvojici islic na jednom adku. Poet
adk je neomezen avak i posledni adek musi bt ukonen odadkovanim (pio
jednoduchost). Paisei tento text zpiacuje a vypie na standaidni vstup tata isla
avak v miin odlinmfoimatu (bez povinnch znamnek, oddlena stednikem).
Text je ten z testovaciho souboiu testle uloenho v adiesai spustitelnho
souboiu (je vyuit zjednoduen konstiuktoi se jmnemsouboiu

). Piotoe vak
me bt obtin souboi vytvoit a udiovat, lze vyuit i jednoduiho mechanis-
mu. Namisto tenae nad souboiovm pioudem lze vyuit instanci tidy Strin-
gReader, je je pouitelna na jakmkoliv mist, kde je oekavana instance obec-
nji tidy TextReader. Ukazkov text tak lze napsat pimo do piogiamu (neme
bt piiozen pili dlouh). Piklad vyuiti tenae nad etzcem je v testova-
cim piogiamu uveden, je vak zakomentovan. Pokud jej chcete vyzkouet, stai
jej odkomentovat (a zakomentovat oteveni paiseiu nad souboiemna pedchozim
adku).
7.2.3. dkov orientovan vstup a vstup
adkov oiientovan vstup a vstup je specialnim pipadem textov (iesp. zna-
kov) oiientovanho vstupu/vstupu. Zpiacovani celch adk textu vak pati
k nejastji implementovanm iutinam a je pioto pimo podpoiovano ve vech
piogiamovacich jazycich.
Kiom bnho teni, zpiacovani a vytvaeni textovch souboi se adkov oii-
entovan vstup/vstup pouiva i v dalich oblastech
1. piogiamovani textovch lti znamch pedevim z Unixu (typickm pi-
kladem jsou piogiamy cat, wc, giep a dali)
z. zpiacovani textov (pesnji adkov) oiientovanch inteinetovch pioto-
kol (HTTP, SMTP, POP)
I. geneiovani dynamickch WWW stianek (na nizk iovni)
Jako jednoduch (ale piaktick) piklad vytvoime piogiam(textov lti) pio cen-
zuiovani text. Na textov cenzoi nebude pili inteligentni, nebo bude cenzu-
iovat jen vskyty uiitch slov (pesnji jist xni posloupnosti znak) a to bez
ohledu na kontext. Nepipustna slova bude nahiazovat nahiadnimtextem(v aktu-
alni veizi piogiamu je to posloupnost znak x o dlce odpovidajici pvodnimu
textu).
Souboiov oiientovan vstup a vstup :e,
using System.Collections.Generic; / / censor.cs
using System.IO;
static class StringExtensions {
public static string FirstUpper (this string s) {
return char.ToUpper (s [0]).ToString () + s.Substring (1);
}
}
class Censor {
private List<string> suppressedWords = new List<string> ();
public Censor AddWord (string s) {
suppressedWords.Add (s);
suppressedWords.Add (s.ToUpper ());
suppressedWords.Add (s.FirstUpper ()); / / pouiti ioziujici metody
return this;
}
public void Censoring (TextReader input, TextWriter output) {
string line;
while ((line = input.ReadLine()) != null) {
foreach (string word in suppressedWords) {
string substitute = new string ('x', word.Length);
line = line.Replace (word, substitute);
}
output.WriteLine (line);
}
}
}
class MainClass {
public static void Main (string[] args) {
Censor c = new Censor ();
c.AddWord ("bomba").AddWord ("sex");
c.Censoring (Console.In, Console.Out);
}
}
Jadiem implementace cenzuiovaciho objektu ( instance tidy Censor) je seznam
nepipustnch slov. Tento seznam je na zaatku piazdn, lze jej vak ioziit po-
:e8
moci metody Add (tidy Censor). Metoda neni zcela tiivialni, nebo kiom vlast-
niho slova do seznamu pidava i jeho bn majuskulni vaiiace slovo tvoen
jen velkmi pismeny a slovo, jeho pivni pismeno je velk. To neni pili iobustni
eeni, nebo lze snadno stejn slovo vloit i vicekiat. To sice neovlivni vslednou
funkci, ale me to vst k viaznmu zpomaleni piogiamu. Nebezpei vicenasob-
nho vloeni lze sniit dslednm vkladanim slov jen v zakladnim minuskulnim
tvaiu ( slovo tvoen jen malmi pismeny).
Zohlednn majuskulni vaiianty tvoi jen malou podmnoinou vech majuskul-
nich vaiiaci. Vaiianty s velkmi pismeny na netypickch mistech nebudou cen-
zuiovany (pestoe jsou bez pioblm iteln). Pokiyti vech vaiiant by vak pio-
giam viazn zkomplikovalo (pedevim v substituni asti).
Vimnte si, e pio ziskani vaiianty s pivnim velkm pismenem je pouita jedno-
ducha ioziujici metoda (tida string tuto uitenou metodu bohuel nenabizi).
Pouita implementace neni pili efektivni, nebo bhem ni vznika a zanika iela-
tivn velk mnostvi objekt (dva vznikaji a dva zanikaji). Optimalizace pomoci
StringBuilderu je vak zbytena, nebo poet piovedeni tto metody je zavisl na
potu nepipustnch slov a jejich vaiiant (ielativn mal poet) a nikoliv na potu
slov v cenzuiovanm textu, jen je bn o nkolik ad vyi.
Dalim zajimavm iysem metody Consor.Add je jeji naviatova hodnota. Zatimco
obdobna metoda u seznam nic neviaci, je iozhiani a kontiakt nai metody zcela
jin. Jak lze snadno zjistit z kodu, nae metoda viaci odkaz na objekt adiesata (tj.
na instanci tidy Censor, na ni byla metoda aplikovana). Pio`
Odpov se skiva v testovacim piogiamu. Viaceni objektu adiesata umouje
tzv. zetzen voln metod. To miin zjednoduuje pidavani, nebo neni nutn
opakovat identikaci adiesata. Adiesat se postupn pedava od jednoho volani ke
diuhmu.
Zatimco bn (nezetzen) pidavani by mlo tvai
c.Add("sex");
c.Add("bomba");
lze pi pouiti dslednho viaceni adiesata pouit kiati (zetzen) tvai
c.Add("sex").Add("bomba");
Na uitenost zetzench volani existuji dosti piotikladn nazoiy nktei tvi-
di, e jsou zbyten a znepehleduje piogiam. Navic u metod s potencialnim
postiannim efektem neni zejm, zda se pedava stale stejn objekt (jen je tak
Souboiov oiientovan vstup a vstup :e,
mnohonasobn modikovan skuten zetzeni), nebo nov vytvaen kopie
(objekty jsou nemnn funkcionalni kolona). lxistuji vak i aktivni zastanci,
ktei tvidi, e piogiamatoi by ml mit alespo monost zetzeni pouit (a tudi
mit i vti svobodu). Podpoia zetzeni (tj. dsledn viaceni adiesata u modi-
kujicich metod, ktei by jinak nic neviaceli) si toti zetzena volani nevynucuje.
Metody lze samozejm volat i bez vyuiti jejich naviatovch hodnot. Me to si-
ce vst k malmu zpomaleni, ale s timsi vtinou poiadi i jednoducha automaticka
optimalizace v pekladai.
Knihovna .NlT zetzena volani pili nepodpoiuje (stai se podivat na modi-
kani metody kolekci), ale je dobi je znat alespo pasivn. lxistuji toti objektov
knihovny, ktei je vyuivaji masivn (nap. knihovna Jery v jazyce JavaScript).
Kliova metoda piovadjici cenzuiu (Censoring) je pimoaia. Paiametiem meto-
dy je objekt tidy TextReader ve funkci textovho vstupu a objekt tidy TextWri-
ter, do nho je zapisovan cenzuiovan text. Jadiem implementace je cyklus pes
vechny adky vstupu, za pouiti cyklu while, v jeho sloen podmince je adek
ten, ukladan do piomnn a vsledek poiovnavan s hodnotou null (iepiesentujici
konec souboiu). Obiat je dali inkainaci ckovskho cyklu pes vstupni hodnoty
(viz diskuse v pedchozi sekci).
Uvnit cyklu pes adky vstupu je vnoen cyklus pes vechna nepipustna slova
(uloena uvnit objektu v seznamu, jen je odkazovan datovm lenem suppres-
sedWords). V kad iteiaci vnoenho cyklu je volana metoda Replace, kteia viaci
nov etzec, v nm jsou vechny vskyty aktualniho nepipustnho slova na-
hiazeny nahiadnim textem. Potom je na tento nov text pesmiovan odkaz v
piomnn line (pvodni text adku je zapomenut). Nahiadni text je vytvoen po-
moci explicitniho konstiuktoiu tidy string, jen oekava vplov znak (u nas je
to x) a poet jeho opakovani (u nas je to dlka nahiazovanho slova).
Takto pojata implementace neni pili efektivni, nebo
1. nahiadni text vznika pio kad vstupni adek (bez ohledu na bude i nebude
pouit pio substituci)
z. nov (cenzuiovan) etzec me vznikat i v pipad, e se nepipustn
text na adku vbec nenachazi. Kontiakt metody Replace toti nespecikuje,
co se dje v pipad, e nahiazovan text v etzci vbec neni. Je viacen
pvodni etzec nebo jeho (nezmnna) kopie`
Lze-li pedpokladat, e se nepipustna slova vyskytuji jen zidka (jednou za n-
kolik desitek i stovek adk), pak je vhodnji nejdive otestovat pitomnost
:,o
nepitomnho slova v adku a a pak vytvoit nahiadni test a piovst substituci.
foreach (string word in suppressedWords) {
if (line.Contains(word)) {
string substitute = new string ('x', word.Length);
line = line.Replace (word, substitute);
}
}
Je-li naopak oekavana etnost nepipustnch slov vysoka (nkolik slov na adku),
pak je test nadbyten, na diuhou stianu je vak nutno eliminovat vytvaeni na-
hiady uvnit (vnoenho) cyklu. Optimalnim eeni je vytvoeni slovniku, ktei
mapuje texty na jejich nahiady. Kada poloka slovniku je inicializovana pouze
jednou v metod Censor.Add.
Na zavi se podivejme na vyuiti nov vytvoen tidy. Pokud chceme cenzuiovat
texty ze standaidniho vstupu a pio vstup vyuivat standaidni vstup, neni pote-
ba vytvaet novho itae a zapisovatele. Na mist pivniho paiametiu cenzuiova-
ci metody se pouije objekt, jen je viacen statickou vlastnosti System.Console.In.
Tento objekt tidy TextReader existuje v kadm konzolov oiientovanm piogia-
mu. Podobn existuje i vlastnost viacejici instanci tidy TextWriter iepiesentujici
standaidni vstup System.Console.Out.
Standaidni vstup iesp. vstup vyuiva konzoli (v unixov teiminologii teiminal),
lze je vak pesmiovat na iovni shellu. To se vyuiva pedevim v Unixu, kde
jsou pomoci mechanismu pesmiovani implementovany nap. kolony.
Na mist tenae a zapisovatele, vak lze pouit i objekty tidy StreamReader iesp.
StreamWriter
using (TextReader reader = File.OpenText("original.txt"),
TextWiter writer = File.CreateText("censored.text")) {
c.Censoring(reader, writer);
}
Oba vstupn-vstupni objekty musi bt po svmpouiti uzaveny, a pioto by mla
bt vyuita konstiukce using. Opioti dive uvedenm ukazkam je vyuita iozi-
ena syntaxe umoujici vytvoeni vice objekt v hlavice (jednotliv denice a
inicializace jsou oddleny aikou).
kiom standaidniho vstupu a vstupu podpoiuje Unix i tzv. standaidni chybov vstup. Tento
vstup je alespo foimaln dostupn i v konzolovch aplikacich MS Windows. V.NlT je dostupn
pomoci statick vlastnosti System.Console.Error
A. Pehled syntaxe (EBNF)
Pio popis syntaxe piogiamovacich jazyk existuje specializovan (meta)jazyk
oznaovan jako Bausova-Naurova normln forma (nebo jen Bausova nor-
mln forma). Tento metajazyk se popiv pouival pio zapis jazyka Algol (zaatek
ec. let). l kdy je tento metajazyk schopen popsat libovoln bezkontextov jazyk
(viz http://en.wikipedia.org/wiki/Context-free_grammar) a tudi dokae popsat pod-
statnou ast syntaxe vech piogiamovacich jazyk, je zapis v BNl dosti iozvlan.
Pioto vznikla jeho ioziena veize EBNF (Extended Baus-Naur form), kteia pe-
vzala nktei syntaktick pivky iegulainich viaz (pedevim tzv. kvantika-
toiy). Ma stejnou popisnou silu, viazn vak zkiacuje popis jazyka, nebo neni
nutno denovat nktei pomocn neteiminaly.
Zapis v lBNl obsahuje ti zakladni typy symbol
terminly text, jen se pimo objevi v textu popisovanho jazyka tj. v naem
pipad pimo ve zdiojovm textu piogiamu
neterminly pojmenovan odkazy na dive (i vjimen pozdji) denovan
syntaktick pivky. Neteiminaly jsou ve vslednm textu nahiazeny piav-
mi stianami denic (za znakem ). Pokud denice na piav stian obsa-
huje (alespo jeden) neteiminal, pokiauje nahiazovani iekuizivn (dokud
nezstanou je teiminaly)
opertory spojuji i modikuji zapisy lBNl. Zakladnim opeiatoiem je svislit-
ko, ktei oddluje jednotliv vaiianty. Pi iozvijeni se musi vdy zvolit jed-
na z vaiiant (ale piav jen jedna!). Dali opeiatoiy zavisi na diuhu pouit
lBNl. Zde jsou to napiklad tzv. kvantikatoiy (opakovae), ktei denuji,
e uiita ast piavidla je nepovinna, i se me vicekiat opakovat.
Syntaxe pouit lBNl notace
terminl
teiminalni symbol (text pouivan pimo ve zdiojovm kodu)
neterminl~
z1
:,:
neteiminal tj. odkaz na jin syntaktick piavidlo. Neteiminaly zainajici
a konici pomlkou nejsou explicitn denovany, nebo oznauji znaky z
jist znakov mnoiny, kteiou nelze zapsat vtem. Jejich vznam vyplva
z pouitho jmna neteiminalu.
opertor vznam
oddlova alteinativ
* c a neomezen opakovani
- 1 a neomezen opakovani
` c a 1 opakovani (nepovinna ast)
n piav opakovani
( lBNl ) seskupeni pi aplikaci opakovae na sloenou lBNl denici
Omezen
Syntakticka piavidla uvedena nie nepopisuje vechny platn zdiojov texty ja-
zyka C=! Od pln denice jazyka se lii v tchto (vzajemn se pekivajicich)
bodech
popsany jsou pouze konstiukce zaveden v tchto skiiptech. Jazyk C= vak
podpoiuje i dali konstiukce, ktei jsou nejen platn, ale i v piaxi asto
vyuivan.
nejsou zahinuty nktei zidka pouivan kombinace syntaktickch pivk.
To umonilo viazn zjednoduit a pedevim zpehlednit nkteia syntak-
ticka piavidla (nap. neteiminalu pio vraz). Pikladem eliminovan kom-
binace je monost pouiti piazeni na libovolnm mist viaz (napiklad
na mist skutenho paiametiu)
denice v nkteich pipadech zohleduji (nepovinn) zus. Vynucuji si
tak napiklad pouiti velkch pismen na zaatku jmen tid, nebo piivatni
datov leny.
piavidla nezohleduji nejen nepovinn, ale i povinn pouivani mezeio-
vch znak (vetn odadkovani). Mezeiov znaky mohou bt mezi jak-
mikoliv teiminalnimi symboly (a tudi i neteiminaly). Povinn jsou jen mezi
dvma teiminaly tvoenmi alfanumeiickmi znaky. Zahinuti bilch znak
by viazn zkomplikovalo zapis piavidel a pioto se nepouiva ani u piofe-
sionalnich lBNl denic.
Pehled syntaxe (lBNl) :,
Pedevim si je vak nutno uvdomit, e lBNl nedokae vyjadit kontextov za-
visla syntakticka piavidla (pestoe jsou mnohdy tiivialni). Pomoci lBNl tak nelze
napiklad zapsat poadavek, e pi pouiti nekvalikovanho jmna ( jmna bez
jmennho piostoiu) je nutno tento piostoi impoitovat pomoci denice using. Po-
dobn nelze zapsat piavidlo, e kada piomnna musi bt ped pouitim deno-
vana.
Zcela mimo monosti lBNl (a jakkoliv bezkontextov giamatiky) jsou i typov
kontioly. Nelze si tudi vynutit piavidlo, e podminka cyklu while musi bt viaz
viacejici instanci tidy bool (a adn jin). Kontiolovat nelze ani spiavn pouiti
opeiatoi a tim spie metod. l kdy nae syntakticka piavidla pipoutji napi-
klad zapis "Frodo"[0] * "Gandalf".Add(3), nezaiuuje to jet, e bude spn
peloen (znakem nelze nasobit a etzec nema metodu Add).
To, e piogiam lze popsat pomoci lBNl piavidel, je pouze nutna nikoliv dosta-
ujici podminka jeho syntaktick spiavnosti a peloitelnosti pekladaem.
Kontiola smantick spiavnosti, je pak zcela mimo monosti foimalnich notaci
(nezvlada to ani peklada).
A.1. Znaky a poznmky
majuskule~ A B Z
minuskule~ a b z
psmeno~ majuskule~ minuskule~
oktalov-slice~ 0 1 2 3 4 5 6 7
dekadi-slice~ oktalov-slice~ 8 9
alfanumeri-znak~ psmeno~ dekadi-slice~
hexadecimln-slice~
dekadi-slice~
a b c d e f
A B C D E F
poznmka-dkov-bn~
// -unicode-znak-vyjma-lomtka~
-unicode-znak-vyjma-oddkovn-~* -nov-dek-~
poznmka-dkov-dokumentan~
/// -unicode-znak-vyjma-oddkovn-~* -nov-dek-~
:,
poznmka-blokov~
/* -unicode-znak-~* */
poznmka~
poznmka-dkov-bn~
poznmka-dkov-dokumentan ~
poznmka-blokov~
mezerov-znak~ -tabultor-~ -nov-dek-~ poznmka~
A.2. Identifiktory
identiktor-promnn~ minuskule~ alfanumeri-znak~*
identiktor-metody~ majuskule~ alfanumeri-znak~*
identiktor-vlastnosti~ majuskule~ alfanumeri-znak~*
identiktor-poloky-vtu~ majuskule~ alfanumeri-znak~*
identiktor-primitivn-tdy~
int double char string bool byte
identiktor-jmennho-prostoru~
majuskule~ alfanumeri-znak~* ( . majuskule~ alfanumeri-znak~* )*
prost-jmno-tdy~ majuskule~ alfanumeri-znak~*
seznam-typov-parametr~ identiktor-tdy~ ( , identiktor-tdy~ )*
jmno-specializace-generi-tdy~
prost-jmno-tdy~ seznam-typovch-paiameti ~
kvalikovan-jmno-tdy~
identiktor-jmennho-prostoru~ . prost-jmno-tdy~
identiktor-jmennho-prostoru~ . jmno-specializace-generi-tdy~
identiktor-tdy~
prost-jmno-tdy~
jmno-specializace-generi-tdy~
kvalikovan-jmno-tdy~
identiktor-primitivn-tdy~
A.3. Literly
dekadi-int-literl~ dekadi-slice~-
Pehled syntaxe (lBNl) :,
hexadecimln-int-literl~ 0x hexadecimln-slice~-
celoseln-literl~ dekadi-int-literl~ hexadecimln-int-literl~
double-literl~
dekadi-slice~- . dekadi-slice~*
dekadi-slice~- . dekadi-slice~* e dekadi-slice~
dekadi-slice~- e dekadi-slice~
seln-literl~ celoseln-literl~ double-literl~
nikov-sekvence~
\" \' \\ \t \n \u hexadecimln-slice~1
ar-znak~
-unicode-znak-vyjma-apostrofu-~ nikov-sekvence~
znakov-literl~ ' ar-znak~ '
string-znak~
-unicode-znak-vyjma-uvozovky-~ nikov-sekvence~
etzcov-literl~ " string-znak~* "
boolovsk-literl~ true false
literl~
seln-literl~ znakov-literl~
etzcov-literl~ boolovsk-literl~
A.4. Vraz
aditivn-binrn-opertor~ + -
multiplikativn-binrn-opertor~ * / %
aritmeti-binrn-opertor~
aditivn-binrn-opertor~ multiplikativn-binrn-opertor~
opertor-inkrementace~ ++
opertor-dekrementace~ --
aritmeti-unrn-opertor~ - +
opertor-shodnosti~ == !=
opertor-uspodn~ < > >= <=
relan-opertor~ opertor-shodnosti~ opertor-uspodn ~
:,e
binrn-logi-opertor~ && ||
unrn-logi-opertor~ !
unrn-opertor~ aritmeti-unrn-opertor~ unrn-logi-opertor~
binrn-opertor~
aritmeti-binrn-opertor~
relan-opertor~
binrn-logi-opertor~
seznam-vraz~ vraz~ ( , vraz~)*
voln-stati-metody~ identiktor-tdy~` . identiktor-metody~
( seznam-vraz~` )
voln-instan-metody~ primitivn-vraz~ . identiktor-metody~
( seznam-vraz~` )
strukturovan-inicializtor~ { seznam-vraz~ }
voln-konstruktoru~
new identiktor-tdy~ seznam-parametr~ strukturovan-inicializtor~`
l-vraz~
identiktor~
identiktor~ . identiktor-promnn~
identiktor~ . identiktor-vlastnosti~
identiktor~ [ vraz~ ]
primitivn-vraz~
l-vraz~
literl~
voln-instan-metody~
voln-stati-metody~
voln-konstruktoru~
identiktor-tdy~ . identiktor-poloky-vtu~
( vraz~ )
vraz~
primitivn-vraz~
vraz~ binrn-opertor~ vraz~
unrn-opertor~ vraz~
( identiktor-tdy~ ) craz~
vraz~ ? vraz~ : vraz~
piazen~
l-vraz~ = vraz~
Pehled syntaxe (lBNl) :,,
l-vraz~ binrn-opertor~ = vraz~
l-vraz~ opertor-inkrementace~
l-vraz~ opertor-dekrementace~
opertor-inkrementace~ l-vraz~
opertor-dekrementace~ l-vraz~
piazen-s-porovnnm~ ( piazen ~ ) opertor-shodnosti~ vraz~
A.5. Pkazy
vrazov-pkaz~
piazen ~ ;
vraz~ opertor-inkrementace~ ;
vraz~ opertor-dekrementace~ ;
voln-instan-metody~ ;
voln-stati-metody~ ;
pkaz-ukonen-metody~ return vraz~ ;
pkaz-ukonen-cyklu~ break ;
pkaz-vyhozen-vjimky~ throw voln-konstruktoru~ ;
pkaz-skoku~
pkaz-ukonen-cyklu~
pkaz-ukonen-metody~
pkaz-ukonen-cyklu~
pkaz-vyhozen-vjimky~
przdn-pkaz~ ;
jednodu-pkaz~ pkaz-skoku~ vrazov-pkaz~ przdn-pkaz~
denin-pkaz~
denice-promnn~ ;
denice-promnn-s-inicializac ~ ;
blok~ { pikaz- }
podmnkov-konstrukce~
if ( vraz~ ) pkaz~
if ( vraz~ ) pkaz~ else pkaz~
seznam-denic-s-inicializac~
denice-promnn-s-inicializac ~ ( , denice-promnn-s-inicializac ~ )*
konstrukce-using~ using ( seznam-denic-s-inicializac ~ ) blok~
:,8
while-cyklus~
while ( vraz~ ) pkaz~
while ( piazen-s-porovnnm~ ) pkaz~
for-cyklus~
for ( denice-promnn-s-inicializac ~ ; vraz~ ; piazen ~ )
pkaz~
forea-cyklus~
foreach ( denice-promnn~ in primitivn-vraz~ )
pkaz~
cyklus~ while-cyklus~ for-cyklus~ forea-cyklus~
sloen-pkaz~ podmnkov-konstrukce~ cyklus~
pkaz~
jednodu-pkaz~
denin-pkaz~
blok~
sloen-pkaz~
A.6. Definice tdy
speciktor-pstupu~ public private
denice-datovho-lenu~
private denice-promnn~ ;
private denice-promnn-s-inicializac ~ ;
denice-parametru~
denice-promnn~
ref denice-promnn~
out denice-promnn~
seznam-formln-parametr~
denice-parametru~
( , denice-parametru~ )* ( , denice-promnn-s-inicializac ~ )*
denice-promnn-s-inicializac ~ ( , denice-promnn-s-inicializac ~ )*
denice-konstruktoru~
public prost-jmno-tdy~ ( seznam-formln-parametr~ ) blok~
nvratov-typ~ identiktor-tdy~ void
Pehled syntaxe (lBNl) :,,
denice-metody~
speciktor-pstupu~ nvratov-typ~ identiktor-metody~
( seznam-formln-parametr~ ) blok~
getter~ get blok~
setter~ speciktor-pstupu~` set blok~
denice-vlastnosti~
speciktor-pstupu~ nvratov-typ~ identiktor-metody~
{ geer~ seer~` }
speciktor-pstupu~ nvratov-typ~ identiktor-metody~
{ get; ( speciktor-pstupu~ set; )` }
denice-tdy~
class prost-jmno-tdy~ {
denice-datovho-lenu~-
denice-konstruktoru~*
denice-metody~-
}
seznam-formln-parametr-roziujc-metody~
this denice-promnn~ ( , seznam-formln-parametr~ )`
denice-roziujc-metody~ public static
nvratov-typ~ identiktor-metody~
( seznam-formln-parametr-roziujc-metody~ ) blok~
denice-tdy-pro-roziujc-metody~
static class prost-jmno-tdy~ {
denice-roziujc-metody~-
}
seznam-poloek-vtov-tdy~
identiktor-poloky-vtu~ ( = celoseln-literl~ )`
( , identiktor-poloky-vtu~ ( = celoseln-literl~ )` )*
denice-vtov-tdy~
enum prost-jmno-tdy~ {
seznam-poloek-vtov-tdy~
}
denice-nejvy-rovn~
denice-tdy~ denice-tdy-pro-roziujc-metody~ denice-vtov-tdy~
:8o
A.7. Program
import-jmennho-prostoru~ using identiktor-jmennho-prostoru~ ;
startovac-metoda~
public static void Main ( ) blok~
tda-startovac-metody~
static class prost-jmno-tdy~ {
startovac-metoda~
}
program~
import-jmennho-prostoru~*
denice-nejvy-rovn~*
tda-startovac-metody~
B. Pedvn parametr
Jazyk C= nabizi velmi iiok iepeitoai iznch mechanism pedavani paiamet-
i. Kiom bnch vstupnich paiameti jsou to dva typy paiameti pedavanch
iefeienci (vstupni a vstupn-vstupni) a pedavani vaiiabilniho potu paiameti
pomoci pole. Pi specikaci paiameti lze navic nktei paiametiy vynechavat
(ty pak nabvaji pedem uiench implicitnich hodnot) iesp. je lze identikovat
jmnem nikoliv pozici. adn z ve uvedench mechanism neni nezbytnm
iysem jazyka (v zasad si jakkoliv jazyk vystai s bnmi pozinimi vstupnimi
paiametiy), ale v mnoha pipadech znan zpehleduji a zkiacuji zapis. Jedna se
tedy o typick syntaktick pozlatko.
B.1. Vstupn parametry
Vstupni paiametiy sloui k pedavani objekt z volan funkce do funkce vola-
jici (tedy v opanm smiu opioti bnm paiametim). Dopluji tak zakladni
mechanismus naviatov hodnoty zajiovan pikazem return.
Vpiaxi by se vak mly pouivat jen v pipad skuten poteby. Ve vtin pipa-
d je mnohem pehlednji viacet objekty v pepiavce (doasnm objektu, jeho
jedinou funkci je spojit nkolik objekt do jedinho). Vstupni paiametiy nejsou
v mnoha jazycich vbec podpoiovany (pedevim z dvod jejich sloitosti).
Vstupni paiametiy funguji na piincipu odkaz na piomnn (tzv. pedvn pa-
rametr referenc ). Do metody se peda odkaz na piomnnou (nikoliv na objekt!).
Tato piomnna nesmi bt navic inicializovana (dvod je zejm vstupni pa-
iametiy nemohou slouit k penosu infoimace do funkce).
Uvnit metody (optimaln tsn ped jejim ukoneni) lze do odkazovan piomn-
n vloit objekt (je-li jeji tida iefeienni) nebo iefeienci na nj (je-li jeji tida
hodnotova). Stai pouze piadit objekt do vstupniho paiametiu. Po skoneni
volani tak nalezneme objekt (i iefeienci na nj) v piomnn, kteia byla pedana
na mist vstupniho paiametiu.
zs1
:8:
Tiochu matouci me bt skutenost, e pi pouiti iefeiennich typ na mist v-
stupnich paiameti, musime piacovat s pedstavou dvojit iefeience (tj. iefeience
na iefeienci). Z pohledu volan funkce, je vstupni paiameti bnou piomnnou,
do ni lze bn piazovat odkaz na objekt. Ve skutenosti to vak je odkaz na
jinou piomnnou (existujici vn volan funkce), kteia tepive obsahuje odkaz na
objekt. Jazyk ped nami ob iefeience skiva, dobi piogiamatoi vak musi mit
o tchto iefeiencich povdomi.
Podivejme se nasledujici ukazkov kod, v nm je metoda se dvma paiametiy.
Jeden je vstupni, diuh vstupni.
static bool TestOutParam(string inpar, out string outpar) {
inpar = "false_output"; / / nema adn skuten efekt
outpar = "output"; / / nastaveni pedan piomnn
/ / stav v tomto mist, viz obiazek B.1
return true;
}
/ / volani
string vstup = "input";
string box; / / neninicializovana
bool result = TestOutParam(vstup, out box);
Console.WriteLine(s); / / vypie input
Console.WriteLine(box); / / vypie output
Piazeni do paiametiu inpar je bn piazeni do lokalni piomnn. Tato pio-
mnna vznikla na zaatku metody a byl do ni zkopiiovan odkaz na objekt-etzec
input. Tento odkaz byl pivotn uloen v piomnn vstup (a stale se v ni nachazi).
Tato piomnna lei v jin metod a tak k ni zevnit metody TestOutParamnemame
adn pistup (na iozdil od objektu, ktei byl ped piazenim obma piomnn-
mi sdilen). Po piazeni odkazuje piomnna inpar nov etzec (false output). Je
to vak zcela zbyten, nebo dive ne staime etzec pouit, metoda skoni, lo-
kalni piomnn zanikaji a etzec se stava nedostupnm (a bude piavdpodobn
bizy odstiann z pamti). V piomnn vstup samozejm stale zstava odkaz na
pvodni objekt ( etzec input)
Piazeni do vstupniho paiametiu outpar vypada navenek zcela stejn, inteini
iealizace je vak zcela jina a viazn se lii i dsledky. Piomnna outpar toti neni
bnou piomnnou, ale doasnm odkazem na piomnnou, kteia byla pouita na
mist diuhho paiametiu (se specikaci out). Zde tedy odkazuje piomnnou box.
Odkaz na objekt-etzec output je tak uloen do piomnn box (tato piomnna
je uvnit metody viditelna jen pes odkaz). Po skoneni piomnna-odkaz zanika
Pedavani paiameti :8
(je tak lokalni), ale v pedan piomnn (box) zstava nova hodnota (tj. jedna se
skuten o vstupni paiameti).
Pio jistotu se jet podivejte na obiazek B.1, ktei ukazuje stav tsn ped ukon-
enim funkce (tj. ped pikazem return).
vstup
box
inpar
outpar
kontext volajc metody
kontext metody
TestOutParam
string:output
string:input string:false_output
hromada (heap)
loit! objekt"
Obiazek B.1. Pedani vstupniho paiametiu iefeienci
B.2. Obecn pedvn parametr referenc
Uiitm zobecnnim vstupnich paiameti jsou parametry pedvan referenc
(iesp. odkazem). Tyto paiametiy jsou vstupn-vstupni tj. lze je vyuivat jak pio
penos dat do metody, tak i pio penos opanm smiem.
Stejn jako u vstupnich paiameti je jejich zakladem iefeience na piomnnou v
nadizen metod. Tato piomnna vak musi bt ped ped pedanim inicializo-
vana tj. musi obsahovat objekt nebo objekt odkazovat. Tento objekt je nasledn
dostupn uvnit volan metody (nepimo pes odkaz na piomnnou) tj. funguje
jako vstup. Odkazovanou piomnnou vak lze stejn jako u vstupnich paiamet-
i zmnit tj. nahiadit objekt za jin (nov vytvoen). Tento objekt peije zanik
volan metody a me tak bt vyuit jako jeji vstup.
Paiametiy pedavan iefeienci se v C= pouivaji jen zidka (dokonce mn asto
ne paiametiy vstupni). Navic nejsou v mnoha jazycich vbec podpoiovany (Ja-
va, Python) a to vetn mnoha jazyk vyuivajicich platfoimu .NlT (Iron Python).
Pioto je pouivejte jen ve skuten vjimench situacich. Ve vtin pipad je
:8
lze nahiadit bnm (vstupnim) paiametiem a bnou naviatovou hodnotou (v
pipad poteby v iamci pepiavky spojujicich vice vslednch objekt).
Navic lze potebu pedavani iefeienci tm vdy eliminovat vyuitim pedavani
mnitelnch objekt iefeiennich typ. Uvnit metody lze pedan objekt bez
potii modikovat, piem se tyto zmny zachovaji i po ukoneni metody (tj.
metody mohou mit na pedanch objektech vedleji efekt). To sice neni tak siln
jako viaceni novho objektu, ale ve vtin pipad to postauje.
Syntakticky se pedavani paiameti iefeienci oznauje pomoci kliovho slova
ref, a to jak ped denici foimalniho paiametiu (v denici funkce) tak i ped
skutenm paiametiem (piomnnou) v iamci volani (obdobn jako u kliovho
slova out).
Klasickm pikladem metody vyadujici pedavani iefeienci (bez monosti jed-
noduchho opsani) je metoda pio zamnu obsahu dvou piomnnch (swap). Tato
metoda neni bnou instanni metodou, nebo objekt adiesata nelze pedat iefe-
ienci. Musi to bt funkce tj. staticka metoda bez vazby na na objekt i tidu sku-
tench objekt. loimaln vak musi bt denovana ve tid (k ni vak nemusi
mit adn vztah) jako staticka (tidni) metoda. Me bt denovana napiklad ve
tid s hlavni (Main) metodou.
using System;
class MainClass {
public static void Swap<T>(ref T a, ref T b) {
T p = a; / / ben algoiitmus vmny pes pomocnou piomnnou
a = b;
b = p;
}
public static void Main(string[] args) {
string x = "Ahoj";
string y = "svete";
Swap(ref x, ref y); / / volani s iefeienci na dv piomnn
Console.WriteLine("{0}{1}", x, y);
}
}
Pedavani paiameti :8
Metoda Swap je denovana jako geneiicka, tj. pio paiametiy mohou bt instan-
cemi libovoln (ale toton) tidy, oznaen foimaln jmnem T'. Tento identi-
katoi je pouit i pi denici pomocn piomnn. Piomnna tak bude mit stejn
typ jako paiametiy (tj. me obsahovat i odkazovat objekty stejnho typu jako
jsou paiametiy).
Pi pouiti (volani) peklada zjisti typ obou pedanch piomnnch. Pokud jsou
stejn (v naem piklad jsou oba typu string), je vytvoena a peloena metoda, v
ni je kad vskyt identikatoiu T nahiazen skutenm jmnem tidy (zde tedy
identikatoiem string). Tato specializovana metoda pak pijme iefeienci na ob
piomnn a piovede zamnu jejich obsahu.
l kdy je tento piklad zajimav a poun, v piaxi byste mli vmnu piovst
spie pimmkodem(bez vyuiti metody). Neni to o mnoho deli a lze jej snadnji
poitovat do jinch jazyk.
public static void Main(string[] args) {
string x = "Ahoj";
string y = "svete";
string p = x;
x = y;
y = p;
Console.WriteLine("{0}{1}", x, y);
}
'T je identikatoi, na jeho mist lze pouit libovoln jmno (podle zu by vak mlo zainat velkm
T)
C. Rozshlej programy
Tato piloha obsahuje komentovan vpis tch piogiam, jejich iozsah neumo-
nil zahinuti do hlavniho textu skiipt.
C.1. Vyrovnvac pam (generick verze nad
slovnkem)
Tato veize vyiovnavaci pamti vyuiva slovnik a fiontu pio vytvoeni efektivni
a pitom iychl vyiovnavaci pamti. Vyiovnavaci pam ma omezenou velikost
(maxSize) a po jejim pekioeni se maou nejdle alokovan poloky (tj. poloky
od jejich vloeni ubhlo nejvice asu).
Tida je implementovana jako geneiicka, tj. jedna se pouze o ablonu, z ni je kon-
kitni tida vytvoena dosazenim konkitnich jmen tid namisto obecnch iden-
tikatoi TKey (tida pio objekty kli) a TValue (tida pio objekty ukladanch
hodnot). Lze tak vytvaet individualni tidy vyiovnavacich pamti pizpsoben
pio ukladani hodnot libovoln (konkitni) tidy s kliem (obecn jin, avak tak
libovoln tidy).
class Cache<TKey, TValue> {
public int MaxSize { get; private set; } / / maximalni velikost
private Dictionary<TKey, TValue> data = new Dictionary<TKey, TValue>();
private Queue<TKey> keyQueue = new Queue<TKey>(); / / fionta alokaci
public Cache (int maxSize) {
MaxSize = maxSize;
}
public void Insert(TKey key, TValue value) {
if (data.Count >= MaxSize) {
data.Remove(keyQueue.Dequeue()); / / vyjmuti nejstaii hodnoty
zs
:88
}
data.Add(key, value); / / pidani hodnoty (pod danm kliem)
keyQueue.Enqueue(key);
}
public bool Contains(TKey key) {
return data.ContainsKey(key);
}
public TValue Find(TKey key) { / / vjimka, pi pistupu k piozatim neuloen hodnot
return data[key];
}
public TValue Find(TKey key, TValue defaultValue) {
TValue box;
return data.TryGetValue(key, out box) ? box : defaultValue;
}
}
Pouivani pedpoklada, e uivatel instance tidy nejdive zkontioluje pitomnost
hodnoty s danmkliem. Pidat je me jen v pipad, kdy si je jist, e vyiovnavaci
pam danou hodnotu neobsahuje. V opanm pipad je chovani nedenovan.
Ve vtin pipad vznikne vjimka (opakovan vloeni klie do podkladovho
slovniku), vjimen se to vak me zdanliv podait (je-li pislun kli vyjmut
pi uvolovani mista).
Piklad vyuiti (ukladana jsou data, kliem je jejich etzcova identikace)
Cache<string, DateTime> cache = new Cache<string, DateTime>();
....
DateTime finish;
if(cache.Contains("konecsveta"))
finish = cache["konecsveta"];
else {
finish = prophet.GetProphecy("konecSveta").Date; / / velmi pomala opeiace
cache.Insert("konecsveta", finish);
}
Rozsahleji piogiamy :8,
C.2. Program pro zjitn velikosti kolizn skupiny
v hashovac tabulce
Pomocn piogiam vyuit pio geneiovani giaf na obiazku e.1 na stian zIc. lm-
plementovany jsou dv tidy. Pomocna tida Counter vyuiva slovnik pio iealizaci
itae vsledk hashovaci funkce. Piotoe kliem mohou bt jen kladna isla (viz
dale), mapuje slovnik hodnoty tidy uint na poet (iepiesentovan jako int). Uint
(zkiatka za unsigned int) je specializovana iselna tida, jejimi instancemi jsou
kladna cela isla v iozsahu c a z
Iz
.
Hlavni tidou je HashTester, je vypoitava piminou velikost kolizni skupiny.
Kolizni skupina je mnoina kli se stejnou hodnotou hashovaciho indexu ( v-
sledku hashovaci funkce).
Hashovaci hodnota je ziskavana pio vechny hodnoty pedan kolekce (kolekce
musi bt schopna piochazeni tj. musi implementovat iozhiani IEnumerable). Pio
ziskani hashovaci hodnoty je vyuita metoda GetHash, kteiou poskytuji vechny
objekty. Tato metoda viaci islo typu int tj. islo v iozsahu z
I1
a z
I1
1. Toto is-
lo je petypovano na typ uint tj. tiansfoimovano do iozsahu c a z
Iz
(zapoina isla
se stavaji velkmi kladnmi). Potom je pevedeno do iozsahu c a HashTableSize
(velikost hashovaci tabulky) pomoci opeiace zbytek po dleni (hashovaci hodnota
je tedy vdy kladna). etnost iznch hashovacich hodnot je akumulovana po-
moci itae a nasledn je z tchto etnosti vypotena pimina velikost kolizni
skupiny (pomoci tiivialniho algoiitmu).
Hlavni piogiamvytvai textovou tabulku piminch velikosti pio tabulky o veli-
kosti a z1c potu hashovanch objekt (kiok je ). Hashovan objekty jsou
ziskany z textovho souboiu (ten vznikl expoitem a piavou excelovsk tabulky
z piimainiho zdioje http://www.mvcr.cz/soubor/2012-zctpr-zctpr-rijen-zip.aspx).
using System; / / hashtester.cs
using System.Collections.Generic;
using System.IO;
using System.Globalization;
class Counter { / / specializovan ita vskyt
private Dictionary<uint, int> c = new Dictionary<uint, int>();
public void Occur(uint o) {
if (c.ContainsKey(o)) {
:,o
c[o]++;
} else
c[o] = 1;
}
public int Frequency(uint o) {
return c.ContainsKey(o) ? c[o] : 0;
}
public IEnumerable<uint> Keys {
get { return c.Keys;}
}
}
class HashTester {
public uint HashTableSize { get; private set; }
public HashTester (uint hashTableSize) {
this.HashTableSize = hashTableSize;
}
public double MeanCollisionGroupSize(IEnumerable<object> keys) {
Counter counter = new Counter();
foreach (object key in keys)
counter.Occur((uint)(key.GetHashCode()) % HashTableSize);
int sum = 0;
int count = 0;
foreach (uint index in counter.Keys) {
int freq = counter.Frequency(index);
sum += freq;
count++;
}
return (double)sum / (double)count;
}
}
class MainClass {
public static void Main() {
List<string> names = new List<string>(500000);
TextReader tfile = File.OpenText("/home/fiser/doc/prijmeni");
string name;
Rozsahleji piogiamy :,1
while ((name = tfile.ReadLine()) != null)
names.Add(name);
double count = (double)names.Count;
for (double k=0.05; k<=2.1; k+=0.05) {
uint size = (uint)(k*count);
HashTester tester = new HashTester(size);
Console.WriteLine("{0},\t{1}", k.ToString(),
tester.MeanCollisionGroupSize(names).ToString());
}
}
}
Piklad vstupniho souboiu (zkiaceno, ve skutenosti ma tm pl milionu adek
a .s MiB)
A HASAN
AALTONENOV
ABAD GONZLEZ
ABANINOV
....
JAK
ERRIU
MANOLEA
HOUTENBRINK
Piklad vstupu (pouito neutialni jazykov nastaveni, v Linuxu pouijte nasta-
veni LANGC)
0.05, 20.0003619254434
0.1, 10.000985320732
0.15, 6.67519830351511
0.2, 5.0351708428246
0.25, 4.07519480838721
0.3, 3.4593137698145
...
1.85, 1.29914139210979
1.9, 1.2899794578107
1.95, 1.28119002661047
2, 1.2744075088595
2.05, 1.26713766694353
Seznam obrzk
1.1. Objektov oiientovan piogiamovaci jazyky . . . . . . . . . . . . . . . . . 1c
1.z. Objekty a tidy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
z.1. Skladani z elementainich objekt . . . . . . . . . . . . . . . . . . . . . . . 1v
z.z. Zetzen volani metody . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ic
z.I. lndexace v etzci . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ie
z.1. Denice a inicializace piomnn pio objekty hodnotovch tid . . . . . . . 11
z.. Denice a inicializace piomnn pio objekty iefeienni tidy . . . . . . . . 1I
z.e. Sloitji denice a inicializace . . . . . . . . . . . . . . . . . . . . . . . . . 11
z.. Vmna obsahu dvou piomnnch . . . . . . . . . . . . . . . . . . . . . . . 1v
I.1. Jmenn piostoi System a jeho podpiostoiy . . . . . . . . . . . . . . . . . . s
I.z. Poitani slov (piklad) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ev
1.1. Asymptoticka sloitost. Piklady funkci . . . . . . . . . . . . . . . . . . . . vv
1.z. lnteini stiuktuia seznamu . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1cz
1.I. Cyklus foi, iozboi piovadni . . . . . . . . . . . . . . . . . . . . . . . . . . 11s
1.1. Chybn algoiitmus selektivniho vmazu . . . . . . . . . . . . . . . . . . . 1z1
1.. Kopiiovani objekt s vice iovnmi odkaz (poateni stav) . . . . . . . . 1z
1.e. Kopiiovani objekt s vice iovnmi odkaz (stav po duplikaci) . . . . . . . 1z
1.. Kopiiovani objekt s vice iovnmi odkaz (stav po pidani adku) . . . . 1zs
1.s. Kopiiovani objekt s vice iovnmi odkaz (konen stav) . . . . . . . . . 1zv
1.v. Test setidni seznamu (typy pibh) . . . . . . . . . . . . . . . . . . . . 1Is
1.1c. Logika vtveni v tle cyklu (test setidnosti) . . . . . . . . . . . . . . . . . 11e
.1. Vznik objektu (s podobjekty hodnotovch tid) . . . . . . . . . . . . . . . . 1
.z. Piomnn a objekty pi vytvaeni seznamu mnitelnch objekt . . . . . . 1es
.I. Sniovani zavislosti mezi objekty . . . . . . . . . . . . . . . . . . . . . . . . 1sz
.1. Piomnn a objekty pi vytvaeni seznamu nemnitelnch objekt . . . . . 1s1
.. Ukazka kompozice objektu tidy Cae . . . . . . . . . . . . . . . . . . . . 1vs
e.1. Slovnik zobiazeni kli na hodnoty . . . . . . . . . . . . . . . . . . . . . zcv
e.z. Slovnik jako iepiesentace ielani tabulky . . . . . . . . . . . . . . . . . . . z1
zvI
:,
e.I. List tabulkovho piocesoiu idk pole . . . . . . . . . . . . . . . . . . . . zz1
e.1. Velikost kolizni skupiny pio hashovaci funkci nad etzci . . . . . . . . . . zIc
e.. Hashovaci tabulka . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . zI1
.1. Stiuktuia l/O tid . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . zI
B.1. Pedani vstupniho paiametiu iefeienci . . . . . . . . . . . . . . . . . . . . zsI

You might also like