-
Nßsledujφcφ Φßst programu p°eΦte textov² soubor a °ßdky textu ulo╛φ v operaΦnφ
pam∞ti. P°edpoklßdßme, ╛e soubor obsahuje maximßln∞ 1000 °ßdk∙ textu (°ßdky
textu nebudou del╣φ ne╛ 99 znak∙) a pro ulo╛enφ °ßdku rezervujeme pouze
pot°ebn² poΦet slabik. Na zßv∞r programu jsou pou╛itΘ dynamickΘ prom∞nnΘ
uvoln∞ny.
char radek[100];
char *radky[1000];
FILE *soubor;
int i, n = 0;
if ((soubor = fopen("SOUBOR.TXT",
"rt")) == NULL) {
cout <<
"Soubor nelze otev°φt" << endl;
return 1;
}
while (fgets(radek,
sizeof(radek), soubor) != NULL) {
radky[n] =
new char[strlen(radek) + 1];
strcpy(radky[n++],
radek);
}
for (i = 0; i <
n; i++) delete[] radky[i];
Zm∞≥te tento program tak, aby bylo mo╛no specifikovat Φten² soubor
a aby obsah souboru ulo╛en² v pam∞ti byl vypsßn na obrazovku.
-
V p°edchozφm zadßnφ jsme pro ulo╛enφ ukazatel∙ na jednotlivΘ °ßdky textu
pou╛ili statickΘ pole (velikost pole je v na╣em p°φpad∞ omezena na 1000
°ßdk∙). Abychom toto omezenφ obe╣li pou╛ijeme spojov² seznam s prvky
struct prvek {
prvek *dalsi;
char radek[100];
}
Polo╛ka dalsi ukazuje na dal╣φ prvek seznamu (dal╣φ °ßdek textu)
a polo╛ka radek obsahuje vlastnφ text °ßdku. Abychom se spojov²m
seznamem mohli pracovat, musφme mφt statickou prom∞nnou, kterß ukazuje
na zaΦßtek seznamu. Jeliko╛ nov∞ p°eΦtenΘ °ßdky p°idßvßme na konec seznamu
je vhodnΘ mφt i ukazatel na konec seznamu.
Nßsleduje Φßst programu vytvß°ejφcφ spojov² seznam °ßdk∙ a Φßst uvol≥ujφcφ
seznam.
char radek[100];
struct prvek {
prvek *dalsi;
char radek[100];
} *zacatek = NULL,
*konec, *pom;
FILE *soubor;
if ((soubor = fopen("SOUBOR.TXT",
"rt")) == NULL) {
cout <<
"Soubor nelze otev°φt" << endl;
return 1;
}
while (fgets(radek,
sizeof(radek), soubor) != NULL) {
pom = (prvek
*)new char[strlen(radek)+sizeof(prvek *) + 1];
strcpy(pom->radek,
radek);
if (zacatek
== NULL) zacatek = pom;
else konec->dalsi = pom;
konec = pom;
konec->dalsi
= NULL;
}
while (zacatek->dalsi
!= NULL) {
pom = zacatek;
zacatek =
zacatek->dalsi;
delete[] pom;
}
Dopl≥te tento program o v²pis v pam∞ti ulo╛enΘho obsahu souboru.
-
C++ umo╛≥uje pracovat s funkcemi, kterΘ majφ stejnΘ jmΘno ale r∙znΘ parametry.
Funkce, kterΘ sdφlejφ spoleΦnΘ jmΘno, se naz²vajφ p°ekrytΘ funkce. P°edpoklßdejme,
╛e mßme funkci nasob, kterß nßsobφ dva celoΦφselnΘ parametry a vracφ
v²sledek nßsobenφ. M∙╛eme ale takΘ pot°ebovat podobnou funkci, kterß nßsobφ
dv∞ reßlnß Φφsla. V C bylo nutno pou╛φvat r∙znΘ funkce:
int nasobInt(int
cislo1, int cislo2);
float nasobFloat(float
cislo1, float cislo2);
short nasobShort(short
cislo1, short cislo2);
V C++ ale m∙╛eme pracovat s p°ekr²vajφcφmi se funkcemi. Na╣e funkce
tedy budou mφt tyto prototypy:
int nasob(int cislo1,
int cislo2);
float nasob(float
cislo1, float cislo2);
short nasob(short
cislo1, short cislo2);
V╣echny funkce majφ stejnΘ jmΘno. P°ekladaΦ pak urΦφ volanou funkci
na zßklad∞ p°edan²ch parametr∙. Nap°.
float x = 1.5;
float y = 17.2;
float vysledek =
nasob(x, y);
P°ekladaΦ vidφ dva parametry typu float, kterΘ jsou p°edßvßny
funkci nasob a volß funkci nasob s dv∞ma parametry typu float.
Pokud parametry budou typu int, pak bude pou╛ita verze funkce s
parametry typu int.
Volanß funkce je tedy urΦena seznamem parametr∙ (ka╛dß deklarace p°ekr²vajφcφ
funkce musφ mφt jin² seznam parametr∙; tj. poΦet parametr∙ a typy parametr∙).
Nelze vytvo°it p°ekrytΘ funkce, kterΘ se budou li╣it pouze vrßcenou hodnotou.
P°ekladaΦ rozli╣uje p°ekrytΘ funkce pomocφ procesu nazvanΘho komolenφ
jmen. Komolenφ jmen spoΦφvß v zak≤dovßnφ poΦtu a typu parametr∙ v internφm
jmΘn∞ funkce, kterΘ je udr╛ovßno p°ekladaΦem.
-
Pou╛φvßnφ p°ekryt²ch funkcφ vy╛aduje pou╛itφ sprßvn²ch datov²ch typ∙ p°i
volßnφ funkce. P°i p°evodu datovΘho typu pou╛φvßme p°etypovßnφ, tj. p°evod
jednoho datovΘho typu na jin². Nap°.
float x = (float)10
* 5.5;
V tomto p°φpad∞ p°etypovßnφ °φkß p°ekladaΦi "ud∞lej z Φφsla 10 typ
float". Druh² operand je automaticky interpretovßn jako typ float,
proto╛e obsahuje desetinnou teΦku. Podφvejte se je╣t∞ na nßsledujφcφ p°φklad:
int cele = 5;
float realne = 10.5;
float vysledek =
nasob(cele, realne);
V tomto p°φpad∞ p°ekladaΦ generuje chybu, proto╛e nem∙╛e nalΘzt funkci
nasob
s prvnφm parametem typu int a druh²m parametrem typu
float.
Podobnou chybu bude generovat i v p°φpad∞ p°φkazu:
int vysledek = nasob(10,
10);
Zde p°ekladaΦ nedokß╛e urΦit jakΘho typu jsou pou╛itΘ ΦφselnΘ konstanty.
V tΘto situaci mßme dv∞ mo╛nosti. Konstanty p°ed volßnφm funkce p°i°adφme
do prom∞nn²ch nebo provedeme p°i volßnφ p°etypovßnφ. Prvnφ mo╛nost ukazuje
nßsledujφcφ k≤d:
int x = 10;
int y = 10;
int vysledek = nasob(x,
y);
a druhou mo╛nost k≤d:
int vysledek = nasob((int)10,
(int)10);
Nynφ p°ekladaΦ vφ, ╛e mß tyto konstanty brßt jako typ int. P°etypovßnφ
lze takΘ pou╛φt k doΦasnΘ zm∞n∞ jednoho datovΘho typu na jin². Nap°.
int cele = 5;
float realne = 10.5;
float vysledek =
nasob((float)cele, realne);
V tomto p°φpad∞ je prvnφ parametr p°eveden na typ float a p°ekladaΦ
je ji╛ schopen najφt po╛adovanou funkci.
-
Funkce implementujφcφ implicitnφ parametry m∙╛e vypadat takto:
// deklarace - parametr
"poprve" mß implicitnφ hodnotu false
void Redraw(bool
poprve = false);
// definice
void Redraw(bool
poprve)
{
if (poprve){
// k≤d pro prvnφ kreslenφ
}
// k≤d kreslenφ
}
Tuto funkci m∙╛eme volat s nebo bez parametru. Pokud je p°i volßnφ
funkce parametr uveden, pak funkce se chovß jako normßlnφ funkce. Pokud
p°i volßnφ funkce parametr nenφ uveden, pak je automaticky pou╛ita implicitnφ
hodnota parametru. Pro nß╣ p°φklad jsou nßsledujφcφ dva °ßdky k≤du identickΘ:
Redraw();
Redraw(false);
Kdy╛ parametr mß implicitnφ hodnotu, pak p°i volßnφ funkce m∙╛e b²t
vynechßn. V jednΘ funkci mohou b²t takΘ implicitnφ i neimplicitnφ parametry:
int PlaySound(char*
name, bool loop = false, int loops = 10);
// volßnφ funkce
int vysl;
vysl = PlaySound("chime.wav");
vysl = PlaySound("ding.wav",
true);
vysl = PlaySound("bell.wave",
true, 5);
Implicitnφ parametry jsou z mnoha d∙vod∙ u╛iteΦnΘ. Pokud p°i volßnφ
n∞kterΘ funkce pou╛φvßme Φasto stejnΘ parametry, pak pou╛itφ implicitnφch
parametr∙ nßm usnadnφ prßci.
Implicitnφ parametry musφme uvßd∞t na konci seznamu parametr∙. Nßsledujφcφ
deklarace funkce je chybnß:
int mojeFunkce(int
x, int y = 10, int t = 5, int z);
Implicitnφ parametry musφme p°esunout na konec seznamu parametr∙:
int mojeFunkce(int
x, int z, int y = 10, int t = 5);
-
Metody (ΦlenskΘ funkce t°φdy) se pou╛φvajφ stejn∞ jako normßlnφ funkce.
Mohou b²t p°ekrytΘ, mohou mφt implicitnφ parametry atd. Metody mohou b²t
volßny pouze prost°ednictvφm objekt∙ t°φdy, do kterΘ metoda pat°φ. K volßnφ
metody pou╛φvßme p°φm² nebo nep°φm² selektor slo╛ky. Nap°. mßme t°φdu nazvanou
Letadlo,
kterou budeme pou╛φvat v simulaΦnφm programu letadla. Tato t°φda pravd∞podobn∞
bude mφt mo╛nost zφskat souΦasnou rychlost danΘho letadla pomocφ metody
nazvanΘ ziskejRychlost. Nßsledujφcφ p°φklad ukazuje, jak volßme
tuto metodu objektu Letadlo:
Letadlo sokol;
// vytvo°enφ instance t°φdy
int rychlost = sokol.ziskejRychlost();
cout << "SouΦasnß
rychlost letadla je " << rychlost << endl;
Tento k≤d pou╛φvß k volßnφ funkce ziskejRychlost operßtor p°φmΘho
selektoru slo╛ky. Metody definujeme podobn∞ jako normßlnφ funkce, je zde
zapot°ebφ navφc uvΘst jmΘno t°φdy a operßtor ::. Nap°. definice
na╣φ metody m∙╛e vypadat takto:
int Letadlo::zφskejRychlost()
{
return rychlost;
// rychlost je datovß slo╛ka t°φdy
}
Operßtor :: °φkß p°ekladaΦi, ╛e funkce zφskejRychlost
je metodou t°φdy Letadlo. Vφce o t°φdßch a metodßch se dozvφme pozd∞ji.
-
Normßln∞ strojov² k≤d funkce se v p°elo╛enΘm proveditelnΘm k≤du vyskytuje
pouze jednou. P°i volßnφ funkce je proveden skok na vstupnφ bod funkce
a p°i ukonΦenφ funkce se op∞t vrßtφme na mφsto volßnφ funkce. Existujφ
takΘ vlo╛enΘ (inline) funkce, kde k≤d funkce je vlo╛en do proveditelnΘho
k≤du programu na mφsto volßnφ funkce. Vlo╛enΘ funkce se deklarujφ podobn∞
jako normßlnφ funkce, ale jejich definice zaΦφnß klφΦov²m slovem inline.
Poka╛dΘ, kdy╛ p°ekladaΦ ve zdrojovΘm k≤du nalezne volßnφ vlo╛enΘ funkce,
pak umφstφ separßtnφ kopii k≤du funkce na toto mφsto do p°elo╛enΘho programu.
Vlo╛enΘ funkce pracujφ rychle, proto╛e nenφ zapot°ebφ provßd∞t volßnφ funkce.
Je vhodnΘ, aby vlo╛enΘ funkce byly velmi malΘ. Del╣φ funkce nenφ vhodnΘ
pou╛φvat jako vlo╛enΘ, nebo╗ v²sledkem je zv∞t╣enφ p°elo╛enΘho spustitelnΘho
programu.
Vlo╛enΘ funkce jsou obvykle metody. ╚asto definici vlo╛enΘ funkce umis╗ujeme
do hlaviΦkovΘho souboru deklarace t°φdy. Metoda ziskejRychlost z
p°edchozφho zadßnφ je krßtkß a je tedy mo╛no z nφ ud∞lat vlo╛enou funkci.
To provedeme takto:
inline int Letadlo::zφskejRychlost()
{
return rychlost;
// rychlost je datovß slo╛ka t°φdy
}
NovΘ pojmy:
-
P°ekrytΘ funkce tvo°φ dv∞ nebo vφce funkcφ se stejn²m jmΘnem, ale
s r∙zn²mi seznamy parametr∙.
-
P°etypovßnφ °φkß p°ekladaΦi, ╛e mß doΦasn∞ brßt jeden datov² typ,
jako jin² datov² typ.
-
Funkce v C++ mohou mφt implicitnφ parametry, kterΘ poskytujφ implicitnφ
hodnoty pro parametry, kdy╛ hodnota parametru p°i volßnφ funkce nenφ zadßna.
-
T°φdy mohou obsahovat svΘ vlastnφ funkce. Tyto funkce naz²vßme metody
(ΦlenskΘ funkce t°φdy - jsou slo╛kami t°φdy).
-
Vlo╛enΘ funkce umis╗ujφ p°elo╛en² k≤d do p°elo╛enΘho programu na
mφsto volßnφ funkce.
Kontrolnφ otßzky:
-
Musφme v╛dy zru╣it objekt, kter² byl vytvo°en dynamicky pomocφ operßtoru
new?
-
Kdy vytvß°φme objekty v zßsobnφku a kdy v hromad∞?
-
Co to jsou p°ekrytΘ funkce?
-
Kdy pou╛φvßme vlo╛enΘ funkce?
-
Co je to ukazatel?
-
Co d∞lß dereference ukazatele?
-
Co je vrßcenß hodnota operßtoru new?
-
Lze instance t°φd a struktur p°edßvat funkcφm odkazem nebo hodnotou?
-
Co d∞lß klφΦovΘ slovo const?
-
Vytvß°ejφ nßsledujφcφ deklarace p°ekrytΘ funkce?
void mojeFunkce(int
x);
int mojeFunkce(int
x);
-
Je lep╣φ pou╛φvat odkazy nebo ukazatele?
-
Co je metoda?
-
Jak se li╣φ zachßzenφ p°ekladaΦe s vlo╛enou funkcφ od normßlnφ funkce?
-
Co je chybnΘ na nßsledujφcφ ukßzce?
char* buff = new
char[200];
// a pozd∞ji
delete buff;
╪e╣enφ