-
Struktura je typ, kter² reprezentuje u╛ivatelsky definovanou mno╛inu pojmenovan²ch
slo╛ek (prvk∙). Tyto slo╛ky mohou b²t libovolnΘho typu a mohou mφt libovolnΘ
po°adφ. Struktury se deklarujφ pomocφ klφΦovΘho slova struct, nap°.
struct TStruktura
{
// TStruktura je oznaΦenφ struktury
deklarace slo╛ek struktury
};
...
struct TStruktura
s, *ps, poleS[10] // s je struktura TStruktura,
ps je ukazatel na strukturu TStruktura
// poleS je pole prvk∙ typu TStruktura
Pokud vynechßme jmΘno (oznaΦenφ) struktury, dostaneme tzv. nepojmenovanou
strukturu. NepojmenovanΘ struktury se mohou pou╛φvat p°i deklaraci prom∞nn²ch
danΘho strukturovΘho typu, ale nikde jinde ji╛ dal╣φ objekty tohoto typu
definovat nem∙╛eme:
struct { ... } s,
*ps, poleS[10];
P°i deklarovßnφ struktur je mo╛nΘ pomocφ typedef (stejn∞ jako
pro jinΘ typy - poslednφ identifikßtor na °ßdku je nov² nßzev pro typ popsan²
mezi typedef a tφmto identifikßtorem) vytvo°it nov² specifikßtor
datovΘho typu:
typedef struct TStruktura
{ ... } STRUKT;
STRUKT s, *ps, poleS[10];
// totΘ╛ jako p∙vodnφ deklarace
V∞t╣inou nenφ zapot°ebφ pojmenovßnφ struktury a typedef souΦasn∞.
M∙╛eme je ale pou╛φt. Je takΘ mo╛nΘ vytvo°it specifikßtor nepojmenovanΘ
struktury.
Seznam deklaracφ slo╛ek uzav°en² ve slo╛en²ch zßvorkßch deklaruje typy
a jmΘna slo╛ek struktury.
Funkce m∙╛e vracet strukturu nebo ukazatel na strukturu. Struktura
m∙╛e b²t p°edßna jako parametr funkce p°φmo, jako ukazatel nebo odkaz na
strukturu.
P°φstup ke slo╛kßm struktur se provßdφ prost°ednictvφm operßtor∙ .a
->.
Operßtor .se naz²vß p°φm² selektor
slo╛ky, operßtor -> se naz²vß nep°φm²
selektor slo╛ky (v²raz ukazs->m
je synonymum pro (*ukazs).m
-
pou╛φvß se, kdy╛ mßme ukazatel na strukturu).
struct TStructura
{
int i;
char str[2];
double d;
} s, *ukazs = &s;
...
s.i = 3;
// p°i°azenφ slo╛ce i struktury s
ukazs->d = 1.23;
// p°i°azenφ slo╛ce d struktury s (struktura je identifikovanß ukazatelem
ukazs)
Pokud jednou ze slo╛ek struktury B je struktura A, pak
slo╛ky struktury A mohou b²t zp°φstupn∞ny dvojφ aplikacφ selekΦnφch
operßtor∙. Struktury je mo╛no p°i°azovat jen v tom p°φpad∞, ╛e jsou stejnΘho
typu.
Ukazatel na strukturu typu A se m∙╛e objevit v deklaraci jinΘ
struktury B je╣t∞ p°edtφm, ne╛ je A deklarovßno. Nap°.
struct A;
// p°edb∞╛nß deklarace
struct B { struct
A *pa; };
struct A { struct
B *pb; };
Prvnφ deklarace A se naz²vß p°edb∞╛nß, proto╛e A prozatφm
nenφ celß definovßna. Takovßto p°edb∞╛nß deklarace staΦφ k tomu, aby jsme
mohli pou╛φt v definici B ukazatel na A, nebo╗ B nepot°ebuje
znßt velikost A.
-
P°edpoklßdejme, ╛e si chceme udr╛ovat adresß° sv²ch znßm²ch. Vytvo°φme
tedy strukturu se slo╛kami, kterΘ se obvykle pou╛φvajφ v adresß°i. Nap°.
struct adresar {
char jmeno[20];
char prijmeni[20];
char ulice[50];
char mesto[20];
int psc;
bool pritel;
};
Struktura mß 4 znakovΘ, jednu celoΦφselnou a jednu logickou slo╛ku.
Po deklaraci struktury ji m∙╛eme pou╛φt. Nejprve je nutno vytvo°it instanci
struktury (prom∞nnou pro ulo╛enφ struktury). To provedeme takto:
adresar zaznam;
Tento p°φkaz alokuje pam∞╗ pro strukturu a p°i°adφ alokovanou pam∞╗
prom∞nnΘ zaznam. Nynφ, kdy╛ mßme instanci struktury, m∙╛eme p°i°adit
hodnoty jejφm slo╛kßm:
strcpy(zaznam.jmeno,
"Karel");
strcpy(zaznam.prijmeni,
"Novak");
strcpy(zaznam.ulice,
"Palackeho 876");
strcpy(zaznam.mesto,
"Pardubice"
zaznam.psc = 53002;
zaznam.pritel = false;
Toto lze provΘst takΘ p°φmo p°i deklaraci struktury:
adresar zaznam =
{ "Karel", "Novak", "Palackeho 876",
"Pardubice", 53002, false};
Stejn∞ jako m∙╛eme mφt pole cel²ch Φφsel nebo pole znak∙, m∙╛eme mφt
i pole struktur. Nap°.
adresar seznam[5];
strcpy(seznam[0].jmeno,
"Karel");
seznam[4].pritel
= false;
// atd.
Zde pou╛φvßme operßtor indexace a operßtor selektoru slo╛ky.
-
Zdrojov² soubor je textov² soubor obsahujφcφ zdrojov² k≤d programu. P°ekladaΦ
p°ebφrß soubory zdrojovΘho k≤du, zpracovßvß je a vytvß°φ strojov² k≤d,
kter² m∙╛e b²t spu╣t∞n na poΦφtaΦi.
P°i na╣em seznamovßnφ s programovßnφm, °e╣φme samΘ jednoduchΘ ·lohy.
P°i vytvß°enφ reßln²ch aplikacφ se bude jednat o podstatn∞ slo╛it∞j╣φ ·lohy.
Normßlnφ program se obvykle sklßdß z n∞kolika zdrojov²ch soubor∙. Programov²
k≤d je rozd∞len do n∞kolika r∙zn²ch zdrojov²ch soubor∙ z n∞kolika d∙vod∙.
Zßkladnφm d∙vodem je udr╛ovßnφ k≤du t²kajφcφho se jednoho problΘmu v jednom
souboru, co╛ umo╛≥uje v p°φpad∞ pot°eby snadnΘ nalezenφ jistΘ Φßsti k≤du.
P°i p°ekladu, je nejprve p°elo╛en ka╛d² zdrojov² soubor (CPP) do objektovΘho
souboru (OBJ) a potom ka╛d² p°elo╛en² modul je sestaven sestavovacφm programem
do jednoho spustitelnΘho souboru (EXE). Sestavovacφ program takΘ p°ipojφ
dal╣φ pot°ebnΘ soubory, jako jsou soubory zdroj∙ (RES) a knihovnφ soubory
(LIB).
Deklarace pro t°φdy a struktury jsou dr╛eny v odd∞len²ch souborech
nazvan²ch hlaviΦkovΘ soubory. Tyto soubory majφ p°φponu H nebo HPP. HlaviΦkovΘ
soubory obsahujφ pouze deklarace t°φd, struktur a funkcφ. Nenφ vhodnΘ vklßdat
do nich k≤d p°φkaz∙. Z tohoto pravidla je jedna v²jimka. Do hlaviΦkov²ch
soubor∙ je mo╛no vklßdat vlo╛enΘ (inline) funkce. S tφm se ale seznßmφme
pozd∞ji.
Jestli╛e pot°ebujeme vytvo°it hlaviΦkov² soubor, pak zvolφme File
| New a na strßnce New dvojit∞ klikneme na ikonu Text.
C++ Builder vytvo°φ nov² textov² soubor a zobrazφ jej v Editoru k≤du. Zadßme
k≤d na╣eho hlaviΦkovΘho souboru a ulo╛φme vytvo°en² soubor s p°φponou H.
Po vytvo°enφ hlaviΦkovΘho souboru pro t°φdu nebo strukturu, m∙╛eme
direktivou include vlo╛it tento hlaviΦkov² soubor do libovolnΘho
zdrojovΘho souboru, ve kterΘm deklaraci t°φdy nebo struktury pot°ebujeme.
HlaviΦkovΘ soubory obvykle vytvß°φme tak, aby bylo zaji╣t∞no, ╛e do
programu budou vlo╛eny pouze jednou. Pou╛φvßme k tomu direktivy podmφn∞nΘho
p°ekladu (viz zadßnφ 1 v kapitole 10).
HlaviΦkovΘ soubory mohou obsahovat vφce ne╛ jednu deklaraci t°φdy nebo
struktury. Pou╛itφ samostatnΘho hlaviΦkovΘho souboru pro ka╛dou t°φdu nebo
strukturu ale pomßhß udr╛ovat organizaci projemtu a usnad≥uje op∞tovnΘ
pou╛itφ t°φd a struktur v dal╣φch programech. N∞kdy je mo╛no vlo╛it skupinu
svßzan²ch t°φd do jednoho hlaviΦkovΘho souboru.
-
Nynφ se pokusφme vytvo°it konzolovou aplikaci, ve kterΘ u╛ivatel zadß t°i
jmΘna a adresy a ulo╛φ tyto zßznamy do pole struktur. Po zadßnφ t∞chto
informacφ, jsou informace zobrazeny na obrazovce. Dßle je mo╛no zadat Φφslo
zßznamu, kter² chceme op∞tovn∞ zobrazit. V tΘto aplikaci definici struktury
uvedeme v samostatnΘm hlaviΦkovΘm souboru. Nejprve nßsleduje v²pis vlastnφho
programu.
#include <iostream.h>
#include <conio.h>
#include <stdlib.h>
#pragma hdrstop
#include "structur.h"
void zobrazZaznam(int,
adresar adrZaz);
int main(int argc,
char **argv)
{
adresar seznam[3];
cout <<
endl;
int index
= 0;
do {
cout << "JmΘno: ";
cin.getline(seznam[index].jmeno, sizeof(seznam[index].jmeno)-1);
cout << "P°φjmenφ: ";
cin.getline(seznam[index].prijmeni,
sizeof(seznam[index].prijmeni)-1);
cout << "Ulice: ";
cin.getline(seznam[index].ulice, sizeof(seznam[index].ulice)-1);
cout << "M∞sto: ";
cin.getline(seznam[index].mesto, sizeof(seznam[index].mesto)-1);
cout << "PsΦ: ";
char buff[10];
cin.getline(buff, sizeof(buff)-1);
seznam[index].psc = atoi(buff);
index++;
cout << endl;
} while (index
< 3);
clrscr();
for(int i
= 0; i < 3; i++) {
zobrazZaznam(i, seznam[i]);
}
cout <<
"Zadej Φφslo zßznamu: ";
int zaz;
do {
zaz = getch();
zaz -= 49;
} while (zaz
< 0 || zaz > 2);
adresar pom
= seznam[zaz];
clrscr();
zobrazZaznam(zaz,
pom);
getch();
return 0;
}
void zobrazZaznam(int
cis, adresar adrZaz)
{
cout <<
"Zßznam " << (cis + 1) << ":" << endl;
cout <<
"JmΘno: " << adrZaz.jmeno << " " << adrZaz.prijmeni <<
endl;
cout <<
"Adresa: " << adrZaz.ulice << endl;
cout <<
" " << adrZaz.mesto <<
endl;
cout <<
" " << adrZaz.psc <<
endl << endl;
}
a hlaviΦkov² soubor STRUCTUR.H je tento (ulo╛φme jej do stejnΘho adresß°e
jako zdrojov² soubor):
#ifndef _STRUCTUR_H
#define _STRUCTUR_H
struct adresar {
char jmeno[20];
char prijmeni[20];
char ulice[50];
char mesto[20];
int psc;
};
#endif
V programu vidφme n∞kolik nßm zatφm neznßm²ch v∞cφ. Program pou╛φvß
funkci getline t°φdy cin k zφskßnφ vstupu od u╛ivatele. Je
to z d∙vodu nep°φjemnΘho chovßnφ operßtoru >> p°i Φtenφ text∙, kterΘ mohou
obsahovat mezery. Druh² parametr getline je pou╛it k omezenφ dΘlky
vstupujφcφho °et∞zce (zajistφme tφm nep°epsßnφ informacφ za koncem slo╛ky).
Operßtor sizeof je pou╛it k urΦenφ velikosti slo╛ky a tedy k urΦenφ,
kolik znak∙ je do nφ mo╛no bezpeΦn∞ ulo╛it.
Funkce atoi je takΘ novß (je pou╛ita p°i Φtenφ po╣tovnφho sm∞rovacφho
Φφsla). Tato funkce p°ebφrß znakov² °et∞zec a p°evßdφ jej na celoΦφselnou
hodnotu. Zadan² text pro slo╛ku psc je nutno p°evΘst na celΘ Φφslo.
Funkce zobrazZaznam mß dva parametry. Prvnφ parametr udßvß Φφslo
zobrazovanΘho zßznamu. Zßznamy jsou Φφslovßny od nuly a jeliko╛ ve v²pisu
dßvßme p°ednost jejich Φφslovßnφ od 1, p°iΦφtßme k tomuto Φφslu p°ed v²pisem
jedniΦku. Druh² parametr funkce zobrazZßznam je instance struktury
adresar.
Je pou╛ita lokßlnφ instance tΘto struktury a uvnit° funkce je jejφ obsah
zobrazen.
V tomto p°φpad∞ p°edßvßme strukturu hodnotou. Tzn. b∞hem volßnφ funkce
je vytvo°ena kopie struktury. Toto nenφ moc efektivnφ, proto╛e vytvo°enφ
kopie n∞jakou dobu trvß a spot°ebovßvß mφsto v pam∞ti. Je v²hodn∞j╣φ p°edßvat
strukturu odkazem, ale to zatφm neumφme.
Funkci zobrazZaznam volßme na dvou mφstech v na╣em programu.
Na t∞chto mφstech by mohl b²t uveden obsah t∞la funkce a program by pracoval
stejn∞. Vlo╛enφm tohoto k≤du do funkce se sna╛φme zabrßnit opakovanΘmu
v²skytu stejnΘho k≤du. Pokud se v na╣em programu opakovan∞ vyskytuje stejn²
k≤d, je vhodnΘ z n∞j ud∞lat funkci, kterou pak volßme, kdy╛ tento k≤d je
zapot°ebφ provΘst.
Podφvejme se je╣t∞ na nßsledujφcφ k≤d:
do {
zaz = getch();
zaz -= 49;
} while (zaz <
0 || zaz > 2);
Tento k≤d Φte znak z klßvesnice pomocφ funkce getch (zatφm jsme
ji pou╛φvali k Φekßnφ na konci programu). Tato funkce vracφ k≤d stisknutΘ
klßvesy. Proto╛e ASCII hodnota klßvesy 1 je 49, klßvesy 2 je 50, atd.,
zφskßme odeΦtenφm 49 od k≤du p°eΦtenΘho znaku Φφselnou hodnotu klßvesy
zmen╣enou o 1 (nap°. p°i stisknutΘ klßvese 1 dostaneme hodnotu 0). Tento
cyklus tedy probφhß tak dlouho, dokud nestiskneme n∞kterou z klßves 1,
2 nebo 3.
Podφvejme se je╣t∞ na °ßdek
adresar pom = seznam[zaz];
Tento k≤d vytvß°φ instanci struktury adresar a p°i°adφ ji obsah
jednΘ struktury z pole struktur. Je zde mo╛no pou╛φt operßtor p°i°azenφ,
proto╛e p°ekladaΦ vφ, jak kopφrovat jednu strukturu do jinΘ. M∙╛eme tedy
snadno vytvo°it kopii celΘ struktury.
-
Pokuste se upravit p°edchozφ program tak, aby bylo mo╛no zadßvat vφce zßznam∙
(a╛ 9).
-
V p°edchozφ konzolovΘ aplikaci jsme p°eΦetli ·daje o n∞kolika osobßch.
Tyto ·daje je mo╛no vlo╛it do binßrnφho souboru. Musφme deklarovat:
FILE *soubor;
a p°ed ukonΦenφ programu vlo╛φme p°φkazy (p°edpoklßdßme, ╛e aktußlnφ
poΦet zßznam∙ je ulo╛en v prom∞nnΘ n):
if ((soubor = fopen("KART.DTA",
"wb")) == NULL) {
cout <<
"Nelze vytvo°it soubor" << endl;
return 1;
}
for (i = 0; i <
n; i++)
fwrite(&seznam[i],
sizeof(adresar), 1, soubor);
fclose(soubor);
Prove∩te tyto zm∞ny a program vyzkou╣ejte. Funkce fwrite zapisuje
poΦet v∞t urΦen² t°etφm parametrem do souboru urΦenΘho Φtvrt²m parametrem.
DΘlku v∞ty urΦuje druh² parametr a poΦßtek prvnφ v∞ty urΦuje prvnφ parametr.
-
Soubor vytvo°en² v p°edchozφm zadßnφ je mo╛no op∞t naΦφst a pou╛φvat v
jinΘm programu. Nßsledujφcφ program ukazuje, jak informace ze souboru ulo╛it
do pole v pam∞ti a vypsat je na obrazovce.
#include "struktur.h"
FILE *soubor;
int n, i;
adresar veta[10];
if ((soubor = fopen("KART.DTA",
"rb")) == NULL) {
cout <<
"Nelze otev°φt soubor" << endl;
return 1;
}
i = 0;
while (fread(&veta[i],
sizeof(adresar), 1, soubor) > 0)
i++;
n = i;
fclose(soubor);
for (i = 0; i <
n; i++)
zobrazZaznam(i,
veta[i]);
Vyzkou╣ejte. Vlo╛enφm hlaviΦkovΘho souboru STRUCTUR.H zajistφme, ╛e
program bude pracovat se stejnou strukturou zßznamu.
-
P°ejdeme op∞t k aplikacφm GUI. Nejprve se zaΦneme zab²vat formulß°em. Mimo
vlastnostφ, se kter²mi jsme se ji╛ seznßmili, mß formulß° dal╣φ d∙le╛itΘ
vlastnosti. Vlastnost BorderStyle urΦuje styl
okraje formulß°e (nap°. hodnota bsNone urΦuje
formulß° bez okraj∙, tzn. nelze m∞nit jeho velikost). M∞≥te tuto vlastnost
a vyzkou╣ejte, jak se zm∞na projevφ na vzhledu a chovßnφ formulß°e za b∞hu
aplikace.
-
Formulß° mß dßle vlastnost BorderIcons (ikony
rßmu formulß°e, tj. minimalizaΦnφ a maximalizaΦnφ tlaΦφtka apod.). P°ed
jmΘnem tΘto vlastnosti je v Inspektoru objekt∙ uveden znak + (indikace,
╛e vlastnost se sklßdß z podvlastnostφ). Klikneme-li dvojit∞ na takto oznaΦenΘm
jmΘn∞ vlastnosti, jsou na nßsledujφcφch °ßdcφch zobrazeny podvlastnosti
a znak + se zm∞nφ na - (op∞tovn²m dvojit²m kliknutφm se vrßtφme k p∙vodnφmu
zobrazenφ). P°i tomto ?rozbalenφ? vlastnosti, m∙╛eme jednotlivΘ podvlastnosti
nastavovat samostatn∞. Pokuste se z formulß°e odstranit maximalizaΦnφ tlaΦφtko
(BorderStyle musφ b²t nastaveno na bsSizeable;
zm∞na se projevφ a╛ p°i spu╣t∞nφ aplikace).
-
Vlastnosti Position a WindowState
urΦujφ zp∙sob zobrazenφ formulß°e na obrazovce. Position
urΦuje, zda formulß° zφskß pozici a velikost danou p°i nßvrhu, nebo zda
se pou╛ije velikost a pozice navr╛enß Windows za b∞hu aplikace. WindowState
urΦuje poΦßteΦnφ stav formulß°e (minimalizovan², maximalizovan² nebo normßlnφ).
Pokuste se zm∞nit n∞kterou z t∞chto vlastnostφ a vyzkou╣ejte jak se zm∞na
projevφ.
-
Vlastnost ShowHint komponenty urΦuje, zda
komponenta zobrazφ nßpov∞du, kdy╛ se na nφ na okam╛ik zastavφme kurzorem
my╣i. Zobrazen² text je urΦen vlastnostφ Hint.
Umφst∞te na formulß° n∞jakou komponentu a zajist∞te pro nφ zobrazovßnφ
nßpov∞dy.
-
Komponentu Panel lze pou╛φvat pro uklßdßnφ
dal╣φch komponent. M∙╛eme z nφ vytvo°it nap°. stavov² °ßdek nebo na nφ
vlo╛it komponenty, kterΘ tvo°φ n∞jak² logick² celek. Vlastnost Align
urΦuje umφst∞nφ komponenty. Mo╛nΘ hodnoty tΘto vlastnosti majφ nßsledujφcφ
v²znam: alTop (panel je umφst∞n na hornφ okraj
formulß°e, zabφrß celou ╣φ°ku formulß°e a sleduje i zm∞nu ╣φ°ky formulß°e;
obdobn∞ platφ i pro dal╣φ hodnoty tΘto vlastnosti), alRight
(panel je umφst∞n na prav² okraj formulß°e), alBottom
(spodnφ okraj), alLeft (lev² okraj), alClient
(celß plocha formulß°e) a alNone (nem∞nφ se;
z∙stßvß tak jak nastavil u╛ivatel). Umφst∞te na formulß° komponentu panelu
a vyzkou╣ejte vliv hodnot vlastnosti Align
na umφst∞nφ komponenty.
-
U komponenty Panel lze pomocφ vlastnostφ BevelInner,
BevelOuter,
BevelWidth,
BorderStyle
a BorderWidth m∞nit zp∙sob orßmovßnφ panelu.
Nastavte hodnotu vlastnosti BevelWidth na
10 (pro lep╣φ viditelnost) a vyzkou╣ejte vliv zm∞n ostatnφch t∞chto vlastnostφ
na zobrazenφ okraje.