Programování 3

Transkript

Programování 3
1. Zobrazení informací v počítači
Číselné soustavy
Převod mezi dvěma soustavami odpovídá jednoznačnému zobrazení mezi dvěma množinami.
1. množina – množina čísel
2. množina – množina cifer
Příklad: číslo 123 je v desítkové soustavě 1 stovka, 2 desítky a tři jednotky, v šedesátkové dvě šedesátky a tři
jednotky. (2 minuty, 3 vteřiny)
Desítková soustava:
25610 = 2*102 + 5*101 + 6*100
Číslo vyjadřujeme pomocí mocnin 10 a cifer 0,1..9, k zápisu použijeme jen zhuštěnou formu (tuční činitelé)
Analogicky ve dvojkové soustavě užíváme mocnin dvou a cifer 0,1.
Obecně hovoříme o polyadických soustavách o základu z.
anzn + an-1zn-1 + … a0z0
Pro desetinná (racionální čísla) můžeme pokračovat dále:
anzn + an-1zn-1 + … a0z0 + a-1z-1 + a-2z-2 + …
ai ∈ {0, 1, … z-1}
Dvojková soustava:
Postup při převodu z desítkové do dvojkové soustavy:
Číslo postupně dělíme dvěma a zapisujeme zbytky, dokud není celočíselný podíl roven nule. Zbytky pak
opíšeme v opačném pořadí.
Dělení: 13 : 2 = 6 : 2 = 3 : 2 = 1 : 2 = 0
Zbytky:1
0
1
1
Výsledek: 1310 = 11012
(Stejný postup lze použít i při převodu do jiných soustav)
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*20
U delších čísel by byl postup s výpočtem mocnin neefektivní, proto používáme Hornerovo schéma pro výpočet
hodnoty polynomu:
Anxn + an-1xn-1 +an-2xn-2 + …a1x +a0 =(…((anx+an-1)x + an-2)x + …a1)x+a0
Šestnáctková soustava
Protože zápisy v dvojkové soustavě jsou dlouhé, používá se prakticky soustava šestnáctková, která umožňuje
jejich zhuštění. Obě soustavy se snadno vzájemně převádějí, viz. dále.
Tato soustava má základ 16 a používá tedy 16 cifer, rp. naků pro cifry.
0,1, …9
a dále písmena pro dvouciferná čísla desítkové soustavy:
A
10
B
11
C
12
D
13
E
14
F
15
Převody mezi dvojkovou a hexadecimální soustavou
Jeden znak hexadecimální soustavy odpovídá čtyřem znakům binární soustavy. (Např A16 = 1010 =10102)
Číslo ve dvojkové soustavě rozdělíme po čtveřicích cifer odzadu a každou čtveřici přepíšeme do šestnáctkové
soustavy a naopak.
Příklad:
3 6 D16 =11 0110 11012
1
Algoritmus převodu desetinných čísel
0,410 = 0,314631463146…8
0,4 * 8
3
2
1
6
4
8
6
4
3
2
Také díky těmto výsledkům je aritmetika reálných čísel vždy nepřesná, na rozdíl od práce s celočíselnými typy.
Aritmetické operace v jiných soustavách
Analogicky desítkové – příklad písemné sčítání:
3268
1258
4538
(5+6=11=8+3, takže trojku zapíšeme a 8 převedeme jako 1 (81) do vyššího řádu
Zobrazení celých čísel
Celé kladné číslo se většinou ukládá do čtyř B převedené do dvojkové soustavy. (16bitové procesory používaly
pouze 2B.) Např.: 12310 = 11110112 se uloží takto:
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
1
1
1
1
0
1
1
Záporná čísla se zobrazují pomocí dvojkového doplňkového kódu; jeho kladná podoba se převede do binární
soustavy, provede se inverze všech bitů (0-1,1-0) a k výsledku se přičte jednička.
Příklad pro zobrazení čísla do dvou bitů (z praktických důvodů):
00
0
-1: 01 inverze 10 +1 =11
01
+1
-2: 10
01+1=10
10
-2
11
-1
Podobně se kódují větší celá čísla, jiný způsob ukládání se užívá u reálných čísel, kde se ukládá do skupin bytů
nejprve normalizovaná mantisa (z intervalu<0,1; 1), pak exponent.
Př.: 123,4 =0,1234 *103
mantisa: 0,1234; exponent: 3
Zobrazení znaků
Dosud nejznámější je osmibitový kód ASCII . (Každý znak se ukládá do 1 B) Prvních 128 znaků je všude
stejných, druhých 128 se liší pro různé druhy abeced (národní abecedy) a jejich kódování (Např. Windows
užívají kódovou stránku 852, některé starší programy mohou pracovat s poněkud odlišným kódem Kamenických
apod.)
Příklad:
Znak pořadové číslo v tabulce ASCII
Dvojková reprezentace
@
64
01000000
A
65
01000001
~
126
01111110
Stisknete-li současně klávesu Alt a pořadové číslo v tabulce (na numerické klávesnici), napíše se příslušný znak.
Všimněte si, že od znaku 128 záleží také na volbě klávesnice.
V současnosti nabývá na významu Unicode, kde se znaky zobrazují do 2B a vejdou se tedy všechny potřebné
znaky národních abeced jednoznačně.
Kromě toho existuje kód UTF 8 s proměnnou délkou 1-3 B.
2
Cvičení
Naprogramujte následující převody:
1. Dvojková soustava -> desítková soustava (použijte Hornerovo schéma)
2. Desítková soustava-> soustava o základu z<=9
3. Desítková soustava -> šestnáctková soustava
4. Šestnáctková soustava -> dvojková soustava, každé hexadecimální cifře přiřaďte odpovídající čtveřici
binárních cifer.
Řešení:
1.
procedure TForm1.BitBtn2Click(Sender: TObject);
{prevod ze soustavy o yakladu z, Hornerovo schema}
var vys,z,i,k:integer;s,p:string;
begin z:=strtoint(edit2.Text);
s:=edit1.Text;
k:=length(s);
vys:=0;
for i:=1 to k do
begin vys:=strtoint(s[i])+vys*z;
end;
showmessage(inttostr(vys));
end;
2.
function prevod(x,z:integer):string;
{prevod do soustavy se zakladem mensim nez 10}
var s:string;p:integer;
begin s:='';
repeat p:= x mod z;
s:= inttostr(p)+s;
x:= x div z;
until x=0;
prevod:=s;
end;
3.
function prevodhex(x:integer):string;
{prevod do sestnactkove soustavy}
var s:string;p:integer;
begin s:='';
repeat p:= x mod 16;
if p<10 then
s:= inttostr(p)+s
else
case p of 10:s:='A'+s;
11:s:='B'+s;
12:s:='C'+s;
13:s:='D'+s;
14:s:='E'+s;
15:s:='F'+s;
end;
x:= x div 16;
until x=0;
prevodhex:=s;
end;
4.
převodní tabulka:
3
type binhex=record hex:string;
bin:string;
end;
var kod:array[0..15]of binhex;
procedure TForm1.FormCreate(Sender: TObject);
{vytvoreni prevodni tabulky}
var i:0..15;
begin for i:=0 to 15 do
begin
case length(prevod(i,2)) of 1: kod[i].bin:='000'+prevod(i,2);
2: kod[i].bin:='00'+prevod(i,2);
3: kod[i].bin:='0'+prevod(i,2);
4:kod[i].bin:=prevod(i,2);
end;
kod[i].hex:=prevodhex(i);
end;
end;
procedure TForm1.Label8Click(Sender: TObject);
{prevod 16koveho cisla z editu na dvojkove cislo pomoci převodní tabulky}
var s,vys,pom:string;i,j:integer;
begin s:= edit6.Text;
vys:='';
for i:=1 to length(s) do
begin pom:=s[i];
j:=0;
while kod[j].hex<>pom do inc(j);
vys:=vys+kod[j].bin;
end;
showmessage(vys);
end;
2. Syntaxe programovacích jazyků, syntaktický analyzátor
Syntaxe =souhrn gramatických pravidel (Jak ze slov dělat věty)
Sémantika = význam vět
Syntakticky správná věta může být sémanticky nesmyslná.
Gramatika přirozených jazyků je příliš složitá a nejednoznačná, navíc má potenciálně neomezený slovník – pro
komunikaci člověka s počítačem se vytvářejí jazyky umělé s přesně definovanou syntaxí.
Definice
Gramatika = (N, Σ, P ,S)
N
konečná množina neterminálů – symboly, které se dále definují (Věta, podmět, program, podmíněný
příkaz…)
Σ
konečná množina terminálů („slovník“ – abeceda jazyka, může obsahovat i víceznakové symboly – if
apod.)
Σ∩N=∅ – terminály a neterminály jsou disjunktní
S
kořen gramatiky – neterminál, od kterého se začíná odvozovat (věta, program)
P
množina přepisovacích pravidel :
Konečnou posloupnost neterminálů a terminálů….vyjádři jako….jinou konečnou posloupnost
neterminálů a terminálů
Podle typů pravidel rozlišujeme více druhů gramatik:
Chomského hierarchie:
4
Regulární, bezkontextové, kontextové, bez omezení (Přirozený jazyk)
Bezkontextové gramatiky CFG mají velký význam při konstrukci programovacích jazyků, pravidla vypadají tak,
že nalevo stojí jediný neterminál, napravo konečná posloupnost terminálních a neterminálních symbolů.
Derivace – odvození – začíná kořenem gramatiky a končí posloupností terminálů
Věta jazyka – takto odvozená posloupnost terminálů
Jazyk generovaný gramatikou – množina všech vět.
Díky tomu, že jazykové konstrukce programovacích jazyků jsou přesně definované gramatickými pravidly,
může syntaktickou správnost kontrolovat překladač.
Formalismy zápisů pravidel
BNF (Backus Nauerova Forma)
Terminál X (bez <>)
Syntaktické diagramy
X
X
Neterminál<X>
X1
<X>::=<X1>|<X2>|<X3>
alternativní možnost
X2
X3
řetězec
<X>::=<X1><X2><X3>
X1
<X>::={<Y>}
symbol ve složených závorkách
se může vyskytovat libovolněkrát (také vůbec ne)
X2
X3
Y
Příklad 1: identifikátor v Pascalu (původní nejjednodušší definice) = posloupnost písmen a číslic, začínající
písmenem..
BNF:
<identifikátor>::=<písmeno>|<identifikátor><písmeno>|<identifikátor><číslice>
<písmeno>::=A|B|………….|z
<číslice>::=0|1|2……|9
SD:
písmeno
identifikátor
písmeno
identifikátor
číslice
A
Písmeno
z
5
0
Číslice
9
Syntaktický analyzátor – program, který pozná, zda je nějaká posloupnost symbolů správně vytvořená.
Předpokládáme, že věta, kterou budeme analyzovat je v řádku textového souboru, terminály jsou jednotlivé
znaky. Proměnná ch typu znak reprezentuje načítaný symbol, načtení znaku –
read(f,ch);
Velká písmena označují neterminály –v programu rekurzivní procedury, malá písmena jsou znaky –terminály.
Postup: pomocí syntaktických diagramů odvodíme vývojový diagram a přepíšeme ho do programovacího jazyka.
Příklad 2:
1. Uveďte příklad derivace věty v dále popsaném jazyce.
2. Napište syntaktický analyzátor, který rozhodne, zda posloupnost znaků v editačním políčku je věta dané
gramatiky.
G={{A,B,C};{x,+,(,)},A}
Pravidla:
A::=x|(B)
B::=AC
C::={+A}
x
Syntaktické diagramy:
A
B
(
B
A
)
C
C
A
+
Postupným nahrazováním:
(
A
A
)
A
Příklady generovaných vět:
x, (x), (x+x),((x))….
+
x
Vstup tedy bereme z textového souboru, kde můžeme snadno načítat jednotlivé znaky procedurou read(f,znak)
procedure TForm1.Button2Click(Sender: TObject);
var ch:char; er:boolean; f:textfile;
procedure A;
begin er:=false;
if ch='x'
then read(f,ch)
else
if ch='('
then begin read(f,ch);
6
A;
while ch='+' do
begin
read(f,ch);A;
end;
if ch=')'
then read(f,ch)
else
er:=true
end
else er:=true;
end;
begin
assignfile(f,'File1.txt');
listbox1.Items.LoadFromFile('File1.txt');
reset(f);
read(f,ch);
A;
if not er then showmessage('BERU')
ELSE showmessage('neberu');
end;
Příklady:
1.
2.
3.
Naprogramujte generátor náhodných řetězců náhodné délky.
Naprogramujte generátor náhodných řetězců náhodné délky, bude obsahovat písmena malé a velké abecedy
bez diakritiky a číslice.
Naprogramujte nerekurzívní logickou funkci, která pozná pascalský identifikátor a vyzkoušejte ji na
řetězcích 1,2. (Např. můžete geberovat řetězce do jednoho listboxu a identifikátory pak přesouvat do
druhého.)
Řešení
1. procedure TForm1.Button4Click(Sender: TObject);
var i,pocet,delka,j,x:integer;s:string;
begin pocet:=random(20)+1;
delka:=random(20)+1;
for i:=1 to pocet do
{generovani slov}
begin s:='';
for j:=1 to delka do
begin
x:=random(207)+48;
s:=s+chr(x);
end;
listbox1.items.add(s);
end;
end;
2.
procedure TForm1.Button1Click(Sender: TObject);
{program generuje nahodne znaky a z nich bere potrebne, efektivnejsi
by bylo nejprve si rozsahy zjistit}
var i,pocet,delka,j,x:integer;s:string;
begin pocet:=random(20)+1;
delka:=random(20)+1;
for i:=1 to pocet do
{generovani slov}
7
begin s:='';
for j:=1 to delka do
begin
repeat x:=random(207)+48;{bez ridicich znaku}
until (chr(x) in ['A'..'Z']) or
(chr(x) in ['a'..'z'])or
(chr(x) in ['0'..'9']);
s:=s+chr(x);
end;
listbox1.items.add(s);
end;
end;
3.
procedure TForm1.Button3Click(Sender: TObject);
function id(s:string):boolean;
var i:integer;
begin if (s[1] in ['A'..'Z'])or
(s[1] in ['a'..'z'])then
begin i:=2;
while (i<=length(s)) and
((s[i] in ['A'..'Z'])or
(s[i] in ['a'..'z'])or(s[i] in ['0'..'9']))do
inc(i);
id:=(i>length(s))
end
else id:=false;
end;
var i:integer;
begin
for i:=0 to listbox1.items.count-1 do
if id(listbox1.items[i]) then
listbox2.items.add(listbox1.items[i]);
end;
3. Úvod do numerických metod
Vyhodnocování výrazů
A*B/C může být: a*b div c
a*b / c – může způsobit přetečení i když c je dost velké, aby byl výsledek rozumný
(řešení a / c * b )
výsledek může být nula pokud a* b je strojová nula (číslo menší než nejmenší
zobrazitelné číslo) i když c je hodně malé.
Problémy s přetečením mohou nastat i když např.
Var a,b:integer;x:real
X:=(a*b)/3 – pokud a*b přeteče, výsledek nemusí být správný.
Test na rovnost
Pozor u rovnosti reálných čísel (viz. zobrazení čísel v počítači), spolehlivější je porovnání provést pouze
s určitou přesností.
Function rovnost(a,b,eps:real);
Begin rovnost=abs(a-b)<eps
End
Výpočet hodnoty polynomu
(Hornerovo schéma)
Přímý výpočet by byl jednak časově náročný vzhledem k umocňování, jednak může být neúspěšné z důvodu
přetčení.
8
Pn(x)=Anxn + an-1xn-1 +an-2xn-2 + …a1x +a0 =(…((anx+an-1)x + an-2)x + …a1)x+a0
function horner(x:real;a:pole;n:integer):real;
var i:integer;s:real;
begin s:=0; {od nejvyssi mocniny}
for i:=0 to n do
s:=s*x+a[i];
horner:=s;
end;
Numerické integrování
Výpočet obsahu plochy pod křivkou:
b
Obdélníkové pravidlo
Přesně:
∫ f ( x)dx = F (b) − F (a)
a
A
s
B
P=(b-a)*f((a+b)/2)
Lichoběžníkové pravidlo: P=[f(a)+f(b)]*(b-a)/2
Když počítáme všechny lichoběžníky, vlastně můžeme vytknout délku dílku a počítat pouze
funkční hodnoty ve středech dílků.
function lichob(a,b:real;n:integer):real;
var x,h,s:real;i:integer;
begin h:=(b-a)/n;
s:=(f(a)+f(b))/2;
x:=a+h;
for i:= 1 to n-1 do
begin s:=s+f(x);x:=x+h;
end;
s:=s*h;
lichob:=s;
end;
Řešení rovnic s jednou neznámou
F(x)=0
9
Př.. Sin(x)-exp(x)+x3=0 analyticky řešit neumíme.
Numerický postup:
1. Separace kořenů – vyhledání intervalů, ve kterých existuje jediný kořen
2. Zpřesnění kořenů – kořeny vyhledáme s určitou požadovanou přesností.
Věta: Nechť je f fce spojitá na intervalu <a,b>., f(a)*f(b)<0
Pak má daná rovnice v intervalu alespoň jeden kořen.
Pokud je funkce monotónní (1.derivace nemění znaménko), je kořen právě jeden.
Metoda půlení intervalu
1. Střed intervalu:
(a+b)/2
2. f(s)
3. Pokud f(a)*f(s)<0.
Křen náleží <a,s> a v tomto
A
s
Intervalu budeme pokračovat, jinak zvolíme druhý interval <s,b>
Opakujeme, dokud se |f(s)| neblíží nule podle našich požadavků.
program pulint;
{$F+}
{tato direktiva umoznuje vzdalene volani prcedur
fce muze byt parametr jine fce}
type ufce=function(x:real):real;
function pul(a,b,eps:real;f:ufce):real;
var s:real;
begin repeat s:=(a+b)/2;
if f(s)*f(a)<0 then b:=s
else a:=s;
until abs(f(s))<eps;
pul:=s;
end;
function f1(x:real):real;
begin f1:=x*x*x-8;
end;
var a1,b1,e1:real;
begin readln(a1,b1,e1);
writeln(pul(a1,b1,e1,f1):6:2);
readln;
end.
Metoda sečen
tgα =
y − f ( x1 ) f ( x1 ) − f ( x0 )
=
x − x1
x1 − x 0
Rovnice sečny:
y − f ( x1 ) =
f ( x1 ) − f ( x0 )
( x − x0 )
x1 − x0
Průsečík s osou x:
Y=0
− f ( x1 ) =
f ( x1 ) − f ( x0 )
( x 2 − x1 )
x1 − x 0
10
B
x 2 = x1 −
x1 − x 0
* f ( x1 )
f ( x1 ) − f ( x 0 )
Obecně:
x n +1 = x n −
x n − x n −1
* f ( xn )
f ( x n ) − f ( x n −1 )
function secny(f:userfce;a,b,eps:real):real;
var n,s,p:real;
begin p:=a;s:=b;
repeat n:=p-(p-s)/(f(p)-f(s))*f(p);
s:=p;p:=n;
until abs(f(n))<eps;
secny:=n;
end;
Cvičení:
1. Vymyslete si způsob jak zadat vstupní hodnoty a vyzkoušejte si uvedené algoritmy.
2. Hodnoty některých funkcí se dají vypočítat pomocí součtu nekonečných řad. (Taylorovy, MacLaurinovy
rozvoje)
Naprogramujte výpočet pro exponenciální funkci a funkci sinus, nepoužívejte přitom oddělený výpočet mocnin a
faktoriálu, protože by brzy došlo k přetečení.
V zásadě půjde o to, že v každém kroku vypočítáme člen, který se bude k předchozí řadě přičítat a výpočet
ukončíme, když bude dostatečně malý. (Uživatelsky omezíme přesnost)
x x2 x3
+
+
+ ...
1! 2! 3!
x3 x5 x7
sin x = x −
+
−
+ ...
3! 5! 7!
ex =
Řešení:
2.
function expx(X,eps:Real):real;
{eps-presnost, clen-nasledujici clen rozvoje}
var clen,s:real;n:integer;
begin s:=1;
clen:=1;
n:=1;
while clen>eps do
begin clen:=clen*x/n;
n:=n+1;
s:=s+clen;
end;
result:=s;
end;
function sinxx(x,eps:real):real;
{eps-presnost, clen-nasledujici clen rozvoje}
var clen,s:real;n:integer;
begin s:=0;
clen:=x;
n:=1;
while abs(clen)>eps do
begin s:=s+clen;
n:=n+2;
clen:=-clen*x*x/((n)*(n-1));
end;
result:=s;
end;
11
4. Řešení soustavy lineárních rovnic Gaussovou eliminační
metodou.
Mějme soustavu n lineárních rovnic o n neznámých:
a11 x1 + a12 x 2 K + a1n xn = b1
a21 x1 + a22 x2 K + a2 n xn = b2
…
an1 x1 + a n 2 x2 K + a nn xn = bn
Pokud existuje právě jendo řešení ( x1 , x2 ,K xn ), říkáme, že je soustava regulární.
Pokud řešení nemá, nebo jich je nekonečně mnoho, nazýváme soustavu singulární.
Například pro n=2
3 x1 + 2 x 2 = 1
x1 − x2 = 2 má soustava právě jeno řešení (1,-1)
Singulární soustava
3 x1 + 2 x 2 = 1
6 x1 + 4 x2 = 2
má řešení nekonečně mnoho, kdyby na pravé straně druhé rovnice nebyla dvojka, soustava by řešení neměla.
Eliminační metody převádějí soustavu na přijatelnější tvar, přitom zachovávají množinu řešení původní rovnice.
Takovým soustavám říkáme ekvivalentní. (Ekvivalentní jsou také úpravy, které nemění množinu řešení výchozí
rovnice)
Jedním ze zmiňovaných přijatelnějších tvarů je tvar trojúhelníkový:
a11 x1 + a12 x 2 K + a1n xn = b1
a 22 x 2 K + a 2 n xn = b2
ann xn = bn
je to tedy soustava, kde všechny koeficienty pod hlavní diagonálou jsou nulové. Z poslední rovnice je snadné
vypočítat xn , to pak dosadit do rovnice předposlední atd.
Ekvivalentní úpravy:
• Záměna dvou rovnic soustavy (budeme potřebovat v i-té rovnici mít neznámou xi )
•
•
Vynásobení některé rovnice nenulovou konstantou
Přičtení násobku jedné rovnice ke druhé (eliminace proměnné)
Gaussova eliminační metoda:
1. soustavu přecedem na trojúhelníkový tvar
2. zpětný chod – výpočet hodnot neznámých.
Místo celých rovnic budeme upravovat jen matice jejich koeficientů.
a11 x1 + a12 x 2 K + a1n xn = b1
a21 x1 + a22 x2 K + a2 n xn = b2
Abychom z druhé rovnice eliminovali a21 x1 , musíme k ní přičíst první rovnici vynásobenou koeficientem
− a21 / a11
Obecně i-tou rovnici: − ai1 / a11
Převod na trojúhelníkový tvar:
for k:=1 to n-1 do
{eliminace xk}
for i:=k+1 to n do {uprava i-te rovnice}
begin for j:=k+1 to n do {pozor: abychom skutečně získali pod hlavní diagonálou nuly, bylo by třeba začít
cyklus od j=k. Jakmile se ale vynuluje aik, od dalších členů už by se nic neodčítalo. Pokud bychom tedy chtěli
mít pod hlavní diagonálou nuly (třeba aby se dala upravená soustava vypsat, ve skutečnosti na těchto členech
nezáleží), je nutno si nejprve aik zapamatovat do jiné proměnné a tu pak místo aijk použít.}
aij:=aij-aik/akk*akj; {uprava leve strany}
bi:=bi-aik/akk*bk {uprava prave strany}
end ;
12
Zpětný chod :
Poznámka: po skončení všech úprav bude platit, že xk=bk.
for k:=n downto 1 do
begin for i:= k+1 to n do
bk:=bk-aki*bi;
bk:=bk/akk;
end;
Možný problém:
Dělení nulou: pokud koeficient proměnné, kterou odstraňujeme z dalších rovnic, pokusíme se mezi následujícími
rovnicemi najít takovou, která má tentokoeficient nenulový a rovnice vyměníme. Pokud se nám to nepodaří, je
soustava singulární a mohou nastat dva případy.
0=0
nekonečně řešení
0=bk<>0 žádné řešení
Cvičení:
Naprogramujte řešení n lineárních rovnic o n neznámých. Koeficienty lze zadávat např. do komponenty
Stringgrid.
Řešení
soustava=record n:integer;
lev:array[1..6,1..6]of real;{koeficienty leve strany}
prav:array[1..6]of real;{prava strana}
end;
var
Form1: TForm1;
a:soustava;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var i:integer;
begin
a.n:=spinedit1.Value;
stringgrid1.ColCount:=a.n+2;
stringgrid1.RowCount:=a.n+1;
stringgrid1.cells[0,0]:='rovnice';
for i:=1 to a.n do
begin
stringgrid1.Cells[0,i]:=inttostr(i);
stringgrid1.Cells[i,0]:='koef u x'+inttostr(a.n-i+1);
end;
stringgrid1.Cells[a.n+1,0]:='prava strana';
stringgrid1.Visible:=true;
end;
procedure vymen(var x,y:real);
var pom:real;
begin pom:=x;
x:=y;
y:=pom;
end;
procedure TForm1.Button2Click(Sender: TObject);
{reseni soustavy linearnich rovnic Gaussovou metodou; koeficienty
neznamych jsou v matici a.lev, koeficienty prave strany v poli a.prav
U regularni soustavy jsou vysledky v poli b, u singularni se resi, zda ma
nekonecne nebo zadne reseni}
var p,i,j,k,m:integer;sing:boolean;
begin {nacteni koeficientu}
13
for i:=1 to a.n do
begin for j:=1 to a.n do
a.lev[i,j]:=strtofloat(stringgrid1.cells[j,i]);
a.prav[i]:=strtofloat(stringgrid1.cells[a.n+1,i]);
end;
sing:=false; {predp., ze soustava ma reseni}
k:=1;
while not sing and (k<=a.n) do {eleminujem xk}
begin if a.lev[k,k]=0 then {upravujeme soustavu, kde jsou
na hlavni diagonale nuly}
begin m:=k+1;
while (a.lev[m,k]=0) and (m<a.n) do {hledam a[m,k]<>0}
m:=m+1;
if a.lev[m,k]=0
then begin sing:=true; {neuspech jednoznacneho
reseni}
p:=k; {zapamatujeme si, kde je problem}
end
else
begin {vymena m teho a k-teho radku}
for i:=k to a.n do
vymen(a.lev[k,i],a.lev[m,i]);
vymen(a.prav[k],a.prav[m]);
end;
end;
if not sing then {a[k,k]<>0, muzeme eliminovat xk}
for i:=k+1 to a.n do {uprava i-te rovnice}
begin for j:=k+1 to a.n do {uprava koef. pri xj}
a.lev[i,j]:=a.lev[i,j]-a.lev[i,k]/a.lev[k,k]*a.lev[k,j];
a.prav[i]:=a.prav[i]-a.lev[i,k]/a.lev[k,k]*a.prav[k];
end;
inc(k);
end;
if not sing {regulerni soustava je prevedena na trojuh. tvar
-zpetny chod}
then for k:=a.n downto 1 do
begin for i:= k+1 to a.n do
a.prav[k]:=a.prav[k]-a.lev[k,i]*a.prav[i];
a.prav[k]:=a.prav[k]/a.lev[k,k];
listbox1.items.add ('x'+floattostr(k)+'='+floattostr(a.prav[k]));
end;
if sing then begin showmessage('singularni soustava');
if a.prav[p]=0 then showmessage('nekonecne reseni')
else showmessage('nema reseni');
end;
end;
end.
5. Statistika, modelování náhodných dějů
Statistika
Statistický soubor – množina všech objektů výzkumu
Prvky souboru – prvky této množiny
Rozsah souboru – počet prvků
Stat. Znak – sledovaná vlastnost prvků souboru – x
Jednotlivé údaje oznaku – hodnoty znaku x1 x2 …xk.(př. počet dětí v jednotlivých rodinách)
Četnost hodnoty znaku xj – počet prvků, které vykazují stejnou hodnotu znaku – nj
14
(počet rodin s 5 dětmi…)
Relativní četnost k
∑nj = n
j =1
nj
k
∑ν
j =1
= ν j prakticky v %
n
j
=1
Tabulka rozdělení četnosti
j
xj
nj
Čárkovací metoda: Hodnoty znaku napíšeme pod sebe a jak procházíme prvky souboru, děláme čárky do
příslušných řádků
While not eof(f) do begin read(f,x),inc(počet[x]) –je třeba, aby x bylo ordinální. Jinak např. použití záznamu:
Prvek=record znak:typprvku;
Počet: integer;
Hotov:boolean;
End;
Soubor procházíme a zpracované prvky zaslepujume (hotov=true)
Histogram – sloupcový diagram, sloupce – obdélníčky a obsahy úměrnými četnostem
Aritmetický průměr x =
1 n
∑njxj
n j =1
Geometrický průměr x =
n
Harmonický průměr x =
x1 x 2... x n
n
1 1
...
x1 xn
Modus – hodnota znaku s max.četností – maximum tabulky četností
Medián – hodnota prostředního znaku v setříděné tabulce četností (asi stejný počet prvků je menších jako
větších oproti mediánu)
Pro lichý počet prvků má index (n+1) div 2, pro sudý počet se vypočítá jako průměr „prostředních“ prvků
n 
n
a   + a  + 1
2 
2
2
1
1
xi − x = ∑ ni ( ) ( xi − x )
∑
n
n
2
1 n
1
2
2
Rozptyl s x = ∑ ( xi − x ) = ∑ ni ( x i − x )
n i =1
n
Průměrná odchylka d =
For i:=1 to n do s:=s+sqr(x[i]-prumer); s:=s/n
Směrodatná odchylka s =
s x2
Pro zjištění závislosti dvou znaků:
Koeficient korelace r=
k=
k
s1 s 2
s1 =
1
( x i − x )2
∑
n
s1 =
1
( yi − y )2
∑
n
1
∑ (xi − x )( yi − y )
n
Pokud r se blíží k 1, je mezi znaky x a y velká závislost, pokud k 0, malá. Hodnoty kolem -1 naznačují nepřímou
úměrnost.
15
Modelování náhodných dějů
Generátor náhodných čísel
Pascal: Randomize – inicializace generátoru (používá obvykle systémový čas)
Random
Random(10)
Random(10)+11 –generuje celá čísla od 11 do 20
Excel Náhčíslo(), Celá.část(náhčíslo()*100) –náhodná celá čísla od 0 do 99 nebo randbetween(10) jako
pascalské random(10)
Algoritmy
Většinou se vypočítá následující číslo z předchozího, generovaná posloupnost musí vykazovat
charakteristiky požadované od náhodných čísel.
Př. yk+1=(A yk+B) mod C
A, B, C – konstanty, C udává periodu opakování posloupnosti.
Příklad: A =17 (prvočíslo), B = 1, C je nějaká mocnina 2.
Polem: y[i+1]:=(17 y[i] + 1] mod 4
Programování vzájemně se vylučujících jevů
Pokud mají pravděpodobnost p, 1-p:
If random <p Then výskyt 1.jevu
Else výskyt druhého jevu
Cvičení:
1. Načtěte z textového souboru data, (celá čísla 0-9), setřiďte ho a vypočítejte jeho statistické charakteristiky.
Zobrazte příslušný histogram.
2. Můžete vyzkoušet vlastní algoritmus generování náhodných čísel
Řešení
1. var
Form1: TForm1;
cet:array[0..9]of integer;
implementation
uses Unit2;
{$R *.DFM}
procedure TForm1.Button1Click(Sender: TObject);
begin
listbox1.items.loadfromfile('data.txt');
listbox2.items.loadfromfile('data.txt');
end;
procedure TForm1.Button2Click(Sender: TObject);
var a:array[1..1000]of integer;
n,i,mods:integer;
pr,roz,med,smch:real;
begin n:=listbox1.items.count; pr:=0;
for i:=0 to 9 do cet[i]:=0;
for i:=1 to n do
begin a[i]:=strtoint(listbox2.items[i-1]);
inc(cet[a[i]]);
pr:= pr+a[i];
end;
pr:=pr/n;
16
if odd(n) then med:=a[(n+1) div 2 ]
else med:=(a[n div 2]+a[n div 2+1])/2;
mods:=0;
for i:=0 to 9 do if cet[i]>mods then mods:=i;
roz:=0;
for i:=1 to n do roz:=roz+sqr(a[i]-pr);
roz:=roz/n;
smch:=sqrt(roz);
listbox3.items.add('rozsah '+inttostr(n));
listbox3.items.add('prumer '+floattostr(pr));
listbox3.items.add('median '+floattostr(med));
listbox3.items.add('znak jeho cetnost');
for i:=0 to 9 do
listbox3.items.add(inttostr(i)+'
'+inttostr(cet[i]));
listbox3.items.add('modus '+inttostr(mods));
listbox3.items.add('rozptyl '+floattostr(roz));
listbox3.items.add('smer.odch '+floattostr(smch));
end;
procedure TForm1.Button3Click(Sender: TObject);
var i:integer;
begin form2.show; form2.image1.canvas.brush.color:=clsilver;
for i:=0 to 9 do
form2.image1.canvas.rectangle(30*i,200-cet[i]*30,i*30+30,200);
end;
2.
procedure TForm1.BitBtn1Click(Sender: TObject);
const max=1000;
var i,n,a,b,c:integer;
d:array[1..max]of integer;
begin
listbox1.Clear;
d[1]:=spinedit5.value;
n:=spinedit1.Value;
a:=spinedit2.Value;
b:=spinedit3.Value;
c:=spinedit4.Value;
for i:=1 to n-1 do
begin
d[i+1]:=(a*d[i]+b)mod c;
listbox1.items.Add(inttostr(d[i+1]))
end;
end;
6. Multitasking a Delphi
Historie
Pokud má počítač jeden procesor a chceme mít spuštěno několik aplikací, musí operační systém strojový čas
mezi aplikace dělit a správně je přepínat.
16 bitové verze Windows užívala kooperativní multitasking, každá aplikace měla vyhrazenu dobu na
zpracování části kódu a puk musela předat řízení další aplikaci. Pokud něco přestalo komunikovat s okolím, celý
systém zkolaboval.
32 bitový opační systém (od Windows 95) užívá preemptivní multitasking – rozdělení strojového času nezávisí
na aplikacích a je plně řízeno operačním systémem.
Poznámka: hroutění Windows vyplývá ze skutečnosti, že všechny spuštěné aplikace využívají část sdílené
paměti, do které mají přístup všechny. Když nějaký program přepíše část paměti, která mu nenáleží, systém se
z toho nezotaví.
17
Prostředky po využití multitaskingu
Události a správy
Aplikace, které píšeme v Delphi jsou řízené událostmi: program většinu svého času čeká na událost. Když ji
obdrží, provede její obsluhu a čeká dál.Příchozí zprávy jsou řazeny do fronty a obsluhovány až po zpracování
předchozí zprávy.
Pokud během obsluhy dojde k chybě nebo vznikne velmi dlouhá smyčka, program další aplikace nepustí ke
slovu a jediná možnost je Ctrl Alt Del.
Řešení spočívá buď v zpracování procesů na pozadí nebo použití časovačů.
Zpracování procesů na pozadí
Nejběžnější způsoby:
• Zařadit do kódu volání metody Application.ProcessMessages, která zajistí zpracování všech zpráv
Windows, čekajících ve frontě
• Jednotlivé kroky procesu provádět vždy, když aplikace obdrží událost OnIdle.
V prvním případě se program věnuje plně zpracování procesu a zpracování ostatních zpráv povoluje jen
nezbytně nutnou dobu.
Ve druhém naopak aplikace běží jen když ve frontě nečeká žádná zpráva.
V obou případech nemáme možnost jeden z procesů potlačit a druhý upřednostnit.
Časovače
Kód procesu, který má být zpracován na pozadí se rozdělí na malé části, které se vloží do obsluhy události
OnTimer časovače. Pomocí intervalu časovače lze měnit rychlost zpracování, v případě potřeby vypnutím
časovače proces zastavit.
Vlákna
Shrnutí: Od Windows95 má každá aplikace vyhrazen čas, během něhož je zpracovávána procesorem. Po jeho
uplynutí se aktivuje další úsek vyhrazený sousední aplikaci. Těmto úsekům, během nichž se provádějí části
programů se říká vlákna. (thread)
Rozdělení procesů se může dít nejen na úrovni aplikací, ale i v rámci jedné aplikace. Potřebujeme-li např.
paralelně zpracovávat dva úkoly v jedné aplikaci, můžeme pro každý z nich vytvořit další vlákno přímo v této
aplikaci. Vlákna pak běží současně a do jisté míry nezávisle.
Třída TThread
Je abstraktní třída nadefinovaná ve VCL, zapouzdřuje v sobě funkce potřebné pro práci s vlákny.
Constructor Create(createsuspend:boolean) – konstruktor pro vytvoření instance vlákna. Má logický
parametr, který rozhoduje o tom, jestli se vlákno spustí hned nebo se vytvoří pozastavené. ( s parametrem false
se spouští hned)
Prcedure Suspend – přeruší činnost běžícího vlákna
Procedure Resume – opětné spouštění zastaveného vlákna
Procedure Free – vlákno uvolní po skončení jeho práce
Function Terminate: integer – ukončení běhu vlákna
Function WaitFor: Integer – pozdrží vlákno do té doby, než jiné vlákno skončí.
Procedure excecute;virtual;abstract; – metoda, kterou naprogramujeme (Override) co vlastně má blákno dělat.
Procedure Synchronize(Method: Tthreadmethod) – viz dále
Synchronizace vláken
Pokud by v jednom programu běželo více vláken, mohlo by docházet ke konfliktům při práci s VCL. Proto je
nezbytné, aby se zde vlákna synchronizovala a přistupovala k objektům VCL postupně.
Synchronize – metoda, jejím parametrem je procedura, která přistupuje k VCL.
Procedury volané tuto metodou mají být co nejkratší a mají obsahovat pouze příkazy, které používají VCL.
Kromě toho je také třeba synchronizovat přístup ke společným proměnným.
Možnosti pru tuto synchronizaci:
• Kritické sekce
• Čekání na vlákno
• Mutexy
Priority
Každé vlákno může mít sedm stupňů důležitosti.
18
TthreadPriority=(tpIdle, tpLowest, tpLower, tpNormal, tpHoghe,tpHighest, tpTimeCritical)
Nastavení: vlakno.priority:=tpHigher
Příklady:
1. Multitasking:
Chceme vytvořit text, který se posouvá na pozadí, mizí na jedné straně a na druhé se zase objevuje. (marquee).
Pro řízení tohoto pohybu vyzkoušíme postupy:
Application.Processmessages
OniIdle
Timer
Vlastní posuv textu bude provádět jednoduchá funkce
type
…
Timer1: TTimer;
procedure IdleProc(Sender: TObject; var Done: Boolean);
{defunuje co se ma provest OnIdle}
procedure Timer1Timer(Sender: TObject);
…
var
Form1: TForm1;
k1,k2:boolean;
implementation
{$R *.DFM}
function posunText(text:string):string;
var s:string;
begin s:=Copy(Text,1,1);
{1. znak se zkopiruje do pomocne promenne}
delete(text,1,1);
{smaze se}
result:=text+s;
{prida se nakonec}
end;
procedure TForm1.FormCreate(Sender: TObject);
begin k1:=true;
k2:=true;
{logicke promennu ukoncujici procesy}
label1.caption:=label1.caption+'
';
label2.caption:=label1.caption;
label3.caption:=label1.caption;
end;
procedure TForm1.Button1Click(Sender: TObject);
{ Application.Processmessages}
var i:integer;
begin k1:=not k1;
while not k1 do
begin label1.caption:=PosunText(Label1.caption);
for i:=0 to 100000 do {zpomal.smycka}
Application.Processmessages
{pokud se App.proc. vynecha, jde to vypnout
jedine Ctrl Alt Del}
end;
end;
{pokud bezi smycka posouvajici text, nelze okno uzavrit.
19
protoze cekajici zpravy jsou sice obslouzeny, ale
proces je stale aktivni.
Chceme-li skoncit zavrenim formulare, je treba
do metody OncloseQuery formulare vlozit
prikaz k1:=true}
procedure TForm1.IdleProc(Sender: TObject; var Done: Boolean);
{Co se bud edit, kdyz processor nema na praci nic dulezitejsiho}
var i:integer;
begin for i:=1 to 100000 do;
label2.caption:=posuntext(label2.caption);
end;
procedure TForm1.Button2Click(Sender: TObject);
begin {kdyz ma program cas, posunuje textem}
k2:=not k2;
if not k2 then Application.OnIdle:=IdleProc
else Application.onIdle:=nil;
end;
procedure TForm1.Button3Click(Sender: TObject);
{timer}
begin timer1.enabled:=not timer1.enabled;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
label3.caption:=posuntext(label3.caption);
end;
end.
2. Vlákna
Naprogramujeme dvě vlákna, každé bude vykreslovat náhodné body na formulář. (Jedno červené, druhé modré).
Umožníme nastavovat prioritu vláken prostřednictvím trackbaru, takže jedna z barev může převládat.
type
vlakno=class(tthread)
private x,y:integer;
b:tcolor; {barva vlakna}
protected procedure execute;override;
procedure maluj;{vykresleni bodu}
public constructor create(bb:tcolor);
end;
TForm1 = class(TForm)
CheckBox1: TCheckBox;{vyber spuštěni vlakna}
CheckBox2: TCheckBox;
TrackBar1: TTrackBar;{priorita jednoho z vlaken}
TrackBar2: TTrackBar;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure CheckBox1Click(Sender: TObject);
procedure CheckBox2Click(Sender: TObject);
procedure TrackBar1Change(Sender: TObject);
procedure TrackBar2Change(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
public
{ Public declarations }
end;
20
var
Form1: TForm1;
v1,v2:vlakno;
implementation
{$R *.DFM}
constructor vlakno.create(bb:tcolor);
begin b:=bb;
inherited create(false);
end;
procedure vlakno.maluj;
begin
form1.canvas.pixels[x,y]:=b;
end;
procedure vlakno.execute;
var i:integer;
begin randomize;
repeat for i:=1 to 1000 do;
x:=random(form1.clientwidth);
y:=random(form1.clientheight);
synchronize(maluj);
Application.ProcessMessages;
until terminated;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin v1:=vlakno.create(clred);
v2:=vlakno.create(clblue);
v1.suspend;v2.suspend;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
v1.free;v2.free;
end;
procedure TForm1.CheckBox1Click(Sender: TObject);
begin
if checkbox1.checked then v1.resume
else v1.suspend;
end;
procedure TForm1.CheckBox2Click(Sender: TObject);
begin
if checkbox2.checked then v2.resume
else v2.suspend;
end;
procedure TForm1.TrackBar1Change(Sender: TObject);
begin
v1.priority:=tthreadpriority(trackbar1.position);
end;
procedure TForm1.TrackBar2Change(Sender: TObject);
begin
v2.priority:=tthreadpriority(trackbar2.position);
21
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
v1.Terminate;
v2.Terminate;
end;
end.
Cvičení:
(Souvisí ještě s modelováním)
Hra život
Společenství organizmů se může vyvíjet v prostoru rozděleném na elementární jednotky. Organizace životního
prostoru je pravidelná, můžeme si ji představit jako šachovnici.Každá jednotka má tedy 8 sousedů, čtyři podél
stěn a čtyři ve směru úhlopříček. V každé jednotce se může marodit živočich, ten v ní také prožije celý život,
nebude se stěhovat. Volný životní prostor obsazují noví živočichové.
Vývoj společenství začíná v určité prvotní fázi, pak probíhá neustálá výměna generací, Nová generace vzniká
jako důsledek tří současně probíhajících událostí:
Narození: v prázdné jednotce, která má právě tři sousedy, se narodí nový živočich.
Smrt: Organismus, který má nejvýš jednoho souseda umírá zoufalstvím, organismus, který má víc než tři
sousedy umírá hlady.
Přežití: Organismus se dvěma nebo třeni sousedy přežívá.
Hrubý algoritmus hry:
repeat podle pravidel 1-3 vytvoř novou generaci
z nové generace udělej starou generaci
until konec
Ukončení hry: společnost vymře nebo vytvoří ustálený stav – budou se neustále opakovat dvě po sobě
následující generace. (Zjednodušeno)
Řešení:
simulováno dvojrozměrným statickým polem, zobrazeno do StringGridu.
const n=14;
type pole=array[0..n,0..n]of string;
var
Form1: TForm1;
s,no:pole;
{s stara generace, no-nova generace}
implementation
{$R *.dfm}
procedure ukaz(a:pole);
var i,j:integer;
begin for i:=0 to n do
for j:=0 to n do
form1.stringgrid1.cells[i,j]:=a[j,i];
end;
procedure TForm1.BitBtn3Click(Sender: TObject);
var i,j,p:integer;
begin
randomize;
for i:=0 to n do
for j:=0 to n do
begin p:=random(2);
if p=0 then s[i,j]:=''
else s[i,j]:='*';
end;
ukaz(s);
22
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
stringgrid1.ColCount:=n+1;
stringgrid1.rowcount:=n+1;
end;
function sousede(a:pole;k,l:integer):integer;
{pocet sousedu bunky [k,l]}
var p,id,ih,jd,jh,i,j:integer;
begin
p:=0;
{stredova bunka se nepocita}
if k=0 then id:=0 {1.radek}
else id:=k-1;
if k=n then ih:=n{posledni radek}
else ih:=k+1;
if l=0 then jd:=0 {1.sloupec}
else jd:=l-1;
if l=n then jh:=n{posledni sloupec}
else jh:=l+1;
for i:=id to ih do
for j:=jd to jh do
if (k<>i) or (l<>j){neni stred} then
if a[i,j]='*' then inc(p);
result:=p;
end;
procedure TForm1.BitBtn1Click(Sender: TObject);
var i,j:integer;
begin for i:=0 to n do
for j:=0 to n do
begin
no[i,j]:='';
if (s[i,j]='') and (sousede(s,i,j)=3)
{narodi se novy organismus}
then no[i,j]:='*';
if (s[i,j]='*') and((sousede(s,i,j)=2) or (sousede(s,i,j) =3))
then no[i,j]:='*';{preziti}
end;
s:=no;
ukaz(s);
end;
7. Úvod do databází
Základní pojmy
ČSN 36900/1-1987
Data mn. Č údaje – obraz vlastnosti objektu, vhodně formalizovaný pro přenos, interpretaci nebo zpracování
prostřednictvím lidí nebo automatů
Informace – význam, který člověk přisuzuje údajům.
Soubor – množina fyzických záznamů dat na diskové paměti počítače.
Báze dat je množina souborů, které se užívají pro zabezpečení různých uživatelských funkcí.
Modelování reálného světa
Podnik – organizační jednotka (klub sběratelů)
Model – soubor nástrojů, který umožňuje odvodit obecné vlastnosti podniku.
Datový model je soubor technik a nástrojů pro popis prvků a vztahů v podniku.
Výsledkem modelování podniku je popis dat a vazeb mezi nimi – schéma báze dat.
23
E-R model (Entity-Relation) – grafická metoda
Typ entity
Atribut (vlastnost)
Typ vztahů mezi entitami
Příklad:
věk
název
jméno
student
klubu
Je člen
adresa
rok založení
poplatek
bydliště
Vztahy mezi entitami
N:1 (funkční)
1:N (hierarchický)
N:M (síťový)
1:1
Příklady: vztahy mezilidské (polyandrie, polygamie, volné skupinové vztahy, běžné manželství)
Počítačově realizovatelné modely
Hierarchický, síťový (systémy se propojují pomocí ukazatelů), relační (tabulky)
Tvorba databáze
• Přípravná fáze – návrh schéma báze dat (modelování reálného světa)
• Technická fáze – pomocí databázového systému vytváříme databázi na počítači
• Uživatelská fáze – užíváme databáze, aniž bychom museli projít předchozími etapami
Systémy řízení báze dat
Systém programů pro správu databází – Paradox, Fox Pro, DBase,Access, Oracle, Informix, MySQL…
Hlavní funkce databázového systém(DBS)
DBS = báze dat + systém řízení báze dat
• Create
zápis schémata databáze do počítače
• Append přidávání nových záznamů
• Edit
úpravy záznamů
• View
zobrazování dat na obrazovce
• Ask (Query)
získání odpovědi na určitou otázku
• Forms
definice a využití specifických oken
• Report
tiskové sestavy
• Sort
třídění
Relační datový model
Obecný tvar tabulky:
Jméno
Příjmení
Jiří
sloupce(pole)
……
Plat
Prouza
80 000
24
Řádek
(záznam)
Požadavky na tabulku:
Všechny hodnoty elementární – tj. dále nedělitelné
Pořadí sloupců je nevýznamné
Pořadí řádků rovněž
Sloupce jsou homogenní (údaje stejného druhu)
Každý sloupec má jednoznačné jméno
Řádky musí být rozlišitelné – tabulka nesmí obsahovat dva zcela stejné řádky
Sloupec, který jednoznačně určuje řádky v tabulce se označuje jako primární klíč.
Definování tabulek
Příklad:
Číslo sběratele
Jméno
Město
Autíčko
1
Jiří
Kladno
Fabia
1
Jiří
Kladno
Mercedes
2
Karel
Praha
Mercedes
2
Karel
Praha
Fabia
3
Tomáš
Praha
Trabant
Několikrát zbytečně stejné hodnoty – lepší rozdělit na tři samostatné
Sběratel:
Číslo sběratele
Jméno
Město
Ulice
1
Jiří
Kladno
Liberecká 32
2
Karel
Praha
Chámova 52
3
Tomáš
Praha
Růžová 36
Autíčka
Číslo sběratele
1
1
2
2
3
Číslo typu
500
505
505
502
800
Typ auta
Číslo typu
500
505
502
800
Cena
200
100
100
160
300
Věk
13
20
15
Cena
200
100
100
160
300
popis
Fabia
Mercedes
Fabia žlutá
Trabant
Výhody rozdělení:
Jednoduchost a přehlednost, šetření paměti, pro propojení tabulek je nutnost společných sloupců.
Celkem:
Vytváříme malé a jednoduché tabulky, které lze propojit pomocí společných sloupců. K propojování většího
množství tabulek se hodí uměle vytvořená číselná pole. Braňme nadbytečnosti – opakovatelnosti údajů a
nevkládejme zbytečnosti. (sloupec lze vždy přidat)
Příklady databází s propojenými tabulkami
25
Databáze v Delphi
Tabulky můžeme buď vytvářet programově pomocí formulářů nebo v Paradoxu, který je součástí Delphi. (Nebo
v dalších databázových systémech) Nejprve se naučíme pracovat s hotovými tabulkami, které jsou k dispozici,
pak zakládat nové databáze jednak v Paradoxu, jednak přímo v Delphi.
Do formuláře umístíme neviditelné komponenty Table1 (paleta BDE) a DataSource1 (DataAccess),
DBgrid1,DBEdit a DBNavigator ze záložky DataConrols.
Datasource slouží k propojení údajů, Table je tabulka existující databáze a ostatní komponenty slouží pro práci
s údaji.
Propojení:
• Table1.DatabaseName Data (lze vybrat z hotových databází)
• Table1.TableName
Animals.db (lze vybrat)
• Table1.Active
TRUE
• DataSource1.DataSet Table1
• DBgrid1.DataSource
DataSource1
• DBImage. DataSource DataSource1
• DBImage.DataField
BMP (lze vybrat)
• DBEdit. DataSource
DataSource1
26
• DBEdit.DataField
Name
DatabaseName udává, se kterou databází bude komponenta Table1 pracovat. TableName pak určuje konkrétní
tabulku. Jako DatabaseName lze u některých druhů databází (Paradox, DBase) uvést adresář nebo zástupné
jméno – Alias.
Table1 a Datasource1 jsou neviditelné a poskytují data ostatním komponentám.
Komponenty ze skupiny DataControls se pak užívají jako ovládací a zobrazovací prvky.
Už v režimu návrhu, jakmile Table1.active nastavíme na True, tabulka se otevře a načte data.
Komponenta DBGrid dovoluje prohlížet i editovat záznamy (ukončení a potvrzení přechodem na další řádek,
únik Esc), přidávat záznamy klávesou Insert a mazat záznamy Ctrl+Del.
U dalších komponent kromě DataSource musíme nastavit DataField na pole, které chceme zobrazit.
DBEdit – prohlížení a editace jednoho pole databáze textového typu.
DBImage – prohlížení a editace jednoho pole databáze typu obrázek. (bitová mapa, možno vkládat přes schránku
nebo použít metodu DBImage1.Picture. Loadfromfile(název obrázku)
Cvičení:
1. Navrhněte vlastní databázi s minimálně třemi propojenými tabulkami.
2. Využijte připravené databáze a připravte formulář pro práci s tabulkou Events.
8. Vytváření databáze v Paradoxu
27
Tvorba nové tabulky
Delphi/Tools/Database Desktop
File/New/Table, potvrdíme Paradox7
28
Názvy polí by měly splňovat pravidla pro identifikátory (Dosovské), typ vybereme ze seznamu.
Každá tabulka musí mít primární klíč, podle kterého lze každý záznam jednoznačně identifikovat. Většinou k
tomuto účelu volíme pole ID, obvykle typu Short nebo Long Integer nebo AutoIncrement. (Pole nevyplňuje
uživatel, ale hodnoty dodává systém) K propojování je vhodnější první varianta.
U některých polí je třeba zadat velikost (text – Alpha), primární klíč nastavíme dvojklikem v poli Key.
Chceme-li tabulku dál třídit podle jiných kritérií, je vhodné nastavit v roletce Table properties Sekundární
indexy.
Pro jednotlivá pole lze nastavit minimální a maximální hodnoty, masky pro zadávání apod.
Po stisknutí OK ještě doplníme název indexu.
Strukturu tabulky uložíme pod vhodným jménem, (dá se ještě měnit – např. tlačítko Restructure panelu nástrojů),
otevřeme ji (File/Open/Table) a po uvedení do editačního režimu – opět podobné tlačítko panelu nástrojů
vpravo, můžeme zadávat údaje.
Struktura našich tabulek:
29
Ještě k tvorbě nové tabulky: – pokud to
systém dovolí, vyberme nejdřív alias,
abychom všechny tabulky měli uložené
pohromadě.
Tools/Alias manager – nejprve
vytvoříme alias pro databasename
Vložíme vytvořenou strukturu do
vhodného adresáře (viz Alias)
Tabulku otevřeme v DBDesktopu
poklepáním na ikonu tabulky, kliknutím
na poslední ikonu spustíme editační
režim a můžeme vyplnit údaje a tabulku
uložit..
Cvičení:
Naplňte hodnotami tabulky z některé
databáze, kterou jste navrhovali
minulou hodinu. Dbejte na společná pole pro propojování a primární i sekundární indexy, alby se tabulky daly
třídit.
9. Hodnoty polí
Komponenta Table1 má vlastnost Fields, která se chová jako pole atributů. Prvky Fields jsou objekty typu
TField, které mají mj. vlastnosti AsBoolean, AsCurrency, AsDateTime, AsFloat, asInteger, AsString,
AsVariant sloužící pro přístup k hodnotě pole.(Variant je datový typ, kterým může být cokoliv – pohodlné, ale
pomalé a zabírá hodně místa)
Pole jsou číslována od nuly do FiledsCount -1.
table1.fields[2].asstring – zobrazí hodnotu 3.pole aktuálního záznamu. (Pro Employee.db křestní jméno)
Jinak:
table1.fieldByName('FirstName').asstring
30
Metoda FieldbyName vrací odkaz na objekt typu TField, který odpovídá atributu zadaného jména.
Nevýhoda: Pokud v komponentě DBGrid přeházíme sloupce, Fileds[2] odpovídá jinému atributu.
Editor polí
Dvojklik na Table1, Add fileds
Zatímco v předchozích řešeních proměnná typu TField vznikala za běhu programu, tímto způsobem ji máme
k dispozici při návrhu programu.
V definici třídy TForm přibyla pro každé pole jedna proměnná:
• Table1EmpNo: TIntegerField;
• Table1LastName: TStringField;
• Table1FirstName: TStringField;
• Table1PhoneExt: TStringField;
• Table1HireDate: TDateTimeField;
• Table1Salary: TFloatField;
Inspektorem objektů lze editovat vlastnosti polí – Alignment (zarovnání), DisplayLabel(nadpis sloupečku
v komponentě DBGrid), ReadOnly…
Šířka sloupečků jde měnit přímo v komponentě DBGrid1.
Vypočítaná pole
Příklad: chceme přidat do tabulky sloupec s měsíčním platem.
Postup:
Dvojklik na Table1 – editor polí – New Field
Vyplníme Type a Field Type
Pro komponentu Table1 napíšeme proceduru
OnCalcFields
Table1Msnplat.AsFloat:=
Table1Salary.AsFloat/12
Tato procedura se volá při každém načítání
záznamu a protože je dána programově,
zobrazuje se až za běhu.
Vyhledaná pole
V tabulce můžeme zobrazit i údaj vyhledaná pomocí jiné tabulky, je ovšem nutné tabulky propojit přes společné
pole.
Table1.TableName – Orders (objednávky), Table2.TableName – Customer.(zákazníci) –
propojíme přes CustNo – číslo zákazníka.
Table1 zobrazíme přes DBGrid, Použijeme editor polí Table1 a vyplníme údaje podle obrázku.
ORDERS obsahuje objednávky. Každá objednávka se vztahuje k určitému zákazníkovi – zákazník má CustNo
číslo zákazníka. CUSTOMER je tabulka zákazníků, mezi její atributy patří také CustNo a Compamy – jméno
společnosti.
31
DBGRID1 zobrazí obsah tabulky ORDERS s přidaným sloupečkem Zákazník.
Hodnota v něm se získá tak, že se v tabulce Customer (Dataset Table2)vyhledá záznam s hodnotou atributu
CustNo (Lookup Keys=CustNo), která se rovná CustNo (KeyField ĆustNo) a z nalezeného záznamu vezme
hodntu Company.
(ResultField=Copany)
Vyhledávaná pole mohou být zobrazena už v době návrhu, protože se na nich kód programu nijak nepodílí.
Sloupce tabulky
Dvojklikem na komponentu DBGrid vyvoláme editor sloupců, tlačítkem Add All Fileds přidáme definici
sloupců pro všechna pole a v inspektoru objektů nastavíme vlastnosti jednotlivých sloupců.
Ošetření akcí
Nedovolí zapsat záznam s nevyplněným jménem:
procedure TForm1.Table1AfterPost(DataSet: TDataSet);
begin
if table1lastname.IsNull then
begin dbgrid1.selectedfield:=table1lastname;
dbgrid1.setfocus;
showmessage('vypln prijmeni');
abort
end;
end;
Po zavolání metody post je před zápisem do databáze volána metoda Beforepost. Metoda DBgridu Selectedfiled
udává, ve kterém sloupečku stojí kurzor.
Vlastní dotaz, zda mazat záznam:
procedure TForm1.Table1BeforeDelete(DataSet: TDataSet);
begin
if messagedlg('smazat'+table1lastname.asstring,mtconfirmation,[mbyes,mbno],0)<>mryes
then abort;
end;
Nastavení výchozí hodnoty nového záznamu:
procedure TForm1.Table1AfterInsert(DataSet: TDataSet);
begin
table1hiredate.AsDateTime:=date;
table1salary.asfloat:=12*2000
end;
Cvičení:
1.Doplňte do tabulky nové pole pro hustotu obyvatel a upravte zobrazení tabulky podle vzoru:
32
2. Vložte na formulář dva DBGridy, obsahující propojení tří tabulek: Customer-Orders, Employee-Orders
(Kdyby nás zajímaly např. veškeré prodeje prodejců nebo naopak veškeré prodeje zákazníkům, bylo by třeba
použít tzv. závislé tabulky. (dále)
3. Pracujte na databázovém projektu s vlastními tabulkami.
Řešení:
1. procedure TForm1.Table1CalcFields(DataSet: TDataSet);
begin
Table1Density.asfloat:=round(table1population.AsFloat/table1area.asfloat*100)/100
end;
10. Hledání, třídění a filtrování, závislost tabulek
Vybrané záznamy
(Filtrování)
Nastavením filtru se záznamy omezí na ty, které vyhovují dané podmínce.
Je-li možné použít jako filtr řetězcovou konstantu:
Table1.Filter:= 'Salary < 30000';
Table1.filtered:=true;
Filtr může obsahovat i logické spojky, (State = 'CA' or State = 'MA') případně částečnou shodu: State = 'M*'
vybere stát začínající na M.
Výhodné je za běhu programu nastavovat filtr přes nějaký text: Table1.filter:=Memo1.text
Jiný způsob: Následující příklad vybere zaměstnance přijaté v určitý den týdne. (neděle je 0)
procedure TForm1.Button2Click(Sender: TObject);
begin
table1.filtered:=true;
33
end;
procedure TForm1.Table1FilterRecord(DataSet: TDataSet;
var Accept: Boolean);
begin
accept:=dayofweek(table1Hiredate.asdatetime)=strtoint(edit1.Text)
end;
metoda OnFilterrecord se volá pro každý právě načítaný záznam, accept určuje, zda se záznam načte.
Pozor – je-li také vyplněna vlastnost Filter, zobrazí se jen záznamy vyhovující oběma podmínkám.
Pokud jsou s načítáním filtru nějaké problémy, je výhodné použít funkci, která převádí řetězec na řetězce
v apostrofech.
function QuotedStr(const S: string): string;
Table1.Filter := 'continent = ' + QuotedStr(
combobox1.Items[combobox1.itemindex]);
table1.filtered:=true;
Vyhledání záznamu
Pokud je tabulka setříděná podle nějakého pole, můžeme použít logickou funkci findKey. Její parametr píšeme
do hranatých závorek – je pole s proměnnou velikostí. (open arrray)
If table1.FindKey([edit1.text])
Když existuje záznam s danou hodnotou pole (v tomto případě číslo záznamu jako string), přesuneme se na něj a
funkční hodnota je true. Jinak funkce vrací false.
Třídění
Tabulka je obvykle setříděna podle jednoho údaje (nebo skupiny údajů)=primární klíč.
Chceme-li záznamy procházet v jiném pořadí, potřebujeme sekundární index – něco jako soubor setříděný
podle hodnot jiných polí a obsahující odkazy do primárního souboru. (obsahuje jen hodnoty těchto polí).
Sekundární indexy jsou součástí definice tabulky.
Table1.Indexname udává podle kterého klíče (primární, některý ze sekundárních) chceme tabulku procházet.
Nastavení klíče ovlivňuje funkci metod First, Last, Next a Prior.
K nastavení setřídění se dá také použít vlastnost indexFiledNames, dosazení do této vlastnosti vynuluje vlastnost
Indexname a naopak.
table1.IndexName:='byname';
Stavy tabulky – nejpohodlněji obsluhujeme s db navigátorem.
Table1.state –table1.insert (vkládání záznamu -+ na db navigátoru apod,)
Edit, Post, Cancel
Závislost tabulek
Příklad – druhá tabulka obsahuje objednávky zákazníka vybraného v první tabulce.
Table1.tablename – customer.db
Table2.tablename – orders.db
Každou tabulku propojit s příslušným datasource a Dbgrid.
Vytvoření závislosti:
Table2.mastersource – datasource1
Vyvoláme dialog pro nastavení vlastnosti Table2.masterfields, kde vyplníme, jak bude podřízená (detail)
tabulka záviset na nadřízené. (master). Tato závislost se vždy vztahuje ke klíči, podle kterého je tabulka
setříděná.
Detail Fields – atributy tvořící klíč podřízené tabulky
Master Fields – atributy nadřízené tabulky.
Ze seznamu Available indexes (dostupné indexy) vybereme položku CustNo, pak ji označíme v detail fields i
Master fields a stiskem tlačítka Add přidáme toto propojení do propojených atributů. (Joined fields)
34
V tabulce Table2 pak budou dostupné pouze záznamy, jejichž hodnota CustNo odpovídá téže hodnotě aktuálního
záznamu v Table1.
Závislá tabulka může být nadřízenou jiné tabulky…
Cvičení:
1. Nastavte filtr podle následujících obrázků: (country.db)
2. Doplňte do tabulky Country.db indexy DleRozlohy a Dlepopulace, nastavte třídění a vyhledávání podle názvu
země, rozlohy a počtu obyvatel.
3. Nastavte tři závislé tabulky podle obrázku, abystě pro každého zaměstnance mohli zobrazit jeho objednávky a
pro aktuální objednávku příslušného zákazníka.
4. Pracujte na databázovém projektu s vlastními tabulkami
Řešení:
1.
procedure TForm1.ComboBox1Click(Sender: TObject);
begin
Table1.Filter := 'continent = ' + QuotedStr(
35
combobox1.Items[combobox1.itemindex]);
table1.filtered:=true;
end;
procedure TForm1.BitBtn1Click(Sender: TObject);
begin
table1.filter:='Capital='+QuotedStr(edit1.Text)+'or Capital='+
QuotedStr(edit2.Text) ;
table1.filtered:=true;
end;
2.
procedure TForm1.Button2Click(Sender: TObject);
begin
table1.IndexName:= 'DleJmena';
end;
procedure TForm1.Button3Click(Sender: TObject);
begin
table1.IndexName:= 'DleRozlohy';
end;
procedure TForm1.Button4Click(Sender: TObject);
begin
table1.IndexName:= 'DlePopulace';
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
If not table1.FindKey([edit1.text])then showmessage('neexistuje')
end;
3.
Employee a Orders propojíme přes Empno (V Orders je třeba vytvořit sekundární index), oOrders a Customer
přes CustNo.
11. Tvorba vlastní tabulky, pohyb po tabulce a výpočty
Pohyb po tabulce a výpočty
Průměrný plat:
procedure TForm1.Button1Click(Sender: TObject);
var p:integer; s:real;
begin p:=0;s:=0;
table1.First;
while not table1.Eof do
begin s:=s+table1salary.asfloat;
inc(p);
table1.Next;
end;
showmessage(FloatTostrF(s/p,fffixed,10,2))
end;
Metody komponenty Table1 First, Last, Next, Prior – pro přesun mezi záznamy
EOF je True na konci databáze (předtím se volalo Last nebo neúspěšně Next) Analogicky BOF.
Pokud nechceme, aby bylo vidět pohyb po záznamech (mj. zpomalení programu), vložíme příkaz
Table1.DisableControls, díky kterému ovládací prvky přestanou reagovat na změny hodnot.
Chráněný blok v programu (try-finally-end) zaručuje, že při přerušení výpočtu se provede opětné připojení
řídících prvků metodou Table1.EnableControls. (Viz Výjimky)
36
Záložky
Chceme-li se po akci spojené s procházením tabulky vrátit na původní místo, použijeme záložku – vlastnost
tabulky Bookmark.
Var z:TBookmark;
……
z:=table1.GetBookmark; vytvoří záložku=objekt, popisující aktuální pozici v tabulce.
Table1.GotoBookmark(z) přejde na pozici určenou záložkou
Table1.Freebookmark (z) – uvolní nepotřebnou záložku.
Vytvoření naové tabulky programově:
Na formulář umístíme DBGrid, Datasource a Table1, propojíme je.
Table1.DatabaseName vyplníme Alias nebo adresář, kde chceme tabulku vytvořit.
procedure TForm1.Button1Click(Sender: TObject);
begin
Table1.tablename:= 'nova.db';
table1.FieldDefs.Add('cislo',ftAutoInc,0,true);
table1.FieldDefs.Add('jmeno',ftstring,20,true);
table1.FieldDefs.Add('prijmeni',ftstring,20,true);
table1.CreateTable;
table1.open;
end;
FieldDefs obsahuje definice polí, IndexDefs definice indexů. Parametry metody Add udávají jméno, typ, velikost
a zda musí být údaj vyplněn. Metoda CreateTable vytvoří novou tabulku.
Otevření už vytvořené tabulky (aby se nesmazala)
procedure TForm1.Button2Click(Sender: TObject);
begin
table1.TableName:='nova.db';
table1.open;
end;
Více – nápověda Delphi
The following example shows how to create a table.
with Table1 do begin
Active := False;
DatabaseName := 'DBDEMOS';
TableType := ttParadox;
TableName := 'CustInfo';
{ Don't overwrite an existing table }
if not Table1.Exists then begin
{ The Table component must not be active }
{ First, describe the type of table and give }
{ it a name }
{ Next, describe the fields in the table }
with FieldDefs do begin
Clear;
with AddFieldDef do begin
Name := 'Field1';
DataType := ftInteger;
Required := True;
end;
with AddFieldDef do begin
Name := 'Field2';
DataType := ftString;
37
Size := 30;
end;
end;
{ Next, describe any indexes }
with IndexDefs do begin
Clear;
{ The 1st index has no name because it is
{ a Paradox primary key }
with AddIndexDef do begin
Name := '';
Fields := 'Field1';
Options := [ixPrimary];
end;
with AddIndexDef do begin
Name := 'Fld2Indx';
Fields := 'Field2';
Options := [ixCaseInsensitive];
end;
end;
{ Call the CreateTable method to create the table }
CreateTable;
end;
end;
Cvičení:
1. Pracujte na databázovém projektu s vlastními tabulkami
2. Pracujte s tabulkou Country, vyhledejte zemi s maximální rozlohou, ošetřete záložky.
3.Vyhledejte nejlidnatější zemi Jižní ameriky, použijte ošetření výjímek při vypnutí ovládacích prvků.
Řešení:
2.
procedure TForm1.Button1Click(Sender: TObject);
Var z:TBookmark; max:real;kdo:string;
begin z:=table1.GetBookmark;
table1.First;
max:=0;kdo:='';
while not table1.Eof do
begin if table1area.asfloat>max
then begin max:=table1area.asfloat ;
kdo:=table1name.asstring
end;
table1.Next;
end;
showmessage(FloatTostrF(max,fffixed,10,2)+#13+
kdo);
Table1.GotoBookmark(z);
Table1.Freebookmark (z)
end;
procedure TForm1.Button2Click(Sender: TObject);
var max:real;kdo:string;
begin
Table1.DisableControls;
try table1.First;
max:=0;kdo:='';
while not table1.Eof do
begin
if table1continent.asstring='South America'
38
then if table1population.asfloat>max
then begin max:=table1population.asfloat ;
kdo:=table1name.asstring
end;
table1.Next;
end;
showmessage(FloatTostrF(max,fffixed,10,2)+#13+
kdo);
finally
Table1.EnableControls;
end;
end;
12. SQL
Je databázový dotazovací jazyk.
Pořadí dotazů na databázi:select – from – where
Select uvádí seznam sloupců (polí) v relaci
From uvádí seznam tabulek, na které se klade dotaz
Where kvalifikuje dotaz pomocí podmínek
Komponenta Query (TQuery a TTable jsou DBE komponenty pro přístup k datům) má vlastnost SQL typu
TStrings, který obsahuje příslušný dotaz jako řetězec.
Ten se odesílá databázovému serveru (u tabulek Paradox, DBase pouze simulace), ten provede příkazy dotazu a
pošle zpět data jako odpověď.
Query1.Databasename nastavíme na DBDemos, přes dataset propojíme s DBGridem a můžeme vyzkoušet přímé
zadání dotazů do mema:´
procedure TForm1.Button1Click(Sender: TObject);
begin
query1.SQL:=memo1.Lines;
query1.open;
end;
SELECT * FROM CUSTOMER
Zobrazí všechny záznamy tabulky
SELECT COMPANY,CITY FROM CUSTOMER
Jen sloupce Company a city
SELECT COMPANY,CITY FROM CUSTOMER
WHERE STATE=’CA‘
Jen sloupce Company a city, pro firmy z Kalifornie
SELECT COMPANY,CITY FROM CUSTOMER
WHERE STATE=‘CA‘ and City<’P‘
Jen sloupce Company a city, pro firmy z Kalifornie, města abecedně před P
SELECT COMPANY,CITY FROM CUSTOMER
WHERE Company LIKE ‘%Div%‘
Zobrazí záznamy firem obsahujících ve svém názvu řetězec Div
SELECT State,COMPANY,CITY FROM CUSTOMER
ORDER BY State, City, Company (ORDER BY State, city DESC,Company)
Záznamy uspořádané lexikograficky podle státu, města, názvu firmy.
(city DESC, -setřídění podle tohoto atributu bude sestupné)
SELECT Company, City||”, “|| State FROM CUSTOMER
Výsledek dotazu bude obsahovat atribut město a stat (sloupec City, State)
Ke spojování řetězců slouží operátor ||, textové konstanty se uzavírají mezi uvozovky.
SELECT FirstName, LastName, Salary/12 FROM EMPLOYEE
Výsledek dotazu bude zahrnovat pole s měsíčním platem
SELECT FirstName, LastName, Salary/12 as Mesicni FROM EMPLOYEE ORDER BY Mesicni
Výsledek dotazu bude zahrnovat pole s měsíčním platem, abychom tuto položku mohli uvést
v ORDRER BY, je třeba ji pojmenovat – klíčové slovo AS
SELECT AVG(Salary) FROM EMPLOYEE
Vypočítá průměrný plat
Další funkce: MIN, MAX, SUM, COUNT
SELECT State, COUNT(Company) AS pocet FROM CUSTOMER
39
GROUP BY STATE
ORDER BY POCET DESC
Výsledek : seznam států a počet zákazníků v nich.
GROUP BY – seskupit podle
Propojování tabulek
SELECT Company, COUNT(OrderNo) FROM CUSTOMER, ORDERS
WHERE CUSTOMER.CustNo=ORDERS.CustNo
GROUP BY Company
Vrací seznam společností a počty jejich objednávek.
Dotaz požaduje záznamy tabulky Customer a Orders, podmínkou WHERE vybíráme pouze dvojice,
které se shodují v atributu CustNo (číslo zákazníka)
SELECT Company, OrderNo, Description
FROM CUSTOMER, ORDERS,ITEMS,PARTS
WHERE CUSTOMER.CustNo=ORDERS.CustNo and ORDERS.OrderNo=ITEMS.OrderNo and
ITEMS.PartNo=Parts.PartNo
ORDER BY Company
Pro každou společnost zobrazí prvky objednávek, spojovat lze i pomocí atributů, které nejsou obsaženy
ve výsledku
SELECT Description, COUNT(Qty), SUM(Qty) AS Pocet FROM ITEMS,PARTS
WHERE ITEMS.PartNo=Parts.PartNo
GROUP BY Description
ORDER BY Pocet DESC
Zobrazí seznam druhů zboží s počtem objednávek a počtem kusů
Spojení tabulek je použito k získání atributu Description – název zboží.
Count(Qty) – (atribut Qty udává objednané množství) vypočítá počet záznamů se stejnou hodnotou
Description (klauzule Group By)
SUM(Qty) – součet – tj množství objednané celkem ve všech objednávkách
Změny v tabulkách
INSERT INTO CUSTOMER
(CustNo,Company,ADDr1)
VALUES (777,“RUM software“,“Poltava 261“)
Vloží záznam do tabulky s uvedenými hodnotami atributů
DELETE FROM CUSTOMER
WHERE CustNo=777
Vymaže záznam vyhovující podmínce
UPDATE EMPLOYEE
SET Salary=Salary+100
WHERE HireDate<”1.6.1990”
Zvýší plat o 100 každému zaměstnanci přijatému před daným datem
Server změny provede, ale nevrací data. (nutno zobrazit zvlášť)
Cvičení:
1. Tabulka country:
Zobrazte počet zemí
v jednotlivých kontinentech
Zobrazte celkovou plochu
zemí na kontinentech
40
2. Tabulky Customer, Orders, employee
Zobrazte společnost kupce, příjmení prodejce, zaplacenou částku a datum
prodeje.
Zobrazte pro každého prodejce počet prodejí
3. Pracujte na databázovém projektu s vlastními tabulkami
Řešení:
1.
SELECT Continent, COUNT(name) AS pocet FROM country
GROUP BY continent
ORDER BY POCET DESC
SELECT Continent, Sum(area) AS Celkova_plocha FROM country
GROUP BY kontinent
2.
SELECT Customer.Company, Employee.LastName,Orders.AmountPaid,Orders.Saledate FROM CUSTOMER,
ORDERS,Employee
WHERE Customer.CustNo=ORDERS.CustNo and Employee.EmpNo=Orders.EmpNO
3.
SELECT LastName as prodejce,count(LastName) as Pocet_Prodeji FROM ORDERS,Employee
WHERE Employee.EmpNo=Orders.EmpNO
Group by Lastname
13. Úvod do počítačové grafiky – grafické komponenty
Následující kapitoly se budou zabývat počítačovou grafikou z hlediska některých jejích algoritmů.
Každá komponenta umožňující práci s grafikou má vlastnost Canvas typu TCanvas. Ta vytváří pracovní plochu,
na kterou se dá kreslit, případně pracovat s obrázky. Sama třída plátna obsahuje všechny metody potřebné pro
kreslení.
Dá se užít canvas formuláře, ale ten si nepamatuje obrázek. Lepší je užít komponentu Image, jejíž vlastnost
picture pak jde uložit , eventuelně otevřít přes Opendialog nebo Savedialog.
procedure TForm1.Button2Click(Sender: TObject);
begin
if Opendialog1.execute then Image1.Picture.Loadfromfile(Opendialog1.FileName);
end;
Picture umí pracovat s formáty bmp, wmf, případně uživatelsky definovanými formáty. (picture.bitmap,
případně Picture.graphic. Pokud před spuštěním načtete obrázek .jpg, dá se použít, ale ne dál upravovat) Plocha
komponenty Image zbělá teprve při kreslení – prostor se vytvoří až při naplnění vlastnosti picture.bitmap.)
Některé metody a vlastnosti canvasu:
Brush,color – barva výplně
Pen.color – barva kreslicího pera
Pen.width – tloušťka
Moveto(x,y) – přesun na pozici x,z
Lineto(x,y) – čára z aktuální pozice na pozici x,y
Rectangle(a,b,c,d); – obdélník, a,b souřadnice levého horního, c,d pravého dolního rohu
Elipse(a,b,c,d) – elipsa vepsaná tomuto obdélníku
41
Pixels[x,y]:=clred; – bod o souřadnicích x,y se vybarví červeně.
TextOut(x,y,’text’) – vypíše text na dané souřadnice. Vlatnosti textu – viz nápověda, font.
Font – font s dalšími vlastnostmi – style, (fsbold…),color,size…
Kreslení grafu funkce:
Princip je jasný – každému x přiřadíme právě jedno y podle funkčního předpisu a zakreslíme příslušný bod. Je
ovšem třeba převést souřadnice – na papíru má obvykle střed souřadnice [0,0], na formuláři [clientwidth div 2,
clientheight div 2], x-ová souřadnice roste v obou případech doprava, y-ová na papíru roste směrem vzhůru, na
obrazovce směrem dolů. Podle volby funkce je také třeba volit jednotku – vhodný počet pixelů.
Příklad: funkce y=3sinx
procedure TForm1.Button1Click(Sender: TObject);
var x,y:real; {skutecne souradnice}
xx,yy,j:integer; }obrazovkove souradnice}
begin j:=spinedit1.Value; {uživatelské nastaveni jednotky–pro sinus radove desitky px}
for xx:=1 to image1.Width do {pro všechny body formulare}
begin x:=(xx-image1.Width div 2)/j;{prevod na realne souradnice}
y:=3*sin(x);
yy:=-round(y*j)+image1.height
div 2;{prevod na obrazovkove
souradnice}
image1.Canvas.pixels[xx,yy]:=clblue;
{nakresleni bodu}
end;
end;
Cvičení
1. Naprogramujte kreslení grafů
standardních funkcí af(b(x+c))+d, kde a,
b, c, d jsou reálné konstanty. Využijte
možnost definování uživatelské funkce,
abyste používali jedinou proceduru pro
kreslení obecné funkce f.´
2. Naprogramujte kreslicí editor typu
PaintBrush.
Řešení
1. implementation
{$F+}
{$R *.DFM}
type ufce=function(x:real):real;
function si(x:real):real;
begin si:=sin(x);
end;
function co(x:real):real;
begin co:=cos(x);
end;
function ex(x:real):real;
begin ex:=exp(x);
end;
function dr(x:real):real;
begin dr:=sqr(x);
end;
function ab(x:real):real;
begin ab:=abs(x);
42
end;
function sq(x:real):real;
begin if x>=0 then sq:=sqrt(x);
end;
procedure kresli(f:ufce;b:tcolor);
var j,r,o,xx,yy:longint;x,y:real; c,d,k,q,p:real;
begin j:=form1.spinedit1.value ;
k:=strtofloat(form1.edit3.text);
c:=strtofloat(form1.edit1.text);
d:=strtofloat(form1.edit2.text);
p:=strtofloat(form1.edit4.text);
r:=form1.clientwidth div 2;
o:=r;
while r<form1.clientWidth do
begin r:=r+j; o:=o-j;
form1.Canvas.MoveTo(r,form1.clientHeight div 2 -2);
form1.Canvas.lineto(r, form1.clientHeight div 2 +2);
form1.Canvas.MoveTo(o,form1.clientHeight div 2 -2);
form1.Canvas.lineto(o, form1.clientHeight div 2 +2);
end;
form1.canvas.pen.color:=b;
for xx:=0 to form1.clientwidth do
begin x:=(xx-form1.clientwidth div 2) /j;
y:=d+k*f(p*(x+c));
yy:=-round(y*j)+form1.clientheight div 2;
form1.canvas.pixels[xx,yy]:=b;
end;
end;
procedure TForm1.sin1Click(Sender: TObject);
begin
kresli(si,clred);
end;
procedure TForm1.fce1Click(Sender: TObject);
begin canvas.pen.color:=clblack;
canvas.moveto(0,clientheight div 2);
canvas.lineto(clientwidth, clientheight div 2);
canvas.moveto(clientwidth div 2,0);
canvas.lineto(clientwidth div 2,clientheight);
end;
procedure TForm1.cos1Click(Sender: TObject);
begin
kresli(co,clblue);
end;
procedure TForm1.exp1Click(Sender: TObject);
begin
kresli(ex,clwhite);
end;
procedure TForm1.x21Click(Sender: TObject);
begin
kresli(dr,clgreen);
end;
procedure TForm1.x1Click(Sender: TObject);
begin
43
kresli(ab,clyellow);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
spinedit1.value:=50;
edit3.text:='1';
edit2.text:='0';
edit1.text:='0';
edit4.text:='1';
end;
procedure TForm1.sqrtx1Click(Sender: TObject);
begin
begin
kresli(sq,clolive);
end;
end;
procedure TForm1.clear1Click(Sender: TObject);
begin
canvas.pen.color:= clbtnface;
canvas.Brush.Color:=clbtnface;
canvas.Rectangle(0,0,clientwidth,clientheight);
end;
end.
2. – jen pro inspiraci
procedure TForm1.FormCreate(Sender: TObject);
var i:integer;
begin
for i:=0 to 12 do
begin image1.canvas.Brush.Color:=rgb(20*i,0,0);
image1.canvas.rectangle(50*i,1, 50*i+49,50);
end;
jedu:=false;
end;
procedure TForm1.Image2MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
jedu:=true;
image2.Canvas.MoveTo(x,y);
end;
procedure TForm1.Image2MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
if jedu then image2.canvas.lineto(x,y);
end;
procedure TForm1.Image2MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
jedu:=false;
end;
procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
44
begin
if button=mbleft then image2.Canvas.Pen.Color:=
image1.Canvas.pixels[x,y];
end;
14. Algoritmus kreslení úsečky, animace
Často opakované úlohy je třeba optimalizovat, jako ukázku uvedeme: Bresenhamův algoritmus pro kreslení
úsečky.
Výstupem je rastr, zobrazovací plocha je reprezentována maticí bodů, pixelů, zařízení řídí intenzitu a barvu
každého pixelu.Pixel je dán svými souřadnicemi.
[xk, yk]
Mřížkové body jsou zobrazitelné body obrazovky.
(pixely)
Abychom nakreslili úsečku, je třeba zobrazit jí nejbližší
mřížkové body.
Kromě algoritmu pro úsečku existují další pro oblouk
kružnice, ořezávání, výplně…
[0, 0]
Úsečka z bodu [0,0] do bodu [xk,yk] : y =
For x:=0 to k do begin y:=round(
yk
x
xk
yk
*x);
xk
canvas.pixels[x,y]:=clblue;
End;
Nevýhody:
Zaokrouhlování, násobení, neceločíselná aritmetika => pomalé
Bresenhamův algoritmus
1.oktant: 0<=yk<=xk
(Pro další oktanty se postupuje analogicky)
Vyjdeme z počátku a nahrazujeme úsečku požadovaným sledem bodů. Spojnice sousedních bodů sledu jsou buď
rovnoběžné s x nebo s ní svírají úhel 45o.
Úsečka je potom modelována řadou bodů s x –ovými souřadnicemi 0,1,…xk,
y-ové vypočítáme. Koncový bod sledu [xk, yk]
Z bodu [xj, yj] jdeme buď do bodu [xj+1, yj] nebo do bodu [xj+1, yj+1],
Podle toho, který je blíž bodu dané úsečky .
Rozhodující prvek d: (1. obrázek)
45
yk 1
< pak 2 y k − x k < 0
xk 2
Označme: d= 2 y k − x k
Když
Podle něj rozsvěcíme 1. vedlejší bod.
Pro 2. sousední bod vypočítáme další rozhodující prvek: Když 2
4 y k − xk
yk 1
< 0 a tedy dnový
< tak
2xk
xk 2
=4yk-xk = d+2yk´ Když označíme 2yk = p1 dnový = p1+d
Pokud ovšem (2. obrázek)
2
4 y k − 3xk
yk 3
< 0 a tedy dnový = 4yk -3xk =d+2 yk-2xk 2 yk-2xk = p2 pak dnový = p2+d
< tak
2 xk
xk 2
procedure úsečka (xk,yk:integer);
{ ve druhém oktantu stačí vyměnit x a y}
var x,y,d,p1,p2:integer;
begin
d :=2*yk-xk ;
p1 :=2*yk ;
p2 :=2*(yk-xk) ;
x :=0 ;y :=0 ;
{ násobení a dělení před cyklem}
canvas.pixels[x,y]:=clblue;
while x<xk do
begin inc(x);
if d<0 then d:=d+p1
else begin d:=d+p2;
y:=y+1;
end;
canvas.pixels[x,y]:=clblue;
end;
end;
Animace
– vymazání a následné objevení posunutého obrázku umísťujeme do metody OnTimer
Pohyb po přímce: nejlépe Bresenhamův algoritmus, jinak z počátku: y=round(yk/xk*x), z bodu x1,y1 do bodu
x2, y2… y=round((y2-y1)/(x2-x1)*x+(y1x2-y2x1)/(x2-x1)) (přímka dána dvěma body) – proměnným
parametrem je x
Pohyb po kružnici – také nejlépe Bresenham, jinak parametrická rovnice:
x:= xs+round(cos(fi)*r);
y := ys+round(sin(fi)*r);
– poloměr, xs,ys souřadnice středu, fi – úhel v radiánech
Pohyb po elipse
x:= xs+round(cos(fi)*r);
y := ys+round(sin(fi)*r);
a,b – poloosy
Cvičení:
1. Vyzkoušejte animaci několika souvisejících obrázků, umožněte nastavit rychlost.
2. Vyzkoušejte pohyb grafického objektu po lomené čáře – např. jeho odrážení o okraje formuláře a
kružnici.(Můžete buď vytvořit objekt nebo použít nějakou hotovou komponentu – např. shape)
Řešení:
46
var
Form1: TForm1;
var i, v,s,xs,ys,r:integer;fi:real;
procedure TForm1.FormCreate(Sender: TObject);
begin
timer1.enabled:=false; s:=10;v:=10; i:=1; fi:=0;
timer2.enabled:=false;
xs:=clientwidth div 2;
ys:=clientheight div 2;
r:=150;
shape2.left:= xs+round(cos(fi)*r);
shape2.top := ys+round(sin(fi)*r);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
timer1.enabled:=not timer1.enabled;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
if shape1.left<0 then v:=10;
if shape1.left> clientwidth-shape1.width then v:=-10;
if shape1.top<0 then s:=10;
if shape1.top> clientheight-shape1.height then s:=-10;
shape1.left:=shape1.left+v;
shape1.top:=shape1.top+s;
image1.picture.loadfromfile('prerod'+inttostr (i mod 6 +1)+'.bmp');
inc(i);
end;
procedure TForm1.SpinEdit1Change(Sender: TObject);
begin
timer1.interval:=spinedit1.value;
timer2.interval:=spinedit1.Value;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
timer2.enabled:=not timer2.enabled;
end;
procedure TForm1.Timer2Timer(Sender: TObject);
begin
fi:=fi+0.1;
shape2.left:= xs+round(cos(fi)*r);
shape2.top := ys+round(sin(fi)*r);
end;
15. Rastrová grafika
Algoritmy rastrové grafiky vycházejí z počítání polohy jednotlivých pixelů. Vybarvení jednotlivého bodu:
canvas.pixels[x,y]:=barva
Při aplikaci efektů nějakým způsobem přepočítáváme souřadnice bodů.
Na formulář umístíme dvě komponenty image, do jedné načteme bitovou mapu a do druhé ji budeme zobrazovat
po různých úpravách.
Vymazání obrázku
47
image1.Canvas.Brush.color:=clwhite;;
image1.Canvas. rectangle(0,0,image1.Width,image1.Height)
Načtení obrázku ze souboru (.bmp)
if opendialog1.execute then
image1.picture.loadfromfile(opendialog1.FileName);
end;
Kopie
var x,y:integer;
begin
for x:=0 to image1.Width do
for y:=0 to image1.Height do
image2.Canvas.pixels[x,y]:=
image1.Canvas.pixels[x,y]
end;
Převrácení
for x:=0 to image1.Width do
for y:=0 to image1.Height do
image2.Canvas.pixels[x,y]:=
image1.Canvas.pixels[x,image2.Height-y];
Získání červené složky obrázku
Při práci s barvami můžeme používat funkci rgb(x,y,z), kde x, z,y jsou od nuly do 255 nebo hexadecimální
reprezentaci $abc, kde a, b,c jsou šestnáctková čísla 00 – FF. $0000FF je červená
Operátor and se užívá k bitovému součinu čísel – tedy k vybrání určitých bitů z čísla, operátor shr provádí
bitový posun čísla o zadaný počet bitů doprava
var x,y:integer;c:tcolor; b:byte;
begin for x:=0 to image2.Width do
begin image2.Repaint; {prekresleni obrazku}
for y:=0 to image2.Height do
begin c:=image1.Canvas.pixels[x,y];
b:=(c and $FF0000) shr 16;
image2.Canvas.Pixels[x,y]:= b;
end;
end;
end;
Převedení obrázku na šedivý
Různé barvy přispívají různou mírou k celkovému jasu. Program vypočítá světlost jako vážený průměr
a vynásobí jím $010101, což je tmavošedá.
const rp=0.2989; {podil cervene}
gp=0.5866; {zelene}
bp=1-rp-gp;{modre}
var x,y:integer;c:tcolor; r,g,b:byte;
begin for x:=0 to image2.Width do
begin image2.Repaint;
for y:=0 to image2.Height do
begin c:=image1.Canvas.pixels[x,y];
r:=(c and $0000FF);
g:=(c and $00FF00) shr 8;
b:=(c and $FF0000) shr 16;
image2.Canvas.Pixels[x,y]:=
round(r*rp+g*gp+b*bp)*$010101;
end;
end;
end;
48
Inverze
var x,y:integer;c:tcolor; r,g,b:byte;
begin for x:=0 to image2.Width do
begin image2.Repaint;
for y:=0 to image2.Height do
begin c:=image1.Canvas.pixels[x,y];
r:=(c and $0000FF);
g:=(c and $00FF00) shr 8;
b:=(c and $FF0000) shr 16;
r:=255-r;
g:=255-g;
b:=255-b;
image2.Canvas.Pixels[x,y]:=
r+g shl 8 +b shl 16; {shl posouva bity doleva}
end;
end;
end;
Zvětšenina
Budeme třikrát zvětšovat oblast kolem bodu o souřadnicích 100,100
var x,y,x2,y2:integer;
begin
for x:=0 to image2.width-1 do
begin
image2.repaint;
for y:=0 to image2.height-1 do
begin x2:=100+x div 3;
y2:= 100+y div 3;
image2.Canvas.pixels[x,y]:=image1.Canvas.pixels[x2,y2];
end;
end;
end;
Deformace
var x,y,x2,y2:integer;
begin
for x:=0 to image2.width-1 do
begin
image2.repaint;
for y:=0 to image2.height-1 do
begin x2:=x+round(20*sin(y/50));
y2:= y+round(20*cos(x/50));
image2.Canvas.pixels[x,y]:=image1.Canvas.pixels[x2,y2];
end;
end;
end;
Zvětšenina
Bod, na jehož okolí se chceme podívat lupou vybereme kliknutím do výchozího obrázku. Zvětšení se zmenšuje
se vzdáleností od vybraného bodu, nad určitou vzdálenost je 1.
var x0,z0:integer;
…
procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
x0:=x;y0:=y;
end;
procedure TForm1.BitBtn6Click(Sender: TObject);
49
var r,x,y,x2,y2:integer;z:real;
begin
for x:=0 to image2.width-1 do
for y:=0 to image2.height-1 do
begin
image2.repaint;
r:=sqr(x-x0)+sqr(y-y0);
if r>10000 then z:=1
else try z:=10000/r
except z:=100;
end;
x2:=round(x0+(x-x0)/z);
y2:=round(y0+(y-y0)/z);
image2.Canvas.pixels[x,y]:=image1.Canvas.pixels[x2,y2];
end;
end;
Cvičení
Vyzkoušejte si uvedené algoritmy.
16. Vektorová grafika
Výsledkem použití kreslicích metod canvasu je změna barvy jednotlivých pixelů. Informace, jak k této změně
došlo je ztracená. Chceme-li nakreslené objekty dodatečně upravovat, musíme si pamatovat jejich seznam a
vlastnosti. Hodí se například pole nebo spojový seznam záznamů či objektů.
Příklad 1.
Levou myší kreslíme na canvas elipsy pomocí z levého horního rohu jako v malování. Elipsy si zapamatujeme
v dynamickém poli objektů. Když pak klikneme uvnitř nějaké elipsy pravou myší, elipsa se zvětší.
type kruznice=class x1,y1,x2,y2:integer;
constructor create(x1,y1,x2,y2:integer);
procedure zvetsi;
procedure kresli;
end;
pole=array of kruznice;
var a:pole;i,k,b,c,d,e:integer;kreslim:boolean;
constructor kruznice.create (x1,y1,x2,y2:integer);
begin self.x1:=x1;
self.x2:=x2;
self.y1:=y1;
self.y2:=y2;
end;
procedure kruznice.kresli;
begin form1.Canvas.Ellipse(x1,y1,x2,y2);
end;
procedure kruznice.zvetsi;
begin x1:=x1-5;
x2:=x2+5;
y1:=y1-5;
y2:=y2+5;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin i:=1;
setlength(a,i);
end;
50
function urci(var kk:integer;xp,yp:integer):boolean;
{je true, je-li bod o souřadnicích xp,yp uvnitr kruznice a[kk]}
var i:integer;
begin kk:=100; urci:=false;
for i:=0 to high(a)-1 do
if ((a[i].x1<xp) and (a[i].x2>xp) and
(a[i].y1<yp) and (a[i].y2>yp)) then
begin urci:=true;
kk:=i;
end
end;
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if button=mbleft then
begin b:=x;
c:=y;
kreslim:=true;
canvas.Brush.Style:=bsclear;
canvas.pen.style:=pssolid;
canvas.Pen.Mode:=pmnot;
{Mode urcuje vyslednou barvu nakreslene cary podle toho, jaka
byla puvodne.pmNotvysledna hodnota je negace soucasneho obsahu
Canvasu}
d:=x;
e:=y;
{budeme malovat novou elipsu}
canvas.ellipse(b,c,d,e);
end
else begin if urci(k,x,y)
then begin canvas.pen.mode:=pmnot;
a[k].kresli;
canvas.pen.mode:=pmnot;
a[k].zvetsi;
a[k].kresli;
end;
end;
end;
procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
if kreslim then
begin {vymazat minulou elipsu}
canvas.ellipse(b,c,d,e);
d:=x;e:=y;
{namalovat novou elipsu}
canvas.ellipse(b,c,d,e);
end;
end;
procedure TForm1.FormMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if button=mbleft then
begin
kreslim:=false;
{vymazat minulou elipsu}
51
canvas.ellipse(b,c,d,e);
canvas.Pen.style:=pssolid;
a[i-1]:=kruznice.create(b,c,d,e);
a[i-1].kresli;
inc(i);
setlength(a,i);
end;
end;
Příklad 2.
Příklad dovolí kreslit úsečky obvyklým způsobem a dodatečně je upravovat. Program si pamatuje seznam bodů
reprezentovaný souřadnicemi x,y a seznam úseček (reprezentovaný čísly bodů tvořících začátek a konec úsečky)
Myší lze potom buď nakreslit novou úsečku nebo uchopit a přesunout některý dosavadní krajní bod.
type
TForm1 = class(TForm)
Image1: TImage;
procedure Image1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
procedure Image1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
private
{ Private declarations }
public
{ Public declarations }
procedure NakresliUsecku( i: integer ); {tato procedura pak patri formulari}
end;
…
implementation
…
const
MaxBODY = 100;
MaxUsecky = 50;
var
BODY: array[1..MaxBODY] of TPoint; {TPoint definuje obrazovkový bod, potřebuje unit Types
type TPoint = packed record
X: Longint;
Y: Longint;
end;}
xBODY: integer;
Usecky: array[1..MaxUSECKY] of
record
zacatek, konec: integer
end;
xUsecky: integer;
function NejblizsiBOD( x,y: integer ): integer;
var i: integer;
vzd, min, mini: integer;
const Epsilon = 10;
begin
min := 10000;
mini := 0;
for i := 1 to xBODY do
begin
vzd := abs(BODY[i].x-x) + abs(BODY[i].y-y);
52
if vzd < min then
begin
min := vzd;
mini := i
end
end;
if min > Epsilon then mini := 0;
NejblizsiBOD := mini
end;
procedure TForm1.NakresliUsecku( i: integer );
begin
Image1.Canvas.Pen.mode := pmNot;
with BODY[ Usecky[i].zacatek ] do
Image1.Canvas.MoveTo( x,y );
with BODY[ Usecky[i].konec ] do
Image1.Canvas.LineTo( x,y );
end;
var
HybuBodem: integer;
HybuUseckou: integer;
procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var b: integer;
i: integer;
begin
b := NejblizsiBOD( x,y );
if b=0 then
{ zacinam kreslit novou usecku: }
begin
Inc( xBODY );
BODY[ xBODY ].x := X; BODY[ xBODY ].y := Y;
Inc( xBODY );
BODY[ xBODY ].x := X; BODY[ xBODY ].y := Y;
Inc( xUsecky );
Usecky[ xUSECKY ].zacatek := xBODY-1;
Usecky[ xUSECKY ].konec := xBODY;
HybuBodem := xBODY;
HybuUseckou := xUsecky;
NakresliUsecku( HybuUseckou )
end
else
{ hybu useckou: }
begin
HybuBodem := b;
for i:= 1 to xUsecky do
if (Usecky[ i ].zacatek = HybuBodem)
or (Usecky[ i ].konec = HybuBodem) then
begin
HybuUseckou := i;
exit
53
end
end
end;
procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
if HybuBodem = 0 then exit;
NakresliUsecku( HybuUseckou );
{ smazat minulou usecku }
BODY[ HybuBodem ].x := x;
BODY[ HybuBodem ].y := y;
NakresliUsecku( HybuUseckou )
end;
procedure TForm1.Image1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
HybuBodem := 0
end;
end.
Cvičení
Vymyslete si vlastní příklad na vektorové kreslení.
17. Tvorba komponent
Knihovna vizuálních komponent je navržena tak, aby do ní bylo možno dále přidávat.
Zásady:
• Je třeba znát Object Pascal včetně polymorfismu a dědičnosti
• Je třeba znát hierarchii VCL
• Komponenty by měly být nezávislé
• Každá komponenta by měla mít svůj zdroj s jedinečnou ikonou
• Všechny alokované zdroje je nutné po skončení práce komponenty uvolnit
• Názvy vlastností a událostí jednoduché, logické, anglické
• Kód se píše bez grafické podpory
Příklad 1.
Vytvoříme komponentu odvozenou od typu TComboBox, která bude obsahovat rozbalovací seznam měsíců.
Postup:
• Zavřeme všechny otevřené projekty (File/Close All)
• Komponent/New Component
54
Ancestor type – třída předka
Palette Page – lze použít starou (Samples) nebo vytvořit novou
Cestu doplní Delphi automaticky.
• Vyplníme údaje a stiskneme OK – průvodce připraví kostru nové komponenty
unit Mesice;
interface
uses
SysUtils, Classes, Controls, StdCtrls;
type
TMesice = class(TComboBox)
private
{ Private declarations }
protected
{ Protected declarations }
public
{ Public declarations }
published
{ Published declarations }
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('New', [TMesice]);
end;
end.
Ve třídě TMesice předefinujeme zděděnou virtuální metodu CreateWnd:
TMesice = class(TComboBox)
…
public
procedure CreateWnd; override;
…
implementation
procedure TMesice.CreateWnd;
begin inherited Creatwnd;
Items.add('Leden');
Items.add('Únor');
55
Items.add('Bøezen');
Items.add('Duben');
Items.add('Kvìten');
Items.add('Èerven');
Items.add('Èervenec');
Items.add('Srpen');
Items.add('Záøí');
Items.add('Øíjen');
Items.add('Listopad');
Items.add('Prosinec');
ItemIndex:=0;
end;
Tento kód nemůže být v konstruktoru Create, protože komponenta je kompletně vytvořená až po vykonání všech
příkazů konstruktoru. Do té doby nejsou její všechny vlastnosti nastavené a tedy do seznamu nehotové
komponenty nelze přidávat hodnoty.
Komponenty Delphi jsou shromážděny v balíčcích komponent – zvláštní typ DLL knihoven.
• Instalace komponenty do balíčku
Component/Install Komponent
Vyberme si nový balíček nebo ji nainstalujeme do již existujícího.
• Po vyplnění všech údajů potvrdíme OK, komponenta se přidá do balíčku
V části Contains je seznam komponent v balíčku, v části Requires balíčky potřebné pro fungování komponent
(Jinak: nejprve File/new..vytvořit nový balíček a do něj pak přidávat)
•
Potvrdíme tlačítko Install, potvrdíme, že chceme balíček překompilovat a naše nová komponenta se
objeví na paletě komponent.
Pokud je třeba provést nějaké změny, je třeba balíček znovu překompilovat – tlačítko Compile vlevo
nahoře
Příklad 2 – běžící text
Nová komponenta bude odvozena od třídy TLabel, navíc bude obsahovat časovač a metody pro modifikaci
vlastností. Vlastnosti: Speed – pro rychlost pohybu textu a Active, která spouští a zastavuje pohyb.
Předefinujeme konstruktor Create.
56
unit BLABEL;
interface
uses
SysUtils, Classes, Controls, StdCtrls,ExtCtrls;{kvůli časovači}
type
TBLABEL = class(TLabel)
private
{ Private declarations }
fTimer:TTimer; {nepovinné konvence: identifikátor skrytých atributů začínají písmenem f, metody nastavující
vlastnost obsahují set, funkce vracející obsah proměnných get}
Aby se podkomponenta Timer zobrazila v inspektoru objektů, je třeba jednak do části Published přidat položku
property Timer:TTimer read fTimer ;
a v konstruktoru uvést příkazy:
ftimer.Name:='casovac'; – pojmenování časovače
ftimer.SetSubComponent(true); – zpřístupnění časovače jako subkomponenty v inspektoru objektů
procedure posuntext(sender:Tobject);
function GetACtive:boolean;
procedure setactive(start:boolean);
function GetSpeed:cardinal;
procedure setspeed(Msec:cardinal);
protected
{ Protected declarations }
public
{ Public declarations }
constructor create(AOwner:Tcomponent);override;
published
{ Published declarations }
property active:boolean
read getactive write setactive;
property speed:cardinal
read getspeed write setspeed;
{aby se timer objevil v OI}
property Timer:TTimer read fTimer ;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('Samples', [TBLABEL]);
end;
procedure TBLABEL.posuntext(sender:Tobject);
var s,pom:string;
begin pom:=caption;
s:=copy(pom,1,1);
delete(pom,1,1);
pom:=pom+s;
caption:=pom;
end;
function TBLABEL.GetACtive:boolean;
begin result:=ftimer.enabled;
end;
procedure TBLabel.setactive(start:boolean);
begin ftimer.enabled:=start;
57
end;
procedure TBlabel.setspeed(Msec:Cardinal);
begin ftimer.interval:=Msec;
end;
function TBlabel.GetSpeed:cardinal;
begin result:=ftimer.interval;
end;
{abychom mohli používat časovač, je třeba jej vytvořit, proto je nutné předefinovat konstruktor třídy TLabel.
Destruktor TTimeru není třeba psát, protože komponenta tuto třídu vlastní a tedy s jejím zrušením dojde i ke
zrušení časovače.}
Constructor TBlabel.create(AOwner:Tcomponent);
begin inherited create(AOwner);
ftimer:=TTimer.Create(self);
ftimer.Name:='casovac';
ftimer.OnTimer:=posuntext;
ftimer.Interval:=500;
ftimer.Enabled:=true;
ftimer.SetSubComponent(true);
end;
end.
Ikona na paletě komponent:
Pokud nepřiřadíme zvláštní ikonu, na paletě se objeví ikona předka, což může být matoucí. V editoru zdrojů
(Tools/Image editor) vytvoříme (File/NewComponent Resource File) nový soubor se zdroji komponenty, v něm
nakreslíme novou bitmapu 24*24 bodů pojmenovanou stejně jako třída komponenty a velkými písmeny.
(TBLABEL.DCR) Celý soubor se zdroji se pak uloží se stejným názvem jakou
jako soubor s definicí komponenty (BLABEL.DCR) na stejné místo kde kde je
zdrojový kód komponenty. Komponentu přidáme do vybraného balíčku a nová
ikona se objeví na paletě komponent.
Pro jistotu je vhodné na začátek zdrojového kódu komponenty připojit direktivu
{$R BLABEL.DCR} a balíček s komponentou překompilovat.
Cvičení:
Naprogramujte si vlastní komponentu nebo raději dvě.
18. Několik příkladů na závěr
1. Internetové aplikace
Delphi obsahují mnoho nástrojů komunikujících s internetem. Patří sem především komponenty Indy – internet
direkt – původně opensource, který se stal postupně integrální součástí Delphi.
Dají se pomocí nich vytvořit například funkce pro práci s POP3, SMTP, FTP apod.
Http klient
Vytvoříme snadno pomocí komponenty idHTTP z palety IndyClients (Pro komponentu je podle aktuálního
přístupu k internetu někdy třeba nastavit Proxy.Params)
Načtení obsahu webové stránky z adresy udané v editačním políčku do Mema:
Memo1.text:=IdHTTP1.get(edit1.text)
Prohlížeč
Stačí komponenta WebBrowser z palety Internet.
Zobrazení webové stránky z adresy udané v editačním políčku do této komponenty:
WebBrowser1.Navigate(Edit1.text);
Pro běžný pohyb v prohlížeči můžeme využít metod této komponenty:
Webbrowser1.Refresh
Webbrowser1.GoHome
Webbrowser1.GoBack
Webbrowser1.GoForaward
Webbrowser1.Stop
58
…
2. Příklad na kombinatorické téma
Nalezněte všechna přirozená čísla menší než dané N, jejichž dekadický zápis je tvořený pouze ciframi 2, 3, 5.
Varianta 1.: Naprogramujeme logickou funkci, která zjistí, zda číslo obsahuje pouze požadované cifry a
otestujeme všechna čísla menší než N.
Varianta 2.: (efektivnější) – čísla dané vlastnosti vygenerujeme přímo.
Nástin řešení:
procedure TForm1.Button2Click(Sender: TObject);
{novy člen rady budeme pocitat z predchoziho}
var a:array[1..100] of string;
i,j,k,n,p:integer;
begin n:=spinedit1.Value;
a[1]:='2';
a[2]:='3';
a[3]:='5';
i:=3;
while StrToInt(a[i])<n do
begin inc(i);
j:=length(a[i-1]);
{delka predchoziho clenu}
while (j>0)and (a[i-1][j]='5')do
dec(j);{zjistujeme cifru pred
koncovymi petkami}
if j=0 {nove cislo bude ze samych dvojek}
then
begin a[i]:='';
for k:=1 to length(a[i-1])+1
do
a[i]:=a[i]+'2' ;
end
else {koncove petky se vymeni na dvojky
a cislo pred nimi na naslednika}
begin a[i]:=a[i-1];
for k:=j+1 to length(a[i]) do
a[i][k]:='2';
if (a[i][j]='2')
then a[i][j]:='3'
else if (a[i][j]='3')
then a[i][j]:='5';
end;
end;
p:=i-1; {pocet nalezenych cisel}
for i:=1 to p do
listbox1.Items.Add(a[i]);
end;
3. Příklad na práci s velkými čísly
Napište program pro přesnou práci s celými čísly většími, než je rozsah, který vymezují Delphi
(Sčítání, násobení, faktoriál)
Čísla budeme implementovat pomocí polí nebo řetězců.
function secti(a,b:string):string;
var i,j,k,pom,prenos:integer;vys:string;
begin prenos:=0;
i:=length(a);
j:=length(b);
vys:='';
repeat pom:=prenos+Strtoint(a[i])+
59
Strtoint(b[j]);
dec(i);
dec(j);
vys:=IntToStr(pom mod 10)+vys;
prenos:=pom div 10;
until (i=0) or (j=0);
if (i<>0) or (j<>0) then
begin
if i=0 then
repeat pom:=prenos+strtoint(b[j]);
dec(j);
vys:=IntToStr(pom mod 10)+vys;
prenos:=pom div 10;
until j=0
else
if j=0 then
repeat pom:=prenos+strtoint(a[i]);
dec(i);
vys:=IntToStr(pom mod 10)+vys;
prenos:=pom div 10;
until i=0;
end;
if prenos<>0 then
vys:=inttostr(prenos)+vys;
secti:=vys;
end;
function nasobjednocif(cifra,b:string):string;
var i,x,pom,prenos:integer;vys:string;
begin vys:='';
x:=StrToint(cifra);
prenos:=0;
for i:=length(b) downto 1 do
begin pom:=strtoint(b[i])*x+prenos;
vys:=IntToStr(pom mod 10)+vys;
prenos:=pom div 10;
end;
if prenos<>0 then vys:=inttostr(prenos)+vys;
nasobjednocif:=vys;
end;
function nasob(a,b:string):string;
var i:integer;pom,nul,vys,s:string;
begin vys:='0'; nul:='';
for i:=length(a) downto 1 do
begin
pom:=nasobjednocif(a[i],B);
pom:=pom+nul;
vys:=secti(vys,pom);
nul:=nul+'0';
end;
nasob:=vys;
end;
function faktor(s:string):string;
var i,cislo:integer;fak:string;
{predpokladam, ze nebudu pocitat faktorial neceho,
co se nevejde do integeru}
begin cislo:=strtoint(s);
60
fak:='1';
for i:=1 to cislo do
begin
fak:=nasob(fak,inttostr(i));
end;
faktor:=fak;
end;
Jednodušší řešení:
procedure TForm1.Button2Click(Sender: TObject);
var x,y:string;
function secti1(a,b:string):string;
{kratsi cislo doplnime nejprve zleva nulami}
var i,j,k,p,pom,prenos:integer;vys:string;
begin prenos:=0;
i:=length(a);
j:=length(b);
vys:='';
if i>j then
for k:=1 to i-j do
b:='0'+b
else
for k:=1 to j-i do
a:='0'+a;
{ted jsou stejne dlouhe-p}
p:=length(a);
repeat pom:=prenos+Strtoint(a[p])+
Strtoint(b[p]);
dec(p);
vys:=IntToStr(pom mod 10)+vys;
prenos:=pom div 10;
until (p=0);
secti1:=vys;
if prenos<>0 then
vys:=inttostr(prenos)+vys;
secti1:=vys;
end;
function nasob1(a,b:string):string;
{nasobeni je opakovane scitani}
var i:integer;pom:string;
begin pom:='0';
for i:=1 to strtoint(a) do
pom:=secti1(pom,b);
nasob1:=pom;
end;
begin x:=edit1.Text;
y:=edit2.text;
showmessage(secti1(x,y));
showmessage(nasob1(x,y));
end;
4. Úloha na dynamické programování
Jsou dány dvě posloupnosti kladných celých čísel A, B, s délkami m, rp. n.
Tyto posloupnosti jsou uloženy v polích, jejichž obsah nelze měnit Uvažujme takovou
společnou vybranou podposloupnost posloupností A, B, ve které je součet všech jejích
členů největší možný.
Napište program, který vypíše součet členů takovéto společné vybrané podposloupnosti.
Příklad:
61
m=6, n=7
A=(1,11,2,1,4,99)
B=(9,4,1,2,7,1,99)
Výstup: 103
(Společné vybrané podposloupnosti s tímto součtem existují dvě (4,99) a (1,2,1,99)
Primitivní řešení:
postupně generujeme všechny vybrané podposloupnosti z A,
pro každou ověříme, zda je také vybranou podposloupností z b a když ano,
zjistíme součet. ze součtů udržujeme maximum, které je výsledkem.
Závada: příliš velká časová složitost.(exponenciální)
(Každá posloupost délky n má 2 na n-tou podposloupností.)
Dynamické programování:
Obecné principy:
Při řešení se postupuje od jednoduššího ke složitějšímu, při řešení složitějších úloh využíváme známé řešení
jednodušších.
Ai - posloupnost prvních i členů posloupnosti A.
(A1,A2,...Ai)
Bj - posloupnost prvních i členů posloupnosti B.
(B1,B2,...Bj)
Obecnější úloha: pro každou dvojici čísel i, j (od nuly do m, případně n)určíme maximální součet prvků společné
vybrané podposloupnosti Ai, Bj. Výsledky budeme průběžně ukládat do dvojrozměrné tabulky P[0..m,0..n].
Hodnota P[i,j] vždy představuje řešení úlohy por posloupnosti Ai, Bj.
Výsledkem původní úlohy bude tedy hodnota P[m,n], půjdeme od nejmenších hodnot i,j k vyšším a při výpočtu
používat výsledky z tabulky P.
Tabulku budeme vyplňovat po řádcích, i-tý řádek bude využívat i-1 řádek.
Nultý řádek
bude obsahovat samé nuly. (Z prázndé posloupnosti
nelze nic vybrat)
I-tý řádek:
P[i,0]=0
P[i,j] vypočítáme na základě známých hodnot P[i-1,j],P[i,j-1], P[i-1,j-1].
Pokud ai<>bj, každá vybraná podposloupnost Ai a Bj je buď vybranou posloupností Ai-1, Bj nebo Bj, Ai-1.
P[i,j] je tedy maximum z čísel P[i-1,j] a P[i,j-1].
Pokud ai=bj, jedna z možných vybraných podposloupností Ai, Bj je společná vybraná podposloupnost Ai-1,Bj-1
doplněná o ai. P[i,j] je tedy P[i-1,j-1]+ai.
Časová složitost je O(m*n) pro výpočet celé tabulky P. Paměťová rovněž.
Vylepšení:
Protože každý řádek tabulky P závisí pouze na předchozím řádku, stačí pamatovat si dva řádky, ještě šikovněji
vystačíme s jediným polem, kde se střídají hodnoty prvků. Pměťová složitost je zde pouze m+n.
(Viz elegantnější řešení)
Řešení s maticí:
procedure TForm1.Button3Click(Sender: TObject);
const max=100;{max.delka posloupnosti}
var a,b:array[1..max] of integer;
{zkoumane posloupnosti}
m,n:integer;{delky posloupnosti a,b}
p:array[0..max,0..max] of integer; {tabulka}
i:integer;{pocitany radek tabulky}
j:integer;{pocitany prvek v radku tabulky}
begin m:=strtoint(edit1.text);{pocet prvku A}
n:=strtoint(edit2.text); {pocet prvku B}
for i:=1 to m do
a[i]:=strtoint(memo1.Lines[i-1]);
for i:=1 to n do
62
b[i]:=strtoint(memo3.Lines[i-1]);
for j:=0 to n do p[0,j]:=0;
{nulty radek tabulky p}
for i:=0 to m do p[i,0]:=0;
{nulty sloupec tabulky p}
for i:=1 to m do
for j:=1 to n do
{pocitame p[i,j] z i-1teho radku}
begin if a[i]=b[j] then
p[i,j]:=p[i-1,j-1]+a[i]{nova hodnota p[j]}
else
if p[i,j-1]>p[i-1,j] then
p[i,j]:=p[i,j-1]
else
p[i,j]:=p[i-1,j]
end;
showmessage('max soucet spol. vyb. posl:'+inttostr(p[m,n]));
end;
Elegantnější řešení s jednorozměrným polem:
procedure TForm1.Button4Click(Sender: TObject);
const max=100;{max.delka posloupnosti}
var a,b:array[1..max] of integer;
{zkoumane posloupnosti}
m,n:integer;{delky posloupnosti a,b}
p:array[0..max] of integer; {radek tabulky}
Pred:integer;{predchozi hodnota p[i-1,j-1] pri
vypoctu p[i,j]}
x:integer;{uschovani hodnoty Pred}
i:integer;{pocitany radek tabulky}
j:integer;{pocitany prvek v radku tabulky}
begin m:=strtoint(edit1.text);{pocet prvku A}
n:=strtoint(edit2.text); {pocet prvku B}
for i:=1 to m do
a[i]:=strtoint(memo1.Lines[i-1]);
for i:=1 to n do
b[i]:=strtoint(memo3.Lines[i-1]);
for j:=0 to n do p[j]:=0;
{nulty radek tabulky p}
for i:=1 to m do
begin pred:=0;
for j:=1 to n do
{pocitame p[j] z i-teho radku}
begin x:=p[j];{uschovame aktualni p[j]}
if a[i]=b[j] then
p[j]:=pred+a[i]{nova hodnota p[j]}
else
if p[j-1]>p[j] then
p[j]:=p[j-1];
pred:=x;{pred pro dalsi prvek}
end;
end;
showmessage('max soucet spol. vyb. posl:'+inttostr(p[n]));
end;
63
Obsah
1. Zobrazení informací v počítači ...................................................................................................................... 1
2. Syntaxe programovacích jazyků, syntaktický analyzátor................................................................................ 4
3. Úvod do numerických metod ........................................................................................................................ 8
4. Řešení soustavy lineárních rovnic Gaussovou eliminační metodou.............................................................. 12
5. Statistika, modelování náhodných dějů........................................................................................................ 14
6. Multitasking a Delphi.................................................................................................................................. 17
7. Úvod do databází ........................................................................................................................................ 23
8. Vytváření databáze v Paradoxu ................................................................................................................... 27
9. Hodnoty polí............................................................................................................................................... 30
10. Hledání, třídění a filtrování, závislost tabulek ............................................................................................ 33
11. Tvorba vlastní tabulky, pohyb po tabulce a výpočty................................................................................... 36
12. SQL.......................................................................................................................................................... 39
13. Úvod do počítačové grafiky – grafické komponenty .................................................................................. 41
14. Algoritmus kreslení úsečky, animace......................................................................................................... 45
15. Rastrová grafika........................................................................................................................................ 47
16. Vektorová grafika ..................................................................................................................................... 50
17. Tvorba komponent.................................................................................................................................... 54
18. Několik příkladů na závěr ......................................................................................................................... 58
Obsah............................................................................................................................................................. 64
64

Podobné dokumenty

Úvod do databází ado Accessu

Úvod do databází ado Accessu Pro různé datové typy můžeme nastavit další vlastnosti pole. Velikost u textu určuje délku řetězce, počet deset. míst lze nastavit u čísla nebo měny.Vstupní maska se hodí pro data nebo řetězce,např...

Více

Stáhnout materiál Úvod do Deplhi

Stáhnout materiál Úvod do Deplhi 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 Pasc...

Více

1. Seznámení s C++ Builderem

1. Seznámení s C++ Builderem tlačítka bude tvořit příkaz: Label2->Caption = "Výsledek: " + AnsiString(Edit1->Text.ToInt() / 60) + ":" + AnsiString(Edit1->Text.ToInt() % 60); V našem programu není ošetřeno případné zadání nečís...

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 Vytvoření eliptického formuláře regiónem ................................................................201

Více

PG 2

PG 2 Načtěte osobu a zobrazte zprávu zda má nebo nemá dnes narozeniny, má-li je, kolik je jí přesně let. K použití datových funkcí je třeba do klauzule uses unitu přidat jednotku DateUtils. Konstanta da...

Více

C++ Builder 4.0 - Tvorba software

C++ Builder 4.0 - Tvorba software Následuje deklarace ukazatele na instanci třídy TForm1, která v programu reprezentuje hlavní okno aplikace. Zbytek není nic jiného než deklarace konstruktoru třídy TForm1. Jediná věc, kterou tento ...

Více

Cracking 4 newbies…

Cracking 4 newbies… Takže pokud vyxoruji to, co mi vzniklo po XORu v EAX 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, ...

Více