-
Pokud jsme doposud v na╣ich programech pracovali se soubory, pak to bylo
zp∙sobem, kter² se pou╛φval v jazyku C. Je nutno se takΘ seznßmit se Φtenφm
a zßpisem soubor∙ pomocφ datov²ch proud∙. Zßkladnφ souborovΘ vstupn∞/v²stupnφ
operace jsou v C++ provßd∞ny pomocφ t∞chto t°φd:
-
t°φda ofstream provßdφ v²stup do souboru,
-
t°φda ifstream provßdφ vstup ze souboru,
-
t°φda fstream provßdφ jak vstup, tak i v²stup soubor∙.
Nßsledujφcφ jednoduchß konzolovß aplikace Φte sv∙j vlastnφ zdrojov² soubor
a zobrazuje jej na obrazovce (program ulo╛φme do CTENISOUBORU.CPP). Pokud
program ulo╛φme pod jin²m jmΘnem, pak nebude sprßvn∞ pracovat.
#include <condefs.h>
#include <fstream.h>
#include <conio.h>
#pragma hdrstop
#pragma argsused
int main(int argc,
char **argv)
{
char buff[80];
ifstream vstsoubor;
vstsoubor.open("ctenisouboru.cpp");
if (!vstsoubor)
return 0;
while (!vstsoubor.eof()){
vstsoubor.getline(buff, sizeof(buff));
cout << buff << endl;
}
vstsoubor.close();
getch();
return 0;
}
Na zaΦßtku programu vytvß°φme instanci t°φdy ifstream nazvanou
vstsoubor.
Na dal╣φm °ßdku otvφrßme nß╣ soubor pro vstup. Nßsleduje test ·sp∞╣nosti
otev°enφ souboru (v p°φpad∞ ne·sp∞chu je program ukonΦen). Podmφnkou ukonΦenφ
cyklu je volßnφ metody eof t°φdy ifstream. Tato metoda vracφ
true
p°i nalezenφ konce souboru. JednotlivΘ °ßdky souboru jsou Φteny metodou
getline.
Text °ßdku je umφst∞n do znakovΘho pole buff a potom je vypsßn na
obrazovku. Po doΦtenφ souboru je soubor je╣t∞ uzav°en (metoda
close).
Pro pou╛φvßnφ t°φdy ifstream je nutno vlo╛it hlaviΦkov² soubor FSTREAM.H.
Jeden z konstruktor∙ ifstream p°ebφrß jako parametr ukazazel
na char a umo╛≥uje tak zadat jmΘno souboru p°i vytvß°enφ instance
t°φdy. Pomocφ tohoto konstruktoru lze nahradit ΦervenΘ °ßdky z p°edchozφho
programu nßsledujφcφm °ßdkem:
ifstream vstsoubor("ctenisouboru.cpp");
Kdy╛ vytvo°φme objekt tφmto zp∙sobem, pak pou╛itφ metody open
ji╛ nenφ nutnΘ, nebo╗ soubor je automaticky otev°en konstruktorem. Nezapom∞≥te
p°i zadßvßnφ specifikace souboru i s adresß°evou cestou nahrazovat znaky
\ pomocφ \\.
Uzav°enφ souboru nenφ nutnΘ. Destruktor ifstream testuje, zda
soubor z∙stal otev°en a pokud ano, pak jej p°ed zru╣enφm instance t°φdy
uzav°e. Pou╛φvßnφ close tedy nenφ vy╛adovßno. Pokud jej pou╛ijeme,
pak tφm naznaΦujeme, ╛e soubor ji╛ dßle nenφ zapot°ebφ.
-
V na╣em programu je malß chyba. Program vypφ╣e p°ed ukonΦenφm cyklu jeden
prßzdn² °ßdek navφc. Abychom tuto chybu odstranili, musφme nß╣ cyklus zapsat
takto:
while (!vstsoubor.getline(buff,
sizeof(buff)).eof()){
cout <<
buff << endl;
}
Z°et∞zenφ metod je dovoleno, i kdy╛ nenφ moc pou╛φvßno. Jeho pou╛itφm
zφskßme mΘn∞ srozumiteln² k≤d. Umo╛≥uje ale snadno odstranit n∞kterΘ chyby.
-
Proto╛e t°φdy zpracovßvajφcφ soubory jsou odvozeny od iostream,
m∙╛eme takΘ pou╛φvat operßtory vlo╛enφ a v²b∞ru do/z datovΘho proudu a
to stejn∞ jako u datov²ch proud∙ cin a cout. V na╣em programu
jsme pou╛ili getline, proto╛e >> ukonΦφ Φtenφ po nalezenφ prvnφ
mezery (nebo od°ßdkovßnφ).
Operßtor >> je v²hodn² p°i Φtenφ jednotliv²ch hodnot. Nap°. nßsledujφcφ
Φßst programu Φte celß Φφsla ze souboru a zobrazuje je na obrazovce.
ifstream vstsoubor("nejakysoubor.dat");
while (!vstsoubor.eof()){
int x;
vstsoubor
>> x;
cout <<
x << endl;
}
Operßtor v²b∞ru z proudu Φte data z textovΘho souboru ale ne z binßrnφho
souboru. Tento operßtor Φte text ze souboru a p°evßdφ jej na Φφslo.
-
Vytvß°enφ soubor∙ je snadn∞j╣φ ne╛ jejich Φtenφ. Namφsto vytvo°enφ instance
t°φdy ifstream, vytvo°φme instanci t°φdy ofstream a pro zßpis
do souboru pou╛φvßme operßtor vlo╛enφ do proudu. Nap°.
ofstream vystsoubor("Test.dat");
if (!vystsoubor)
return 0;
for (int i = 0; i
< 10; i++) {
vystsoubor
<< "Toto je °ßdek " << (i + 1) << endl;
}
vystsoubor.close();
-
Vytvo°te konzolovou aplikaci, kterß bude p°ebφrat vstup od u╛ivatele a
zapφ╣e jej do textovΘho souboru.
Modifikujte p°edchozφ zadßnφ tak, ╛e na zßv∞r vytvo°en² soubor op∞t
p°eΦtete a vypφ╣ete na obrazovku. V tomto p°φpad∞ musφme, p°ed otev°enφm
souboru pro Φtenφ, zapsan² soubor uzav°φt.
-
V C++ je mo╛no d∞dit p°i vytvß°enφ novΘ t°φdy metody a datovΘ slo╛ky od
dvou nebo vφce t°φd p°edk∙. Toto se oznaΦuje jako vφcenßsobnß d∞diΦnost.
Vφcenßsobnß d∞diΦnost je ukßzßna v nßsledujφcφm programu.
class dodavka {
protected:
float naklad;
float vaha_objektu;
float spotreba;
public:
void inicializace(float
na, float va, float sp){
naklad = na;
vaha_objektu = va;
spotreba = sp;
}
float ucinnost(void){
return (naklad / (naklad + vaha_objektu));
}
float naklady_na_tunu(float
cena_paliva){
return (cena_paliva / (naklad / 2000.0));
}
};
class ridic {
protected:
float hod_mzda;
public:
void inicializace(float
mzda){hod_mzda = mzda; }
float naklady_na_km(void)
{return (hod_mzda / 90.0); }
};
class rizene_auto
: public dodavka, public ridic {
public:
void celk_inicializace(float
na, float va, float sp, float mzda){
naklad = na;
vaha_objektu = va;
spotreba = sp;
hod_mzda = mzda;
}
float naklady_na_cely_den(float
naklady_na_palivo){
return (8.0 * hod_mzda +
8.0 * naklady_na_palivo * 90.0 / spotreba);
}
};
int main(int argc,
char **argv)
{
rizene_auto
novak_ford;
novak_ford.celk_inicializace(5000.0,
3000.0, 8.3, 76.5);
cout <<
"┌Φinnost Fordu je " << novak_ford.ucinnost() << endl;
cout <<
"Nßklady na km pro °idiΦe Novßka jsou " <<
novak_ford.naklady_na_km() << endl;
cout <<
"Nßklady na °φzenφ Fordu °idiΦem Novßkem jsou na den " <<
novak_ford.naklady_na_cely_den(20.0) << endl;
return 0;
}
Pro zjednodu╣enφ hledßnφ k≤du v tomto programu jsou v╣echny metody
implementovßny jako vno°enΘ. V╣echny slo╛ky t°φd jsou deklarovßny jako
chrßn∞nΘ a jsou tedy p°φstupnΘ v odvozen²ch t°φdßch. K≤d pro v╣echny t°φdy
je velmi jednoduch², nebo╗ se zam∞°ujeme hlavn∞ na studium d∞diΦnosti.
Na ΦervenΘm °ßdku deklarujeme t°φdu rizene_auto, kterß d∞dφ v╣echna
data a metody od obou d°φve definovan²ch t°φd. P°i vφcenßsobnΘ d∞diΦnosti
zapisujeme za klφΦovΘ slovo public (p°φpadn∞ jinΘ p°φstupovΘ specifikßtory)
jmΘna v╣ech t°φd p°edk∙. V tomto p°φpad∞ nedefinujeme v odvozenΘ t°φd∞
╛ßdnΘ novΘ datovΘ slo╛ky, ale p°idßvßme do nφ dv∞ novΘ metody.
V hlavnφm programu deklarujeme objekt novak_ford, kter² popisuje
n∞jakΘho Novßka °φdφcφho dodßvku Ford. Tento objekt se sklßdß ze Φty° datov²ch
slo╛ek z nich╛ t°i pochßzejφ od t°φdy dodavka a jedna od t°φdy ridic.
Se v╣emi t∞mito Φty°mi slo╛kami m∙╛eme pracovat ve v╣ech metodßch t°φdy
rizene_auto
a to stejn∞ jako p°i jednoduchΘ d∞diΦnosti. V╣echna pravidla platφcφ pro
jednoduchou d∞diΦnost platφ i pro vφcenßsobnou d∞diΦnost. V hlavnφm programu
jsme nedeklarovali ╛ßdn² objekt t°φd p°edk∙. Pou╛ily bychom je normßlnφm
zp∙sobem. V na╣em programu je v obou t°φdßch p°edk∙ deklarovßna metoda
inicializace. Zjist∞te, kterß z nich se pou╛ije, za╣leme-li objektu novak_ford
zprßvu inicializace.
-
V nßsledujφcφ verzi programu jsou ve v╣ech t°φdßch metody naklady_na_cely_den.
Tento program ukazuje jak pou╛φvat tyto stejnojmennΘ metody a jak urΦit,
kterou z nich chceme pou╛φt. Program si prostudujte.
class dodavka {
protected:
float naklad;
float vaha_objektu;
float spotreba;
public:
void inicializace(float
na, float va, float sp){
naklad = na;
vaha_objektu = va;
spotreba = sp;
}
float ucinnost(void){
return (naklad / (naklad + vaha_objektu));
}
float naklady_na_tunu(float
cena_paliva){
return (cena_paliva / (naklad / 2000.0));
}
float naklady_na_cely_den(float
naklady_na_palivo){
return (8.0 * naklady_na_palivo * 90.0 / spotreba);
}
};
class ridic {
protected:
float hod_mzda;
public:
void inicializace(float
mzda){hod_mzda = mzda; }
float naklady_na_km(void)
{return (hod_mzda / 90.0); }
float naklady_na_cely_den(float
prescas_mzda){
return (8.0 * hod_mzda);
}
};
class rizene_auto
: public dodavka, public ridic {
public:
void celk_inicializace(float
na, float va, float sp, float mzda){
naklad = na;
vaha_objektu = va;
spotreba = sp;
hod_mzda = mzda;
}
float naklady_na_cely_den(float
naklady_na_palivo){
return (8.0 * hod_mzda +
8.0 * naklady_na_palivo * 90.0 / spotreba);
}
};
int main(int argc,
char **argv)
{
rizene_auto
novak_ford;
novak_ford.celk_inicializace(5000.0,
3000.0, 8.3, 76.5);
cout <<
"┌Φinnost Fordu je " << novak_ford.ucinnost() << endl;
cout <<
"Nßklady na km pro °idiΦe Novßka jsou " <<
novak_ford.naklady_na_km() << endl;
cout <<
"Nßklady na Ford jsou na den " <<
novak_ford.dodavka::naklady_na_cely_den(20.0)
<<
endl;
cout <<
"Nßklady na °idiΦe Novßka jsou na den " <<
novak_ford.ridic::naklady_na_cely_den(95.0)
<< endl;
cout <<
"Nßklady na °φzenφ Fordu °idiΦem Novßkem jsou na den " <<
novak_ford.naklady_na_cely_den(20.0)
<< endl;
return 0;
}
-
V dal╣φ ukßzce se pou╛φvß u obou t°φd p°edk∙ datovß slo╛ka se jmΘnem vaha_objektu.
Objekt t°φdy rizene_auto tedy d∞dφ dv∞ slo╛ky stejnΘho jmΘna. Prostudujte
si v tomto programu, jak se takovΘto slo╛ky pou╛φvajφ.
class dodavka {
protected:
float naklad;
float vaha_objektu;
float spotreba;
public:
void inicializace(float
na, float va, float sp){
naklad = na;
vaha_objektu = va;
spotreba = sp;
}
float ucinnost(void){
return (naklad / (naklad + vaha_objektu));
}
float naklady_na_tunu(float
cena_paliva){
return (cena_paliva / (naklad / 2000.0));
}
};
class ridic {
protected:
float hod_mzda;
float vaha_objektu;
public:
void inicializace(float
mzda, float vaha){
hod_mzda = mzda;
vaha_objektu = vaha;
}
float naklady_na_km(void)
{return (hod_mzda / 90.0); }
float vaha_ridice(void)
{return (vaha_objektu);}
};
class rizene_auto
: public dodavka, public ridic {
public:
void celk_inicializace(float
na, float va, float sp, float mzda){
naklad = na;
dodavka::vaha_objektu = va;
spotreba = sp;
hod_mzda = mzda;
}
float naklady_na_cely_den(float
naklady_na_palivo){
return (8.0 * hod_mzda +
8.0 * naklady_na_palivo * 90.0 / spotreba);
}
float celkova_vaha(void){
return (dodavka::vaha_objektu + ridic::vaha_objektu);
}
};
int main(int argc,
char **argv)
{
rizene_auto
novak_ford;
novak_ford.celk_inicializace(5000.0,
3000.0, 8.3, 76.5);
novak_ford.ridic::inicializace(80.0,
85.0);
cout <<
"UΦinnost Fordu je " << novak_ford.ucinnost() << endl;
cout <<
"Nßklady na km pro °idiΦe Novßka jsou " <<
novak_ford.naklady_na_km() << endl;
cout <<
"Nßklady na °φzenφ Fordu °idiΦem Novßkem jsou na den " <<
novak_ford.naklady_na_cely_den(20.0) << endl;
cout <<
"Celkovß vßha je " << novak_ford.celkova_vaha() << endl;
return 0;
}
Proto╛e Object Pascal neznß vφcenßsobnou d∞diΦnost, nelze pou╛φvat
vφcenßsobnou d∞diΦnost ve t°φdßch odvozen²ch od t°φd VCL (t°φd knihovny
vizußlnφch komponent; knihovna je naprogramovanß v Object Pascalu). Vφcenßsobnou
d∞diΦnost lze tedy pou╛φvat pouze mimo rßmec VCL.