Programování 3 a 4 – poznámky k výuce Algoritmus a jeho vlastnosti

Transkript

Programování 3 a 4 – poznámky k výuce Algoritmus a jeho vlastnosti
Programování 3 a 4 – poznámky k výuce
verze 2007-05-04
Tento text není v žádném případě učebnicí Delphi nebo programování, jsou to pouze (mírně) uspořádané
poznámky, které chronologicky kopírují to, co děláme na semináři z programování. V textu jsou odkazy i další
dokumenty a literaturu k danému tématu.
U jednotlivých komponent nejsou uváděny všechny vlastnosti, ale jen ty, které budeme ze začátku potřebovat.
Podobně i další informace v tomto textu nejsou leckdy úplné, často jde o zjednodušení dané problematiky.
RNDr. Jan Preclík, Ph.D.
Další literatura
Text se odkazuje na další literaturu, zejména na:
[1] Pavel Satrapa. Pascal pro zelenáče. Neokortex spol. s r.o., Praha, 2000. (výborná knížka o jazyce Pascal)
[2] dokument „Algoritmus a jeho vlastnosti“.
http://ivt.gymnachod.cz/materialy/programovani/ALGORITMUS.PDF
[3] dokument „Jazyk Pascal – úvod“.
http://ivt.gymnachod.cz/materialy/programovani/PASCAL_UVOD.PDF
[4] dokument „Pole (vícerozměrné i jednorozměrné)“.
http://ivt.gymnachod.cz/materialy/programovani/POLE.PDF
[5] dokument „Vyhledávání v poli“.
http://ivt.gymnachod.cz/materialy/programovani/VYHLEDAVANI_V_POLI.PDF
[6] nápověda k Delphi (menu Help/Delphi Help)
Algoritmus a jeho vlastnosti
Viz dokument [2] – „Algoritmus a jeho vlastnosti“.
Delphi – úvod, aneb jak se programuje pod Windows
Delphi jsou nástrojem pro RAD = Rapid Application Development (rychlý vývoj aplikací), vzhled aplikace se
skládá z předpřipravených prvků – komponent, jde o tzv. vizuální programování (programování pomocí myši,
bez psaní programového kódu).
Co se stane například po stisku tlačítka (stisk tlačítka = event, událost) je ale už třeba psát přímo
v programovacím jazyce (tzv. event handler = zpracující procedura této události). Delphi jsou založeny na
jazyce Pascal a jeho rozšíření Object Pascal.
Hlavní program je v podstatě nekonečná smyčka, ve které se zpracovávají události, které nastanou, tj. vyvolávají
se odpovídající event handlery, ve kterých se skrývá celá funkčnost programu. Hovoříme o programování
řízeném událostmi (event-driven programming).
„Dneska všechny programy běží v nekonečné smyčce a čekají, až si nějakej cvok zvykne na myš.“
Dr. Rudolf Kryl, MFF UK, přednáška Metodika programování a filozofie programovacích jazyků, 2005
Komponenty v Delphi
Komponentu umístíme na formulář jejím výběrem v paletě komponent a kliknutím na formulář (komponenta
bude mít svoji standardní velikost) nebo tažením myší (a tím určíme velikost komponenty).
Object Inspector
Okno slouží k nastavování vlastností komponent (karta Properties) a reakcí na události (karta Events).
Vlastnosti mohou být:
• jednoduché (mohou obsahovat pouze jednu hodnotu, například číslo – Left)
• výčtového typu (nabízí se nám seznam možných hodnot – symbolických konstant s prefixem
odpovídajícím názvu vlastnosti, např. BorderStyle a možné hodnoty bsSizeable, bsDialog…)
• strukturované – položky se zobrazí po kliknutí na symbol , případně tlačítko
vyvolá editor této
vlastnosti (samostatné dialogové okno)
Vlastnosti společné všem komponentám (až na pár výjimek)
•
Name – jméno komponenty, musí být (na formuláři) jedinečné, komponentu jednoznačně na formuláři
•
Left – x-souřadnice levého horního rohu komponenty v pixelech (pozor, odkud se počítá – od levého
•
•
•
Top – y-souřadnice levého horního rohu komponenty v pixelech (pozor, odkud se počítá!)
Width – šířka komponenty
Height – výška komponenty
identifikuje
horního rohu uživateli dostupné plochy, tj. ne od levého horního rohu okna!)
Nevizuální komponenty (reprezentované na formuláři pouze svojí ikonou, např. MainMenu nebo Timer) mají
pouze vlastnost Name.
Formulář (TForm)
•
•
•
Caption – text v titulkovém pruhu
BorderStyle – vlastnosti okraje okna (bsDialog, bsSizeable, bsNone)
Position – umístění formuláře (poDesigned – podle vlastností Top a Left, poScreenCenter –
vždy ve středu bez ohledu na rozlišení obrazovky)
Ještě pár obecnějších vlastností
− společné pro TLabel, TEdit, TButton, TBitBtn
•
Font – písmo
• Hint – text popisku (žluté okno se stručnou nápovědou), objeví se, pokud kurzor myši chvíli setrvá nad
komponentou
• ShowHint – zda se bude popisek zobrazovat
• Visible – zda je komponenta viditelná (při běhu, při návrhu je viditelná vždy)
• Enabled – zda je komponenta povolená (pro uživatele přístupná)
Komponenta Label (TLabel)
− pro zobrazení textu na formuláři
• Caption – text
• AutoSize – automatická změna velikosti (velikost komponenty se přizpůsobuje jejímu obsahu)
• Color – barva podkladu (barva písma se nastavuje ve vlastnosti Font)
• Transparent – zda je pozadí průhledné (pokud ano, pak se na barvu Color nebere ohled)
• Alignment – zarovnání textu v rámci komponenty (nemá smysl, pokud je AutoSize = TRUE)
• WordWrap – zalamování textu na více řádků
Komponenta Edit (TEdit)
− editační řádek (políčko), pro vstup hodnot od uživatele
• Text – text zobrazený v editačním políčku (je dobré vymazat přednastavený název komponenty)
• ReadOnly – zda je komponenta určená pouze pro čtení
Komponenta Button (TButton)
− tlačítko
• Caption – text na tlačítku
Tlačítku nejde nastavit barva pozadí (tj. barva tlačítka).
Komponenta BitBtn (TBitBtn)
− podobné jako TButton, ale navíc má vlastnost Kind
• Kind – určuje druh tlačítka (podle toho se nastaví text a obrázek)
Komponenta Image (TImage)
− obrázek (formát JPG, BMP, ICO, EMF, WMF, GIF)
Picture – obrázek, okno pro práci s obrázkem se objeví také po dvojkliku na komponentu
• AutoSize – velikost komponenty se přizpůsobí velikosti obrázku
• Stretch – velikost obrázku se přizpůsobí velikosti komponenty, algoritmus pro změnu velikosti není
příliš podařený, je lepší obrázek zmenšit/zvětšit v grafickém editoru a do Delphi ho nahrát v té
velikosti, ve které je potřeba (vhodné i pro úsporu místa)
• Center – pokud je obrázek menší jak komponenta, bude umístěn v rámci komponenty na střed
• Transparent – zda bude pozadí obrázku průhledné (záleží na formátu: ICO, WMF, EMF – průhledné
vždy, GIF – průhlednost podle alfa-kanálu obrázku, JPG – nemá průhlednost, BMP – jako průhledná
barva se bere barva pixelu v levém dolním rohu obrázku)
Některé kombinace vlastností jsou nemá smysl používat, např. AutoSize a Strech, Center a AutoSize…
Komponenta Shape (TShape)
− geometrické tvary pro umístění na formulář
• Shape – tvar
• Brush – štětec = výplň (Color – barva, Style – typ výplně)
• Pen – pero = čára (Color – barva, Style – typ čáry, Width – tloušťka čáry v pixelech)
Komponenta CheckBox (TCheckBox)
− samostatné zaškrtávací (označovací) tlačítko, může jich být označeno více najednou
• Caption – text vedle označovacího čtverečku
• Checked – zda je označené
• Color – barva pozadí
Související komponenty CheckBox můžeme umístit do komponenty GroupBox nebo na komponentu Panel.
Komponenta RadioGroup (TRadioGroup)
− skupina radiových tlačítek, z této skupiny může být označeno nejvýše jedno tlačítko
• Caption – nadpis skupiny
• Color – barva pozadí skupiny
• Columns – počet sloupců, do kterých jsou položky rozmístěny (pokud je počet sloupců stejný jako
počet položek, budou položky v řadě vedle sebe)
• Items – položky (jejich názvy), každá na jednom řádku
• ItemIndex – číslo vybrané položky (první položka v seznamu má číslo 0), -1 znamená, že není
vybraná žádná položka
Můžeme také použít komponenty RadioButton (samostatná rádiová tlačítka) a umístit je do komponenty
GroupBox, která je sváže dohromady. Je to však komplikovanější.
Komponenta MainMenu (TMainMenu)
− hlavní menu aplikace, jde o nevizuální komponentu – na formuláři je reprezentována pouze svojí ikonou, která
se při běhu aplikace nezobrazuje (nemá vlastnosti Top, Left, Height, Width), po dvojkliku se objeví Menu
Designer – editor menu
Pro položky menu můžeme nastavovat:
•
Caption – text položky menu, přiřazením „-“ (mínus) do této vlastnosti vytvoří vodorovnou čáru místo
položky
•
ShortCut – klávesová zkratka položky
Komponenta Panel (TPanel)
− slouží pro umísťování dalších (vizuálních) komponent, jde o tzv. kontejner (=komponenta, která může
obsahovat další komponenty)
• BevelInner – vnitřní okraj
• BevelOuter – vnější okraj
• BevelWidth – šířka okraje, kombinací těchto tří vlastností lze vytvářet nejrůznější efekty (rámeček,
vyvýšení/snížený panel…)
• Caption – nadpis panelu, většinou je potřeba standardní text (jméno komponenty) vymazat
• Color – barva panelu
Zarovnávání komponent na formuláři
Chceme-li, aby například tlačítko bylo vždy umístěno u dolního okraje formuláře i při změně jeho velikosti,
nemusíme hned programovat, ale můžeme využít vlastnost Align u většiny komponent. Tato vlastnost určuje,
jak bude komponenta zarovnána v rámci kontejneru, který ji obsahuje (buď formulář nebo komponenta Panel).
Nastavování vlastností více komponentám najednou
Pokud vybereme více komponent na formuláři, v Object Inspectoru se objeví pouze ty vlastnosti, které jsou
společné všem komponentám, a lze je nastavit najednou.
Programování v Delphi
Borland Delphi jsou založeny na programovacím jazyce Pascal, viz dokument [3] – „Jazyk Pascal – úvod“.
Konzolová aplikace aneb programování ve stylu operačního systému MS DOS
Konzolová aplikace využívá pouze standardní textový vstup (z klávesnice) a standardní textový výstup (na
textovou konzoli – „DOSovské okno“). Můžeme tak programovat (s některými omezeními) podobně jako
v Turbo Pascalu pro operační systém MS DOS.
Konzolovou aplikaci založíme v Delphi z menu File/New/Other…, Console Application.
Důležitý je řádek {$APPTYPE CONSOLE}, který překladači specifikuje, o jaký typ aplikace se jedná.
Poznámka: Překladač lze přímo ovládat pomocí příkazů ve tvaru {$...}. Z hlediska Pascalu jde o komentář –
nemá tedy význam pro program, ale je to informace pro překladač.
Výhodou konzolových aplikací je malá velikost výsledného exe souboru (v porovnání s aplikací pro Windows).
Příklad KONZOLE_LINEARNI_ROVNICE
Příklad KONZOLE_KVADRATICKA_ROVNICE
Programování pod Windows
Jak pojmenovávat komponenty
Je výhodné zavést a dodržovat určité konvence, například jméno komponenty začínat prefixem určujícím typ
komponenty, tj. například: Buton → btnTlacitko
Label → lblNapis
Edit → edtPolicko
Image → imgObrazek
CheckBox → ckbZaskrtavatko
RadioButton → rdbRadioveTlacitko
RadioGroup → rdgSkupinaRadiovychTlacitek
Panel → pnlPanel
Při psaní kódu v editoru Delphi po napsání části názvu komponenty a stisku CTRL+SPACE nám budou
nabídnuty všechny komponenty, jejichž název začíná zapsaným textem. Takže pokud napíšeme edt a stiskneme
CTRL+SPACE, budou nám nabídnuta jména všech editačních políček na formuláři (pochopitelně pokud
dodržujeme výše uvedenou konvenci).
Události
V Delphi nenajdete žádný hlavní program ale pouze několik podprogramů (event-handler, zpracující
procedura události), které se vyvolají, pokud nastane určitá událost (event). Událost může vygenerovat
například uživatel (stisk tlačítka, pohyb myší, kliknutí myší, vypnutí počítače…) nebo ji může vygenerovat
operační systém (po uplynutí určitého času, v pravidelných časových intervalech…).
Události pro vybranou komponentu nastavujeme v Object Inspectoru na kartě Events. Každá komponenta má
jiné vlastnosti, některé jsou společné.
Nastavování vlastností komponent za běhu
Tečková notace umožňuje přistupovat k vlastnostem komponent jako by to byly proměnné určitého typu.
Syntaxe je JmenoKomponenty.JmenoVlastnosti. Jméno vlastnosti je stejné, jako v Object Inspectoru.
Po napsání jména komponenty a tečky nám Delphi po chvíli nabídnou seznam vlastností komponenty (pro
urychlení lze stisknout CTRL+SPACE).
Co budeme dále potřebovat…
Načtení hodnoty uložené v editačním políčku do proměnné – konverzní funkce
HodnotaRetezec := edtPolicko.Text
Toto bude fungovat pouze pokud je proměnná HodnotaRetezec typu string (textový řetězec), jinak musíme
řetězcovou hodnotu uloženou v edtPolicko.Text převést na číslo pomocí konverzní funkce StrToFloat
(řetězec na reálné číslo) nebo StrToInt (řetězec na celé číslo).
HodnotaRealneCislo := StrToFloat(edtPolicko.Text)
HodnotaCeleCislo := StrToInt(edtPolicko.Text)
Výpis hodnoty proměnné do komponenty Label
Výpis hodnoty řetězcové proměnné je jednoduchý: lblNapis.Caption := HodnotaRezetec
Vlastnost Caption je typu string, proto pro výpis číselných hodnot musíme použít konverzní funkce –
FloatToStr (reálné číslo na řetězec) nebo IntToStr (celé číslo na řetězec).
lblNapis.Caption := FloatToStr(HodnotaRealneCislo)
lblNapis.Caption := IntToStr(HodnotaCeleCislo)
Příklad KVADRATICKA_ROVNICE
Poznámka: Řešení kvadratické rovnice, algoritmus je stejný jako v příkladu
KONZOLE_KVADRATICKA_ROVNICE, ale jedná se o „okenní“ aplikaci.
Podmíněný příkaz
Syntaxe viz dokument [3] – „Jazyk Pascal – úvod“ a [1] – Pascal pro zelenáče (str. 33–34 kap. 3.5, 53–58
kap. 5.1 a 5.2).
Složené podmínky, priorita operátorů, tabulky pravdivostních hodnot viz [1] – Pascal pro zelenáče (str. 53–58
kap. 5.1 a 5.2).
Příklad POHYB_KOLECKA_1
Poznámka: Kolečko se pohybuje bez ohledu na rozměry formuláře.
Příklad POHYB_KOLECKA_2
Poznámka: Pomocí podmínek nepovolíme kolečku opustit formulář, kolečko se na okrajích formuláře
zarazí. Rozměry oblasti formuláře, kam lze umísťovat komponenty (tzv. klientská oblast) zjistíme
pomocí vlastností ClientWidth a ClientHeight. Vlastnosti Width a Height udávají velikost okna
formuláře, tj. včetně titulkového pruhu, okrajů apod.
Příklad POHYB_KOLECKA_3
Poznámka: Stejné jako POHYB_KOLECKA_3, ale kolečkem pohybujeme pomocí kláves A, S, D, W –
pomocí události OnKeyPress. Klávesnice má funkci autorepeat, takže stačí klávesu držet a kolečko se
bude pohybovat.
Příklad POHYB_KOLECKA_4
Poznámka: Stejné jako POHYB_KOLECKA_3, ale kolečkem pohybujeme pomocí kurzorových šipek –
k tomu je potřeba události OnKeyDown, která na rozdíl od události OnKeyPress dovoluje pomocí
virtuálních kódů kláves ošetřit i kurzorové klávesy, funkční klávesy a další.
Zkrácené a úplné vyhodnocování booleovských výrazů viz [1] – Pascal pro zelenáče (str. 57 kap. 5.2), v Delphi
je ho možno (kromě direktiv překladače {$B+} a {$B-}) zapnout/vypnout v menu Project/Options, karta
Compiler, volba Complete boolean eval. Toto nastavení se ukládá pro daný projekt do souboru
JMENO_PROJEKTU.CFG.
Cyklus s podmínkou na začátku a na konci
Syntaxe viz dokument [3] – „Jazyk Pascal – úvod“ a [1] – Pascal pro zelenáče (str. 34–37 kap. 3.6).
Příklad KONZOLE_HVEZDICKY_TROJ_1
Poznámka: Pravoúhlý trojúhelník z hvězdiček v textovém režimu.
Příklad KONZOLE_HVEZDICKY_TROJ_2
Poznámka: Rovnoramenný trojúhelník z hvězdiček v textovém režimu.
Číselné datové typy
Dělí se na celočíselné a reálné.
Celočíselné jsou buďto se znaménkem (Integer, Shortint, Smallint, Longint, Int64) nebo bez znaménka
(Byte, Word, Longword, Cardinal), viz [6] – nápověda k Delphi (klíčové slovo integer). Ze znalosti, kolik
daný celočíselný typ zabírá místa v paměti odvodíme rozsah hodnot tohoto typu: integer zabírá 32 bitů, tj.
může uchovávat 232 různých hodnoty, a protože je se znaménkem, tak tato čísla budou z intervalu
2 32 232
;
− 1 , tj. 2147483648 , 2147483647 . Horní mez je o 1 menší kvůli 0.
2 2
Pozor, díky omezenému rozsahu nemusí být například sčítání asociativní, viz [1] – Pascal pro zelenáče, str. 40
(kap. 4.1) a 50–52 (kap. 4.5).
Reálné datové typy jsou ukládány v semilogaritmickém tvaru, viz [1] – Pascal pro zelenáče, str. 41 (kap. 4.2).
Reálná čísla jsou vždy uchovávána na konečný počet desetinných míst nebo jako zlomky – jedná se tedy vždy
pouze o čísla racionální!!! V Delphi jde o datové typy Single, Extended, Real48, Double, Comp,
Currency, Real, viz [6] – nápověda k Delphi (klíčové slovo real).
Pozor, díky zaokrouhlovacím chybám může porovnávání reálných čísel působit problémy, viz [1] – Pascal pro
zelenáče, str. 49 (kap. 4.4) – není vhodné testovat reálné hodnoty na rovnost.
Datový typ Char
Reprezentuje jeden znak. Znaková konstanta je (podobně jako řetězec) uzavřena do apostrofů. Apostrof
zapíšeme tak, že ho zdvojíme – tj. '''' je znaková konstanta pro zápis apostrofu.
Znaky jsou uspořádány v pořadí podle tzv. ASCII tabulky (American Standard Code for Information
Interchange).
Jazyk Pascal předpokládá o ASCII tabulce následující – viz [1] – Pascal pro zelenáče, kapitola 6.1 (str. 61).
Příklad ASCII_TABULKA_1
Poznámka: Konzolová varianta – výpis ASCII tabulky na textovou konzoli.
Příklad ASCII_TABULKA_2
Poznámka: Výpis ASCII tabulky do ListBoxu.
Konstanty
Pro zpřehlednění kód a zjednodušení případných změn – stačí změnit danou hodnoty pouze na jednom místě, viz
[1] – Pascal pro zelenáče, kapitola 4.3 (str. 43–46).
Používání symbolických konstant nijak neovlivňuje výsledný exe soubor, protože preprocesor ještě před
vlastním překladem nahradí všechny zápisy identifikátorů konstant jejich hodnotami.
Typované konstanty
Jsou to v podstatě inicializované proměnné (tj. již při deklaraci jim je přiřazena hodnota), viz [1] – Pascal pro
zelenáče, kapitola 4.3 (str. 45–46). Pozor, pokud se jedná o lokální konstantu, hodnota je jí přiřazena pouze
jednou – ne při každém volání podprogramu.
V Delphi je tato nebezpečná možnost standardně vypnuta, lze ji ale povolit – Project/Options, karta Compiler,
pole Assignable typed constant. Stejnou funkci má direktiva překladače {$J+} – musí být uvedena na začátku
zdrojového kódu.
Co dělá preprocesor
Preprocesor upraví zdrojový kód ještě před vlastním překladem, například odstraní komentáře a nahradí
identifikátory konstant jejich hodnotami.
program Pokus;
const CISLO = 25; {symbolická konstanta}
var A, B: integer;
begin
A:=CISLO;
{inicializace proměnné A}
B:=A+CISLO;
{výpočet hodnoty proměnné B}
end;
Zdrojový kód
preprocesor
program Pokus;
var A, B: integer;
begin
A:=25;
B:=A+25;
end;
Upravený
zdrojový kód
překladač
Strojový kód
Pole
Deklarace viz [1] – Pascal pro zelenáče, kapitola 9.1 (str. 77–79).
Vícerozměrné pole a kompatibilita typů viz [4] – „Pole (vícerozměrné i jednorozměrné)“.
Příklad POLE_1
Poznámka: Kopírování obsahu jednoho pole do druhého – kompatibilita typů v praxi.
Příklad POLE_2
Poznámka: Ukázka generování náhodných čísel z určitého rozmezí, ukládání do pole a výpis obsah pole
do komponenty TListBox.
Delphi při standardním nastavení projektu při běhu nekontrolují meze polí, takže následující kód neohlásí chybu
při překladu (což je vcelku logické) ale ani při běhu (!):.
var pole: array[1..10] of integer;
i: integer;
begin
i:=11;
pole[i]:=999;
end;
Bude však přistupovat k paměti, která mu není vyhrazena – to je hodně nebezpečné a bývá to příčinou těžko
odhalitelných chyb („program občas spadne, zatuhne…“). Při běhu se můžeme v lepším případě (tj. víme, že je
něco špatně) dočkat následujícího hlášení, v horším případě se bude program chovat nepředvídatelně a nevypíše
žádnou chybovou hlášku:
Proto je vhodné ve vlastnostech projektu nastavit kontrolu mezí polí za běhu – Project/Options, karta Compiler,
pole Range Checking. Je to bezpečnější (každé překročení mezí pole bude hlášeno vyvoláním výjimky), ale
mírně to zpomaluje výsledný kód.
Vyhledávání v poli (lineární vyhledávání)
Viz dokument [5] – „Vyhledávání v poli“.
Příklad SPORTKA
Poznámka: Program generuje 6 náhodných neopakujících se čísel ze 49. Pro vyhledávání v poli je
použito lineární vyhledávání se zarážkou.
Komponenta TTimer – časovač
V pravidelných intervalech generuje zprávu – vyvolává událost OnTimer. Je to nevizuální komponenta (nezáleží
na jejím umístění a nelze nastavovat její velikost). Vlastnost Enabled udává, zda bude tato událost generována
(tj. časovač bude aktivní) a ve vlastnosti Interval je časový interval v milisekundách.
Příklad HODINY
Práce s datumem a časem
Datový typ TDateTime je totožný s reálným typem Double, datum a čas se uchovává jako počet dní od
30. 12. 1899 12.00 dopoledne (čas se uchovává jako zlomky dne – 1/24 je jedna hodina, 1/(24*60) jedna
minuta…). Díky tomu lze od sebe dva datumy odečíst a dostaneme počet dní mezi nimi.
Funkce Now vrací aktuální datum a čas, Date vrací pouze datum, Time pouze čas.
Pro převod datumu a času na řetězce slouží funkce DateTimeToStr, funkce DateToStr převádí pouze datum
na řetězec, TimeToStr pouze čas. Nejvíce možností pro formátování datumu a času nabízí funkce
FormatDateTime. K převodům řetězců na datum a čas slouží funkce StrToDateTime, StrToDate,
StrToTime.
Více viz [6] – nápověda k Delphi (klíčové slovo date/time routines)
Příklad STOPKY_1
Poznámka: Nepřesné stopky – časovač není příliš přesný.
Příklad STOPKY_2
Poznámka: Stopky s vylepšenou přesností využívající systémového času.
Jednoduché animace pomocí časovače
Komponentu TTimer můžeme využít k jednoduché animaci. Výhodou (na rozdíl od použití cyklů) je, že tento
způsob neblokuje celou aplikaci, která tam může reagovat na myš, klávesnici apod.
Příklad POHYB_KOLECKA_5
Poznámka: Pohyb kolečka pomocí časovače. Klikáním na šipky zvětšujeme rychlost pohybu v daném
směru. Kolečko se odráží od okrajů formuláře.
Datový typ String (řetězec) – práce s textem
Datový typ String slouží pro uložení posloupnosti znaků, mohli bychom ho nahradit polem znaků, tj. deklarací:
const MaxDelka = 100;
var retezec: array[1..100] of char;
Při použití datového typu řetězec určeného pro práci s textem nám Delphi dávají k dispozici další funkce –
například pro spojení řetězců, zjištění délky, vyhledávání v řetězci apod.
K jednotlivým znakům řetězce přistupujeme podobně jako v prvkům pole – index znaku je uzavřen v hranatých
závorkách.
V jazyce Pascal je datový typ řetězec ukládán jako pole znaků o maximální délce 255 znaků (Pascalovské
řetězce). V nultém indexu pole je uložen znak, jehož ordinální hodnota udává aktuální počet znaků v řetězci. Do
závorek je možno při deklaraci uvést maximální možný počet znaků v řetězci (do hranatých závorek, tj. např.
String[13]). Tomuto odpovídá v Delphi datový typ ShortString.
Delphi umožňují (a upřednostňují) používání i tzv. null-terminated strings (pocházejících z jazyka C) – řetězců
ukončených znakem s ordinální hodnotou nula (null, #0), tento znak označuje konec řetězce. Řetězec může mít
délku až 230 znaků a zabírá v paměti 4 B až 2 GB. Tomuto odpovídají datové typy AnsiString a WideString.
Jak se chová obecný datový typ String určuje nastavení překladače – menu Project/Options, karta Compiler,
volba Huge strings: pokud je zapnuto, tak String=AnsiString (standardně), jinak String=ShortString.
Lze přepínat i volbami překladače {$H+} zapne Huge strings, a {$H-} vypne tuto volbu.
Pozor, v Delphi nemůže řetězcová konstanta obsahovat více jak 255 znaků. Tj. zápis
retezec := 'více jak 255 znaků';
je chybný (i když proměnná retezec je typu AnsiString), chybu ohlásí už při překladu („String literals may
have at most 255 elements.“).
Tuto dlouhou řetězcovou konstantu je nutno rozdělit na dvě a ty spojit (sečíst):
retezec := 'první část - méně jak 255 znaků' + 'druhá část - méně jak 255 znaků';
Přetypování
Jde vlastně o „násilnou“ změnu typu proměnné – donutím překladač, aby s hodnotou, která je uložena
v proměnné určitého typu, pracoval jako s hodnotou jiného typu. Pozor, je to dosti nebezpečné!!! Musím přesně
vědět, co dělám, proč to dělám a zda si mohu přetypování dovolit.
Přetypování může být bezpečné (překladač provádí základní kontroly, zda takto přetypovat mohu) a
nebezpečné (bez jakýchkoli kontrol).
Bezpečné přetypování: <proměnná> as <nový typ>
Nebezpečné přetypování: <nový typ>(<proměnná>)
var znak: char;
cislo: byte;
begin
znak:='A';
//
//
cislo:=znak;
cislo:=znak as byte;
cislo:=byte(znak);
//
//
//
//
//
prosté přiřazení - nelze, chyba!!!
bezpečné přetypování - nelze, chyba!!!
nebezpečné přetypování – lze
nyní bude v proměnné cislo hodnota 65,
tj. ordinální číslo znaku 'A'
end;
Použití přetypování pro načítání a výpis hodnot výčtového typu
Hodnoty výčtového typu nelze jednoduše načítat ani vypisovat.
Při načítání hodnot výčtového typu, které uživatel vybírá z rozbalovacího seznamu (TComboBox), si lze ulehčit
práci pomocí přetypování. Musí ale platit, že hodnoty uvedené při deklaraci výčtového typu jsou ve stejném
pořadí jako hodnoty v rozbalovacím seznamu. Zde využíváme toho, že symbolické konstanty ve výčtovém
typu mají hodnoty 0, 1, 2… podle jejich pořadí při deklaraci.
type TStav = (svobodny, zenaty, rozvedeny, vdovec);
var stav: TStav;
Doporučený postup pomocí case – delší, ale bezpečné:
procedure TForm1.ComboBox1Change(Sender: TObject);
begin
case ComboBox1.ItemIndex of
0: stav:=svobodny;
1: stav:=zenaty;
2: stav:=rozvedeny;
3: stav:=vdovec;
end;
end;
Kratší, ale nebezpečnější postup pomocí přetypování:
procedure TForm1.ComboBox1Change(Sender: TObject);
begin
stav:=TStav(ComboBox1.ItemIndex);
end;
Podobný přístup můžeme využít při výpisu hodnot uložených v proměnné stav. Připravíme si pole hodnot
výčtového typu (tak, jak chceme, aby se v textové podobě vypisovaly) a poté jednoduše pomocí ordinální
hodnoty konstanty uložené v proměnné stav toto pole indexujeme. Můžete také využít přetypování proměnné
stav na typ byte (to je ale méně bezpečné).
const stav_hodnoty: array[0..3] of string = ('svobodný', 'ženatý', 'rozvedený',
'vdovec');
...
ShowMessage(stav_hodnoty[ord(stav)]);
// pomocí ordinální hodnoty
ShowMessage(stav_hodnoty[byte(stav)]);
// pomocí přetypování
Příklad VYCTOVY_TYP_PRETYPOVANI
Práce se soubory
Soubor = abstrakce, kterou nám poskytuje OS; takže pracuji se souborem a nezajímá mě, kde a jak jsou data
skutečně fyzicky uložena (na HDD, disketě, flash disku, magnetické pásce…).
Práce se souborem má většinou následující fáze:
1.
otevření souboru (OS zjistí, zda takový soubor existuje, zda aplikace má právo pracovat s tímto
souborem, provede zamčení souboru, aby do něho ostatní aplikace nemohly zapisovat…)
2.
zpracování dat (čtení a zápis dat)
3.
uzavření souboru (uložení dat z vyrovnávací paměti na disk, uvolnění souboru)
Dělení souborů:
1.
textové (informace v nich jsou čitelné v textové podobě)
2.
binární (data v binární podobě) – typové nebo netypové (amorfní)
Jak v Delphi?
Příkazy pro práci se soubory v Delphi se mírně liší od příkazů jazyka Turbo Pascal, ale až na pár odlišností je
vše uvedeno v [1] – Pascal pro zelenáče, kapitola 15 (str. 143–158).
V Delphi pracujeme s proměnnou typu soubor, tu nejprve svážeme s fyzickým souborem na disku pomocí
AssignFile(<prom. typu soubor>, 'c:\...').
Poté soubor otevřeme procedurou Reset(<prom.
soubor>).
typu
soubor>) nebo Rewrite(<prom.
typu
Data do souboru zapisujeme pomocí write(<prom. typu soubor>, <prom1>, <prom2>, …), ze souboru
čteme data pomocí read(<prom. typu soubor>, <prom1>, <prom2>, …).
Na konec soubor uzavřeme procedurou CloseFile(<prom. typu soubor>).
Pro test, zda jsme přičtení na konci souboru používáme funkci EOF(<prom. typu soubor>).
Textové soubory
Textové soubory jsou čitelné pro „lidi“, data v nich jsou uspořádána do řádků. Řádky jsou odděleny dvojicí
znaků CR+LF (ordinální hodnoty 13 a 10). Pro podrobnější informace viz [1] – Pascal pro zelenáče, kapitola 10
(str. 87–99).
Deklarace
var soubor: TextFile;
Reset otevře soubor pro čtení a nastaví čtecí hlavu na začátek, soubor musí existovat.
Rewrite založí nový soubor (stávající případně smaže) a otevře ho pro zápis.
Append otevře existující soubor pro zápis a nastaví zápisovou hlavu na konec souboru.
Procedura writeln(<prom. typu soubor>) zapíše do souboru znak konce souboru – EOLN (který je
reprezentován dvojicí znaků CR+LF), procedura readln(<prom. typu soubor>) skočí (nastaví čtecí hlavu)
za nejbližší znak EOLN.
writeln(<prom. typu soubor>, <prom1>, <prom2>) je zkratkou za
write(<prom. typu soubor>, <prom1>);
write(<prom. typu soubor>, <prom2>);
writeln(<prom. typu soubor>)
Funkci EOLN(<prom. typu soubor>) používáme pro testování zda je konec řádku.
Textové soubory poskytují pouze sekvenční přístup – čteme jednotlivé znaky od začátku do konce, jeden po
druhém. Nemohu tedy v souboru „skákat“.