Stáhnout materiál Úvod do Deplhi

Transkript

Stáhnout materiál Úvod do Deplhi
1. Úvod, Algoritmus a jeho charakteristiky
Cíl
•
•
•
Naučit se řešit problémy s pomocí prostředků výpočetní techniky – jako výpočetní technika
Pochopit do hloubky co se dá od těchto prostředků očekávat
Naučit se myslet určitým způsobem – jiným než jsou třeba postupy v matematice – zpětné hlubší pochopení
určitých problémů
• Naučit se základům řemesla
Naučit se dá všechno, ale chce to systematickou práci a trpělivost
Jazyk a prostředí
Programovat se dá naučit bez počítače, ale zábavnější je to s ním. Pro psaní programů používáme programovací
jazyk.
Na jazyce tak moc nezáleží (Je to podobné jako s řízením auta. Naučíte-li se formulovat algoritmy v jednom
jazyce stejného typu, není tak těžké přejít na jiný)
• strukturované, které zahrnují práci s objekty – C++, Object Pascal , VBA, PHP
• plně objektové jako JAVA, které se pro začátek moc nehodí a bez zvládnutí strukturovaného programování
se neobejdou (obojí je podobné, dá se mezi tím přecházet)
• funkcionální jako Prolog nebo Lisp – jiný způsob myšlení
Abychom mohli program napsat, potřebujeme také textový editor, nějaký ladicí prostředek, v současnosti se
používá vizuální návrh programů, kde standardní komponenty Windows, jako jsou všelijaká tlačítka a toolbary
nemusíme pracně graficky vytvářet, ale jsou k dispozici – to všechno tvoří integrované prostředí.
(Borland C++, Borland Delphi, Visual Basic,…)
Proč právě Delphi
Jazykem Delphi je Object Pascal, který vychází z původního Pascalu profesoraWirtha, navrženého jako jazyk
k výuce programování. Delpho přitom poskytují všechny vymoženosti moderního programování (vizuální návrh
rozhraní, třídy, výjímky…) a jsou světovými vývojáři považovány za jedno z nejlepších prostředí.
Algoritmus a jeho charakteristiky
Algoritmická úloha a její specifikace:
Jsou dány vstupní údaje vyhovující vstupním podmínkám a výstupní údaje splňující výstupní podmínky.
Vytvoř algoritmus – tj. napiš postup, který pro všechny údaje vyhovující vstupním podmínkám získá výstupní
údaje vyhovující výstupním podmínkám.
Příklad 1: Vejce na tvrdo. Přepokládáme, že existují tři druhy vajec: malá, střední a velká
• Vstup: Vejce syrové, čerstvé
• Výstup: Vejce na tvrdo uvařené, jedlé
Postup:
• Dáme vařit vodu.
• Když se voda vaří (bublá), vložíme vejce.
• V případě, • že je je vejce malé, nastavíme kuchyňský budík na 1 minutu.
• že je je vejce střední, nastavíme kuchyňský budík na 5 minut.
• že je je vejce velké, nastavíme kuchyňský budík na 8 minut.
• Dokud budík nezazvoní, vejce vaříme.
• Když budík zazvoní, vejce vyjmeme a opláchneme studenou vodou.
Příklad 2: řešení lineární rovnice v oboru reálných čísel (ax =b)
• Vstup a,b reálná čísla
• Výstup podle a, b buď kořen rovnice nebo oznámení, že daná rovnice má nekonečně mnoho řešení nebo
nemá řešení.
Postup:
• Zjistíme a,b
• Když a není nula, potom můžeme vypočítat kořen x = b/a, řešení je x
• Jinak když b=0 potom je řešení libovolné reálné číslo
PDF created with pdfFactory trial version www.pdffactory.com
•
•
Jinak řešení neexistuje
Vypíšeme zprávu o výsledcích
Vlastnosti algoritmu:
•
•
•
•
Přesnost a elementárnost: algoritmus musí být formulován vzhledem k procesoru, který podle něj bude
pracovat, tj. jazykem, kterému procesor rozumí a pomocí akcí, které umí vykonávat.
Hromadnost – řeší dost velkou třídu úloh (ne jednu rovnici s konkrétními čísly, ale celou skupinu rovnic –
vzpomínáte si na rovnice s parametry?)
Rezultativnost a konečnost – po určitém počtu kroků musí skončit
Determinovanost – pro tentýž vstup musí algoritmus poskytovat týž výstup. (V každém kroku je zřejmé, co
bude následovat.)
Zápisy algoritmů
• V přirozeném jazyce – nešikovné, nepřehledné
• Graficky – vývojové diagramy, struktogramy – přehledné, ale někdy zbytečně pracné
• V programovacím jazyce – pokud si zvykneme na přehledný zápis, nejobvyklejší
Program je zápis algoritmu v programovacím jazyce.
Tyto jazyky jsou odvozeny z jazyka přirozeného (většinou angličtiny), ale mají jednoznačnou a jednoduchou
gramatiku.
Aby procesor podle programu mohl pracovat, potřebuje překladač, který překládá z programovacího jazyka do
instrukcí strojového kódu. (Ve skutečnosti složitější)
Kompilátory – přeloží celý program najednou (rychlejší)
Interprety – překládají po příkazech (Interpretovány bývají příkazy OS)
Zásady tvorby algoritmů:
• Důkladná analýza problému
• Algoritmický problém nemusí mít vždy řešení (A je to dobře, protože jinak by nás počítače brzy k ničemu
nepotřebovaly)
• Studium literatury
• Metoda shora dolů
• Rozklad problému na podproblémy
• Zpracování částí
• Jejich složení do původního problému
• Zápis v programovacím jazyce
• Ladění
• Dokumentace
Cvičení
Vyzkoušejte si několik příkladů z přijímacích zkoušek na Informatiku na matematicko-fyzikální fakultě v Praze.
1. V algebrogramu nahraďte písmena číslicemi, aby platila rovnost v řádcích i sloupcích. Každé písmeno
nahraďte jednou číslicí, různým písmenům odpovídají různé číslice. Uveďte postup úvah, který vede k řešení.
(Najděte všechna řešení)
A + B = BC
–
–
–
D+B= E
E+C= E
2. Obdélníková tabulka čokoláda má velikost m*n dílků. Tabulku chceme rozlámat na jednotlivé dílky. Každý
zlom musí být rovný a rozlomíme jím jen jeden kus čokolády. Jaký nejmenší počet zlomů potřebujeme?
Zdůvodněte.
3. Máme devět na pohled stejných kuliček a víme, že osm z nich je stejně těžkých, zatímco jedna je těžší než
ostatní. Navrhněte postup, jak na rovnoramenných vahách naleznete tuto kuličku s nejmenším počtem vážení.
Zdůvodněte.
4. Je dána posloupnost cifer 1 2 3 4 5 6 7 8 9 .
PDF created with pdfFactory trial version www.pdffactory.com
Před každou cifru vložte znaménko plus nebo mínus, aby výsledný aritmetický výraz měl hodnotu 33. Nalezněte
všechna řešení a vysvětlete, proč další řešení neexistuje.
5. V pytli je B bílých a C černých kuliček. Postupně opakujte následující tahy: Sáhnete do pytle a vytáhnete dvě
kuličky. Jsou-li obě bílé, jednu vrátíte zpět. Pokud jste vytáhli jednu bílou a jednu černou, vrátíte do pytle
černou. jestliže jste vytáhli dvě černé, dáte do pytle místo nich jednu bílou. Předpokládáme, že máte k dispozici
neomezené množství bílých kuliček.
Každým tahem se tedy počet kuliček v pytli sníží o 1. Skončíme, když v pytli zůstává poslední kulička. Je
možné určit z počátečních hodnot B,C jednoznačně barvu poslední kuličky nebo záleží na pořadí tahů?
6. Ve dvojkovém zápisu čísla jsme některé cifry nahradili písmeny: 1a1b1c010d
Zjistěte hodnoty cifer a, b, c, d, jestliže víte, že číslo je dělitelné 6. Určete všechna řešení.
7. Na hromádce je N zápalek. 2 hráči střídavě odebírají zápalky. V jednom tahu může hráč odebrat 1,2,4 nebo 5
zápalek. Vyhraje ten, kdo odebere poslední zápalku.
a) Určete, pro jaké hodnoty N má zajištěnou výhru ten, kdo je právě na tahu.
b) Jak má postupovat, aby vyhrál.
8. Na stole leží tři zavřené krabice s ovocem. Každá krabice má popsané víko, aby bylo jasné, co je uvnitř.
Krabice označená jako JJ obsahuje dvě jablka, HH dvě hrušky, HJ hrušku a jablko.
9. Jestliže v přirozeném čtyřciferném čísle zvětšíme dvě číslice o 3 a zbývající dvě číslice zmenšíme o 4,
dostaneme dvakrát větší čtyřciferné číslo. Nalezněte všechna řešení.
Řešení
1. C je zřejmě 0, aby fungoval součet jednociferných čísel, musí být B 1. Pak A je 9,
10=2E, tedy E je 5 a D je 4.
9+1=10
- - 4+1= 5
5+0= 5
2. Každým zlomem se počet kusů zvýší o 1. Na začátku je jeden kus, po kompletním rozlámání n*m kusů. Proto
potřebujeme n*m-1 zlomů, na jejich pořadí nezáleží.
3. Kuličky rozdělíme na tři trojice, dvě trojice porovnáme. Buď je trojice obsahující nejtěžší kuličku jedna
z nich, nebo ta třetí. (První vážení)
Z vítězné trojice vezmeme dvě kuličky a porovnáme.dtto (Druhé vážení)
4. Součet čísel je 45. Má-li být výsledek o 12 menší, musí součet čísel, před kterým je mínus dát 6..
Možnosti: 1,2,3, 2,4, 6, 1,5
(x+y=45, x-y=33, 2x =12)
Bílé a černé kuličky
Vytažením dvou bílých kuliček ubyde jedna bílá, počet černých se nezmění.
Vytažení černé a bílé ubyde bílá, počet černých se nezmění.
Vytažením dvou černých přibyde bílá, ubydou dvě černé.
Protože černé kuličky mohou ubývat jen po dvou, byl-ĺi jejich počet původně sudý, nemohou zbýt a poslední
kulička je tedy bílá. Pokud byl počet černých kuliček původně lichý, zbyde černá kulička.
Zápalky
Pozice ve hře je dána počtem zápalek na hromádce. Pozici nazveme vyhranou, může-li si hráč na tahu vynutit
výhru. Pozice, které nejsou vyhrané, nazveme prohrané.
Prohrané jsou právě ty pozice, kdy je počet zápalek dělitelný třemi.
Důkaz:
1. Je-li na hromádce 0 zápalek, hráč na tahu prohrál.
2. Z libovolné pozice, v níž je zápalek dělitelný třemi, se libovolným povoleným tahem dostáváme do pozice,
v níž počet zápalek není dělitelný třemi.
3. Z libovolné pozice, kdy počet zápalek na hromádce není dělitelný třemi. Stačí odebrat tolik zápalek, kolik je
zbytek počtu ve výchozí pozici o dělení třemi.
PDF created with pdfFactory trial version www.pdffactory.com
Ovoce
Majitel musí sáhnout do krabice s víkem HJ. Vytáhne-li hrušku, jsou v krabici dvě hrušky, v krabici JJ tedy musí
být hruška a jablko a v krabici HH dvě jablka.
Analogicky, vytáhne-li jablko, jsou v krabici dvě jablka, v krabici HH tedy musí být hruška a jablko a v krabici
JJ dvě hrušky.
Dvojková soustava
Aby číslo bylo dělitelné 2, d = 0.
Pak potřebujeme, aby bylo dělitelné třemi.
Převedeme do desítkové soustavy:
676 + 256 a + 64 b + 16 c
Každé z čísel 676, 256, 64 a 16 dává při dělení třemi zbytek 1, proto dvě z cifer a,b,c mohou být rovny 1 a třetí
musí být nula.
Takže úloha má tři řešení.
a=1 b=1 c=0 d=0
a=1 b=0 c=1 d=0
a=0 b=1 c=1 d=0
Přirozené čtyřciferné číslo
Hledané číslo označíme x. Aby se x zvětšilo, musíme zvětšit první cifru.
1. Zvětšíme 1. a 2. cifru. x se zvětší o 3300 a zmenší o 44.
x + 3300 –44 =2x x=3256
2. Zvětšíme 1. a 3. cifru.
x + 3030 – 404 = 2x x=2626
4. Zvětšíme 1. a 4. cifru.
x + 3003 – 440 = 2x x=2563
2. Dephi – úvod do prostředí, Object Pascal – úvod do syntaxe
Object Pascal
Kdybyste si chtěli vytvořit nový jazyk, potřebujete abecedu, na lexikální úrovni slovník a syntaxi – pravidla, jak
ze slov vytvářet věty. V našem kurzu nebudeme podrobně popisovat jazyk Object Pascal, ve kterém budeme
programovat, detaily si můžete najít v nápovědě Delphi. (viz dále)
Abeceda
• Písmena latinské abecedy bez „nabodeníček“
• Číslice desítkové a šestnáctkové soustavy (0 až 9, A až F)
• Speciální symboly: operátory, závorky, vyhrazená slova
Vyhrazená (klíčová) slova
Nemohou být změněna, jejich význam je předem dán.
Příklady: and, array, …if, ….while, ……with, xor
Při psaní kódu editor vyhrazená slova píše obvykle odlišně.
Lexikální jednotky
• Identifikátory
• Čísla
• Návěští
• Řetězce
• Komentáře
V programu se oddělují mezerami, oddělovačem řádků, komentáři.
Identifikátor
Je pojmenování nejrůznějších objektů (proměnných, procedur, programů…). Tvoří ho posloupnost písmen a
číslic, nemůže obsahovat mezeru (U víceslovných jmen můžeme jako oddělovač použít podtržítko nebo velká
první písmena) a může být libovolně dlouhý, prvních 255 znaků je významných pro rozlišení. Tak dlouhé názvy
PDF created with pdfFactory trial version www.pdffactory.com
nejspíš používat nebudete, ale měte na paměti, že vhodné pojmenování objketu snižuje čitelnost a přehlednost
programu.
Příklady: A1, Pole_cisel, PrvniMaximum
Číslo
Je číselná konstanta, rozlišujeme reálná čísla a celá čísla. (Jinak se ukládají v paměti počítače a umožňují některé
odlišné operace)
Šestnáctková čísla začínají znakem $.
Čísla mohou mít znaménko, reálná čísla se zapisují buď v desetinném tvaru s tečkou nebo ve vědecké notaci.
(viz. Excel)
Příklady: 45, -2500, 3.1458
Vědecká notace:
12* 1010 zapíšeme jako 12 E 10
4,2*10-5 zapíšeme 4.2E-5
Některé operace s celými čísly +, - , * , div – operátor celočíselného dělení (45 div 10=4), mod – operátor zbytku
po celočíselném dělení: (45 mod 10 = 5)
Některé operace s reálnými čísly +, - ,* /,
Některé funkce:
Sqr(x) x2
pro celé číslo x je výsledek celé číslo, pro reálné čísolo reálné.
Sqrt(x) √x
výsledek vždy reálné číslo
Abs(x) |x|
pro celé číslo x je výsledek celé číslo, pro reálné čísolo reálné.
Sin(x), cos(x)
výsledek vždy reálné číslo, sinx,cosx
Trunc(x)
výsledek celé číslo – celá část čísla (Trunc(3.9)=3)
Round(x)
zaokrouhlení, výsledek celé číslo
Pi
konstanta – Ludolfovo číslo
Výrazy
Priorita operátorů je podobná jako v matematice, stejně jako v Excelu se používají pouze kulaté závorky, které
lze vnořovat.
Řetězce
Jsou posloupnosti 0 až více znaků rozšířeného kódu ASCII, uzavřených mezi dvěma apostrofy. Apostrofy uvnitř
řetězce je třeba zdvojit.
Příklady:
‘Mám hlad.’
‘You’’ll come’
Kontrolní znaky se vkládají pomocí # a čísla ASCII kódu. (#13 – oddělovač řádků)
Délkou řetězce je počet znaků.
Řetězce můžeme spojovat znaménkem +. (‘3’+’4’=’34’)
Prázdný řetězec jsou dva apostrofy vedle sebe.
Komentáře
Jsou překladačem ignorovány a slouží především k lepší čitelnosti programu. Víceřádkové se vkládají do
složených závorek nebo závorek s hvězdičkami, jednořádkové mohou začínat dvěma lomítky.
Příklady:
{Jakýkoli text, který neobasahuje pravou složenou závorku
****************************************************}
(*Jakýkoli text, který neobasahuje pravou složenou závorku
*************************************************** *)
// jakýkoli text do konce řádku
Programový celek
Může být program, podprogram (procedura, funkce), programová jednotka (unit), projekt.
Struktura je vždy podobná:
Hlavička s identifikátorem;
Deklarační část;
Begin Příkazová část
End.
PDF created with pdfFactory trial version www.pdffactory.com
Delphi
Slouží k rychlému a snadnému vývoji aplikací pro Windows. Poskytuje vizuální, objektově orientované a
komponentově založené prostředí pro tvorbu programů (včetně databázových a webových aplikací, DLL
knihoven apod.)
Vizuální
Uživatelské rozhraní svých programů můžeme vytvářet pouhým přetažením objektů (tlačítek, rozvíracích
roletek, editačních políček…) na formulář.
Objektově orientované
Budeme nejen programovat vlastní třídy, ale také s využitím dědičnosti upravovat komponenty Delphi a vytvářet
komponenty vlastní.
Komponenty
Uživatel má k dispozici knihovnu vizuálních komponent, běžně užívaných ve Windows, kterou může navíc
rozšiřovat a upravovat.
IDE
Integrated development environment – je integrované vývojové prostředí, díky kterému můžeme užívat všechno,
co Delphi nabízejí.
Při prvním spuštění programu se otevře okno programu s formulářem připraveným pro novou aplikaci.
Shora:
Hlavní nabídka
Vlevo – panel nástrojů pro často užívané příkazy, vpravo – paleta komponent (vše uživatelsky
konfigurovatelné)
Vlevo – inspektor objektů , vpravo navrhář formuláře a editor kódu.
V novějších verzích Delphi bývají další okna. (Project Manager. Object Tree View…)
Inspektor objektů
Obsahuje dvě záložky – Properties (vlastnosti) a Events(události), jejichž pomocí nastavujeme vlastnosti
komponent (například rozměry tlačítka) a programujeme události. (Co se stane, když klikneme na tlačítko)
Některé vlastnosti v době návrhu můžeme měnit myší (rozměry), jiné přímo zápisem. Dají se také měnit za běhu
programu, to je ovšem nutné naprogramovat.
PDF created with pdfFactory trial version www.pdffactory.com
Ahoj, lidi – návod k vytvoření první aplikace
1. File/New Application (nebo první spuštění Delphi) vygeneruje nový formulář s příslušným kódem.
2. V Inspektoru objektů (OI) klepneme do okénka Caption (popisek) a napíšeme jméno formuláře – Pozdrav.
3. File/Save All – připravíme složku, do které postupně uložíme soubor Project1 pod jménem Pozdrav.dpr a
Unit1 pod jménem Pozdrav1.pas. (Delphi do této složky uloží ještě další soubory, o jejich významu, o
struktuře unitu i projektového souboru si povíme časem) Je dobré volit vhodné názvy, abychom se
v projektu orientovali. Také si v souborech udržíme lepší přehled, když každou aplikaci (celý projekt se
šemi jeho soubory) uložíme do zvláštní složky.
4. Tažením myší umístíme na formulář tlačítko (OK).
5. V OI nastavíme Caption tlačítka na Řekni ahoj.
6. Poklepeme na tlačítko (Nebo na záložce Events zaklepeme do okénka OnClick¨) a Delphi vygenerují
proceduru, do jejíhož kódu se přesuneme.
7. Zapíšeme následující kód: showmessage (‘Ahoj, lidi!!!’);
Takže to bude vypadat takhle:
8.
Projekt spustíme zelenou šipkou na nástrojové liště nebo Run/Run – přitom se nejprve přeloží, pokud jsme
spáchali nějaké syntaktické chyby (v zápise programu), upozorní nás na ně.
Showmessage
Je procedura, která zobrazí okno se správou. Tato správa je řetězec, který v programu zapíšeme do závorek jako
její parametr. (viz výše).
Zatím tuto proceduru budeme používat pro výstup programů. Protože umí zobrazit pouze řetězec a my budeme
chtít provádět také výpočty, seznámíme se s převodními funkcemi:
IntToStr (číslo) – převede celé číslo na řetězec
FloatToStr (číslo) – převede reálné číslo na řetězec.
Příklady:
Showmessage(floattostr(sqr(2)) – zobrazí odmocninu ze dvou
Showmessage(‘Jméno:’ +’#13’+’Příjmení’) – výpis na dva řádky (+ spojí dva texty dohromady a #13 oodpovídá
odřádkování)
Showmessage(Button1.caption) – zobrazí správu s názvem tlačítka
Některé vlastnosti komponent
Caption – popisek
Color – barva (poklepnáním na barvu se spouští Colordialog, známý např. z Malování, když si mícháte vlastní
barvy)
Font – font (klepnutím na tlačítko s třemi tečkami vlevo se otevře typický FontDialog, kde se dají nastavit různé
vlastnosti písma
Height – výška
Hint – text bublinkové nápovědy (Zobrazuje se, je-li nastaveno ShowHint na True)
Left – vzdálenost levého horního rohu od levého okraje nadřazeného prvku (pro formulář obrazovka)
PDF created with pdfFactory trial version www.pdffactory.com
Name – identifikátor (nemění se když změníme caption, naopak ano)
Top – vzdálenost levého horního rohu od horního okraje nadřazeného prvku (pro formulář obrazovka)
Width – šířka
Práce s vlastnostmi komponent za běhu programu:
JménoKomponenty.vlastnost
Příklady:
Form1.caption – popisek formuláře
Showmessage(‘Tlačítko se jmenuje ‘+ button1.caption)
Nápověda
Help – volíme položku z obsahu, nebo zapíšeme vyhledávaný objekt v rejstříku.
Pokud nastavíme kurzor na rezervované slovo v kódu a stiskneme F1, dostaneme nápovědu o jazyce. V Object
inspektoru podobně získáme nápovědu o vlastnostech komponenty.
Klávesové zkratky
F1 – help
F9 – spuštění programu
F12 – přepíná mezi formulářem a editorem kódu
F11 – zobrazení inspektora objektů (OI)
Cvičení
Každý projekt uložte do zvláštní složky.
1. První projekt – tlačítka
Vložte na formulář tři tlačítka a pojmenujte je lidskými jmény. Při klepnutí na libovolné z nich by se měla
objevit zpráva: Zdraví tě a název tlačítka.
Připojte čtvrté tlačítko, které změní popisek formuláře na jména všech tří tlačítek za sebou, oddělená čárkami..´
2. Druhý projekt – počty
Zobrazte výslednou hodnotu výrazů: (Každou jako reakci na stisknutí
tlačítka) Cílem je naučit se s výrazy pracovat, výsledky si kontrolujte
ručně)
400
10 −6
1 + 11
2.
3
4
1.
3. celá část (2*π*100)
4. Zbytek po celočíselném dělení 100: 3
Třetí projekt.
Po stisknutí tlačítka se zobrazí zpráva s více řádky.
Řešení
1.
…
procedure TForm1.Button3Click(Sender: TObject);
begin
showmessage('Ahoj '+button3.caption);
end;
procedure TForm1.Button4Click(Sender: TObject);
begin
form1.caption:=button1.Caption+', '+button2.Caption+', '+button3.Caption;
end;
PDF created with pdfFactory trial version www.pdffactory.com
procedure TForm1.Button1Click(Sender: TObject);
begin
Showmessage(
FloatToStr(sqrt(400/1E-6)))
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
Showmessage(
FloatToStr((1+11)/(3/4)))
end;
procedure TForm1.Button3Click(Sender: TObject);
begin
Showmessage(
IntToStr(trunc(2*pi*100)))
end;
procedure TForm1.Button4Click(Sender: TObject);
begin
Showmessage(
IntToStr(100 mod 3))
end;
3. – viz příklad v textu
3. Proměnná a její deklarace, přiřazovací příkaz
Proměnná a její deklarace
Jako v matematice, i v programování budeme potřebovat pracovat s proměnnou, tedy s objektem, jehož hodnota
není konstantní, ale může se měnit. Proměnnou si představujeme jako symbolické označení místa v paměti
počítače, kde je uložena její hodnota. Každá proměnná má přiřazen identifikátor – jméno.
Jestliže budeme pracovat s proměnnou, která obsahuje číslo, bude zabírat jinak velký úsek paměti a budeme s ní
moci provádět jiné akce, než například s řetězcem, je tedy zřejmé, že každá proměnná musí být určitého typu.
(V Delphi sice existuje typ variant, do něhož se vejde cokoliv, ale jeho používání je nehospodárné vzhledem
k paměti a navíc zdržuje dobu výpočtu)
Identifikátor a typ proměnné specifikujeme v deklarační části programu.
Var x,z: Real;
x, z budou reálné proměnné, budeme pro ně tedy např. moci používat operátor /.
Index: Integer;
celočíselná proměnná
Jmeno: String;
proměnná typu řetězec
S deklarací je dán nejen typ proměnné (a tedy jakých hodnot může nabývat a co s ním můžeme dělat), ale také
programový celek (procedura, unit…), kde se s proměnnou dá pracovat.
Přiřazovací příkaz
Příkazové konstrukce zapisujeme do příkazové části programu – mezi begin a end a oddělujeme je středníky.
Hodnotu proměnné můžeme měnit buď načtením (dále) nebo pomocí příkazu přiřazení. V Delphi má tvar
Proměnná := výraz;
(:= je operátor přiřazení)
Nejprve se vyhodnotí výraz na pravé straně, pak se získaná hodnota uloží do proměnné nalevo.
Zřejmě výraz musí být stejného typu jako proměnná. (Výjimkou je celočíselná hodnota, kterou můžeme přiřadit
do reálné proměnné)
Příklady (s výše deklarovanými proměnnými)
x:=2*pi;
Index:=20;
Index:=Trunc(x); (Index bude mít hodnotu 6)
Index:=Index+1; (Index bude mít hodnotu 7, tímto příkazem zvětšíme jeho hodnotu o jedničku)
Jmeno:=‘BAF‘;
Jmeno:=Jmeno+IntToStr(Index); (Jmeno bude mít hodnotu ‘BAF7‘)
PDF created with pdfFactory trial version www.pdffactory.com
Editační políčko, Edit
Nejdůležitější vlastností všech komponent je jejich identifikátor, vlastnost Name.
Abychom mohli zajistit také vstup našich programů, budeme (zatím) potřebovat další komponentu, známou
z Windows – editační políčko. (Edit). Nalezneme ji jako čtvrtou na paletě komponent Standard a umístíme na
formulář podobně, jako tlačítko.
V inspektoru objektů si povšimneme kromě některých známých vlastností (width, height, name) vlastnosti Text,
která obsahuje text zapsaný do políčka a je typu řetězec.
Jestliže se políčko jmenuje Edit1, k jeho textu se dostaneme pomocí tečkované notace – Edit1.text. (Pokud ho
přejmenujeme – name – třeba na Vstup, bude to Vstup.text)
Příklad 1. – varianta pozdravu.
Na formulář umístíme komponenty Edit a Button. Name Editu nastavíme na Vstup, name tlačítka na Akce. Do
události Form1.AkceClick zapíšeme kód:
procedure TForm1.AkceClick(Sender: TObject);
{Pozdravna procedura}
var pozdrav:string;
begin pozdrav:='Zdraví tě '+ Vstup.Text;
showmessage(pozdrav);
Vstup.clear;
end;
Poznámky:
• Jako komentář obvykle zapisujeme potřebné informace o programu
• Komponenty mají kromě událostí také metody – metoda editačního políčka Clear políčko vyprázdní. Volá
se rovněž s tečkovanou notací.
• Všimněte si, že jako argument příkazu Showmessage vystupuje proměnná pozdrav, která obsahuje řetězec,
nikoliv řetězcová konstanta v apostrofech.
• Do této události tlačítka se dostaneme také poklepáním na tlačítko, protože je to událost pro tuto
komponentu implicitní.
Příklad 2.
Měli bychom vypočítat obsah kruhu a délku kružnice, ze zadaného poloměru.
Abychom mohli užít editační políčko ke vstupu čísel, potřebujeme konverzní funkce, které převedou řetězec na
reálné (StrToFloat(x)) nebo celé číslo. (StrToInt(x))
StrToInt(‘34’) převede řetězec na celé číslo 34
StrToFloat(‘3.14‘) převede řetězec na reálné číslo 3.14.
procedure TForm1.Button1Click(Sender: TObject);
{vstup: polomer, vystup obvod a obsah, vse realna cisla}
var r,O,S:real;
begin r:=StrToFloat(Edit1.text);
{Nacteni vstupu, prirazeni realneho cisla do polomeru}
O:=2*pi*r;
S:=pi*sqr(r);
{vypocty}
Showmessage('S= '+FloatTostr(S));
Showmessage('O= '+FloatTostr(O));
{zobrazeni vysledku}
end;
Priklad 3.
Na vstupu jsou odvěsny pravoúhlého trojúhelnika, chceme vypočítat jeho obsah a obvod.
procedure TForm1.Button1Click(Sender: TObject);
{vstup: a,b, vystup obvod a obsah, vse realna cisla}
var a,b,c,O,S:real;
begin a:=StrToFloat(Edit1.text);
b:=StrToFloat(Edit2.text);
{Nacteni vstupu, prirazeni realneho cisla )
PDF created with pdfFactory trial version www.pdffactory.com
c:=sqrt(sqr(a)+sqr(b));
O:=a+b+c;
S:=a*b/2;
{vypocty}
Showmessage('S= '+FloatTostr(S));
Showmessage('O= '+FloatTostr(O));
{zobrazeni vysledku}
end;
Příklad 4.
Na vstupu je údaj v milimetrech, chceme ho převést na metry, centimetry a milimetry.
(1205mm=1 m 20 cm 5 mm)
procedure TForm1.Button1Click(Sender: TObject);
{vstup: a,b, vystup obvod a obsah, vse realna cisla}
var VstupMm, VystupMm, Cm, M:integer;
vysledek:string;
{vysledek slouzi k vytvoreni odpovedi pred zobrazenim}
begin VstupMm:=StrToInt(Edit1.text);
{Nacteni vstupu, prirazeni realneho cisla do polomeru}
M:=VstupMm div 1000;
VystupMm:= VstupMm mod 1000; {Dale budeme zpracovavat zbyle mm}
Cm:= VystupMm div 10;
VystupMm:=VystupMm mod 10;
{vypocty}
vysledek:=IntTostr(VstupMm)+'mm ='
+IntToStr(m)+ 'm +'
+IntToStr(Cm)+'cm + '+ IntToStr(VystupMm)+'mm';
Showmessage(vysledek);
{zobrazeni vysledku}
end;
Cvičení
Napište programy, které vypočítají pro zadané vstupní hodnoty požadované hodnoty výstupní.
1. Vstup: strany obdélníka, výstup: obvod, obsah, úhlopříčka
2. Vstup: strana krychle, výstup: povrch, objem, tělesová úhlopříčka, stěnová úhlopříčka
3. Vstup: dva odpory, výstup hodnota celkového odporu při paralelním a sériovém zapojení.
4. Vstup: rychlost v metrech za sekundu (reálné číslo), výstup: rychlost v kilometrech za hodinu.
5. Vstup: poloměr a výška válce, výstup: objem a povrch
6. Vstup: údaj v hodinách (celé číslo), výstup: údaj ve dnech a hodinách
Řešení:
(Výpisům chybí jednotky, dotáhněte to k dokonalosti sami)
1.
var a,b,u,S,o:real;
begin a:=StrToFloat(Edit1.Text);
b:=StrToFloat(Edit2.Text);
o:=2*(a+b);
S:=a*b;
u:=sqrt(sqr(a)+sqr(b));
showmessage
('S= '+FloatTostr(S)+#13+
'o= '+FloatTostr(o)+#13+
'u= '+FloatTostr(u)+#13)
end;
2.
var a,us,ut,S,V:real;
begin a:=StrToFloat(Edit1.Text);
PDF created with pdfFactory trial version www.pdffactory.com
V:=a*a*a;
S:=6*a*a;
us:=sqrt(2)*a;
ut:=sqrt(3)*a;
showmessage
('V= '+FloatTostr(V)+#13+
's= '+FloatTostr(S)+#13+
'us= '+FloatTostr(us)+#13+
'ut= '+FloatTostr(ut)+#13)
end;
3. var R1,R2,RS,RP:real;
begin R1:=StrToFloat(Edit1.Text);
R2:=StrToFloat(Edit2.Text);
RS:=R1+R2;
RP:=R1*R2/(R1+R2);
showmessage
('RS= '+FloatTostr(RS)+#13+
'RP= '+FloatTostr(RP)+#13)
end;
4.
var ms,kmh: real;
begin ms:=StrToFloat(Edit1.Text);
kmh:=ms*3.6;
showmessage
(FloatToStr(ms)+' m/s = '+FloatTostr(kmh)+'km/h');
end;
5.
var r,vy,S,V,podst:real;
begin r:=StrToFloat(Edit1.Text);
vy:=StrToFloat(Edit2.Text);
podst:= pi*sqr(r);
S:=podst+2*pi*r*vy;
V:=podst*vy;
showmessage
('V= '+FloatTostr(V)+#13+
'S= '+FloatTostr(S)+#13)
end;
6.
var h,dny: integer;
begin h:=StrToInt(Edit1.Text);
dny:=h div 24;
h:=h mod 24;
showmessage
('dny= '+FloatTostr(dny)+#13+
'hodiny= '+FloatTostr(h)+#13)
end;
4. Složený příkaz, deklarace konstanty
Někdy budeme potřebovat, aby několik následujících příkazů figurovalo jako celek. (Například vykonalo se za
určité podmínky). Potom tuto posloupnost příkazů uzavřeme mezi příkazové závorky – begin a end.
Příklad: Výměna obsahu dvou proměnných a, b (Obsah dvou skleniček a,b přelévám přes další prázdnou
skleničku pom)
Begin
Pom:=A;
A:=B;
PDF created with pdfFactory trial version www.pdffactory.com
B:=Pom;
End;
Poznámka: takto se dá vyměnit obsah proměnných libovolného typu, u čísel si můžeme třetí proměnnou ušetřit:
Begin
Předpokládejme, že A=3, B=4
A:=A+B;
A=7
B:=A -B;
B=3
A:=A-B;
A=4
End;
Deklarace konstanty
Pracujeme-li v programu s konstantami, (např. hmotnost elektronu ), stane se program čitelnějším a rychleji
upravitelnějším, když hodnotu nahradíme jejím identifikátorem. Deklarace konstanty se provádí v deklarační
části programu a uvádí vyhrazeným slovem const
Const Me=9.1E-31;
Pozdrav=’Ahoj, můj nejmilejší uživateli’;
Pocet=100;
Var x:real; n:integer;
…..
Begin x:=Me*1000;
writeln(Pozdrav);
Počet:=Počet+1;
End;
Také Delphi pracují s konstantami, například při definici barev clRed – červená, clBlue – modrá…)
Komponenta Label
Je třetí zleva na (písmenko A) na paletě komponent Standard a využívá se především její vlastnost Caption,
která obsahuje řetězec. Používá se jako informační popisek.
Změna vlastností komponent za běhu programu
Každá komponenta má identifikátor – Name. Delphi volí identifikátor podle typu komponenty a pořadí, ve
kterém byla vložena na formulář. Např. ptro tlačítka Button1, Button2… Pokud jich máme na formuláři více, je
vhodné vlastnost Name změnit, abychom se v nich vyznali. Většinou se při pojmenování dodržuje obdobná
konvence – VstupEdit, AkceButton apod.
Na další vlastnosti komponent se pak odvoláváme pomocí tohoto identifikátoru a jména příslušné vlastnosti.
Příklady:
Form1.Color – barva formuláře
Button1.Caption – popisek tlačítka
Button1.width – šířka tlačítka
Label1.Caption – text popisku
Edit1.Text – text v editačním políčku.
Tyto vlastnosti vystupují v programu jako proměnné a jejich hodnoty jde měnit přiřazovacím příkazem:
Form1.color:=clRed;
Button1.width:=Button1.width+10; (Rozšíří tlačítko o 10 pixelů)
Label1.caption:=’Zadejte své jméno:’;
Cvičení:
1.
2.
3.
4.
5.
Vstup: počet vrcholů n-úhelníku, výstup – počet úhlopříček
Vstup: údaj v hodinách, minutách sekundách, výstup: údaj v sekundách
Vstup: údaj v sekundách, výstup: údaj v hodinách, minutách sekundách
Vstup: Celé číslo, výstup: jeho poslední cifra
Vstup: slova – podmět, přísudek a předmět, výstup – věta sestavená ze slov v tomto pořadí a zakončená
tečkou.
Dál používejte deklaraci konstanty pro {χ} =6.67 *10-11
6. Vstup – hmotnosti a vzdálenost dvou těles, výstup – gravitační síla, kterou na sebe tělesa působí
7. Vstup – hmotnost tělesa , výstup gravitační síla, kterou na těleso působí Země na sv0m povrchu.
(Rz = 6378 km, Mz =5,983 *1024 kg – další konstanty)
8. Připravte formulář s několika tlačítky, každé ponese jméno nějaké barvy. Při stisknutí tlačítka se adekvátně
změní barva formuláře.
PDF created with pdfFactory trial version www.pdffactory.com
9.
Připravte formulář s tlačítkem, editačním políčkem a popiskem (Label). Při stisknutí tlačítka se obsah
editačního políčka zkopíruje do popisku a editační políčka se vyprázdní.
10. Připravte si formulář s tlačítkem, při každém klepnutí se tlačítko zvětší. (Na všechny strany symetricky)
Řešení:
Protože si už s výpisy a dalšími detaily programu poradíte sami, bedeme, pokud to nebude třeba, uvádět jen části
kódů.
1.
var n,p:integer;
begin n:=StrToInt(Edit1.Text);
p:=n*(n-3) div 2;
ShowMessage(IntToStr(p));
end;
2.
var ho,mi,se:integer;
…
se:=ho*3600+mi*60+se;
…
3.
var ho,mi,se:integer;
begin
se:=StrToInt(Edit1.Text);
ho:=se div 3600;
se:=se mod 3600;
mi:=se div 60;
se:= se mod 60;
ShowMessage(IntToStr(ho)+#13+
IntToStr(mi)+#13+IntToStr(se));
end;
4.
…
posleda= x mod 10;
…
5.
var podmet,prisudek,predmet.veta:string;
begin podmet:=edit1.text;
prisudek:=edit2.text;
predmet:=edit3.text;
veta:=podmet+’ ‘+prisudek+’ ‘+predmet+’.’
ShowMessage(veta);
end;
6.
const kapa=6.67E-11;
var m1,m2,r,F:real;
begin m1:=StrToFloat(edit1.Text);
m2:=StrToFloat(edit2.Text);
r:=StrToFloat(edit3.Text);
f:=kapa*m1*m2/sqr(r);
Showmessage(FloatTostr(F));
end;
7.
const kapa=6.67E-11; Mz=5.983E24;Rz = 6.378E6;
var m,F:real;
begin m:=StrToFloat(edit1.Text);
f:=kapa*m*Mz/sqr(Rz);
Showmessage(FloatTostr(F));
end;
PDF created with pdfFactory trial version www.pdffactory.com
8.
…form1.color:=clred;…{barevne konstanty nejdeme napr. ve vlastnosti color formulare}
9.
…
label1.caption:= edit1.text;
edit1.clear;
10.
begin button1.width:=button1.width+10;
button1.height:=button1.height+10;
button1.left:=button1.left-5;
button1.top:=button1.top-5;
end;
5. Podmíněné příkazy – if
Neúplný podmíněný příkaz
Má tvar:
If Podmínka Then Příkaz;
Nejprve se vyhodnotí podmínka, je-li pravdivá, provede se příkaz. V opačném případě se nestane nic. Pokud
potřebujeme, aby příkaz zahrnoval více akcí, je třeba z nich vytvořit složený příkaz uzavřením mezi klíčová
slova begin a end;
Příklad:
Do dvou editačních políček budeme vkládat čísla, přitom chceme, aby v prvním políčku bylo číslo větší nebo
rovné číslu druhému. Kdyby uživatel zadal čísla obráceně, vyměníme je.
….
Var Mensi, Vetsi:real;
Pom: String; {pro vymenu obsahu policek}
Begin Mensi:=StrToFloat(Edit1.text);
Vetsi:=StrToFloat(Edit2.text);
If mensi>vetsi
Then Begin Pom:=Edit1.text;
Edit1.text:=Edit2.text;
Edit2.text:=Pom;
End;
Úplný podmíněný příkaz
Má tvar:
If podmínka
Then Příkaz1
Else Příkaz2;
Opět se nejdřív vyhodnotí podmínka, platí-li, provede se příkaz1, jinak se provede příkaz2.
Pozor! Za Příkaz1 (tedy před klíčové slovo Else) se nepíše středník.
Příklad 1:
Vstup – reálné číslo, výstup – převrácená hodnota čísla nebo upozornění na chybné zadání v případě, že uživatel
zadá nulu.
Kromě upozornění na chybu editační políčko vymažeme a nastavíme do něho kurzor (Tomu se říká předání
zaměření – metoda SetFocus)
…
Var x, Prevrx:real;
Begin x:= StrToFloat(Edit1.text);
If x<>0
Then
Begin PrevrX :=1/x ;
Showmessage (FloatToStr(PrevrX));
PDF created with pdfFactory trial version www.pdffactory.com
End
Else Begin Showmessage(‘Prevracena hodnota k nule neexistuje’);
Edit1.Clear;
Edit1.SetFocus;
End;
Poznámka: všimněte si způsobu zápisu kódu programu a zvykněte si na dodržování pravidel:
Begin a End, které k sobě patří, píšeme pod sebe, podobně Then a Else. Příkazy, které jsou na stejné úrovni
vnoření, píšeme pod sebe, příkazy, které jsou vnořeny do jiných, odsazujeme doprava. Pak se ve svých
programech budete dobře orientovat.
Příklad 2.
Řešení lineární rovnice Ax +B = 0 v oboru reálných čísel.
procedure TForm1.Button1Click(Sender: TObject);
var a,b, x:Real;
vysl:String;
begin Label3.caption:='Rovnice: ';
Label4.caption:='Řešení: ';
a:=StrToFloat(Edit1.text);
b:=StrToFloat(Edit2.text);
Label3.caption:=Label3.caption + Edit1.text+' x + '+
Edit2.text+' = 0';
if a=0
then
if b=0
then
vysl:='Nekonecne reseni'
else
vysl:='Reseni neexistuje'
else
begin x:=-b/a;
vysl:='x = '+
FloatToStr(x);
End;
Label4.caption:= Label4.caption+ vysl;
end;
Cvičení:
Pro každou úlohu vytvořte nový projekt, co má uživatel zadat specifikujte do příslušných popisků. Nezapomeňte
všechny soubory projektu uložit vždy do nové složky.
1. Vstup: dvojice reálných čísel, výstup: převrácená hodnota k jejich součtu
2. Vstup: dvě kladná reálná čísla, strany pravoúhelníka. Výstup: Oznámení, zda se jedná o čtverec nebo
obdélník, údaje o straně (u obdélníka nejprve menší, pak větší strana), obvod, obsah a úhlopříčka
pravoúhelníka.
3. Na vstupu jsou čtyři údaje, dráha a čas prvního auta, dráha a čas druhého auta. (V km a h). Vytiskněte, které
auto je rychlejší a o kolik
Řešení
Příklad 1.
...
if x+y=0
then showmessage('nelze')
else
begin v:=1/(x+y);
showmessage(floattostr(v));
end;
PDF created with pdfFactory trial version www.pdffactory.com
Příklad 2.
....
if a=b
then
begin {ctverec}
u:=x*sqrt(2);
showmessage('ctverec'+#13+
'strana '+ Edit1.text+#13+
'uhlopricka' + FloatToStr(u));
end
else
begin {obdelnik}
if a>b
then
begin v:=a;a:=b;b:=v;
end;
u:=sqrt(sqr(x)+sqr(y));
showmessage('obdelnik'+#13+
'mensi strana '+ FloatTostr(a)+#13+
'vetsi strana '+ FloatTostr(b)+#13+
'uhlopricka' + FloatToStr(u));
end;
Příklad 3.
...
v1:=s1/t1;
v2:=s2/t2;
rozdil:=abs(v1-v2);
if v1=v2
then
showmessage('rychlost stejna')
else
begin
if v1>v2 then vysl:='Rychlejsi je prvni o '
else vysl:='Rychlejsi je druhe o ';
vysl:=vysl+floattostr(rozdil)+' km/h';
showmessage(vysl);
end;
6. Podmíněné příkazy – pokračování
Spojení obou typů podmíněných příkazů
Pokud za klíčovým slovem then následuje další if, pak je následující konstrukce:
If podmínka1
Then
If podmínka2
Then příkaz1
Else příkaz2;
chápána tak jak je zapsána – tedy:
If podmínka1
Then
Begin If podmínka2
Then příkaz1
Else příkaz2
End;
Pokud potřebujeme, aby se else vztahovalo k prvnímu then, musíme vhodně použít příkazové závorky:
If podmínka1
PDF created with pdfFactory trial version www.pdffactory.com
Then
Begin
If podmínka2
Then příkaz1
End
Else příkaz2;
Událost OnKeypress
Najdeme v Object Inspectoru například pro komponentu Edit. Má parametr Key typu char (znak – později),
Ve kterém je uložena hodnota právě stisknutého znaku v komponentě.
Můžeme ji použít například, když potřebujeme ukončit vstup údajů stisknutím klávesy Enter, jejíž ASCII kód
je 13, což používáme, dělíme-li výpisy řetězců do více řádků.
(Poznámka: Podobná událost editačního políčka t OnKeyDown generuje skutečný kód klávesy (číselný), který
není ovlivněn např. volbou klávesnice)
Příklad:
Do editačního políčka zapíšeme jméno, po stisknutí Enter se objeví pozdrav, políčko se vyprázdní a nastaví se do
něj kurzor.
procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
begin if key=#13
then begin showmessage(‘ Ahoj ‘+Edit1.text);
Edit1.clear;
Edit1.setfocus;
End;
end;
Zarovnání komponent na formuláři
Potřebujeme-li například zarovnat několik editačních políček
pod sebe levými okraji s pravidelným rozmístěním ve
svislém směru, můžeme je vybrat s klávesou Shift a použít
příkaz Align z místní nabídky. S dialogovým oknem se
pracuje podobně jako se zarovnáváním objektů v Corelu.
Pokud chceme na formulář umístit více komponent stejného
typu, můžeme trvale zamáčknout příslušné tlačítko na paletě
komponent rovněž s použitím klávesy Shift. Jeho uvolnění
pak provedeme klepnutím na tlačítko se šipkou, kterým
paleta komponent začíná.
Logické spojky
Logické výrazy v podmínkách můžeme jako v matematice spojovat logickými operátory:
And – konjunkce (a zároveň, je platná platí-li oba výroky)
Or – disjunkce (nebo, je neplatná neplatí-li ani jeden výrok)
Pozor na prioritu operátorů – největší mají multiplikativní (násobení, and), pak aditivní a nejmenší relační
(<,>...)operátory, takže je třeba používat vhodně závorky:
If ((a+b)>c) and ((b+c)>a)…
Složitější příklady na větvení programu
Rozbory příkladů budeme formulovat v jakémsi pseudojazyku – s využitím příkazů Object Pascalu a pomocných
instrukcí, které pak dále rozpracujeme do jednotlivých příkazů jazyka.
1. Řešení kvadratické rovnice v oboru reálných čísel
Rozbor:
Kvadratická rovnice je dána reálnými koeficienty a,b,c.
Ax2 +Bx +C=0
PDF created with pdfFactory trial version www.pdffactory.com
Podobně jako když v matematice řešíme rovnici s parametry, i zde musíme brát v úvahu všechny možnosti
v zadání.
If A=0
Then Řešení lineární rovnice
Else
Begin Výpočet diskriminantu;
If diskriminant=0
Then Výpočet dvojnásobného kořenu
Else
If diskriminant<0
Then Rovnice nemá řešení
Else Výpočet dvou reálných kořenů
End
2. Nalezení maxima ze tří čísel
Rozbor:
If a>b
Then Porovnáme a,c, větší je maximum
Else Porovnáme b,c, větší je maximum
3. Nalezení maxima a minima ze čtyř čísel.
Porovnáme první dvě čísla, menší uložíme do minima, větší
do maxima. Pak porovnáme druhá dvě čísla, menší s minimem,
větší s maximem
4. Vstup: tři kladná čísla. Zjistěte, zda mohou tvořit trojúhelník, jestliže ano, vypočítejte jeho obsah..
Rozbor:
If Platí pro čísla trojúhelníkové nerovnosti
Then Výpočet podle Heronova vzorce
Else Čísla nejsou strany trojúhelníka
5. Vstup dolní, horní mez intervalu a číslo. Vytiskněte, zda číslo náleží otevřenému intervalu.
Rozbor:
if dolni mez>horni mez, then výměna;
of x>=dolni mez a současně x<=horni mez…
Řešení
1.
var a, b, c, D, x1,x2:real;
if a=0 then {linearni}
begin
zprava:='Linearni rce:';
if b=0 then
if c=0 then
zprava:=zprava+'R'
else
zprava:=zprava+'zadne reseni'
else
begin
x:=c/b;
zprava:=zprava+FloatToStr(x);
end;
end
else
begin
zprava:='Kvadraticka rce:';
PDF created with pdfFactory trial version www.pdffactory.com
D:=b*b-4*a*c;
if D<0 then
zprava:=zprava+'zadne reseni'
else
if D=0 then
begin
x:=-b/(2*a);
zprava:=zprava+'Dvojnasobny koren :'+FloatToStr(x);
end
else
begin
zprava:=zprava+'dve reseni';
x1:=(-b+sqrt(D))/(2*a);
x2:=(-b-sqrt(D))/(2*a);
zprava:=zprava+#13+'Koren 1:'+FloatToStr(x1)+#13+'Koren2:'+FloatToStr(x2);
end;
end;
2.
var a,b,c,max:real;
begin …
if a>b
then if a>c then max:=a
else max:=c
else if b>c then max:=b
else max:=c;
…
end;
3.
var a,b,c,d,max,min:real;
begin …
if a>b
then
begin max:=a;
min:=b
end
else
begin max:=b;
min:=a;
end;
if c>d
then
begin if c>max
then max:=c;
if d<min
then min:=d;
end
else
begin if d>max
then max:=d;
if c<min
then min:=c;
end;
…
end;
4.
var a,b,c,Opul,S:real;
begin…
PDF created with pdfFactory trial version www.pdffactory.com
{Existenci trojuhelnika overime pomoci trojuhelnikove nerovnosti,
obsah vypocitame Heronovym vzorcem}
if ((a+b)>c) and ((b+c)>a) and((a+c)>b)
then
begin showmessage('trojuhelnik');
Opul:=(a+b+c)/2;
S:=sqrt((Opul-a)*(Opul-b)*(Opul-c)*Opul);
showmessage('Obsah: '+ FloatToStr(S));
end
else showmessage('netvori trojuhelnik');
…
end;
5. var a,b,x:real;
begin a:=StrToFloat(Edit1.text);
b:=StrToFloat(Edit2.text);
if a>b then
begin x:=a;a:=b;b:=x;
end;
x:=StrToFloat(Edit3.text);
if (x>a) and (x<b) then showmessage('je tam')
else showmessage('neni tam');
end;
7. Cykly – příkaz while
V algoritmech se často vyskytuje situace, kdy je třeba nějaký příkaz zopakovat. Potom používáme příkaz cyklu:
while Podmínka
do Příkaz;
Nejprve se ověří podmínka, pokud platí, provede se příkaz a znovu se ověří podmínka…
Je zřejmé, že má-li cyklus skončit, musí příkaz v těle cyklu zajistit, aby podmínka přestala platit.
Pokud je třeba v těle cyklu vykonat více příkazů, vytvoříme z nich složený příkaz. (begin…end)
Komponenta SpinEdit
Protože budeme často pracovat s celými čísly, můžeme pro jejich vstup používat komponentu SpinEdit, kterou
najdeme na paletě komponent Samples.Z jejích vlastností použijeme Value, což je celočíselná hodnota na
vstupu. MinValue a MaxValue omezuje rozsah vstupu, Increment je přírůstek, o který se mění Value, pokud
používáme šipky vlevo.
Příklad 1.
Zobrazte pětkrát za sebou zprávu, pokaždé u ní bude její pořadové číslo.
Rozbor: Použijeme proměnnou jako počítadlo, jejíž hodnota se při každém průchodu cyklem zvýší o jedničku.
Dalším příkazem v těle cyklu bude zobrazení příslušné zprávy.
var i:integer;
begin i:=1;
while i<=5 do
begin showmessage('baf '+inttostr(i));
inc(i);
end;
end;
Příklad 2.
Vypište všechny dělitele daného čísla.
1. verze
Budeme postupně testovat všechny adepty od 1 do daného čísla, pokud adept číslo děli, převedeme ho na řetězec
a přidáme do výstupního řetězce, který nakonec vypíšeme.
var adept,cislo:integer;vystup:string;
begin cislo:=spinedit1.value;
PDF created with pdfFactory trial version www.pdffactory.com
vystup:='Delitele: ';
adept:=1;{1. adept je 1}
while adept<=cislo do
{dokud neprobereme vsechny adepty}
begin
if cislo mod adept =0
{kdyz je cislo delitelne adeptem}
then vystup:=vystup+' '+
inttostr(adept);
{pridame ho do vystupniho retezce}
adept:=adept+1;
{prejdeme na dalsiho adepta}
end;
showmessage(vystup);
end;
Vylepšení: Dělitele můžeme hledat pouze do poloviny čísla (a číslo samo později doplnit), případně pouze do
odmocniny (Z matematiky víme, že každé složené číslo má alespoň jednoho dělitele menšího nebo rovného
odmocnině z čísla) a dělitele většího než odmocnina průběžně dopočítávat.
V původním příkladu jsme pro číslo x testovali také x adeptů. V druhém případě jich testujte pouze sqrt(x).
Příklad 2.
Celočíselné dělení: Vypočítejte podíl a zbytek při celočíselném dělení pouze pomocí odčítání, aniž byste použili
operátorů div a mod.
32 : 9:
32-9=23-9=14-9=5
Devítku jsme odečítali třikrát – a to je podíl, zbytek je 5 – číslo menší než dělitel.
Budeme tedy postupně odečítat dělitele, dokud nebude menší než to co zbyde {eventuelně roven, pokud by byl
zbytek nula) a průběžně počítat, kolikrát jsme odečítali. Jako počítadlo (podíl) použijeme opět proměnnou, jejíž
hodnota se při každém odečtení (průchod cyklem) zvětší o jedničku.
var zbytek, delitel,delenec, podíl:integer;
…
zbytek:=delenec;
podíl:=0;
While zbytek>=delitel
do
begin zbytek:=zbytek-delitel;
podil:=podil+1;
end;
Cvičení:
1. Proveďte vylepšení příkladu s výpisem dělitelů.
2. Naprogramujte výpočet největšího společného dělitele dvou čísle podle definice – jako největší číslo, které
obě dělí.
3. Naprogramujte podobně největší společný násobek dvou čísel. (nejmenší číslo, kterým jsou obě dělitelná)
Řešení:
1.
var adept,cislo,odmocnina:integer;vystup:string;
begin cislo:=spinedit1.value;
vystup:='Delitele: 1 ';
adept:=2;
odmocnina:=trunc(sqrt(cislo));
while adept<=odmocnina do
begin
if cislo mod adept =0
then vystup:=vystup+' '+
inttostr(adept)+' '+inttostr(cislo div adept)+' ';
PDF created with pdfFactory trial version www.pdffactory.com
adept:=adept+1;
end;
vystup:=vystup+' '+inttostr(cislo);
showmessage(vystup);
end;
1. lépe
procedure TForm1.Button2Click(Sender: TObject);
var adept,cislo,odmocnina:integer;vystup:string;
begin cislo:=spinedit1.value;
vystup:='Delitele: 1 ';
adept:=2;
odmocnina:=trunc(sqrt(cislo));
while adept<=odmocnina do
begin
if cislo mod adept =0
then
if (cislo div adept)<>adept then
vystup:=vystup+' '+
inttostr(adept)+' '+inttostr(cislo div adept)+' '
else
vystup:=vystup+' '+
inttostr(adept)+' ';
adept:=adept+1;
end;
vystup:=vystup+' '+inttostr(cislo);
showmessage(vystup);
end;
2.
var a,b,nsd:integer;
begin a:=spinedit1.value;
b:=spinedit2.value;
if a>b then nsd:=b
else nsd:=a;{adept je nejprve mensi z obou cisel,
pokud obe nedeli, budeme ho postupne zmensovat}
while (a mod nsd <>0) or (b mod nsd <>0) do
nsd:=nsd-1;
showmessage(inttostr(nsd));
end;
3.
procedure TForm1.Button1Click(Sender: TObject);
var a,b,nsn:integer;
begin a:=spinedit1.value;
b:=spinedit2.value;
if a>=b then nsn:=a
else nsn:=b;
while (nsn mod a <>0) or (nsn mod b <>0)
do nsn:=nsn+1;;
showmessage(inttostr(nsn));
end;
8. Cykly – příkaz repeat
V příkazu while se podmínka setrvání v cyklu testovala na začátku, většina programovacích jazyků a Delphi
rovněž, poskytují programátorovi další typ příkazu – kde se nejprve provede příkaz a poté se testuje podmínka.
Má tvar:
Repeat příkaz nebo řada příkazů
Until podmínka.;
PDF created with pdfFactory trial version www.pdffactory.com
Nejprve se provedou příkazy v těle cyklu, pak se otestuje podmínka. Je-li splněna, cyklus se ukončí, jinak se
pokračuje prováděním příkazů.
Všimněte si, že na rozdíl od while podmínka určuje ukončení cyklu.
Klíčová slova Repeat, Until mají také význam příkazových závorek, takže pokud v těle cyklu chceme provést
více příkazů, není třeba z nich vytvořit příkaz složený vkládáním mezi begin a end.
Příklad 1.
Vypočítejte součet čísel 1+2+3+….n, vstupem je n – přirozené číslo.
(Příklad je uveden z cvičných důvodů, z matematiky víme, že součet této posloupnosti jde vyjádřit vzorečkem
n/2*(1+n) ).
Rozbor: Potřebujeme do nějaké proměnné postupně přidávat čísla 1,2,…až n nebo v opačném pořadí n, n-1..až .
Při každém průchodu cyklem tedy přidáme do celkového součtu číslo – nejprve n, pak n-1… Postup budeme
opakovat, dokud přidávané číslo není rovno 0.
var n,suma:integer;
begin n:=StrToInt(edit1.text);
suma:=0;
repeat suma:=suma+n;
n:=n-1;
until n=0;
showmessage(inttostr(suma));
end;
Příklad 2.
Vypočítejte ciferný součet vstupujícího celého čísla.
Rozbor: Protože dopředu nevíme, kolikaciferné je číslo, musíme začít odzadu. Postupně vždy zjistíme poslední
cifru (operace mod 10) a číslo o ni zkrátíme. (operace div 10), až z původního čísla zbyde nula.
var n,cs:integer;
begin n:=StrToInt(edit1.text);
cs:=0;
repeat cs:=cs + n mod 10;
n:=n div 10;
until n=0;
showmessage(inttostr(cs));
end;
Trasování
je v podstatě provádění programu po jednotlivých příkazech, přičemž sledujeme, jak se mění hodnoty
proměnných. Využíváme ho zvlášť při hledání logických chyb – když program sice pracuje, ale nedává
výsledky, jaké bychom očekávali.
Dá se provádět „ručně“ – tak, že si připravíme tabulku potřebných proměnných a zapisujeme si do ní hodnoty.
Pro předchozí příklad, vstup: n=1234 by mohla vypadat takhle:
průchod cyklem
n
cs
0
1234
0
1
123
4
2
12
7
3
1
9
4
0
10
Pohodlnější ovšem je, nechat většinu práce na
počítači. Protože klasické okenní programy obvykle
čekají ve smyčce na nějakou akci uživatele, je třeba
si nejdřív nastavit body přerušení – tj. kam se dojde,
než trasování začne. Provedeme to například
kliknutím do sloupce vlevo vedle kódu programu,
objeví se tam červený puntík a řádek se červeně
vysvítí. Další kliknutí breakpoint odebere.
Sledované hodnoty si připravíme do kukátka –
okno Watch:
Run/Add Watch (Ctrl F5)
Zapisujeme každou zvlášť do políčka Expression.
PDF created with pdfFactory trial version www.pdffactory.com
Program pak spustíme a po zadání příslušné hodnoty trasujeme buď Run/Trace Into nebo stačí opakovaně
mačkat klávesu F7 a ve Watch listu sledovat. jak se mění peoměnné.
bod přerušení
co se bude provádět
dalším F7
kukátko
Porovnání cyklů while a repeat
Připomínáme, že oba cykly se liší jednak tím, že u repeatu se příkaz v těle cyklu provede vždycky, jednak tím, že
zatímco podmínka u while je podmínkou setrvání v cyklu, u repeat se jedná o podmínku opuštění cyklu.
Vyjádření while pomocí repeat:
While Podmínka do Příkaz:
If Podmínka
Then Repeat Příkaz
Until not Podmínka;
Vyjádření repeat pomocí while:
Repeat Příkaz
Until Podmínka
Begin Příkaz;
While not Podmínka do Příkazů
End;
Not je operátor negace, patří k operátorům logickým a má nejvyšší prioritu. Pozor! Uvědomte si, že negujete-li
složenou podmínku, platí:
Not (A and B) = Not A or Not B
Not (A or B) = Not A and Not B
Generátor náhodných čísel
nám poskytuje pseudonáhodná čísla, vypočítaná podle určitého algoritmu.
Random – je funkce, jejíž funkční hodnotou je desetinné náhodné číslo z intervalu <0, 1), vhodným násobenám
získáme čísla větší.
Random(p) kde p je přirozené číslo poskytuje náhodné přirozené číslo z množiny {0,1,…p-1}, chce-me-li tedy
generovat náhodná přirozená čísly v rozmezí {a..b}, použijeme
Random(b-a+1)+a.
Aby vznikající řada čísel nebyla při každém spuštění programu stejná, je třeba inicializovat generátor procedurou
randomize.
Příklad 3.:
Vygenerujte 5 náhodných čísel mezi 0 do 10, zobrazte je a vypočítejte jejich součet.
V cyklu budeme vždy generovat nové číslo, přidáme ho jednak do výstupního řetězce, jednak do proměnné
součet a navíc vždy zvýčíme hodnotu proměnné počet o jedničku, abychom věděli, kdy máme skončit.
PDF created with pdfFactory trial version www.pdffactory.com
var pocet, soucet, cislo:integer;vystup:string;
begin pocet:=0;
soucet:=0;
randomize;
vystup:='';
repeat cislo:=random(11);
soucet:=soucet+cislo;
vystup:=vystup+inttostr(cislo)+' ';
pocet:=pocet+1;
until pocet=5;
showmessage(vystup+#13+'soucet:'+
Inttostr(soucet));
end;
Mazání události komponenty
Vymažeme kód mezi begin a end a při dalším spuštění programu systém proceduru odstraní. (Pokud byste ji
vymazali celou, zůstane uvedena v deklaraci formuláře a může způsobit problémy)
Cvičení
1. Vypočítejte faktoriál vstupujícího čísla n! = 1*2*3….*n
(Pozor, hodnoty rostou velice rychle, takže může dojít k přetečení a pro větší vstup dostanete podivné výsledky.
Vyzkoušejte.)
2. Vytvořte k danému vstupujícímu číslo číslo, které má tytéž cifry, ale v opačném pořadí.
3. Vygenerujte 10 náhodných čísel a zjistěte, kolik z nich je sudých.
4. Vyzkoušejte si pomocí generátoru náhodných čísel házení kostkou. V kolikátém hodu padne poprvé šestka?
(Čísla pro kontrolu zobrazte )
Řešení:
1.
var n,i,f:integer;
begin n:=StrToInt(edit1.text);
f:=1;
i:=1;
repeat f:=f*i;;
i:=i+1;
until n<i;
showmessage(inttostr(f));
end;
2.
var n,obr:integer;s:string;
begin n:=StrToInt(edit1.text);
s:='';{pomocny retezec, do kterho si budeme
odpredu ukladat cifry usekavane z puvodniho cisla
odzadu}
repeat s:=s+IntTostr(n mod 10);
n:=n div 10;
until n=0;
obr:=strtoint(s);
showmessage(s);
end;
3. var pocet, pocsud, cislo:integer;vystup:string;
begin pocet:=0;
pocsud:=0;
randomize;
vystup:='';
repeat cislo:=random(11);
PDF created with pdfFactory trial version www.pdffactory.com
if cislo mod 2=0
then pocsud:=pocsud+1;
vystup:=vystup+inttostr(cislo)+' ';
pocet:=pocet+1;
until pocet=5;
showmessage(vystup+#13+'pocet sudych:'+
Inttostr(pocsud));
end;
4. var pocet, cislo:integer;vystup:string;
begin pocet:=0;
randomize;
vystup:='';
repeat cislo:=random(6)+1;
vystup:=vystup+inttostr(cislo)+' ';
pocet:=pocet+1;
until cislo=6;
showmessage(vystup+#13+'pocet hodu:'+
Inttostr(pocet));
end;
9. Skalární (jednoduché) typy dat
Typy dat v Object Pascalu se dají dělit podle různých hledisek – na jednoduché a strukturované, standardní a
definované programátorem, ordinální a jiné. Postupně se se všemi seznámíme.
Datový typ určuje:
• Jméno – identifikátor (Integer)
• Množina přípustných hodnot
• Množina přípustných operací
Ordinální typy:
množina hodnot je uspořádaná (od nejmenšího k největšímu), každému prvku lze přiřadit jeho pořadové
(ordinální) číslo. (Pojem pochází z matematiky, kde ordinální čísla jsou například čísla přirozená, celá nebo
racionální. Při implementaci na počítači zřejmě nemůže být množina přípustných hodnot nekonečná.)
Jsou pro ně definovány funkce:
• předchůdce – pred(x),
• následník – succ(x),
• pořadové číslo – ord(x)
• největší prvek – high(x)
• nejmenší prvek – low(x)
a procedury:
• Inc(x): x:=succ(x)
• Dec(x): x:=pred(x)
Standardní typy:
Standardní zde znamená, že je naleznete v každé implementaci Pascalu od Turbo Pascalu po Delphi.
Boolean
Množina hodnot={False, True}
Množina logických hodnot je uspořádaná – False<True, ord(False)=0, succ(False)=True.
Operace: and, or, not, xor (výlučné nebo), <= (implikace), = (ekvivalence), <> (not je oprátor negace)
Proměnná typu Boolean zabírá v paměti 1 B.
Integer
velikost záleží na procesoru – standardní Pascal v každém případě 2B, takže se dá pracovat s čísly od 32768..32767, Delphi 32bitové – 4B, odpovídá typu longint ve standardním Pascalu.
Obecně: -Maxint-1,….Maxint
PDF created with pdfFactory trial version www.pdffactory.com
Maxint je standardní identifikátor typu Integer, to, že záporných čísel je o jednu víc vyplývá z jejich
implementace ve dvojkovém doplňkovém kódu. (Ještě bude)
Prakticky se užívají podtypy – Word, Byte, Longint, Shortint aj. (Více – viz. Nápověda Delphi)
Množina hodnot – podmnožina celých čísel
Operace: +, -, *, div, mod, abs(x), sqr(x), trunc(x)
Výhodou tohoto typu je přesná aritmetika, nevýhodou možnost přetečení, pokud se výsledek nevejde do paměti.
Char
Množina hodnot: množina znaků ASCII kódu, zobrazení do 1 B (255 znaků)
Operace: <, =, <=, >=, <>
Ord(x), inverzní funkce chr(ord(x))=x
pred(x) = chr(ord(x)-1)
ord(‘A’) = 65
ord(‘B’) = 66
3=ord(‘3’) - ord(‘0’)
UpCase(‘a’) =’A’ – převede malé písmeno na velké, jinak nedělá nic. (Hodnota vstupního znaku se nemění)
Real
– je standardní, není ordinální
Množina hodnot – podmnožina racionálních čísel –2.9 e-39..1.7e-38
podtypy (single, double, extended, comp) – kromě rozsahu se liší také počtem platných číslic – real 11-12,
extended 19-20
Kromě nuly existuje strojová nula (0, minreal), pokud je výslodek výpočtu menží než minreal, počítač ho
považuje za nulu.
Reálná čísla se zobrazují s omezenou přesností, (vyplývá to jednak z jejich dvojkové reprezentace v počítači,
jednak ze skutečnosti, že případný nekonečný počet desetinných míst je nutno někde ukončit) pozor na možné
zacyklení.
Operace abs(x), sqr(x), sqrt(x), sin(x), cos(x), arctan(x), ln(x). exp(x), trunc(x), round(x), int(x)
Frac(x) – desetinná část argumentu
Konstanta Pi
Komponenta Listbox
se používá pro výstup většího množství textu. Budeme zatím využívat především její metodu
Listbox1.items.add(‘retezec’), která vloží do boxu řetězec, vždy na zvláštní řádek. Podobně jako editační políčko
má listbox metodu clear, která ho vyprázdní.
(Listbox1.clear).
Funkce Sizeof(x)
vrací velikost objektu x v bytech, takže nám pomůže zjistit, kolik paměti dané x zabírá.
Například pro x typu Boolean, je SizeOf(x)=1.
Příklad:
Vygenerujte 20 náhodných čísel od 0 do 100, zobrazte je do Listboxu a vytiskněte největší a nejměnší z nich.
Rozobor: Jak budeme číslo generovat, převedeme je vždy na řetězec a zobrazíme, přitom každé číslo porovnáme
s maximem, pokud je větší, uložíme do maxima, pokud je menší, provnáme ho ještě s minimem.
Efektivnější, ale pracnější způsob by spočíval ve zpracování čísel po dvojicích (viz maximum ze čtyř)
var x,i,min,max:integer;
begin i:=0;
randomize;
max:=low(integer);
min:=high(integer);
{inicializujeme hodnoty tak, aby v nich nemohla zustat nejaka puvodni hodnota}
repeat
Inc(i);
x:=random(100);
Listbox1.Items.Add(IntToStr(x));
if x<min
then min:=x
else if x>max
then max:=x;
PDF created with pdfFactory trial version www.pdffactory.com
until i=10;
listbox1.items.add('************');
listbox1.items.add('max='+inttostr(max));
listbox1.items.add('min='+inttostr(min));
end;
.
Cvičení
1.Umístěte na formulář editační políčko a komponentu Listbox. Po stisknutí klávesy Enter v editačním políčku,
se text přesune do Listboxu, editační políčko se vyprázdní a připraví k dalšímu psaní..
2. Umístěte na formulář tlačítko pojmenovaná Integer , na jeho stisknutí se zobrazí největší a nejmenší hodnota
daného typu a velikost typu v bytech.
3. Umístěte na formulář komponentu Label popsanou velkým číslem -10. Když na komponentu klepneme změní
se caption na následníka původního captionu. (Pokračuje pořád dál…)
4. Vygenerujte a do listboxu zobrazte řadu jednociferných čísel, poslední generované číslo bude 9.
Vypočítejte aritmetický průměr těchto čísel.
5. Vygenerujte a do listboxu zobrazte řadu 10 dvojciferných čísel. Vytiskněte o kolik je víc čísel sudých než
lichých.
Řešení
1.
procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
begin
if key=#13 then
begin Listbox1.Items.Add(edit1.text);
Edit1.clear;
Edit1.setFocus;
end;
end;
2.
procedure TForm1.Button4Click(Sender: TObject);
begin
showmessage(inttostr(low(integer)));
showmessage(inttostr(sizeof(integer)));
showmessage(inttostr(high(integer)));
end;
3.
procedure TForm1.Label1Click(Sender: TObject);
var s:string; x:integer;
begin x:=StrToint(label1.caption);
inc(x);
label1.caption:=inttostr(x);
end;
4.
procedure TForm1.Button6Click(Sender: TObject);
var x,p:integer;s:real;
begin randomize;
listbox1.clear;
s:=0;
p:=0;
repeat x:=random(10);
inc(p);
s:=s+x;
Listbox1.Items.Add(IntTostr(x));
edit1.clear;
PDF created with pdfFactory trial version www.pdffactory.com
edit1.setfocus;
until x=9;
showmessage(floattostr(s/p));
end;
5.
procedure TForm1.Button7Click(Sender: TObject);
var x,i,sud,lich:integer;
begin sud:=0;lich:=0; listbox1.clear;i:=0;
repeat
Inc(i);
x:=random(100);
Listbox1.Items.Add(IntToStr(x));
if odd(x)
then inc(lich)
else inc(sud)
until i=10;
if lich>sud then
showmessage('lichych je vic o'+ inttostr(lich-sud))
else if lich=sud then
showmessage('je jich stejne')
else
showmessage('sudych je vic o'+ inttostr(sud-lich))
end;
10. Cyklus FOR
Tento ty cyklu používáme výhradně tehdy, víme-li dopředu, kolikrát se bude opakovat.
Příklad: chceme-li do výstupního řetězce umístit 100 vykřičníků:
Var s:string;i:integer;
Begin s:=’’;
For i:=1 to 100 do s:=s+’!’
End;
Obecně:
For p:=a to b do Příkaz;
Funguje následujícím způsobem:
If a<=b then
Begin P:=a;
Příkaz;
While p<=b do
Begin inc(p);
Příkaz;
End;
End;
a – dolní mez cyklu
b – horní mez
p – řídící proměnná
Proměnné a, b a p by v průběhu cyklu neměly být měněny, dál je z předchozího popisu zřejmé, že mohou být
pouze ordinálního typu.
I když existují příkazy break a continue, které umožňují ukončit cyklus dřív, dáváme v tom případě přednost
cyklu while nebo repeat.
Pokud chceme krokovat shora dolů, (a>=b) můžeme použít variantu For cyklu:
For a downto b do Příkaz;
Priorita operací:
v Object Pascalu vychází z matematiky, pokud si nejsme jisti, používáme závorky.
1. Použití funkce a operátoru not
PDF created with pdfFactory trial version www.pdffactory.com
2. * / div mod and (multiplikativní operátory)
3. + - or xor (aditivní operátory)
4. < > =… relační operátory
Formátování reálných čísel v Delphi
Prohlédněme si nápovědu na funkci FloattostrF (F1 na slově)
function FloatToStrF(Value: Extended; Format: TFloatFormat; Precision,
Digits: Integer): string;
Tato funkce tedy převádí reálné číslo na řetězec, ale volbou parametrů můžeme ovlivnit jeho tvar.
Příklad:
Listbox1.Items.Add(floattostrf(pi,FfFixed,6,2)); vloží do Listboxu 3,14. (Digits udává počet míst za desetinnou
čárkou)
Příklady:
Příklad 1. ASCII kód:
var i:integer; ch:char;
begin
listbox1.clear;
for i:=1 to 255 do
listbox1.items.add(inttostr(i)+'...'+chr(i));
end;
Příklad 2. Tabelace funkce y=2x-1 od 0 do 1 s krokem 0.1
Protože cyklus for v Pascalu na rozdíl od některých jiných jazyků neumožňuje zvyšovat hodnotu řídící proměnné
o reálnou konstantu, použijeme pouze skutečnosti, že budeme tisknout 11 řádků tabulky. V každém kroku přitom
zvýšíme hodnotu x o 0.1, vypočítáme y a obě hodnoty vytiskneme.
procedure TForm1.Button3Click(Sender: TObject);
var i:integer;x,y:real;
begin
listbox1.clear;
listbox1.items.add('x
2*x-1');
x:=0;
for i:=1 to 11 do
begin y:=2*x-1;
listbox1.items.add(floattostrf(x,fffixed,2,2)+'
+ floattostrf(y,fffixed,2,2));
x:=x+0.1;
end;
end;
'
Příklad 3.
Vygenerujte do Listboxu řadu náhodných čísel (počet určuje konstanta) a vytiskněte největší z nich. (Počet čísel
zadejte konstantou)
Do proměnné max nejprve umístíme nejmenší záporné celé číslo, potom v těle cyklu vždy generujeme a
zobrazujeme číslo a je-li větší, ukládáme ho do proměnné max.
const n=10;
var i,max,x:integer;
begin randomize;
max:=-maxint-1;
for i:=1 to n do
begin x:=random(10);
listbox1.items.add(inttostr(x));
if x>max then max:=x;
end;
showmessage(inttostr(max));
end;
PDF created with pdfFactory trial version www.pdffactory.com
Cvičení:
1. Vypočítejte pro vstupující číslo n jeho faktoriál: n! = 1.2.3…n s využitím For cyklu
2. Tabelace funkce y = 2x-1 pomocí cyklu Repeat. (Meze zadá uživatel, krok může být opět 0.1)
3. Maximum a počet maxim (Vstup z generátoru)
Řešení:
1. var n,i,fakt:integer;
begin n:=spinedit1.value;
fakt:=1;
for i:=1 to n do
fakt:=fakt*i;
showmessage(IntTostr(fakt));
end;
2.
var a,b,x,y:real;
begin a:=StrTofloat(edit1.text);
b:=strtofloat(edit2.text);
x:=a-0.1;
repeat
x:=x+0.1 ;
y:=2*x-1;
listbox1.items.add(floattostrf(x,fffixed,2,2)+'
+ floattostrf(y,fffixed,2,2));
until x>=b;
'
end;
3.
var i,max,x,p:integer;
begin randomize;
p:=0;
max:=-maxint-1;
for i:=1 to n do
begin x:=random(10);
listbox1.items.add(inttostr(x));
if x>max then begin max:=x;
p:=1;
end
else if x=max then inc(p);
end;
showmessage(inttostr(max)+' '+inttostr(p));
end;
11. Typ interval a větvení case
Intervalový typ
Tento datový typ specifikuje neprázdnou souvislou podmnožinu hodnot nějakého ordinálního typu. Dolní a horní
mez je dána konstantami typu.
Příklady:
Type Malint=0..9;
Cifry=’0’..’9’;
Var x:Malint; y:Cifry;
X pak může nabývat hodnot celých čísel od 0 do 9, y znaků od ‘0’ do ‘9’.
Intervalový typ omezuje pouze množinu přípustných hodnot, pro objekt typu interval můžeme používat všechny
operace a funkce jako pro jeho hostitelský typ. (V tomto případě Integer a Char)
PDF created with pdfFactory trial version www.pdffactory.com
Poznámka: Delphi kontrolují dodržování hodnot, pokud je program přeložen s direktivou $R+ – zapnuta kontrola
rozsahu hodnot (range checking), jinak má použití tohoto typu význam spíš pro čitelnost a srozumitelnost
programu.
Větvení case
Je další variantou podmíněného příkazu, používá se tam, kde potřebujeme víc vnořených příkazů IF.
Může mít tvar:
Case Výraz of Hodnota1: Příkaz1;
Hodnota2: Příkaz2;
…….
HodnotaN: PříkazN;
End;
Nebo:
Case Výraz of Hodnota1: Příkaz1;
Hodnota2: Příkaz2;
…….
HodnotaN: PříkazN;
Else
JinýPříkaz;
End;
Výraz musí být ordinálního typu, pokud nabývá hodnoty H1, provede se příkaz Příkaz1 atd. Else použijeme,
pokud chceme, aby se JinýPříkaz provedl, když výraz nenabývá žádné z hodnot H1 až Hn.
Kromě jednotlivé hodnoty v příkazu Case můžeme použít interval nebo několik hodnot, oddělených čárkami.
Přepínací tlačítko (Radiobutton)
Najdeme na paletě komponent
Standard, důležitá je jeho vlastnost
checked, typu boolean, která udává,
zda je tlačítko zaškrtnuto.
If Radiobutton1.checked then…
Pokud na tlačítko klepneme myší,
změní se hodnota checked a
generuje se událost OnClick.
Pokud chceme totéž provozovat bez
zásahu uživatele, stačí do kódu
programu napsat:
Radiobutton1.checked:=not
Radiobutton1.checked
Tato tlačítka se většinou sdružují do
skupin, z nichž může být vybráno
pouze jedno. Potom můžeme
s výhodou použít komponentu
Radiogroup, rovněž z palety
komponent Standard.
Seznam tlačítek je uložen ve
vlastnosti Items a můžeme ho vytvářet a upravovat pomocí String List Editoru., který se spustí, když klepneme
na tlačítko s třemi tečkami vedle položky Items. Skupina umožňuje výběr jediného tlačítka, jehož číslo (počítáno
od nuly) je ve hodnotou vlastnosti ItemIndex.
Chceme-li např. vybrat tlačítko za vybraným:
Radiogroup1.ItemIndex:= Radiogroup1.ItemIndex+1
Větvení programu podle zaškrtnutého políčka:
case radiogroup1.itemindex of 0: p1;
1: p2;
…
n: pn;
end;
Není-li vybráno žádné tlačítko, jei ItemIndex = -1.
PDF created with pdfFactory trial version www.pdffactory.com
Zaškrtávací políčko (Checkbox)
Zde je povolen výběr více políček, pro indikaci výběru můžeme opět použít vlastnost checked, navíc lze využít
vlastnosti state, která má tři stavy: cbChecked (vybrané), cbUnChceked (nevybrané) cbGrayed (podšeděné),
pokud je vlastnost Alowgrayed nastavena na true.
Dají se sdružovat pomocí komponenty GroupBox. (dále)
Příklady:
1. Napište program pro výpočet jízdného. Vstupovat bude délka cesty v celých km, cenü za km definuje
následující tabulka:
Vzdálenost
Cena za km
0..19
15
20..30
12
31..50
10
více než 50
8
var zakm,km,cena:integer;
begin km:=spinedit3.value;
case km of 0..19: zakm:=15;
20..30: zakm:=12;
31..50: zakm:=10;
else zakm:=8;
end;
cena:=km*zakm;
showmessage(inttostr(cena));
end;
Zadání pásem vzdáleností můžeme řešit pomocí komponenty radiogroup, kde si uživatel pásmo vybere.
var cena:integer;celkem,km:real;
begin case radiogroup1.itemindex of 0:cena:=15;
1:cena:=20;
2:cena:=10;
3:cena:=8;
end;
km:=StrToFloat(edit1.text);
celkem:=cena*km;
showmessage(floattostr(celkem));
end;
2. Vstupem jsou dvě celá čísla, výstupem je správa, zda je jedno z nich dělitelné druhým. Dělenec zadejte
pomocí spineditu, možné dělitele radiogroupem. (2,3,4,5,6,…)
Pokud tvoří dělitelé souvislou řadu přirozených čísel, můžeme s výhodou použít vlastnosti ItemIndex.
var x,y:integer;
begin
x:=spinedit2.value;
y:=radiogroup2.itemindex+2;
if x mod y = 0 then showmessage('dělí')
else showmessage('nedělí')
end;
3. Uživatel si může zaškrtnutím políčka vybrat některá čísla z nabídky, po stisknutí tlačítka se zobrazí jejich
součet.
var sum:integer;
begin sum:=0;
if checkbox1. checked
then sum:=sum+strtoint(checkbox1.caption);
if checkbox2. checked
then sum:=sum+strtoint(checkbox2.caption);
PDF created with pdfFactory trial version www.pdffactory.com
…..
Toto (nepěkné) řešení jde elegantně zjednodušit, pokud použijeme pole komponent a přetypování proměnných –
dále.
Cvičení
1. Vstupem je měsíc, výstupem počet dnů v něm. (Pro vstup použijte komponentu Radiogroup).
2. Vstupem jsou body za test (Intervaly hodnocení si vymyslete), výstupem známka
3. Modelujte pomocí generátoru náhodných čísel vrh kostou, počet hodů zadá uživatel. Vytiskněte jednak
výsledky jednotlivých vrhů, jednak kolikrát co padlo.
Řešení:
1.
var pocet,rok:integer;
begin
case radiogroup1.itemindex of
0,2,4,6,7,9,11:pocet:=31;
1: begin rok:=spinedit1.value;
if rok mod 4=0 then pocet:=29
else pocet:=28
end;
else pocet:=30;
end;
showmessage(inttostr(pocet));
end;
Poznámka: Ve skutečnosti jsou přetsupná celá staletí pouze, když jsou dělitelná 400.
2.
Jednodušší varianta jízdného
3.
var i,hod,p1,p2,p3,p4,p5,p6:integer;
begin
randomize;
p1:=0;p2:=0;p3:=0;p4:=0;
p5:=0;p6:=0;
for i:=1 to 20 do
begin hod:=random(6)+1;
listbox1.items.add(inttostr(hod));
case hod of 1:inc(p1);
2:inc(p2);
3:inc(p3);
4:inc(p4);
5:inc(p5);
6:inc(p6);
end;
end;
showmessage('1: '+inttostr(p1)+#13+
'2: '+inttostr(p2)+#13+
'3: '+inttostr(p3)+#13+
'4: '+inttostr(p4)+#13+
'5: '+inttostr(p5)+#13+
'6: '+inttostr(p6));
end;
12. Správnost a efektivnost algoritmu
Úplná správnost: Algoritmus skončí a řeší daný problém.
Parciální správnost: Pokud algoritmus skončí, řeší daný problém.
PDF created with pdfFactory trial version www.pdffactory.com
Dokázat obecně správnost algoritmu je záležitost více matematická a teoreticky obtížná. Proto obvykle
algoritmus testujeme – tedy realizujeme pro nějaké vstupní hodnoty. Cílem testování je spíš nalézt chyby, pokud
nemůžeme takto otestovat celou množinu možných vstupních hodnot, nejedná se o důkaz správnosti.
Časová a paměťová složitost, optimalizace
Ze dvou algoritmů řešících stejnou úlohu je časově efektivnější ten, jehož realizace vyžaduje méně
porovnatelných kroků. (Měl by trvat kratší dobu)
Paměťově efektivnější algoritmus ptřebuje méně místa. (např. proměnných)
Přesněji chápeme časovou a paměťovu složitost algoritmu jako funkci, která velikosti problému (např. počet
vstupujících prvků) přiřazuje počet operací vykonaných při výpočtu.
Rozlišujeme časovou složitost v nejhorším (případně nejlepším) případě a v průměrném případě (hůře se určuje).
Pokud není předem udána velikost vstupních dat, uvažujeme n hodně velké. (např. lineární složitost 10n >
kvadratická n*n do 10) Pro malá data jde totiž prakticky použít i horší algoritmus.
Pro ona velká data pak hovoříme o asymptotické časové složitosti.
Například používáme zápis O (n2), pokud je počet operací 2n2 + 3n +100. V případě polynomu tedy určuje tuto
složitost člen s nejvyšší mocninou n.
V praxi užívané algoritmy mají většinou složitost O(n2), O(n), O(logn),…(kvadratický, lineární, logaritmický…)
Polynomiální – složitost jde omezit polynomem.
Exponenciální – s vyšší složitostí, často O(2n), pokud je n>50, jsouž prakticky nepoužitelné.
Optimalizace – úprava algoritmu na efektivnější tvar.
Několik optimalizačních pravidel:
• Neprovádět v cyklu opakovaně to, co jde provést před ním (Vyjímání před cyklus)
• Optimalizace těla cyklu
• Spojování cyklů, je-li to možné
• Využívání předchozích výsledků
• Metoda Rozděl a panuj (dále)
• Využívání zvláštností aritmetiky počítačů (díky binární reprezentaci dat v počítači jsou operace dělení,
násobení dvěma a test na sudost rychlejší než běžné aritmetické opeace)
• Rychlé vyhodnocování logických výrazů
• Speciální vlastnosti problému (Euklidův algoritmus)
Pozor na zachování čitelnosti a srozumitelnosti programu při optimalizaci.
Příklady:
Naprogramujte výpočet největšího společného dělitele dvou čísel podle definice (největší číslo, které obě
dělí) a podle Euklidova algoritmu. Porovnejte efektivnost obu metod. Zdůvodněte správnost Euklidova
algoritmu.
Euklidův algoritmus pro výpočet největšího společného dělitele dvou čísel vychází ze skutečnosti, že nsd dvou
čísle je také nsd libovolného z nich a jejich rozdílu.
Tedy:
Nsd(a,b)=nsad(a-b,b) když a>b;
Nsd(a,b)=nsd(b-a,a) kdy a<b;
Nsd(a,b)=a=b, když a=b.
Konkrétně:
Nsd(32,24)=nsd(24,8)=nsd(16,8)=nsd(8,8)=8.
Myšlenka důkazu správnosti Euklida: d/x and d/y => d/x-y, takže nsd(x,y)=nsd(x,y-x).
Nsd vstupující dvojice je nsd dvojice vystupující. Protože se čísla, se kterými pracujeme stále zmenšují,
algoritmus po konečném koku skončí – pokud jsou čísla nesoudělná, zastaví se o jedničku.
Varianty řešení:
1.1.
While x<>y do
If x>y then y:=y-x
Else x:=x-y;
Nsd:=x;
Tato varianta je nejjednodušší, ale pokud by jedno z čísel bylo podstatně větší než druhé, (což může nastat i
během výpočtu) testujeme zbytečně obě podmínky, i když se pořád pohybujeme v jedné větvi.
Vylepšení:
2.2.
While x<>y do
1.
PDF created with pdfFactory trial version www.pdffactory.com
Begin while x>y do x:=x-y;
While y>x do y:=y-x;
End;
Nsd:=x;
Třetí uvedená varianta vychází z toho, že opakované odčítání vlastně vede k získání zbytku po celočíselném
dělení:
Repeat x:=x mod y; {x:=x-y, dokud x>=y}
Vymen(x,y); {y:=y-x…}
Until y=0;
Nsd:=x;
2. Prvočíslo
Napište program, který zjistí, zda vstupující číslo je prvočíslo nebo číslo složené.
0. varianta: Hledáme dělitele mezi všemi čísly menšími než dané.
1. varianta: Hledáme dělitele mezi čísly menšími nebo rovnými polovině daného.
2. varianta: Testujeme možné dělitele do odmocniny z čísla.
3. varinata: Protože liché číslo nemá sudé dělitele, zjistíme nejprve zda jde o sudé číslo (poku to není dvojka,
jedná se o číslo složené), pak zkoumáme možné liché dělitele lichého čísla do odmocniny.
2.
var adept, odm, cislo:integer;
begin odm:=trunc(sqrt(cislo));
adept:=2;
while (adept<=odm) and (cislo mod adept<>0) do
inc(adept);
if adept>odm then showmessage(‘prvocislo’)
else showmessage(‘cislo slozene’);
end;
3.
var adept, odm, cislo:integer;
begin cislo:=spinedit1.value;
if odd(cislo)
then
begin
odm:=trunc(sqrt(cislo));
adept:=3;
while (adept<=odm) and (cislo mod adept<>0) do
inc(adept,2);
if adept>odm then showmessage('prvocislo')
else showmessage('cislo slozene');
end
else if cislo=2 then showmessage('prvocislo')
else showmessage('cislo slozene');
end;
Cvičení:
1. Vypočítejte největší společný násobek dvou čísel.
2. Naprogramujte generátor náhodných řetězců z písmen velké anglické abecedy. (A..Z). Délu řetězce zadá
uživatel.
3. Maximum a druhé maximum
Řešení:
1.
(nsn(a,b)=a*b div nsd(a,b)
2.
var delka,pocet,y:integer;s,vystup:string;
x:char;
begin delka:=spinedit1.value;
s:='';
PDF created with pdfFactory trial version www.pdffactory.com
for pocet:=1 to delka do
begin y:=random(26);
x:=chr(ord('A')+y);
s:=x+s;
end;
showmessage(s);
end;
3.
var x,i,max,max2:Integer;
begin randomize;
max:=-maxint;
max2:=max;
for i:=1 to 20 do
begin x:=random(20);
listbox1.items.add(Inttostr(x));
if x>max
then
begin max2:=max;
max:=x;
end
else
if (x>max2) and (x<>max) then
max2:=x;
end;
showmessage(inttostr(max)+' '+inttostr(max2));
13. Vnořené cykly
Často potřebujeme použít cyklus v cyklu, použití těchto konstrukcí si ukážeme na příkladech.
1. Vypište do listboxu trojúhelník z hvězdiček. (V prvním řádku bude jedna, ve druhém dvě, ..v desátem deset)
Tiskneme-li i-tý řádek, je na něm i hvězdiček, Použijeme tedy dva cykly – vnější pro tisk i-tého řádku a vnitřní,
kdy vytvoříme řetězec obsahující i hvězdiček a vytiskneme ho.
(Problém jde ovšem vyřešit pomocí jediného cyklu, což je efektivnější, viz cvičení.)
var s:string;i,j:integer;
begin listbox1.clear;
for i:=1 to 20 do
begin
s:='';
for j:=1 to i
do s:=s+'*';
listbox1.items.add(s);
end;
end;
2. Vypište všechna prvočísla menší než číslo zadané uživatelem.
Vnější cyklus bude zkoumat postupně čísla od 2 do n (ze zadání) a ve vnitřním vždy otestujeme, jde-li o
prvočíslo, jestliže ano, vytiskneme ho.
Problém jde efektivněji vyřešit použitím Eratosthenova síta, ale k tomu si potřebujeme zpracovávaná čísla
pamatovat ve vhodné struktuře – ještě se k němu vrátíme.
var i,n,a,odm:integer;
begin
listbox1.clear;
n:=spinedit1.value;
listbox1.items.add('prvocisla do '+inttostr(n));
listbox1.items.add('2');
for i:=3 to n do
begin odm:=trunc(sqrt(i));
a:=2;
PDF created with pdfFactory trial version www.pdffactory.com
while (i mod a<>0) and (a<=odm) do
inc(a);
if a>odm then listbox1.items.add(inttostr(i));
end;
end;
Cvičení
1.
2.
3.
4.
5.
Řešte první příklad použitím jediného cyklu.
Výpis prvočísel, počet zadá uživatel.
Tabelace funkce přirozená mocnina
Totéž s použitím jediného cyklu.
Kolikrát je třeba hodit kostkou, než padne n šestek? (Hody opět zobrazte do listboxu)
Řešení
1.
s:='';
for i:=1 to 20 do
begin s:=s+'*';
listbox1.items.add(s);
end;
2.
var i,j,n,o,a:integer;
begin
listbox1.items.clear;
n:= spinedit1.value;
j:=2;
i:=1;
repeat
{nalezeni i-teho prvocisla a tisk}
o:=trunc(sqrt(j));
a:=2;
while (j mod a <>0) and (a<=o)do
inc(a);
if a>o then
begin
listbox1.items.add(inttostr(j));
inc(i);
end;
inc(j);
until i>n;
end;
3.
var i,n,m,k:integer;
begin n:=spinedit1.value;
listbox1.items.clear;
for i:=1 to n do
begin m:=1;
for k:=1 to i do
m:=m*2;
listbox1.items.add(inttostr(i)+':'+inttostr(m));
end;
end;
4.
m:=1;
for i:=1 to n do
begin
PDF created with pdfFactory trial version www.pdffactory.com
m:=m*2;
listbox1.items.add(inttostr(i)+':'+inttostr(m));
end;
5.
var n,i,x:integer;
begin randomize;
n:=spinedit1.value;
listbox1.items.clear;
for i:=1 to n do
repeat x:=random(6)+1;
listbox1.items.add(inttostr(x));
until x=6;
end;
14. Procedury – první seznámení
V programování často používáme některé akce opakovaně. Potom je výhodné mít možnost je někde nadefinovat
a potom jednoduše spustit, aniž bychom je museli v kódu pořád kopírovat. Takovým akcím se říká podprogramy,
přesněji, v závislosti na programovacím jazyku procedury, subroutiny nebo funkce. Známe je například jako
makra z Microsoft Office, ale vlastně je používáme od začátku i v Delphi.
Příklady:
Randomize – procedura, která odvodí začátek budoucí posloupnosti náhodných čísel z aktuálního systémového
času
IntToStr(326) – funkce, která převede číslo na jednotlivé číslice, z nich vytvoří znaky a poskládá řetězec
Showmessage(‘Ahoj’) – procedura, zobrazí okno se správou v závorce
Form1.Button1Click(Sender: TObject) – procedura, jejiž kód píšeme my a která se spustí, když stiskneme
tlačítko, v závorce se nachází jakýsi „Odesílatel typu objekt“, se kterým se důvěrně seznámíme později
FloatToStrF(’25.30’,fffixed,2,2) – převedení čísla na řetězec a další údaje v závorce poskytují informace o tom,
jak se to má udělat…
Máme tedy zkušenosti s používáním (voláním) procedur – zapíše se jejich jméno a do závorky informace o tom
s čím co se bude dělat. Obsahu v závorce se říká parametry, jejich prostřednictvím vlastně podprogram
komunikuje se svým okolím. Mohou být i procedury bez parametrů (viz randomize), ale ty se opravdu používají
jen výjímečně.
Definování toho, co procedura dělá se říká deklarace procedury a píše se do deklarační části programu, její
volání pak používáme v příkazové části programu nebo podprogramu. (mezi begin a end)
Příklad:
Umístíme na formulář komponentu Listbox, kterou budeme používat pro výstupy a tlačítko Button, do jehož
události Button1Click zapíšeme náš program s definicí a použitím procedur. Příklady budou z algoritmického
hlediska velmi jednoduché, budeme se soustředit na psaní podprogramů. Užitečným zvykem je psát to, co
poprogramy dělají do komentářů.
procedure TForm1.Button1Click(Sender: TObject);
{deklarace procedur se píše do deklarační části programu a zde se určí, co bude podprogram dělat}
procedure hvezdy1;
{ vypíše 10 hvězdiček do listboxu}
var i:integer;s:string;
begin
s:='';
for i:=1 to 10 do s:=s+'*';
listbox1.items.add(s);
end;
procedure hvezdy2(n:integer);
{ vypíše n hvězdiček do listboxu}
var i:integer;s:string;
begin
s:='';
for i:=1 to n do s:=s+'*';
PDF created with pdfFactory trial version www.pdffactory.com
listbox1.items.add(s);
end;
{deklarace hlavního programu a hlavní program}
var k:integer;
begin listbox1.clear;
hvezdy1; {zde se podprogramy používají jako příkazy}
hvezdy2(20);
k:=spinedit1.value;
hvezdy2(k);
for k:=1 to 10
do hvezdy2(k);
end;
Hvezdy1 – procedura vypíše 10 hvězdiček do listboxu. Protože není nijak variabilní, nepotřebuje parametry
Pokud bychom potřebovali, aby procedura vytiskla počet hvězdiček podle našeho přání, tento počet použijeme
jako její parametr.
Hvezdicky2(n:integer)
Vypíše n hvězdiček do listboxu. Můžeme ji použít jednak když chceme oddělit nějaká data, ale také kdybychom
třeba chtěli zobrazit trojúhelník z hvězdiček: (náš program)
*
**
***
****
*****
až na n-tém řádku bude n hvězdiček
for k:=1 to 10
do hvezdy2(k);
– místo formálního parametru je proměnná k, kterou zadá uživatel.
Volání procedur:
Zatímco v deklaraci procedury vystupují tzv. formální parametry, v jejich volání je třeba použít skutečné
parametry, což mohou být proměnné, konstanty či výrazy hlavního programu. Procedura si je dosadí za ty
formální a proběhne nad nimi.
hvezdy1;
hvezdy2(20); – místo formálního parametru je konstanta 20
k:=spinedit1.value;
hvezdy2(k);
Poznámka:
Deklarace hlavního programu a procedur mohou být v zásadě v libovolném pořadí, jen je třeba pamatovat na to,
že každý podprogram musí být deklarovaný dřív, než je použitý. (Může ho používat třeba následující
podprogram)
Všimněte si, že některé proměnné (i) jsou deklarovány uvnitř procedur. Kdybyste je chtěli použít mimo ně,
překladač je nezná, jejich platnost je omezená na daný podprogram, mimo něj neexistují. Říká se jim lokální
parametry na rozdíl od globálních, deklarovaných v nadřazeném programu nebo podprogramu. Používají se
k různým pomocným akcím.
Procedury mohou také něco počítat, v následujícím příkladu si ukážeme proceduru na výpočet obsahu
trojúhelníka a její použití ve výpočtu obsahu čtyřstěnu.
procedure trojuh1(a,b,c:real);
Procedura rozhodne, zda trojuhelnik exisuje, pokud ano, vypíše jeho obsah, v opačném případě hlášení. Pokud
bychom ji ovšem chtěli použít třeba ve výpočtu povrchu čtyřstěnu, opakované údaje o stěnách vlastně
nepotřebujeme, pak by bylo lepší, kdyby procedura předávala obsah trojúhelníka, i informaci jeho o existenci či
neexistenci jako výstupní patrametr.
procedure trojuh2(a,b,c:real;var S:real;var chyba:boolean);
Před výstupním parametrem musí být v deklaraci vyhrazené slovo var, formální parametry různého druhu si při
deklaraci oddělují středníky, skutečné parametry při volání čárkami.
PDF created with pdfFactory trial version www.pdffactory.com
procedure TForm1.Button2Click(Sender: TObject);
procedure trojuh1(a,b,c:real);
var o,S:real;
begin
if ((a+b)>c)and ((b+c)>a )and((a+c)>b)
then begin
o:=(a+b+c)/2;
S:=sqrt(o*(o-a)*(o-b)*(o-c));
ShowMessage(FloatToStr(s));
end
else ShowMessage('Neni trojuhelnik');
end;
procedure trojuh2(a,b,c:real;var S:real;var chyba:boolean);
var o:real;
begin
if ((a+b)>c)and ((b+c)>a )and((a+c)>b)
then begin
chyba:=false;
o:=(a+b+c)/2;
S:=sqrt(o*(o-a)*(o-b)*(o-c));
end
else chyba:=true;
end;
var ch1,ch2,ch3,ch4:boolean;
S1,S2,S3,S4,Scelk:real;
begin
trojuh1(spinedit1.value,spinedit2.value,spinedit3.value);
trojuh2(spinedit1.value,spinedit2.value,spinedit3.value,S1,ch1);
trojuh2(spinedit1.value,spinedit2.value,spinedit4.value,S2,ch2);
trojuh2(spinedit1.value,spinedit3.value,spinedit3.value,S3,ch3);
trojuh2(spinedit2.value,spinedit3.value,spinedit4.value,S4,ch4);
if ch1 or ch2 or ch3 or ch4
then showmessage('blbost')
else showmessage(floattostr(s1+s2+s3+s4));
end;
Cvičení
Deklarujte procedury v rámci akce ButtonClick a použijte je následujícím způsobem:
1. Procedura znaky – vypíše n znaků ch do listboxu. n i ch jsou její parametry.
Použijte ji k výpisu 10 řádků
AAAA…AAA
BBBB….BBB
….
HHHHHHHH
Počet písmen zadá uživatel prostřednictvím SpinEditu.
2. Procedura Pozdrav v rámečku z hvězdiček – parametrem je text pozdavu
3. Procedura Kostka se vstupním parametrem velikost hrany a s výstupním parametrem objemem krychle,
použijte ji pro výpočet objemu kostek o hranách od 1 do 10 cm. (Výsledky do listboxu)
Řešení
1.
procedure TForm1.Button3Click(Sender: TObject);
var p:integer;x:char;
procedure znaky(n:integer;ch:char);
var i:integer;s:string;
begin
s:='';
for i:=1 to n do s:=s+ch;
PDF created with pdfFactory trial version www.pdffactory.com
listbox1.items.add(s);
end;
begin p:=spinedit1.value;
for x:='A' to 'H' do
znaky(p,x);
end;
2.
procedure TForm1.Button4Click(Sender: TObject);
procedure pozdrav(s:string);
var i:integer;pom:string;
begin pom:='';
for i:=1 to length(s)+3 do
{length(retezec udava delku retezce}
pom:=pom+'*';
showmessage(pom+#13+'*'+s+'*'+#13+pom);
end;
begin pozdrav(Edit1.text);
end;
3.
procedure TForm1.Button5Click(Sender: TObject);
procedure kostka(a:integer;var V:integer);
begin v:=a*a*a;
end;
var i,W:integer;
begin listbox1.clear;
for i:=1 to 10 do
begin kostka(i,W);
listbox1.items.add(inttostr(W)+' centiemetrů krychlových');
end;
end;
15. Procedury po druhé
Parametry
Formální a skutečné
Za formální parametry uvedené v hlavičce deklarace procedury se v programu substituují skutečné parametry.
Musí si odpovídat co do počtu, typu a pořadí.
(Deklarace funguje jako scénář, do kterého při volání procedury dosazujeme konkrétní herce)
Parametr hodnota a parametr proměnná
Parametr volaný hodnotou: skutečný parametr je něco, co nabývá hodnotu: výraz nebo proměnná. Formální
parametr se stane lokální proměnnou procedury, vyhodnotí se skutečný parametr a jeho hodnota se uloží do této
lokální proměnné. Výpočet předepsaný procedurou probíhá nad lokálním parametrem, takže se hodí jako vstup.
(Původní hodnota skutečného parametru zůstane zachována.)
Protože se hodnota skutečného parametru nezmění, nemůže fungovat jako výstup.
Parametr volaný odkazem
(Při deklarování hlavičky procedury je označen var)
Skutečný parametr je výhradně proměnná. Adresa skutečného parametru se spojí se jménem formálního
parametru, a všechno se děje nad ním. Původní hodnota se nevratně a trvale změní – užívá se pro výstup.
Lokální a globální objekty
Lokální objekty mají platnost jen v určitém prostoru, uvnitř podprogramu, ve kterém byly deklarovány.
Nepoužívejte globální parametry uvnitř procedur – je to nepřehledné a může být problém s přenositelností
takových podprogramů.
PDF created with pdfFactory trial version www.pdffactory.com
Paměť přidělená lokálnímu parametru je po skončení procedury opět uvolněna, lokální parametr mimo oblast své
deklarace neexistuje.
Pokud chceme používat nějaké objekty (proměnné, ale také podprogramy) ve více akcích, je třeba je deklarovat
jako globální.
Příklad:
Napíšeme proceduru, která pozná dokonalé číslo. (Číslo, které je rovno součtu svých vlastních dělitelů)
Abychom ji mohli použít k různým účelům – dejme tomu, že bychom chtěli při stisknutí tlačítka vypsat, zda
číslo ve spineditu je dokonalé, případně vypsat všechna dokonalá čísla menší než 100000 do listboxu, budeme ji
deklarovat samostatně: (tj. na stejné úrovni jako např. button1.click – kód celého příkladu následuje)
procedure dokonal(a:integer;var je:boolean);
{ je =true, kdyz je cislo dokonale, jinak je false}
var d,dok:integer;
begin dok:=1;
for d:=2 to a div 2 do
if a mod d=0 then dok:=dok+d;
je:=dok=a;
end;
procedure TForm1.Button4Click(Sender: TObject);
{ Rozhodnutí, zda je číslo dokonalé}
var x:integer; y:boolean;
begin x:=spinedit1.Value;
dokonal(x,y);
if y then showmessage('ano')
else showmessage('ne');
end;
procedure TForm1.Button5Click(Sender: TObject);
{ Výpis dokonalých čísel do 10 000}
var i, x:boolean;
begin
for i:=2 to 10000 do
begin dokonal(i,x);
if x then listbox1.Items.add(inttostr(i));
end;
end;
Pokud potřebujeme nějakou proměnnou používat ve více procedurách, musíme ji deklarovat jako globální –
prozatím tam, kde je deklarován Form1.
Příklad 1.
Na formulář umístíme dvě tlačítka a editační políčko. Stisknutí prvního tlačítka uloží do celočíselné proměnné x
hodnotu z Editu, druhé tlačítko tuto hodnotu zdvojnásobí a zobrazí zprávu.
Vše bude fungovat podle našich představ.pokud x nadeklarujeme globálně.
var
Form1: TForm1;
var x:integer;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
{var x:integer}
begin
x:=StrToInt(edit1.Text);
end;
procedure TForm1.Button2Click(Sender: TObject);
{var x:integer;}
PDF created with pdfFactory trial version www.pdffactory.com
begin x:=2*x;
showmessage(inttostr(x));
end;
end.
Pokud bychom ovšem použili lokální deklaraci (momentálně skrytou v komentářích), zobrazí se nesmyslný
výsledek.
Příklad 2.
Představme si, že máme modrý panel s nápisem budu červený, který po kliknutí zčervená a změní nápis na budu
modrý.
O stavu panelu sice můžeme rozhodnout z jeho okamžitých vlastností, ale můžeme také použít logickou
proměnnou red, která je true když je panel červený. Pak stačí, když při každém kliknutí na panel změní svou
hodnotu na negaci. (Je nutno ji ovšem inicializovat, k tomu se obecně hodí procedura formuláře FormCreate)
….
Var Form1: TForm1;
red:boolean;
…
procedure TForm1.FormCreate(Sender: TObject);
begin
red:=False;
end;
…
procedure TForm1.Panel1Click(Sender: TObject);
begin red:=not red;
if red then
begin panel1.Color:=clred;
panel1.Caption:='Budu modrý'
end
else
begin panel1.Color:=clblue;
panel1.Caption:='Budu èervený'
end ;
end;
Cvičení:
1.
2.
3.
4.
Definujte proceduru mocnina, která vypočítá přirozenou mocninu opakovaným násobením. (Vstupní
parametry základ a exponent, výstupní parametr mocnina.)
Použijte ji při : (Každá akce zvláštní tlačítko)
a. Výpočtu obsahu čtverce (vstup z editu)
b. Výpočtu objemu krychle (Vstup z editu)
c. Výpisu mocnin dvou do Listboxu (od 1 do 10)
Použijte globální celočíselnou proměnnou tak, aby tlačítko ve svém názvu zobrazovalo, kolikrát na něj
bylo kliknuto.
Poskakující tlačítko:
Při kliknutí se tlačítko posune o 20 bodů doprava, když dorazí na kraj formuláře, odrazí se a bude
putovat zpátky, na levé straně formuláře se opět odrazí atd.
…
var
klik,posun:integer;
Form1: TForm1;
implementation
{$R *.dfm}
procedure mocnina(zak:integer;exp:integer;var vys:integer);
var i:integer;
begin vys:=1;
for i:=1 to exp do
vys:=vys*zak;
PDF created with pdfFactory trial version www.pdffactory.com
end;
procedure TForm1.Button1Click(Sender: TObject);
var x,V:integer;
begin x:=StrToInt(edit1.text);
mocnina(x,2,V);
showmessage(floattostr(v));
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Edit1.clear ;
klik:=0; {na tlačítko ještě nebylo kliknuto}
posun:=20; {posuv druhého tlačítka}
end;
procedure TForm1.Button2Click(Sender: TObject);
var x,V:integer;
begin x:=StrToInt(edit1.text);
mocnina(x,3,V);
showmessage(Inttostr(v));
end;
procedure TForm1.Button3Click(Sender: TObject);
var m,i:integer;
begin
listbox1.clear;
for i:=1 to 10 do
begin mocnina(2,i,m);
listbox1.Items.Add(Inttostr(i)+'...'+FloatToStr(m)) ;
end;
end;
procedure TForm1.Button5Click(Sender: TObject);
var i,n:integer; x:boolean;
begin n:=spinedit1.Value;
for i:=2 to n do
begin dokonal(i,x);
if x then listbox1.Items.add(inttostr(i));
end;
end;
procedure TForm1.Button7Click(Sender: TObject);
begin
inc(klik);
button7.Caption:='Kliknuls na mì '+IntTostr(klik);
end;
procedure TForm1.Button6Click(Sender: TObject);
begin if (button6.left>form1.Width-button6.width) or
(button6.left<0)then posun:=-posun;
{když oktaj tlačítka narazí na okraj formuláře, mění se směr posunu}
button6.left:=button6.left+posun;
end;
end.
16. Funkce
Pokud je výsledkem procedury jediná vypočítaná hodnota, je její zjišťování maličko nepohodlné.
Máme-li například deklarovanou:
PDF created with pdfFactory trial version www.pdffactory.com
Procedure Objem_Kvadru(a,b,c:real; var V:real);
Begin V:=a*b*c;
End;
Použití v programu pak může vypada následovně:
Var Objem:real;
…
Objem_Kvadru(3,4,5,Objem);
Showmessage(FloatTostr(Objem));
Také kdybychom chtěli získanou hodnotu použít v dalších výpočtech, musíme nejprve zavolat proceduru a mít
předem deklarovanou příslušnou proměnnou.
V tomto případě je výhodnější (a bližší práci, na kterou jsem zvyklí z matematiky), použít funkci.
Její deklarace:
Function Objem_Kvadru(a,b,c:real):real;
Begin Objem_Kvadru:=a*b*c;
End;
Použití:
Showmessage(FloatTostr(Objem_Kvadru(3,4,5));
Obecně:
Function IdentifikátorFunkce(seznam formálních parametrlů se specifikacemi):typ výsledku;
Begin …
End;
V těle funkce se musí nacházet příkaz, kde je identifikátoru funkce přiřazena hodnota. (Místo jména funkce
můžeme použít slovo result.) Hodnotě funkce, (v matematice funkční hodnotě) se říká v programování návratová
hodnota. (Funkce vrací hodnotu…)
Deklarovanou funkci pak použijeme tak, že zapíšeme její identifikátor tam, kde potřebujeme návratovou hodnotu
– tedy například na pravé straně příkazu přiřazení, v příkazech tisku apod.
Typ výsledku nesmí být strukturovaný.
Delphi procedury a funkce rozlišují méně striktně, než klasický Pascal, některé jiné jazyky vůbec.
Příklad 1.
Napišme funkci, která převede logickou hodnotu na řetězec a použijme ji v programu, který do Listboxu vypíše
definiční tabulku logických operátorů.
function BoolToStr(x:boolean):string;
begin if x then BoolToStr:='True '
else BoolToStr:='False'
end;
K výpisu použijeme dvou vnořených cyklů FOR, kdy proměnné a a b budou postupně nabývat všech logickcýh
hodnot (tedy False a True) a pro každou kombinaci vypíšeme na řádek listboxu výsledek příslušné logické
operace.
procedure TForm1.Button1Click(Sender: TObject);
var a,b:boolean; s:string;
begin s:='a and b a or b a<=>b a xor b';
listbox1.clear;
listbox1.items.add(s);
for a:=false to true do
for b:=false to true do
begin s:=BoolTostr(a and b)+' ' +
BoolTostr(a or b)+' ' +
BoolTostr(a = b)+' '+
BoolTostr(a xor b);
Listbox1.items.add(s);
end;
end;
Příklad 2.
PDF created with pdfFactory trial version www.pdffactory.com
Nadeklarujeme logickou funkci, která pozná prvočíslo (bude vracet True, pokud je jejím argumentem prvočíslo,
jinak False)
Použijeme ji jednak k rozpoznání prvočísla zadaného užiavtelem, jednak k výpisu prvočíselných dvojčat
menších než dané číslo. (Prvočíselná dvojčata jsou prvočísla, lišící se o 2. Např. 3,5…5,7…11,13…)
function prvok(n:integer):boolean;
var odm,d:integer;
begin odm:=trunc(sqrt(n));
d:=2;
while (n mod d<>0) and (d<=odm)
do inc(d);
prvok:=(d>odm);
end;
procedure TForm1.Button3Click(Sender: TObject);
begin if prvok(spinedit2.value)
then showmessage(‘prvocislo’)
else showmessage(‘cislo slozene’);
end;
Povšimněme si, že protože funkce vrací logickou hodnotu, můžeme její identifikátor použít přímo jako
podmínku. (Tato konstrukce se chová stejně jako if prvok(spinedit2.value) =true then…
procedure TForm1.Button4Click(Sender: TObject);
var i,n:integer;
begin listbox1.clear;
n:=spinedit2.value;
for i:=2 to n-2 do
if prvok(i)and prvok(i+2)
then listbox1.items.add(IntTostr(i)+','+IntTostr(i+2))
end;
Ještě jednou o parametrech předávaných odkazem
Zopakujme si: Když je volán podprogram, zjistí se kterou proměnnou označuje skutečný parametr a na ni pak
odkazuje příslušný formální parametr během celého provádění podprogramu.
Příklad:
(procedura pis není podstatná, jde o předání hodnot celočíselných proměnných uživateli např.
procedure pis(x,y,u,z:integer);
begin listbox1.items.add(inttostr(x)+ inttostr(y)+ inttostr(u)+ inttostr(z))
end)
Var a,b: integer;
Procedure P(i:integer; var j:integer);
Begin pis(a,b,i,j);
i:=3;j:=4; pis(a,b,i,j);
a:=5;b:=6; pis(a,b,i,j);
i:=7;j:=8;
End;
….
A:=1; b:=2; p(a,b); pis(a,b,a,b);
Sledujme co se děje při provádění programu:
A=1, B=2.
Při volání procedury P se do I zkopíruje obsah A, parametr J začne odkazovat na proměnnou B.
Pis(a,b,i,j) tedy vypíše: 1 2, 1,2
Když se pak do i přiřadí trojka, v a zůstane jednička, změnou hodnoty j na 4 se změní i b.
Druhý řádek procedury tedy vypíše: 1 4 3 4
Do a se pak přiřadí 5, do b a tedy i do j 6. Hodnota i se nezměnila. Třetí řádek vypíše: 5 6 3 6
Na závěr se do i přiřadí 7 a do j 8, tím se také změní hodnota b. Příkaz pis(a,b) tedy vypíše 5 8 5 8
PDF created with pdfFactory trial version www.pdffactory.com
Cvičení
1) Deklarujte funkci NSD, vstupem budou dvě celá čísla, výstupem jejich největší společný dělitel. Použijte ji
při:
Krácení zlomku na základní tvar (čitatele a jmenovatele zadá uživatel)
a) Výpočtu nejmenšího společného násobku dvou čísel, která opět zadá uživatel
2) Deklarujte funkci, která pro vstupující celé číslo vrací jeho ciferný součet. Použijte ji při:
a) Výpisu ciferného součtu čísla zadaného uživatelem
b) Řešení následujícího problému: Uživatel zadá jistý interval v celých číslech a program vypíše všechna
čísla, z daného intervalu, která mají určitý ciferný součet, opět zadaný uživatelem.
Řešení:
1.
function nsd(a,b:integer):integer;
begin while a<>b do
if a>b then a:=a-b
else b:=b-a;
nsd:=a;
end;
procedure TForm1.Button2Click(Sender: TObject);
var c,j,d:integer;
begin c:=spinedit1.value;
j:=spinedit2.value;
d:=nsd(c,j);
c:=c div d;
j:=j div d;
showmessage(Inttostr(c)+'/'+IntTostr(j));
end;
procedure TForm1.Button3Click(Sender: TObject);
var nsn,c,j:integer;
begin c:=spinedit1.value;
j:=spinedit2.value;
nsn:=c*j div nsd(c,j);
showmessage(inttostr(nsn));
end;
function cs(n:integer):integer;
var s:integer;
begin s:=0;
repeat s:=s+n mod 10;
n:=n div 10;
until n=0;
cs:=s;
end;
procedure TForm1.Button5Click(Sender: TObject);
begin
showmessage(IntTostr(cs(spinedit3.value)));
end;
procedure TForm1.Button6Click(Sender: TObject);
var i,a,b,c:integer;
begin listbox1.clear;
a:=spinedit1.value;
b:=spinedit2.value;
c:=spinedit3.value;
for i:=a to b do
if cs(i)=c then listbox1.items.add(inttostr(i));
end;
PDF created with pdfFactory trial version www.pdffactory.com
17. Programové jednotky
I když se snažíme psát své programy přehledně, používáme podprogramy, komentujeme, odsazujeme atp.,
v delších programech snadno ztratíme orientaci. Bude tedy vhodné kód nějakým způsobem rozčlenit. Kromě
toho – když už jednou naprogramujeme nějaké procedury a funkce, budeme je chtít používat bez zbytečného
kopírování. A co když budeme pracovat v týmu a potřebujeme si nějak rozdělit práci?
Všechny uvedené problémy řeší používání programových jednotek (unitů).
Unit je zvláštní soubor, který obsahuje datové typy, proměnné, procedury a funkce, které spolu zpravidla nějak
souvisí a můžeme je používat v dalších programech.
Unit může obsahovat i příkazovou část, která je volána hned po spuštění programu, který unit obsahuje.
Výhody: – program může být rozčleněn na samostatně přeložitelné součásti
– knihovny procedur pro nejrůznější programy – zvýšení univerzálnosti procedur a funkcí
– snadnější týmová práce
– zvýší se čitelnost programu
– samostatný překlad jednotek urychluje konečný překlad
– obsah jednotky lze skrýt před okolím a povolit pouze používání určitých objektů a metod.
Kvalifikovaný identifikátor: odkazujeme-li se na objekt jiného unitu, můžeme k odlišení použít zápis:
Jméno_unitu.Jméno_objektu
Struktura unitu:
Unit Jméno; (hlavička)
Interface – rozhraní
deklarace přístupné programům nebo jiným jednotkám. Pokud používá jednotka objekty jiných jednotek, je třeba
je umístit do klauzule uses hned za Interface
Implementation
lokální deklarace jednotky, vlastní definování procedur a funkcí
end.
(V případě příkazové čási begin – příkazová část – end.)
Zdrojový soubor unitu má příponu pas
Poznámka: Lze užít inicializační část – Initialization – která se provede před prvním použitím jednotky.
(nastavení počátečních hodnot proměnných apod. Spolu s ní lze zařadit také úklidovou část – Finalization – ta se
provádí těsně před skončením programu. (uvolnění alokované paměti apod.)
Vytvoření nové jednotky
File/New/Unit
Delphi vytvoří Unit2 s následující strukturou:
unit Unit2;
interface
implementation
end.
A stačí dopsat kód.
Přidání a odstranění existující jednotky:
Project /Add to Project
Zásada: jméno unitu musí být v klauzuli USES každé jednotky, která ji používá
Project/Remove from Project
Správa jednotek projektu – View/Project Manager
Použití unitu:
Stačí ho dopsat za klíčové slovo uses v deklarační části programu a už se vším,co nabízí ve svém interface
můžeme pracovat tak, jako bychom to měli deklarováno přímo v tomto programu.
Kruhová reference
V části interface jedné jednotky nesmí být uvedena jednotka, která odkazuje zpátky na první jednotku.
Řešení: v jedné jednotce přesuneme připojení (klauzuli USES) do implementační části.
Příklad
Unit3 deklaruje funkci přirozená mocnina, kterou pak voláme v Unitu2.
unit unit3;
interface
PDF created with pdfFactory trial version www.pdffactory.com
function moc(n,k:integer):integer;
implementation
function moc(n,k:integer):integer;
var i,p:integer;
begin p:=1;
for i:=1 to k do
p:=p*n
moc:=p;
end;
end.
Použití:
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, Spin, unit3, ExtCtrls, Buttons;
….
procedure TForm1.BitBtn1Click(Sender: TObject);
var a,b:integer;
begin a:=spinedit1.value;
b:=spinedit2.value;
showmessage(IntTostr(moc(a,b))
Unit1
V Delphi má každý formulář vlastní jednotku. Prohlédněme si teď trošku informovaněji UNIT1, který Delphi
otvírají s vytvořením prvního formuláře aplikace.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
type
TForm1 = class(TForm)
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
end.
V sekci interface najdeme v klauzuli uses seznam jednotek, které potřebujeme, abychom mohli pracovat
s komponentami, (např. Graphics potřebujeme pro práci s barvami, Dialogs pro užití procedury
Showmessage…) definici typu formuláře (i k té se zanedlouho propracujeme), deklaraci proměnné typu formulář
a implementační část. Pokud vložíme na formulář komponentu a použijeme nějakou její událost, přibude tato
událost jednak v sekci interface u formuláře, jednak se objeví jako prázdná procedura v implementační části, do
které zapisujeme naše kódy.
Cvičení:
Připravte si unit na práci s funkcemi – bude nabízet reálnou mocninu, logaritmus o libovolném základu, a
alespoň 5 geometrických vzorců.
Případy, kdy funkce nejsou definovány ošetřete přímo během zadávání hodnot, k opravdu funkčnímu
zabezpečení programu bychom potřebovali mechanismus výjimek, se kterým se zanedlouho seznámíme.
Použijte ho v programu, kde si uživatel typ výpočtu vybere pomocí komponenty radiogroup.
PDF created with pdfFactory trial version www.pdffactory.com
Nastavte změny popisků u editačních políček, aby odpovídaly řešenému problému. Využijte vlastnosti visible
(true, false)
Řešení
unit Unit2;
interface
function realmoc(z,e:real):real;
function log(z,x:real):real; {z-yaklad,x-argument}
function koule(x:real):real;
implementation
function realmoc(z,e:real):real;
begin realmoc:=exp(ln(z)*e);
end;
function log(z,x:real):real;
begin log:=ln(x)/ln(z);
end;
function koule(x:real):real;
begin koule:=pi*x*x*x;
end;
end.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, Unit2;
...
procedure TForm1.Button1Click(Sender: TObject);
var x,y,z:real;
begin
case radiogroup1.itemindex of 0:
begin
x:=strtofloat(edit1.text);
y:=strtofloat(edit2.text);
if x<=0 then begin showmessage('nedef');
edit1.text:='0';
edit2.text:='0';
edit1.setfocus;
end
else
showmessage(floattostrf(realmoc(x,y),fffixed,10,3))
end;
1:
begin
x:=strtofloat(edit1.text);
y:=strtofloat(edit2.text);
if (x<=0)or (x=1) or (y<=0)
then
begin showmessage('nedef');
edit1.text:='0';
edit2.text:='0';
edit1.setfocus;
end
else
showmessage(floattostrf(log(x,y),fffixed,10,3))
end;
2: begin
x:=strtofloat(edit1.text);
if x<0 then
PDF created with pdfFactory trial version www.pdffactory.com
begin showmessage('nedef');
edit1.text:='0';
edit1.setfocus;
end
else
showmessage(floattostrf(koule(x),fffixed,10,3))
end;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
edit1.Text:='0';
edit2.Text:='0';
end;
procedure TForm1.RadioGroup1Click(Sender: TObject);
var x,y,z:real;
begin
case radiogroup1.itemindex of 0:
begin label1.Caption:='zaklad';
label2.Caption:='exponent';
edit2.Visible:=true;
x:=strtofloat(edit1.text);
y:=strtofloat(edit2.text);
end;
1:
begin label1.Caption:='zaklad';
label2.Caption:='log.cislo';
edit2.Visible:=true;
x:=strtofloat(edit1.text);
y:=strtofloat(edit2.text);
end;
2: begin
label1.Caption:='polomer';
label2.caption:='';
x:=strtofloat(edit1.text);
edit2.visible:=FALSE;
end;
end;
end;
18. Opakování
Připravte si nejprve unit s potřebnými procedurami a funkcemi a použijte ho při řešení problémů.
Podprogramy:
1. Funkce Vypis:
Vstupní parametry: Řetězec a celé číslo
Funkční hodnota: řetězec zleva doplněný mezerami, aby měl délku určenou číselným parametrem. Pokud je
délka vstupního řetězce větší než číslo, nezmění se.
2. Funkce JePythag:
Vstupní parametry: tři celá kladná čísla
Funkční hodnota: True, pokud čísla splňují Pythagorovu větu, jinak False.
3. Pro srovnání čísel použijte proceduru bublej, která má tři vstupně-výstupní parametry a po jejím proběhnutí
bude ve třetím z nich maximum trojice. (Použitá metoda porovná nejprve první dvě čísla, pokud je druhé menší,
vymění je a totéž provede pro druhá dvě čísla.)
PDF created with pdfFactory trial version www.pdffactory.com
4. Funkce Kvadrat:
Vstupní parametry: Dvě kladná celá čísla
Funkční hodnota: součet druhých mocnin těchto čísel.
5. Funkce Aspon3:
Vstupní parametr: čtyřciferné celé číslo
Funkční hodnota: True, pokud má spoń tři cifry stejné, jinak False
Problémy:
1. Zobrazte do listboxu tabulku malé násobilky, pro zarovnání čísel pod sebe použijte funkci Vypis.
(Nezapomeňte u listboxu nastavit v Properties neproporcionální font, například Courier.
2. Vstupem jsou tři kladná celá čísla ze spineditů, vypište, zda mohou být stranami pravoúhlého trojúhelníka.
(Využijte funkci JePythag, předpokládejte vstup v libovolném pořadí a pro potřebné srovnání trojice proceduru
Bublej)
3. Nalezněte všechny pythagorejské trojúhelníky (pravoúhlé trojúhelníky s celočíselnými délkami stran), jejichž
všechny tři strany jsou jsou menší, než dané celé N.
Můžete použít tři vnořené cykly pro a,b,c a funkci JePythag, mnohem efektivnější bude ale způsob, kdy
použijete jen dva cykly pro odvěsny a přeponu vždy dopočítáte funkcí Kvadrat.
4. Spočítejte a vytiskněte všechna čtyřciferná čísla, která obsahují aspoň tři stejné cifry.
Vyzkoušejte variantu s funkcí Aspon3 a průchodem všech čtyřciferných čísel a porovnejte ji (s opět podstatně
rychlejším způsobem) kdy potřebná čísla přímo vytvoříte a přitom zjistíte jejich počet.
Řešení:
unit Unit2;
interface
uses SysUtils;
function Vypis(s:string;d:integer):string;
function JePythag(a,b,c:integer):boolean;
procedure vymen(var a,b:integer);
procedure bublej(var a,b,c:integer);
function kvadrat(a,b:integer):integer;
function aspon3(x:integer):boolean;
implementation
function Vypis(s:string;d:integer):string;
var i,l:integer;
begin if length(s)<d {length(s) vraci delku retezce}
then
begin l:=length(s);
for i:=1 to d-l do
s:=' '+s;
end;
result:=s;
end;
procedure vymen(var a,b:integer);
var p:integer;
begin p:=a;a:=b;b:=p;
end;
procedure bublej(var a,b,c:integer);
begin if a>b then vymen(a,b);
if b>c then vymen(b,c);
end;
function JePythag(a,b,c:integer):boolean;
begin bublej(a,b,c);
result:=sqr(a)+sqr(b)=sqr(c);
end;
function kvadrat(a,b:integer):integer;
begin result:=sqr(a)+sqr(b)
end;
PDF created with pdfFactory trial version www.pdffactory.com
function aspon3(x:integer):boolean;
var a,b,c,d:integer;
begin aspon3:=false;
d:=x mod 10;
x:=x div 10;
c:=x mod 10;
x:=x div 10;
b:=x mod 10;
x:=x div 10;
a:=x mod 10;
aspon3:=(a=b)and(b=c){stejne prvni tri nebo vsechny}
or
(a=b)and(b=d){stejne prvni,druha,ctvrta nebo vsechny}
or
(a=c)and(c=d){stejne prvni,treti,ctvrta nebo vsechny}
or
(c=b)and(b=d);{stejne ,druha,treti ctvrta nebo vsechny}
end;
end.
procedure TForm1.Button1Click(Sender: TObject);
{mala nasobilka}
var s:string; i,j:integer;
begin
for i:=1 to 9 do
begin s:='';
for j:=1 to 9 do
s:=s+vypis(inttostr(i*j),3);
listbox1.items.add(s)
end;
procedure TForm1.Button3Click(Sender: TObject);
{vypis pythagorejských cisel}
var a,b,c,n:integer;
begin n:=StrToInt(edit1.Text);
for a:=1 to n do
for b:=a to n do
for c:= b to n do
{pri tomto reseni by nebylo nutne ve funkvi JePythag
uzivat bublani, protože c je urcite nejvetsi}
if JePythag(a,b,c) then
listbox1.items.add(
IntTostr(a)+' '+IntTostr(b)+' '+
IntTostr(c));
end;
procedure TForm1.Button4Click(Sender: TObject);
{jsou na vstupu pzthagorejska cisla?}
var a,b,c:integer;
begin a:=spinedit1.Value;
b:=spinedit2.Value;
c:=spinedit3.Value;
if JePythag(a,b,c) then showmessage('ano')
else showmessage('ne')
end;
procedure TForm1.Button5Click(Sender: TObject);
{efektivnejsi vypis Pythagorejskych cisel}
var a,b,kvac,n:integer;
begin n:=StrToInt(edit1.Text);
PDF created with pdfFactory trial version www.pdffactory.com
for a:=1 to n do
for b:=a to n do
begin kvac:=kvadrat(a,b);
if (trunc(sqrt(kvac))=sqrt(kvac))and
(sqrt(kvac)<=n)
then
listbox1.items.add(
IntTostr(a)+' '+IntTostr(b)+' '+
IntTostr(trunc(sqrt(kvac))));
end;
end;
procedure TForm1.Button6Click(Sender: TObject);
{vypis čtyrciferných cisel s aspon ctyrmi stejnymi ciframi postupnym proverovanim}
var xx,p:integer;
begin p:=0;
for xx:=1000 to 9999 do
if aspon3(xx)
then begin listbox1.items.add(IntTostr(xx));
inc(p);
end;
showmessage(inttostr(p));
end;
procedure TForm1.Button7Click(Sender: TObject);
{efektivnejsi vypis}
var a,b,c,d,x,p:integer;
begin p:=0;
{stejne posledni tri cifry nebo vsechny}
for a:=1 to 9 do
for b:=0 to 9 do
begin x:=1000*a+100*b+10*b+b;
listbox1.Items.add(inttostr(x));
inc(p);
end;
{stejne prvni tri cifry}
for a:=1 to 9 do
for b:=0 to 9 do
begin if a<>b then {aby se nepridavaly vsechny stejne znova}
begin x:=1000*a+100*a+10*a+b;
listbox1.Items.add(inttostr(x));
inc(p);
end;
end;
{stejna prvni, druha a ctvrta}
for a:=1 to 9 do
for b:=0 to 9 do
begin if a<>b then
begin x:=1000*a+100*a+10*b+a;
listbox1.Items.add(inttostr(x));
inc(p);
end;
end;
{stejna prvni, treti a ctvrta}
for a:=1 to 9 do
for b:=0 to 9 do
begin if a<>b then
begin x:=1000*a+100*b+10*a+a;
listbox1.Items.add(inttostr(x));
inc(p);
PDF created with pdfFactory trial version www.pdffactory.com
end;
end;
showmessage(inttostr(p));
end;
19. Datový typ pole
Strukturované typy
Dosud jsme se zabývali typy, jejichž hodnoty byly nedělitelné. Někdy si ovšem potřebujeme pamatovat víc
hodnot najednou a umět s nimi pracovat jako s celkem.
(Příklad: Získáme měřením sadu hodnot – třeba délek nějakého předmětu a pokud chceme zjistit, jak bylo toto
měření přesné, potřebujeme vypočítat odchylky jednotlivých hodnot od průměru. K tomu si ovšem musíme
pamatovat všechny hodnoty i jejich pořadí)
Objekty, které jsou tvořeny skupinami dalších hodnot, se nazývají strukturované. (Pole, záznam, množina,
soubor, objekt)
Pole
Pole je homogenní struktura, skládající se ze složek stejného typu, které rozlišujeme pomocí indexů. (Vlastně
pořadové číslo prvku v poli) Delphi umožňují pracovat s polem statickým (v této kapitole), jehož velikost je
dána v okamžiku deklarace a dynamickým (za chviličku).
Definice statického pole
type JménoTypu = arrray[typ indexů] of TypPrvků
Příklady:
const n=20;
type cisla=array[1..n] of integer;
slova=array[1..100]of string;
cetnost=array[char] of integer;
mereni=array[1..n]of real;
kod=array[char]of char;
(Poslední pole se dá použít jako kódovací tabulka)
Typ indexů musí být ordinální, často se používá interval. Při deklaraci se vyhrazuje paměť – tedy zde např.
20*4B=80B pro objekt typu cisla. Typ prvků může být libovolný, rovněž strukturovaný.
Jako meze intervalů v indexech jsou ideální konstanty, v rozsáhlých programech změníme rozměr pole pohodlně
a bezpečně jediným zápisem.
Práce s proměnnou typu pole
var a,b: cisla; cet:cetnost;
Přepokládejme, že proměnná a obsahuje tato čísla:
21345678902456785894
pak a[1]=2, a[3]=3…a[10]=4
a[1]:=a[1]+1…změní hodnotu prvního prvku na 3.
I když pro pole téhož typu můžeme použít přiřazovací příkaz (a:=b), v dalších případech zpracováváme pole po
prvcích. (položkách)
For i:=1 to n do a[i]:=I; vytvoří pole 1 2 … 10
For i:=1 to n do listbox1.items.add(IntTostr(a[i])); výpis pole do listboxu
For ch:=’A’ to ‘Z’ do cet[ch]:=0; vynulování všech položek pole
V indexech prvků mohou být i výrazy. (a[2*i-1] )
Funkce low(a) a high(a) vracejí nejmenší hodnotu indexu – zde tedy 1 a 20.
Deklarace s anonymním typem
var x:array[1..n] of integer;
Ušetří nám sice práci se definicí typu, ale takové pole jednak nelze použít jako parametr podprogramů, jednak
nemůžete napsat příkaz x:=a; protože překladač je nepovažuje za tentýž typ.
Příklady
pro vstup budeme zatím používat generátor náhodných čísel.
PDF created with pdfFactory trial version www.pdffactory.com
1. Vygenerujte pole náhodných čísel, vytiskněte ho do Listboxu a zobrazte položku pole, jejíž index zadá
uživatel do Spineditu.
var i:integer;
begin for i:=1 to n do
a[i]:=random(20);
end;
var i:integer;
begin listbox1.clear;
for i:=1 to n do
listbox1.items.add(IntToStr(a[i]));
end;
…
showmessage(Inttostr(a[spinedit1.value]));
Prvky pole bychom mohli tisknout už během generování, ale protože se nimbuse hodit zobrazovat pole po
různých dalších úpravách, bude výhodné obě akce oddělit.
2. Vyměňte dva prvky pole, jejichž indexy zadá uživatel
Proceduru na výměnu dvou čísel nadeklarujeme globálně, abychom ji mohli používat v dalších příkladech.
procedure vymen(var x,y:integer);
var p:integer;
begin p:=x;
x:=y;
y:=p;
end;
procedure TForm1.Button9Click(Sender: TObject);
var i,j:integer;
begin i:=spinedit1.value;
j:=spinedit2.value;
vymen(a[i],a[j])
end;
3. Vygenerujte pole náhodných čísel, vytiskněte ho do Listboxu, vypočítejte aritmetický průměr, odchylky od
něj a ty vytiskněte do dalšího listboxu.
function prum(aa:cisla):real;
var s,i:integer;
begin s:=0;
for i:=1 to n do
s:=s+aa[i];
prum:=s/n;
end;
procedure TForm1.Button7Click(Sender: TObject);
begin showmessage(FloatToStrF(prum(a),fffixed,6,2))
end;
procedure TForm1.Button8Click(Sender: TObject);
var i:integer; p:real;
begin p:=prum(a);
for i:=1 to n do
listbox2.Items.Add(Floattostr(a[i]-p))
end;
Cvičení
1. Vytiskněte počet trojek ve vašem poli.
2. Zdvojnásobte položky pole a opět ho vytiskněte.
PDF created with pdfFactory trial version www.pdffactory.com
3. Nalezněte nejmenší prvek (je-li jich víc, nalezněte ten s nejmenším indexem) a vyměňte ho s prvním prvkem
pole. Upravené pole opět vytiskněte.
4. Otočte pole tak, aby první prvek byl poslední… Upravené pole opět vytiskněte.
Řešení
1.
pt:=0;
for i:=1 to n do if a[i]=3 then inc(pt);
showmessage(inttostr(pt));
2.
for i:=1 to n do a[i]:=2*a[i];
3.
var i,min,imin:integer; {imin je index prvniho nalezeneho minima}
begin min:=maxint; imin:=0;
for i:=1 to n do
if a[i]<min then
begin min:=a[i];
imin:=i;
end;
showmessage(inttostr(min));
vymen(a[1],a[imin]);
end;
4.
var i,p:integer;
begin p:=n div 2;
for i:=1 to p do
vymen(a[i],a[n-i+1]);
end;
20. Pole – vstup dat od uživatele, další příklady
při práci s polem je výhodné mít možnost zobrazovaná data prohlédnout – proto v následujících příkladech
použijeme vždy komponentu Listbox, přes který je také budeme načítat do statických polí. Data uložená
v listboxu jsou typu TStrings, což je objekt se spoustou metod (Zatím jsem používali metodu items.add(S:string)
pro přidání řetězce), jehož datovou část tvoří dynamické pole řetězců (na rozdíl od statického nemá délku
omezenou deklarací) K jednotlivým řádkům se dostaneme přes jejich index – items[i], první řádek má vždy
index nula.
V dalších příkladech budeme používat pole řetězců:
const n=10;
type slova=array[1..n] of string;
deklarované v části interface Unit1.
Na formulář si nachystáme dva Listboxy a Opendialog z Dialogs na paletě komponent. Postupně budeme
přidávat tlačítka pro události.
Procedura pro zobrazení statického pole do listboxu:
procedure ukaz(a:pole;l:Tlistbox);
var i:integer;
begin l.clear;
for i:=1 to n do
l.items.add(a[i]);
end;
Vstup dat z připraveného listboxu:
Položky připravíme do Listboxu v době návrhu programu pomocí StringList editoru (Vyvolá se klepnutím na
tlačítko se třemi tečkami u vlastnosti Items v inspektoru objektů)
procedure TForm1.Button1Click(Sender: TObject);
var i:integer;
PDF created with pdfFactory trial version www.pdffactory.com
begin if listbox1.items.count<N {aby stačila data}
then showmessage('malo dat')
else begin for i:=1 to n do b[i]:=listbox1.items[i-1];
ukaz(b,listbox2);
end;
end;
Vstup dat z editačního políčka
Do vstupního listboxu můžeme data také přidávat – například při stisknutí klávesy Enter v editačním políčku a
pak je použít.
procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
begin
if key=#13 then
begin listbox1.items.add(edit1.Text);
edit1.clear;
edit1.setfocus; {políčko je práydné a je v něm kuryor – čeká na další vstup}
end;
end;
Vstup dat z textového souboru
Data si můžeme připravit do textového souboru například v Poznámkovém bloku a načíst je do Listboxu
s pomocí klasického okenního dialogu pro otevření souboru – komponenta Opendialog.
procedure TForm1.Button2Click(Sender: TObject);
begin
if Opendialog1.execute {je-li vvykonán dialog}
then listbox1.items.loadFromFile(OPendialog1.filename);
{načteme obsah vybraného textového souboru do listboxu1.}
end;
Některé vlastnosti OpenDialogu:
InitialDir – výchozí složka
Filter – Texty|*.txt – druh zobrazovaných souborů v dialogovém okně, pohodlně se nastaví příslušným editorem
Title – text na titulní liště
Příklad:
Napište proceduru, která na jediný průchod najde současně největší a nejmenší číslo v poli reálných čísel.
Vyzkoušejte ji na předem připravené údaje v textovém souboru.
procedure TForm1.Button3Click(Sender: TObject);
type cisla=array[1..n]of integer;
procedure minimax(a:cisla;var min,max:integer);
var i:integer;
begin min:=maxint;
max:=-maxint;
{porovname
vzdy dva sousedy vzajemne, vetsiho z nich s maximem
a mensiho s minimem}
for i:=1 to n-1 do
if a[i]<a[+1] then
begin if a[i]<min then min:=a[i];
if a[i+1]>max then max:=a[i];
end
else
begin if a[i]>max then max:=a[i];
if a[i+1]<min then min:=a[i+1];
end;
if odd(n) {pokud nam zbylo posledni cislo}
then
if a[n]>max then max:=a[n]
else
PDF created with pdfFactory trial version www.pdffactory.com
if a[n]<min then min:=a[n];
end;
var b:cisla;mi,ma,i:integer;
begin if opendialog1.execute then
begin
listbox1.Items.LoadFromFile(opendialog1.filename);
for i:=1 to n do
b[i]:=strtoint(listbox1.Items[i-1]);
minimax(b,ma,mi);
showmessage(inttostr(ma)+' '+inttostr(mi));
end;
end;
Cvičení
1. Pracujte s polem řetězců, které si připravíte do Listboxu při návrhu programu. Posuňte nejdelší řetězec na
konec pole postupným probubláváním – procházejte pole po dvojicích a je-li kratší slovo před delším, vyměňte
je.
2. Připravte si dva textové soubory, do jednoho události, do druhého letopočty. Zobrazte je do dvou listboxů,
pokud uživatel zadá do editačního políčka letopočet, zobrazí se mu v dalším políčku událost.
3. Doplňte předchozí příklad zkoušením – na stisknutí tlačítka se náhodně vybere událost a uživatel k ní má
přiřadit letopočet.
Řešení
1.
procedure TForm1.Button4Click(Sender: TObject);
var i:integer;
procedure vymen(var a,c:string);
var p:string;
begin p:=a;a:=c;c:=p;
end;
begin for i:=1 to n-1 do
if length(b[i])>length(b[i+1])
then vymen(b[i],b[i+1]);
ukaz(b,listbox2);
end;
2.
var
Form1: TForm1;
…akce,roky:pole,;
…
procedure TForm1.Button2Click(Sender: TObject);
{nacteni dat}
var i:integer;
begin
if Opendialog1.execute
then listbox1.items.loadFromFile(OPendialog1.filename);
if Opendialog1.execute
then listbox2.items.loadFromFile(OPendialog1.filename);
for i:=1 to n do
begin akce[i]:=listbox2.items[i-1];
roky[i]:= listbox1.items[i-1];
{oba soubory nacteme najednou}
end;
end;
PDF created with pdfFactory trial version www.pdffactory.com
procedure TForm1.Button5Click(Sender: TObject);
var i:integer;
begin i:=1;
while (i<=n) and (roky[i]<>edit1.Text)do
{vyhledame index letopoctu}
inc(i);
if i>n then showmessage('nemame')
else
edit2.Text:=akce[i];{zobrazime událost}
end;
procedure TForm1.Button6Click(Sender: TObject);
begin
randomize;
k:=random(n)+1; {k je deklarovana globalne, aby se dala pouzit i v nasledujici procedure}
edit1.Text:=roky[k];
edit2.clear;
edit2.setfocus;
{nahodny letopocet}
end;
procedure TForm1.Edit2KeyPress(Sender: TObject; var Key: Char);
{když uživatel odesle Enterem slovo v Edit2, provede se kontrola}
var i:integer;
begin
if key=#13
then
begin if edit2.text=akce[k]
then showmessage('spravne')
else showmessage('spravne ma byt '+akce[k]);
edit1.clear;
edit2.clear;
edit2.SetFocus;
end;
end;
21. Vyhledávání v poli
Velmi častý problém, se kterým se v praxi můžeme setkat je zjistit, zda se v poli údajů vyskytuje nějaký prvek,
případně kde je. (Například chceme editovat nebo odstranit určitý záznam v databázi). Pro tento účel existují
nejen různé algoritmy, ale byly také vytvořeny zajímavé datové struktury jako vyhledávací sitě, binární
vyhledávací stromy apod.
Za daných okolností bývá určitý způsob vyhledávání, případně použití určitého druhu dat vhodnější než jiný, to
je třeba zvážit podle konkrétního problému.
Efektivnost vyhledávacích algoritmů většinou poměřujeme počtem operací srovnání, které algoritmus potřebuje.
Počet prvků dále uvažujeme n, hledáme v poli a, vyhledávaný prvek bude x. Funkce, které budme psát mohou
vracet true nebo false („Našli moji rádcové princezničku?“), případně index prvního výskytu.
Sekvenční vyhledávání v nesetříděné struktuře
Můžeme projít celé pole cyklem for:
function jetam1(a:pole;x:integer):integer;
{vraci posledni index vyskytu nebo 0 kdyz neni}
var i,pom:integer;
begin pom:=0;
for i:=1 to n do
if a[i]=x then pom:=i;
jetam1:=pom;
PDF created with pdfFactory trial version www.pdffactory.com
end;
Tento způsob ovšem není příliš efektivní pokud byste chtěli první výskyt prvku – pak je při jeho objevení lepší
skončit.
Procházíme celá data, pokud vyhledávaný prvek nalezneme, uknočíme vyhledávání. Pokud bychom použili po
procházení složenou podmínku:
While (a[i]<>x) and (i<=n){ dosud nenalezen hledaný prvek a ještě nejsem na konci}
může vzniknout problém když prvek nenajdeme – naposled se bude vyhodnocovat a[n+1] a překročíme rozsah
indexů. Problém lze vyřešit pomocnou logickou proměnnou, (další procedura), tento algoritmus se dá dobře
používat i v dalších datových strukturách.
Složitost v nejhorším případě n – pokud prvek v poli není a je nutné ho projít celé
function Jetam(b:pole;x:integer):boolean;
var nasel:boolean;i:integer;
begin i:=1;
nasel:=false;
while not nasel and(i<=n) do
if b[i]=x then nasel:=true
else inc(i);
jetam:=nasel;
end;
Zarážka
Vyhledávaný prvek se umístí na konec pole, takže není nutné testovat první podmínku. Složitost je asi o 20%
lepší, v nejhorším případě stejná.
function zarazka (b:pole;x:integer):boolean;
{pole ovšem na zacatku musite deklarovat vetsi array[1..n+1] of integer}
var i:integer;
begin b[n+1]:=x;
i:=1;
while b[i]<>x do
inc(i);
zarazka:=(i<=n)
end;
Binární vyhledávání v setříděné posloupnosti
Prvek porovnáme s prostředním, je-li menší, opakujeme hledání v první polovině struktury, je-li větší, ve druhé.
Při prvním porovnání tak vyřadíme polovinu prvků, při druhém čtvrtinu…v nejhorším případě odpovídá počet
porovnání:log2n
Tento způsob je sice nejefektivnější, ale setříděná posloupnost se příliš nehodí pro udržování. (Například při
vkládání na určitou pozici je zase nezbytné zbytek posloupnosti odsunout sekvenčním způsobem.)
function binvyh(b:pole;x:integer):boolean;
var i,j,s:integer;
begin i:=1;
j:=n;
repeat s:=(i+j) div 2; {index prostredniho prvku v akyalni casti pole}
if x>=b[s] then i:=s+1; {jdeme doprava}
if x<=b[s] then j:=s-1; {jdeme doleva}
until i>j;
binvyh:=(x=b[s])
end;
Cvičení
1.
Načtěte pole čísel z textového souboru a implementujte vyhledávací funkce.
Dále:
PDF created with pdfFactory trial version www.pdffactory.com
2.
3.
Upravte funkci s FOR cyklem tak, aby vracela první výskyt prvku.
Vygenerujte setříděné pole náhodných čísel a vyzkoušejte algoritmus binárního vyhledávání.
Řešení
Type
…
pole =array[1..n+1]of integer;
var
Form1: TForm1;
a:pole;
…
function jetam5(a:pole;x:integer):integer;
{vraci prvni index vyskytu nebo 0 kdyz neni - nejrychlejsi reseni s unikem z cyklu neodpovida pravidlum
strukturovaneho programovani}
var i,pom:integer;
begin pom:=0;
for i:=1 to n do
if a[i]=x then begin pom:=i;
break;
end;
jetam5:=pom;
end;
procedure TForm1.Button2Click(Sender: TObject);
{vyvolani libovolne vyhledvaci funkce}
begin
if jetam5…5(a,spinedit1.value)<>0
then showmessage('Našli na '+Inttostr(jetam55(a,spinedit1.value)))
else showmessage('Nenašli')
end;
procedure TForm1.Button4Click(Sender: TObject);
{generovani setrideneho pole}
var i,d:integer;
begin
a[1]:=0;
listbox1.items.add(inttostr(a[1]));
for i:=2 to n do
begin d:=random(5);
a[i]:=a[i-1]+d;
listbox1.items.add(inttostr(a[i]));
end;
end;
22. Třídění
aneb
jak ukládat data, aby k nim byl snadný přístup
Problém: je dáno pole A[1]..A[n] nějakých prvků (v praxi tvorby informačních systémů nejčastěji záznamů
databází)
Chceme, aby po proběhnutí třídícího algoritmu platilo:
a[1]<=a[2]<=… a[n]
U záznamů třídíme podle jedné (v případě rovnosti podle další…) položky, které se říká třídící klíč.
Několik algoritmů a jejich složitost
(opět porovnáváme počet srovnávacích operací, ve všech programových ukázkách třídíme pole, které má n
celých čísel)
PDF created with pdfFactory trial version www.pdffactory.com
Vsouvání
a[1]<=a[2]<=…a[k] a[k+1] ? a[k+2]…? a[n]
První část pole je setříděna, chceme zařadit další prvek. Začneme ho porovnávat se zařazenými prvky, když
zjistíme místo, kam patří, zbytek odsuneme o jedno místo doprava.
Složitost v nejhorším případě (opačně setříděné pole): n+n-1+…3+2+1 = n*(n-1)/2
~ n2 – kvadratický
algoritmus
Nejlepší případ – setříděná posloupnost, složitost ~ n.
(Na umístění jednoho prvku potřebujeme jedno porovnání)
var i,j,x:integer;
begin
p[0]:=-maxint;
for i:= 2 to n do
begin j:=i;
x:=p[i]; {dosud nezařazený prvek}
while p[j-1]>x do begin p[j]:=p[j-1];
dec(j);
end;
p[j]:=x;
end;
end;
Přímý výběr
Nejprve najdeme minimum, vyměníme ho s prvním prvkem a pakpokračujeme dál:
yabýváme se vždy úsekem pole od i do n, vyhledáme v něm minimum a vyměníme ho s i-tým prvkem.
Složitost je opět kvadratická, navíc nerozlišuje nejlepší a nejhorší případ.
(Rychlost při spuštění na počítači vyplývá z toho, že údaje pro for-cykly se připravují do cache procesoru, čímž
se zpracovámí zrychlí)
var i,j,imin:integer;
begin
for i:=1 to n-1 do
begin imin:=i;
for j:=i to n do
if p[j]<p[imin] then imin:=j;
vymen(p[i], p[imin]);
end;
end;
Třídění probubláváním
Procházíme pole po dvojicích a je-li větší prvek před menším, vyměníme je. Po prvním průchodu se dostane
největší prvek nakonec. Po druhém průchodu můžeme podobně zařadit na předposlední místo druhý největší
prvek atd.
Vylepšení: Při každém průchodu evidujeme, zda jsem vyměňovali a algoritmus ukončíme, když se
nevyměňovalo. (setříděné pole)
var i,j:integer;
begin
for i:=n downto 2 do {kam az bublame}
for j:=1 to i-1 do {bublani}
if p[j]>p[j+1] then vymen (p[j],p[j+1]);
end;
var i:integer;b:boolean;
begin repeat b:=false; {dosud se nic nevymenovalo}
for i:=1 to n-1 do
if p[i]>p[i+1] then
begin vymen(p[i],p[i+1]);
b:=true;
end
until not b;
end;
PDF created with pdfFactory trial version www.pdffactory.com
Cvičení:
1. Vygenerujte pole náhodných čísel, připravte si listboxy pro zobrazení setříděného a nestříděného pole a
vyzkoušejte si uvedené algoritmy.
2. Protože jsou celá čísla ordinální, dají se velmi rychle setřídit s využitím jejich četnosti – při prvním průchodu
polem zjistíme četnost jednotlivých prvků, (k tomu použijeme pole cetnost[i] – kde např. cetnost[3]=4 znamená,
že v původním poli jsou čtyři trojky) a potom do pole umístíme postuně každý prvek tolikrát, kolikrát je v poli
cetnost. (Druhý průchod)
Předpokládáme, že generujeme jednociferná čísla.
var cet:array[0..9]of integer;i,j,k:integer;
begin
for i:=0 to 9 do cet[i]:=0;
for i:=1 to n do inc(cet[a[i]]);
{ listbox2.items.add(inttostr(cet[i])); pomocné zobrazení vypočítaných četností}
k:=1;
for i:=0 to 9 do
for j:=1 to cet[i] do
begin a[k]:=i;
inc(k);
end;
for i:=1 to n do
listbox2.items.add(inttostr(a[i]));
end;
23. Dimenzionání pole – seznámení
Složky pole moho být strukturované je-li jejich typem opět pole, původní pole se nazývá dimenzionální.
Var M:array[a..b]of array[c..d]of T
Užívá se zkrácený zápis array[a..b,c..d]of T, v obou případech jde o stejný typ pole.
M[i] – i-tý řádek pole, M[i,j] – prvek v i-tém řádku a j-tém sloupci.
Pokud máme definován typ:
Type dimpole=array[1..n,1..n]of integer;
Var a,b:dimpole;
Můžeme použít přiřazovací příkaz a:=b.
Pozor, pro pole deklarovaná s anonymním typem
Var a: array[1..n,1..n] of integer;
B: array[1..n,1..n]of integer;
se toto přiřazení použít nedá.
Zatím můžeme dvojrozměrné pole zobrazit do Listboxu, příště se seznámíme s komponentou Stringgrid, se
kterou vytváříme tabulky s excelovským exteriérem.
Dvojrozměrným tabulkám čísel se v matematice říká matice a užívali jsme je například k řešení soustav
lineárních rovnic.
Poznámka: dají se používat i pole vícerozměrná, ale při velkém počtu indexů se v nich snadno ztrácí orientace.
Příklad:
abcd
efgh
* #%&
můžeme deklarovat jako
type dimpole=array[1..3,1..4] of char;
var a:dimpole;
a[1,2]=b; a[3,1]=*…
Příklad
Budeme deklarovat obdélníkovou tabulku celých čísel. Naplníme ji ze generátoru náhodnými jednocifernými
čísly, zobrazíme a naučíme se ní pracovat na následujících příkladech:
1. Výpis prvního řádku
2. Součet posledního sloupce
3. Nalezení největšího čísla matice a určení počtu těchto maxim.
PDF created with pdfFactory trial version www.pdffactory.com
const n=10; m=5;
type
pole=array[1..m,1..n]of integer;
var
Form1: TForm1;
b:pole;
…
procedure ukaz(a:pole; l:Tlistbox);
{zobrazeni tabulky do pole po radcich, ktere si pripravime do retezcu:
var i,j:integer; s:string;
begin l.clear;
for i:=1 to m do
begin
s:='';
for j:=1 to n do
s:=s+inttostr(a[i,j])+' ';
l.Items.add(s);
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
{naplneni a zobrazeni}
var i,j:integer;
begin randomize;
for i:=1 to m do
for j:=1 to n do
b[i,j]:=random(10);
ukaz(b,listbox1);
end;
procedure TForm1.Button2Click(Sender: TObject);
{1. radek}
var i:integer;s:string;
begin s:='';
for i:=1 to n do
s:=s+inttostr(b[1,i])+' ';
showmessage(s);
end;
procedure TForm1.Button3Click(Sender: TObject);
{soucet posledního sloupce}
var i,s:integer;
begin s:=0;
for i:=1 to m do
s:=s+b[i,n];
showmessage(inttostr(s));
end;
procedure TForm1.Button5Click(Sender: TObject);
{maximum a počet jeho vyskytu}
var i,j,max,pmax:integer;
begin max:=0;
pmax:=0;
for i:=1 to m do
for j:=1 to n do
if b[i,j]>max then begin max:=b[i,j];
pmax:=1;
end
PDF created with pdfFactory trial version www.pdffactory.com
else
if b[i,j]=max then inc(pmax);
showmessage(inttostr(max)+' '+inttostr(pmax));
end;
Cvičení
Pracujte dál s tabulkou z předchozího příkladu a naprogramujte řešení následujících problémů:
1. Počet dvojek ve sloupci, jehož číslo zadá uživatel
2. Maximum třetího sloupce
3. Počet sudých čísel v matici
Řešení
procedure TForm1.Button6Click(Sender: TObject);
var p,i,k:integer;
begin
k:=spinedit1.value;
p:=0;
for i:=1 to m do
if b[i,k]=2 then inc(p);
showmessage(inttostr(p));
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
spinedit1.MinValue:=1;
spinedit1.MaxValue:=n;
{nastaveni spineditu pro vyber sloupce}
end;
procedure TForm1.Button4Click(Sender: TObject);
var max,i,k:integer;
begin
max:=-1;;
for i:=1 to n do
if b[3,i]>max then max:=b[3,i];
showmessage(inttostr(max));
end;
procedure TForm1.Button7Click(Sender: TObject);
var i,j,p:integer;
begin p:=0;
for i:=1 to m do
for j:=1 to n do
if not odd(b[i,j])then inc(p);
showmessage(inttostr(p));
end;
24. Procvičování dimenzionálního pole
Vstup dat od uživatele
Stejně jako u u jednorozměrného pole můžeme data pro tabulky načítat z komponent Delphi nebo textových či
binárních souborů.
Ukážeme si vstup z editačního políčka, u textových souborů – pokud by byly ve tvaru tabulek, bychom museli
nejprve „rozebrat“ jednotlivé řádky na čísla.
const n=4;
type
PDF created with pdfFactory trial version www.pdffactory.com
pole=array[1..n,1..n]of integer;
var
Form1: TForm1;
i,j:integer; {indexy pro zadavani}
a:pole;
procedure ukaz(a:pole;l:Tlistbox);
…
procedure TForm1.FormCreate(Sender: TObject);
begin
i:=1;j:=1;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin if (i<=n) and (j<=n) then
begin a[i,j]:=spinedit1.value;
if j=n {prechod na dalsi radek}
then begin j:=1;inc(i);
end
else inc(j); {prechod na dalsi prvek}
label1.caption:='Zadej prvek a['+
inttostr(i)+','+inttostr(j)+']'
end
else
label1.Caption:='hotovo' ;
ukaz(a,listbox1);
{prubezne zobrazeni tabulky}
end;
Další příklady:
(Procvičování práce s dvojrozměrným polem, procedurami a funkcemi)
Pracujte s čtvercovou tabulkou náhodně vygenerovaných celých čísel.
1. Definujte funkce pro součet čísel v k-tém sloupci a vypište pod zobrazenou tabulku součty sloupců.
2. Vyhledejte maximum hlavní diagonály. (úhlopříčka z levého horního do pravého dolního rohu tabulky)
3. Vyměňte sloupce, jejichž čísla zadá uživatel. Použijte proceduru na výměnu dvou sloupců a v ní proceduru na
výměnu dvou celých čísel. (Deklarujte ji globálně, aby se dala použít i jinde)
4. Setřiďte vzestupně řádek, jehož číslo zadá uživatel.
5. Určete počet nul pod hlavní diagonálou.
Řešení
1.
function sum(k:integer;a:pole):integer;
var s,i:integer;
begin s:=0;
for i:=1 to m do
s:=s+a[i,k];
sum:=s;
end;
procedure TForm1.Button2Click(Sender: TObject);
var i:integer; s:string;
begin listbox1.items.add('________________________');
for i:=1 to n do
s:=s+' '+inttostr(sum(i,b));
listbox1.items.add(s);
end;
2.
Není nutné používat dvou vnořených cyklů, stačí si uvědomit, že řádkový a sloupcový index hlavní diagonály
jsou stejné. (Podobně pro vedlejší diagonálu jsou indexy [i,n-i+1]
procedure TForm1.Button5Click(Sender: TObject);
PDF created with pdfFactory trial version www.pdffactory.com
var i,max:integer;
begin max:=-1;
for i:=1 to n do
if aa[i,i]>max then max:=aa[i,i];
showmessage(inttostr(max));
end;
3.
procedure vymen(var x,y:integer);
var p:integer;
begin p:=x;x:=y;y:=p;
end;
procedure vymensloupce(i,j:integer;var b:pole);
var k:integer;
begin for k:=1 to n do
vymen(b[k,i],b[k,j]);
end;
procedure TForm1.Button3Click(Sender: TObject);
var p,q:integer;
begin p:=spinedit1.Value;
q:=spinedit2.Value;
vymensloupce(p,q,aa);
ukaz(aa,listbox2);
end;
4.
procedure tridradek(i:integer;var b:pole);
var bu:boolean;k:integer;
begin repeAT bu:=false;
for k:=1 to n-1 do
if b[i,k]>b[i,k+1] then
begin vymen(b[i,k],b[i,k+1]);
bu:=true;
end;
until not bu;
end;
procedure TForm1.Button4Click(Sender: TObject);
var p:integer;
begin p:=spinedit1.Value;
tridradek(P,AA);
ukaz(aa,listbox2);
end;
5.
procedure TForm1.Button2Click(Sender: TObject);
var i,j,p:integer;
begin p:=0;
for i:=1 to n do
for j:=1 to i-1 do
if aa[i,j]=0 then inc(P);
showmessage(inttostr(p));
end;
PDF created with pdfFactory trial version www.pdffactory.com
25. Komponenta StringGrid a zobrazení tabulek
Kdybychom chtěli pracovat s dvojrozměrným polem řetězců nebo čísel s různými počty cifer, museli bychom si
připravit složitější zobrazovací procedury.
Delphi mají komponentu StringGrid na paletě Additional, tabulku, která slouží k zobrazení řetězců a je navržena
podle spreadsheetů v tabulkových kalkulátorech. Kromě buněk pro zobrazení disponuje dalšími vlastnostmi a
funkcemi, z nichž s některými se seznámíme.
Vlastnosti:
ColCount, RowCount – počet sloupců, řádků (číslováno od nuly)
Cells[Col, Row]:string obsah buňky ve sloupci col a řádku row.
Př. Stringgrid1.cells[2,2]:='blabla’;
Fixed…0. řádek a sloupec – obvykle barevně odlišný (Fixcolor)
Procházení tabulkou:
For i:=0 to stringgrid1.colcount-1 do
For j:=0 to stringgrid1.rowcount-1 do…
Zobrazení dvourozměrného pole tabulkou
procedure ukaz(a:tabulka);
var i,j:integer;
begin for i:=1 to n do
for j:= 1 to n do
form1.stringgrid1.cells[j,i]:=inttostr(a[i,j])
end;
(u dvourozměrného pole je první index řádkový, zatímco u StrngGridu sloupcový)
Událost OnSelectCell: (klapnutí myši do tabulky)
procedure TForm1.StringGrid1SelectCell(Sender: TObject; ACol,
ARow: Integer; var CanSelect: Boolean);
begin
edit1.Text:=stringgrid1.Cells[Acol,ARow];
end;
zkopíruje aktuální buňku do editačního okna.
Jednotlivé sloupce nebo řádky jsou typu TStrings – jako např. items listboxu.
Stringgrid1.cols[1]:=listbox1.items; zkopíruje obsah listboxu do 1. sloupce tabulky.
Více – nápověda Delphi.
Příklad
Připravte si do dvou listboxů slovníček – do každého slovíčka v jednom jazyce, ekvivalenty v těchže řádcích.
Přeneste je do dvou sloupců stringgridu a potom klepne-li uživatel do buňky, zobrazí se slovíčko ve druhém
jazyce.
procedure TForm1.FormCreate(Sender: TObject);
var i:integer;
begin for i:=1 to listbox1.Items.Count do
stringgrid1.Cells[0,i]:=inttostr(i);
stringgrid1.RowCount:=listbox1.Items.Count ;
stringgrid1.colcount:=3;
stringgrid1.Cols[1]:=listbox1.items;
stringgrid1.cols[2]:= listbox2.items;
{1.radek v listboxech nechame prazdny, prepise se titulkem}
stringgrid1.Cells[1,0]:='èesky';
stringgrid1.cells[2,0]:='anglicky';
end;
procedure TForm1.StringGrid1SelectCell(Sender: TObject; ACol,
ARow: Integer; var CanSelect: Boolean);
begin
if acol=1 then showmessage(stringgrid1.Cells[2,arow])
else
PDF created with pdfFactory trial version www.pdffactory.com
if acol=2 then showmessage(stringgrid1.Cells[1,arow])
end;
Poznámky:
Options: GoEditing na true – jde přímo editovat
Výběr oblasti:
procedure TForm1.Button1Click(Sender: TObject);
var
myRect: TGridRect;
begin
myRect.Left := 1;
myRect.Top := 1;
myRect.Right := 10;
myRect.Bottom := 10;
StringGrid1.Selection := myRect;
end;
Analogicky lze získat souřadnice obdélníkové pravoúhlé oblasti:
procedure TForm1.Button3Click(Sender: TObject);
var a,,c,d:integer;
myRect: TGridRect;
begin
Myrect:=StringGrid1.Selection;
a:=myRect.Left;
b:=myRect.Top;
c:=myRect.Right;
d:=myRect.Bottom;
end
Cvičení
Vygenerujte čtvercovou tabulku náhodných celých čísel. Připravte si dva StringGridy, do jednoho zobrazte
původní tabulku a do druhého modifikace:
1. Setřiďte vedlejší diagonálu vzestupně
2. Zobrazte jednotkovou matici – tj. matici, která má na hlavní diagonále samé jedničky a jinak nuly
3. Vytvořte matici transponovanou (vyměňte sloupce a řádky)
4. Vyměňte hlavní a vedlejší diagonálu
5. Zobrazte Strinnggrid, který bude vypadat, jako tabulka v Excelu – sloupce označené písmeny, řádky
čísly.
Řešení
1.
procedure TForm1.Button4Click(Sender: TObject);
var i:integer; bu:boolean;
begin repeat bu:=false;
for i:=1 to n-1 do
if b[i,n-i+1]>b[i+1,n-i] then
begin bu:=true;
vym( b[i,n-i+1],b[i+1,n-i])
end
until not bu;
viz(b,stringgrid1);
end;
2.
procedure TForm1.Button3Click(Sender: TObject);
var i,j:integer;
begin for i:=1 to n do
for j:=1 to n do if i=j then jed[i,j]:=1
else jed[i,j]:=0;
end;
PDF created with pdfFactory trial version www.pdffactory.com
4.
procedure TForm1.BitBtn2Click(Sender: TObject);
var i:integer;
begin for i:=1 to n do
vymen(a[i,i],a[i,n-i+1]);
end;
3.
procedure TForm1.Button1Click(Sender: TObject);
{vymenime cisla osove soumerna podle hlavni diagonaly}
var i,j:integer;
begin for i:=1 to n do
for j:=1 to i-1 do
vymen(a[i,j],a[j,i]);
end;
5.
procedure TForm1.Button3Click(Sender: TObject);
var a:char;i:integer;
begin a:='A';
for i:=1 to n do begin stringgrid1.cells[i,0]:=a;
inc(a);
end;
a:='1';
for i:=1 to n do begin stringgrid1.cells[0,i]:=a;
inc(a);
end;
end;
26. Statické pole v procedurách a funkcích, opakování
Shrňme si klady a zápory statických polí:
Výhody:
§ Možnost uložit více hodnot stejného typu v jedné proměnné
§ Snadná manipulace s daty prostřednictvím indexů
§ Možnost volit rozsah indexů, indexovat i jinými typy než celočíselnými
Nevýhody:
§ Velikost pole nelze měnit za běhu programu, takže se musí na začátku nadeklarovat maximální potřebná
velikost
§ Protože velikost pole musí být známa v době překladu, nedá se ani měnit, ani nastavit, což by omezovalo
použití polí jako parametrů podprogramů. (Velká nevýhoda původního Pascalu)
Řešením posledního problému v Delphi je možnost pracovat s otevřeným polem.
Práce s otevřeným polem
V deklaraci formálních parametrů se uvede pouze typ pole, jehož velikost se doplní podle velikosti skutečného
parametru.
Skutečnou velikost pole v proceduře pak zjistíme pomocí standardních funkcí Low High,
Protože Low vrací vždycky nulu a high počet prvků v poli, je třeba indexy vhodně posouvat a nejraději
indexovat od nuly.
Příklad
Nadeklarujeme dvě celočíselná pole různé délky, naplníme je a zobrazíme v listboxu toutéž procedurou.
const n=20;
type cisla1=array[0..n]of integer;
cisla2=array[0..2*n]of integer;
{pole n+1=10 celych cisel}
var
PDF created with pdfFactory trial version www.pdffactory.com
Form1: TForm1;
a:cisla1;
b:cisla2;
procedure ukaz(a:array of integer;l:Tlistbox);
var i:integer;
begin l.clear;
for i:=0 to high(a) do
l.items.add(inttostr(a[i]));
end;
procedure TForm1.Button1Click(Sender: TObject);
var i:integer;
begin
for i:=0 to n do
a[i]:=i;
for i:=0 to 2*n do b[i]:=i;
ukaz(a,listbox1);
ukaz(b,listbox2);
end;
Násobení matic
Matice lze sčítat, násobit reálným číslem (c[i,j]:=a[I,j]+b[I,j], c[I,j]:=k[a[i,j]), ale také násobit vzájemně.
n
ci , j = ∑ a[i, k ] * b[k , j ]
k =1
Příklad:
1 2 0 2  2 8 

 * 
 = 

 3 4   1 3   4 18 
matice=array[1..n,1..n]of integer;
…
procedure nasob(a,b:matice;var c:matice);
var i,j,k,p:integer;
begin
for i:=1 to n do
for j:=1 to n do
begin p:=0;
for k:=1 to n do
p:=p+a[i,k]*b[k,j];
c[i,j]:=p;
end;
end;
Při násobení matice jednotkovou maticí, dostaneme původní matici. (Vyzkoušejte)
Cvičení
Pracujte s čtvercovou tabulkou náhodně vygenerovaných celých čísel a dvěma StringGridy, jedním pro
zobrazení původní tabulky, druhým pro zobrazení úprav.
1. Setřiďte matici tak, že bude platit: a[1,1]<=a[1,2]<=..a[2,1]<=a[2,2]…<=a[n.n].
2. Setřiďte matici tak, že povyměňujete řádky, aby se jejich obsah nezměnil a první sloupec byl setříděn
vzestupně.
Řešení
1.
procedure TForm1.Button3Click(Sender: TObject);
{matici nejprve prerovname do jednorozmerneho pole, to setridime a prevedeme napzatek}
var c:array[1..n*n]of integer;i,j,k,p:integer;
bu:boolean;
begin k:=1;
PDF created with pdfFactory trial version www.pdffactory.com
for i:=1 to n do
for j:=1 to n do
begin c[k]:=b[i,j];
inc(k);
end;
repeat bu:=false;
for i:=1 to n*n-1 do
if c[i]>c[i+1] then
begin p:=c[i];
c[i]:=c[i+1];
c[i+1]:=p;
bu:=true;
end;
until not bu;
k:=1;
for i:=1 to n do
for j:=1 to n do
begin b[i,j]:=c[k];
inc(k);
end;
ukaz(b,stringgrid2);
end;
2.
procedure vymen(var x,y:integer);
var p:integer;
begin p:=x;x:=y;y:=p;end;
procedure radky(x,y:integer;var b:pole);
var i:integer;
begin for i:=1 to n do
vymen(b[x,i],b[y,i]);
end;
procedure TForm1.Button2Click(Sender: TObject);
var j:integer;bu:boolean;
begin
repeat bu:=false;
for j:=1 to n-1 do
if a[j,1]>a [j+1,1]
then begin radky(j,j+1,a);
bu:=true;
end
until not bu;
end;
27. Dynamické pole
V klasickém Pascalu je pole je statická struktura, jeho velikost musí být známa již v době překladu. (deklarace)
V C++, Delphi od verze 4 existuje dynamické pole, které nemá pevně stanovenou délku.
Deklarace:
type Dynpole=array of Zakladnityp;
var a: Dynpole…
Před prvním použitím je nutné nastavit jeho velikost a alokovat tak volný blok paměti.
SetLength(a,10) … v paměti se vyhradí prostor pro 10 hodnot základního typu.
Pak s ním lze pracovat běžným způsobem (a[3]:=4…)
Indexy dynamických polí začínají vždy od nuly. Zde: 0..9.
Nejvyšší index – High(a)
Nejnižší index – Low(a) – vrací vždy 0.
Změna velikosti pole za běhu programu:
PDF created with pdfFactory trial version www.pdffactory.com
Zvětšení rozsahu: SetLength
Zmenšení: a:=copy(a,0,5) – v poli A zůstane 5 prvků od pozice 0.
Celé pole se zruší: a:=nil;
V paměti vyhrazené programu je ve skutečnosti jen ukazatel (adresa) jiné části paměti, které se říká halda a na
kterou se ukládají objekty dynamicky alokované za běhu programu. Nil je ukazatel nikam.
Pokud dojde k překročení rozsahu indexů, nevzniká chyba, ale programátor by měl všechny podobné problémy
správně ošetřit.
Velikost objektu v Bytech obecně určuje funkce SizeOf(object), u dynamického pole ale vždy vrací 4B –
velikost ukazatele.
Přiřazování polí
Statické: obsah se zkopíruje, takže v paměti existují dvě stejná pole
Dynamické – do nové proměnné se přiřadí pouze ukazatel na existující pole.
Změníme-li něco v novém poli, změní se to i v původním. Proto například není možné vyměnit dva objekty typu
Tstrings (např. items listboxu) přes třetí, ale pouze pomocí pomocného statického pole.
Příklady:
1. Zadejte řadu příjmení postupným přidáváním do listboxu, načtěte je do dynamického pole a upravte tak, že,
pokud je poslední písmeno – á, připojíte před řetězec slovo paní, jinak slovo pán. Vyhledejte nejdelší jméno.
type pole=array of string;
var
Form1: TForm1;
a:jmena;
implementation
{$R *.DFM}
procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
{pridani polozky do listboxu}
begin
if key=#13 then
begin listbox1.items.add(edit1.text);
Edit1.clear;
edit1.setfocus;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var i,n:integer;p:char;max:string;
begin n:=listbox1.items.count;
setlength(a,n); max:='';
for i:=0 to high(a) do
begin
a[i]:=listbox1.items[i];
if length(a[i])>length(max) then
max:=a[i];
end;
showmessage(max);
end;
procedure TForm1.Button2Click(Sender: TObject);
var i:integer; x:string;
begin
for i:=0 to high(a) do
begin x:=a[i];
if x[length(x)]='á' {poslední písmenko slova – s řetězcem lze pracovat jako s polem znakú}
then a[i]:='paní '+a[i]
else a[i]:='pan '+a[i];
PDF created with pdfFactory trial version www.pdffactory.com
end;
listbox1.clear;
for i:=0 to high(a) do
listbox1.items.add(a[i]);
end;
2. Vygenerujte řadu náhodných čísel do dynamického pole a zobrazte je do Listboxu. Nechte pak zadat
uživatele číslo a pole přerovnejte tak, aby na jeho začátku byla čísla menší než zadané číslo, za nimi pak čísla
větší než zadané číslo.
Indexem i procházíme pole zleva, indexem j zprava. Když narazíme na prvky, které do svých částí pole nepatří,
vyměníme je. Postup opakujeme tak dlouho, dokud nezkřížíme indexy i a j.
procedure TForm1.Button1Click(Sender: TObject);
{nastavi delku pole podle požadavku uživatele}
begin
setlength(a,spinedit1.Value);
end;
procedure ukaz(b:pole;l:Tlistbox);
{zobrazi pole do listboxu}
var i:integer;
begin l.Clear;
for i:=0 to high(b) do
l.Items.add(IntToStr(b[i]));
end;
procedure TForm1.BitBtn1Click(Sender: TObject);
{vygeneruje pole a zobrazi ho}
vAR i:integer;
begin listbox1.Clear;
for i:=0 to high(a) do
a[i]:=random(20);
ukaz(a,listbox1);
end;
procedure TForm1.BitBtn2Click(Sender: TObject);
{prerovnani}
var x,i,j:integer;
begin x:=spinedit1.Value;
i:=0;
j:=high(a);
repeat
while a[i]<x do inc(i);
while a[j]>x do dec(j);
if i<=j then begin vymen(a[i],a[j]);
inc(i);
dec(j);
end;
until i>j;
ukaz(a,listbox2);
end;
Dvojrozměrné dynamické pole
type TMessageGrid = array of array of string;
var a: TMessageGrid;
Pokud pracujeme s obdélníkovým polem můžeme ho zpracovávat obvyklým způsobem:
setlength(a,10,20);
Je možné také vytvářet pole, jejich řádky mají různý počet prvků.
PDF created with pdfFactory trial version www.pdffactory.com
var Ints: array of array of Integer;
SetLength(Ints,10);
SetLength(Ints[2], 5); – druhý řádek bude mít pět prvků.
Příklad: Vytvoření trojúhelníkové matice řetězců
var
A : array of array of string;
I, J : Integer;
begin
SetLength(A, 10);
for I := 0 to High(A) do
begin
SetLength(A[I], I);
for J := 0 to High(A[I]) do
A[I,J] := IntToStr(I) + ',' + IntToStr(J) + ' ';
end;
end;
Cvičení
1. Vygenerujte dynamické pole náhodných čísel do listboxu, seřaďte jeho prvky tak, že nejprve budou čísla
lichá, potom čísla sudá, na pořadí nezáleží.. (Pokuste se obejít bez pomocného pole)
2. Napište program pro výpis všech prvočísel menších než dané číslo. (Zadá uživatel). Použijte algoritmus
Eratosthenova síta: Začneme dvojkou a vyškrtáme z pole všechny násobky dvou. (kromě dvojky). Pak
pokračujeme dál – ponecháme trojku a vyškrtáme všechny násobky trojky…až v poli zůstanou pouze prvočísla.
Řešení
1.
procedure TForm1.BitBtn3Click(Sender: TObject);
var i,l,s:integer; {liche zleva, sude zprava}
begin l:=1;s:=high(a);
for i:=1 to high(a) do
if odd(a[i]) then
begin a[l]:=a[i];
inc(l);
end
else
begin a[s]:=a[i];
dec(s);
end;
ukaz(a,listbox3);
end;
2.
procedure TForm1.prvoci2Click(Sender: TObject);
var a:array of boolean; n:integer;
d,p,i:integer;
begin n:=strtoint(edit1.Text);
setlength(a,n+1);
for i:=2 to n do a[i]:=true; {a[5]=true znamena, ze se 5 v poli nachazi. Nejprve tam tedy
umistime vsechna cisla mensi nez dane}
for i:=2 to n do
begin d:=2*i;
while d<=n do begin a[d]:=false;;
d:=d+i; {vyskrtavani nasobku i}
end;
end;
memo1.Lines.clear;
for i:=2 to n do
PDF created with pdfFactory trial version www.pdffactory.com
if a[i] then listbox11.items.add(inttostr(i));
end;
Obsah
1. Úvod, Algoritmus a jeho charakteristiky........................................................................................................ 1
2. Dephi – úvod do prostředí, Object Pascal – úvod do syntaxe.......................................................................... 4
3. Proměnná a její deklarace, přiřazovací příkaz ................................................................................................ 9
4. Složený příkaz, deklarace konstanty ............................................................................................................ 12
5. Podmíněné příkazy – if ............................................................................................................................... 15
6. Podmíněné příkazy – pokračování............................................................................................................... 17
7. Cykly – příkaz while................................................................................................................................... 21
8. Cykly – příkaz repeat .................................................................................................................................. 23
9. Skalární (jednoduché) typy dat .................................................................................................................... 27
10. Cyklus FOR.............................................................................................................................................. 30
11. Typ interval a větvení case ........................................................................................................................ 32
12. Správnost a efektivnost algoritmu.............................................................................................................. 35
13. Vnořené cykly .......................................................................................................................................... 38
14. Procedury – první seznámení..................................................................................................................... 40
15. Procedury po druhé................................................................................................................................... 43
16. Funkce...................................................................................................................................................... 46
17. Programové jednotky ................................................................................................................................ 50
18. Opakování ................................................................................................................................................ 53
19. Datový typ pole ........................................................................................................................................ 57
20. Pole – vstup dat od uživatele, další příklady............................................................................................... 59
21. Vyhledávání v poli.................................................................................................................................... 62
22. Třídění...................................................................................................................................................... 64
23. Dimenzionání pole – seznámení ................................................................................................................ 66
24. Procvičování dimenzionálního pole ........................................................................................................... 68
25. Komponenta StringGrid a zobrazení tabulek.............................................................................................. 71
26. Statické pole v procedurách a funkcích, opakování .................................................................................... 73
27. Dynamické pole........................................................................................................................................ 75
Obsah............................................................................................................................................................. 79
PDF created with pdfFactory trial version www.pdffactory.com

Podobné dokumenty

Programování 3

Programování 3 Algoritmus vychází z toho, že opakovaným dělením zjišťujeme, jaké mocniny základu jsou ve výchozím čísle obsaženy. Postup při převodu z dvojkové do desítkové soustavy Příklad: 1012 =1*22 +0*21 +1*2...

Více

PG 2

PG 2 Základní myšlenka OOP se dá zhruba vyjádřit následujícím způsobem: Program provádí určité akce s daty. Chceme-li, aby byl rozšiřitelný a opakovaně použitelný, je lepší jeho návrh založit spíš na da...

Více

datasheetu - DH servis

datasheetu - DH servis Devátý byte – nižší byte vypočteného CRC – CRC se vždy počítá od Header byte 2 včetně, tedy od druhého byte do parametru příkazu, tedy do sedmého byte. Pokud nesouhlasí délka zaslaného paketu, nebo...

Více

Bakalářská práce - Vysoké učení technické v Brně

Bakalářská práce - Vysoké učení technické v Brně se směrovou anténou pouze při prvotní instalaci. Pokud jsou ale potřebné vlastnosti směrové antény a zároveň je potřeba přijímat a vysílat rádiový signál postupně z různých a do různých směrů – tak...

Více

1. Seznámení s C++ Builderem

1. Seznámení s C++ Builderem Tím vytvoříme prázdnou aplikaci (jako při spuštění Builderu). Do středu formuláře vložíme komponentu Edit. Když nyní spustíme naší aplikaci můžeme do této komponenty zapisovat libovolný text. Původ...

Více

Programování v C++ II - Materiály pro výuku IDE C++ Builder

Programování v C++ II - Materiály pro výuku IDE C++ Builder Komponenta TLabel ..................................................................................................51 Komponenta TButton ..............................................................

Více

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

Studijní text  - Personalizace výuky prostřednictvím e Významná část probírané látky je doplněna výukovými programy, které by na základě řízené animované výuky měly vést k snadnému pochopení jednotlivých postupů při programování. Snahou autorů dokonce ...

Více

Cracking 4 newbies…

Cracking 4 newbies… s ECX, tak získám původní EAX, tedy správné registrační číslo. Výsledkem této operace je hodnota 5A494C42h, ale heslem musí být nějaký řetězec, a proto převedeme toto číslo na znaky ASCII. Poněvadž...

Více