Pro další příklady bude bohužel třeba trochu teorie.
Pascal je jazyk deklarativní, lze používat to, co bylo předem nadeklarováno. Například pokud si připravíme podprogram pro nějakou činnost (v Pascalu používáme termín procedura), můžeme jej používat až od místa, kde byl deklarován, dále. To vede v důsledku k tomu, že hlavním programem (tím, co se opravdu spouští) text programu končí. My se v našem případě k hlavnímu programu nedostaneme, protože ten za nás (alespoň v tomto předmětu) vždy celý vygenerují Delphi a bude lépe do něj nezasahovat. V rámci jednotlivých procedur ovšem toto pravidlo platí také (Pascal samozřejmě nabízí prostředky, jak jej obejít, je-li to nutné). Pro nás především znamená, že každou proměnnou musíme nejprve nadeklarovat.
Deklarace proměnných začíná klíčovým slovem var. Klíčová slova je zvykem pro přehlednost psát tučně, v rukopise pak podtženě, zjednodušuje to čitelnost textu. Po klíčovém slově následuje postupně vyjmenování proměnných ve tvaru pojmenování proměnné- dvojtečka - typ - středník. Pascal považuje konce řádků za znak srovnatelný s mezerou, proto vyžaduje středník za každým příkazem (deklarací proměnné, procedurou a podobně). Můžeme jak napsat více příkazů na řádek, tak i jeden příkaz na více řádků.
V rámci deklarace je možné nadefinovat více proměnných stejného typu najednou; jejich jména jsou pak oddělena čárkou. Skutečná deklarace může vypadat například následovně:
var delka, sirka : integer; jmeno : string; prijmeni : pchar; adresa : string[33];
Zde se vyskytlo několik základních typů. Podrobněji se jim budete věnovat na přednášce, nebo se podívejte do nápovědy (viz dále). Jsou to vesměs typy, jejichž charakter závisí na konkrétní verzi jazyka.
integer reprezentuje celé číslo. Proměnná tohoto typu nabývá hodnot v rozsahu přibližně -231 až 231-1 (v Delphi 3 a vyšším, až dosud).
char nebyl použit, ale představuje jeden znak. Ve skutečnosti existují dva typy znaků, ANSI a Wide. První zabírá v paměti 1 byte (má 256 možných hodnot), kdežto druhý 2byte (216, tedy 65536 hodnot, přípustné jsou ty, které jsou v sadě Unicode). Delphi 4 používá kratší, ale lze to změnit tzv. direktivou pro překladač, stejně jako ostatní dnes ještě zmiňované typy.
string od slova řetěz představuje více znaků. Můžeme se indexem obrátit na kterýkoli z těchto znaků, přičemž index se v Pascalu píše do hranaté závorky. Pokud se objeví již v deklaraci, udává nejvyšší přípustnou délku daného řetězce (nejvyšší index, který se může vyskytnout). Tento údaj je dobré při deklaraci uvádět, jinak by se vygeneroval řetězec o maximální možné velikosti, zabírající příliš mnoho operační paměti. Typ string je indexován od jedné (v nulté položce je aktuální počet znaků), kdežto typ pchar je indexován od nuly (poslední znak je ten, za nímž je znak s kódem nula). I string je generický typ - známe tři typy stringů; délka řetězce je buď v jednom bytu (a každý ze znaků je ANSI char), nebo ve dvou znacích (pak jsou možné obě možnosti). Maximální velikost řetězce s délkou ve dvou znacích v paměti je 64KB.
pchar má nevýhodu, že je třeba mu nejprve (před prvním použitím) v paměti vyhradit místo. Pokud jej použijí Deplhi, udělají tuto problematickou činnost za nás. Pchar odpovídá způsobu, jakým jsou řetězce znaků reprezentovány v jazycích C, a je často používán v knihovnách, které jsou převzaty z jazyka C.
Pro další výklad bude třeba uvést na příkladu nejčastější z příkazů, příkaz přiřazení. Má tvar
<proměnná> := <výraz> ;
K výpočtům se dostaneme příště, takže výraz pro nás bude prozatím buď jiná proměnná, nebo konstanta. Celé číslo dokáže napsat každý; řetězec znaků se zapíše podle následujících pravidel:
Uvnitř zápisu hodnoty řetězce vně apostrofů samozřejmě nesmí být žádná mezera a podobně. Pokud chceme zapsat znak (char), napíšeme řetězec o délce jednoho znaku. Správné jsou tedy například zápisy přiřazení proměnné jmeno typu string (druhý a třetí obsahuje apostrof a jsou stejné, poslední dva jsou také stejné):
jmeno := 'Aleš Černý'; jmeno := 'Adam''s voice'; jmeno := 'Adam'#27's voice'; jmeno := 'blue'^I'black'^I'white'; jmeno := 'blue'#9'black'#9'white';
Pokud by bylo nutné napsat znaky pro konec řádku, učinilo by se tak zápisem #13#10, v praxi by však k tomu nemělo dojít. Pro pochopení použití proměnných, které generuje prostředí Delphi, musíme bohužel poněkud přeskočit a věnovat se jedné z posledních kapitol výuky Pascalu, objektům. Objekty jsou nadstavbou záznamů (record), o nichž se zmiňme nejprve.
Pokud nám nestačí předem nadeklarované typy, můžeme si nadefinovat další na základě těch, které již systém zná. Dělá se tak v části, uvozené klíčovým slovem type. Z výše uvedeného plyne, že úsek deklarace typů musí deklaraci proměnných předcházet. Teprve za nimi mohou následovat funkce, které dané typy využívají. Například, pokud často používáme řetězce o maximálně 37 písmenech, můžeme si pro ně nadeklarovat typ. Místo
var pol1,pol3 : string[37];
můžeme psát
type hbk = string[37]; var pol1,pol3 : hbk;
V reálném programu se pojmenování typu objevuje na řadě dalších míst, takže daný postup může ušetřit vypisování a zpřehlednit text programu, samozřejmě za předpokladu, že pro označení typu bude použit nějaký rozumný text, a ne náhodná tři písmena, jako v předchozí ukázce. Označení typu nejčastěji začínáme písmenem T, a za ním je označení první (nebo nejdůležítější) proměnné tohoto typu.
type Tpol = string[37];
Zbývá dodat, že každá deklarace typu vypadá tak, že je zvolené označení typu, za ním rovnítko, a pak následuje popis, jak daný typ vypadá. Za koncem popisu je středník; případně mohou následovat další deklarace. Nás bude nyní zajímat deklarace typu záznam (record).
Záznam se hodí, pokud chceme mít údaje různých druhů pohromadě v jedné proměnné. Jako učebnicový příklad se zpravidla uvádí zápis záznamu "osoba", který je typu "tosoba" a má položky jméno, příjmení, a například výška a váha. Popíše se tak, že se za rovnítko napíše klíčové slovo record a za něj se jednotlivé položky záznamu nadeklarují, jako by šlo o proměnné (jméno - dvojtečka - typ - středník). Jednotlivé deklarace jsou tedy samozřejmě odděleny středníky. Popis záznamu je třeba nějak ukončit - děje se tak klíčovým slovem end, za nímž zpravidla následuje další středník. V našem případě
type Tosoba = record jmeno : string[33]; prijmeni : string[37]; vyska, vaha : integer; end; var osoba, osoba2 : Tosoba;
V průběhu programu se na jednotlivé položky záznamu odkazujeme tak, že napíšeme jméno proměnné (uvedeno v části var), za něj tečku a pak jméno položky záznamu. Jako mnemonickou pomůcku lze uvést, že jako jméno proměnné píšeme to, co bylo v deklaracích před dvojtečkami. Například
osoba.jmeno := 'Petr'; osoba2.vyska := osoba.vyska;
Složitější situace nastane, pokud na základě záznamu Tosoba nadeklarujeme záznam Tzam, obsahující záznamy o zaměstnanci (zbývající dovolená, plat...)
type Tosoba = record jmeno : string[33]; prijmeni : string[37]; vyska, vaha : integer; end; Tzam = record os : Tosoba; plat, dovolena : integer; end; var osoba, osoba2 : Tosoba; z1,z2,z3 : Tzam;
Při použití proměnné z1, pokud budeme pracovat s položkou "jméno", se na ni musíme odkazovat přes položku "os". Celý zápis pak bude vypadat následovně:
z1.os.jmeno := 'Jiří';
Z jedné strany je toto zadání (použít položky již dříve nadefinovaného záznamu) běžné, z druhé strany je zřejmé, že výše uvedená metoda by vyžadovala psát příliš mnoho teček. Řešení tohoto problému je jedním z přínosů objektově orientovanéhö programování, jehož použití bude mimo jiné probíráno v předmětu OOP. Objekt se od záznamu liší tím, že je schopen zdědit vlastnosti po některém již dříve deklarovaném objektu. Jméno tohoto objektu (předchůdce) se napíše za klíčové slovo object (nahrazuje klíčové slovo record) do závorky, například
type Tosoba = object jmeno : string[33]; prijmeni : string[37]; vyska, vaha : integer; end; Tzam = object(Tosoba) plat, dovolena : integer; end; var osoba, osoba2 : Tosoba; z1,z2,z3 : Tzam;
Výsledkem je, že odkaz, uvedený výše, bude mít tvar
z1.jmeno := 'Jiří';
Z uvedeného je zřejmé, jakým způsobem pracuje generátor programu v Delphi. Zkuste si vytvořit formulář, na kterém bude tlačítko (Button1), nápis (Label1) a edit box (Edit1). Tento formulář bude pro automaticky generované objekty používat jedinou proměnnou Form1, jejíž typ je definován následujícím zápisem:
type TForm1 = class(TForm) Label1: TLabel; Edit1: TEdit; Button1: TButton; private { Private declarations } public { Public declarations } end;
Klíčové slovo object zde nahrazuje klíčové slovo class, které je dalším vývojovým stadiem objektově orientovaného programování. Nicméně struktura takto získané proměnné Form1 je zřejmá. Pokud například editovaný text edit boxu Edit1 je v jeho složce Text, pak jej můžeme získat zápisem Form1.Edit1.Text. Některé objekty vznikly složitěji. Například barva nápisu je v jeho položce Font, která teprve obsahuje položku Color (sám Font je objekt). Pokud víme, že hodnotu červené barvy vyjadřuje konstanta clRed, pak ji můžeme nastavit příkazem
Form1.Label1.Font.Color := clRed;
Ještě k okénku Object Inspector (F11), o kterém jsme se již zmiňovali minule. Pokud zvolíme záložku properties, zobrazuje nám properties, vlastnosti, což jsou hodnoty těch položek záznamu příslušného objektu, které lze nastavit již před spuštěním programu (existují vlastnosti, které lze měnit jen za běhu programu, nebo dokonce jen číst). Odpovídají jednotlivým položkám záznamu. Pokud chceme vědět, co všechno vlastně daný předdefinovaný objekt obsahuje, je nejlépe zapsat označení typu objektu (TForm, TButton) kamkoli do programu, umístit do něj editační kursor (kliknutím myší) a stisknout kombinaci kláves Ctrl+F1.
Již minule jsme si zkoušeli dvojklikem na objekt vygenerovat obslužný program (místo, kam lze v Pascalu napsat, co se má při dané akci provést). Pro naše objekty se vygeneruje obsluha pro kliknutí na objekt (objekty tlačítko a nápis), popřípadě pro změnu obsahu (objekt edit - pokud změníme obsah tohoto objektu, vyvolá se tato funkce). V dnešním cvičení by jste si měli zkusit následující zadání: Pokud někdo stiskne tlačítko, zkopíruje se aktuální obsah editboxu do zobrazovaného textu komponenty Label1. Obsah editboxu je dostupný v objektu Edit1 jako položka Text; obsah zobrazovaného nápisu je v property Caption příslušného Label1.
Postupujeme následovně: Dvojklikem na tlačítko si vygenerujeme příslušné místo pro vkládání příkazů. Zde napíšeme samotný příkaz přiřazení:
Form1.Label1.Caption := Form1.Edit1.Text;
Program nezapomeňte uložit (Save Project as...) do vhodného adresáře (viz minulá hodina), spusťte jej a vyzkoušejte (změnit obsah edit boxu, stisknout tlačítko, několikrát zopakovat).
Zadání pro samostatnou práci:
Tak jako tlačítko, tak i samotný formulář Form1 má property
Caption. Vytvořte program, který při
jakékoli změně textu v edit boxu Edit1 obsah edit boxu
přenese do propery Caption formuláře Form1.
Pascal dodržuje původní normu, podle které programátor mohl psát malá i velká písmenka dle okamžitého uvážení. Za tímto účelem je implementován algoritmus, který před porovnání velikost písmen sjednotí. Některé jiné programovací jazyky ovšem tento program postrádají, takže je nutno velikost písmen vždy dodržet. Uvádím to zde proto, že řada lidí se domnívá, že nerozlišovat malá a velká písmena je méně práce, než je rozlišit. Opak je pravdou.
V Pascalu končí příkaz středníkem. Někdy je nutné jednotlivá slova od sebe oddělit, k tomu se používá tzv. oddělovač. Oddělovačem je mezera, tabulátor nebo přechod na novou řádku. Tyto tři příkazy jsou v Pascalu zcela rovnocenné. Může být tedy více příkazů na jednom řádku, nebo jeden příkaz na více řádcích. Na dalším řádku nemůže pokračovat jen zápis textové konstanty (mezi apostrofy), protože v něm není žádný oddělovač.
Komentáře se píší do složených závorek (znaky { a } ). Komentář začíná první levou složenou závorkou a končí první pravou, nedodržuje se tedy párování. Pokud je třeba "odkomentovat" (vypustit z překladu) část programu a rozhodnete se použít komentáře, lze použít kombinovaných závorek s hvězdičkou (* a *), které jsou přednostní. Pokud se v programu najde tato kombinace znaků, překlad pokračuje až za znaky *). Komentář k jednotlivé řádce lze také napsat za dvě lomítka (platí do konce řádku).
Existují další zvyklosti, které je dobré dodržovat, protože zajistí lepší čitelnost programu. Například vnořené části se ze zvyku píší o dva znaky odsazené (viz uváděné příklady). Jednoslovné názvy se píší malými písmeny, u víceslovných se počáteční písmena použijí velká (např. výpočet průměrné výšky zaměstnanců může provádět funkce VypocetPrumerneVyskyZamestnancu).
Hotová úloha je v souboru "edit". Omlouvám se za spletený název projektu.