Iterßtory IV. Vklßdßnφ a datovΘ proudy...

╪eÜenφ z minulΘho dφlu

Minule jste dostali na rozmyÜlenou, jak co nejjednoduÜeji s pomocφ prost°edk∙ STL napsat funkci, kterß otestuje, zda danΘ slovo je Φi nenφ palindrom (tj. od zaΦßtku i od konce se Φte stejn∞). Zde je elegantnφ °eÜenφ

 

bool je_palindrom(const string & slovo)

{

áá return equal(slovo.begin(), slovo.end(), slovo.rbegin());

}

Vklßdacφ iterßtory (proxy)

ZaΦneme trochu netradiΦn∞, popisem funkce copy. Tato funkce vypadß nßsledovn∞

 

template<typename InputIterator,

áááááááá typename OutputIterator>

OutputIterator copy(InputIterator prvni, InputIterator posledni,

áááááááá OutputIterator kam)

{

áá while ( prvni != posledni ) *kam++ = *prvni++;

áá return kam;

}

 

Tato funkce kopφruje data z rozsahu [prvni, posledni), do rozsahu [kam, kam + (posledni - prvni)). Zkusme si te∩ jeden p°φklad û chceme provΘst spojenφ dvou vektor∙ tφm, ₧e jeden nakopφrujeme za druh²

 

vector<int> v;á // + vlo₧enφ n∞jak²ch prvk∙

vector<int> w;á // + vlo₧enφ n∞jak²ch prvk∙

 

// spojenφ: k w prikopirujeme v

copy(v.begin(), v.end(), w.end());á // !!! CHYBA

 

Pokud jste u₧ n∞kdy n∞co takovΘho zkusili, urΦit∞ vßm to nefungovalo sprßvn∞. ProΦ? Proto₧e funkce copy nepracuje s kontejnery (v naÜem p°φpad∞ jde o t°φdu vector), ale s iterßtory na t∞chto kontejnerech. Nemß tudφ₧ kredit k p°idßvßnφ prvk∙ do kontejneru û a o to jsme se tu pokusili.

Jin²mi slovy, funkce copy funguje v takzvanΘm p°episovacφm (overwrite) re₧imu, to znamenß, ₧e p°episuje ji₧ existujφcφ prvky nov²mi hodnotami. Za koncem kontejneru, poΦφnaje iterßtorem end(), ji₧ ₧ßdnΘ prvky nejsou, a proto p°φkaz oznaΦen² t°emi vyk°iΦnφky m∙₧e zp∙sobit i havßrii programu...

Existuje vÜak zp∙sob, jak p°inutit funkci copy k prßci v takzvanΘm vklßdacφm (insert) re₧imu. Musφme vÜak pou₧φt specißlnφ v²stupnφ iterßtory û vklßdacφ iterßtory.

Vklßdßnφ kamkoli

Jak takovß v∞c funguje? P°edem si musφme uv∞domit, ₧e jde o v²stupnφ iterßtory (viz [3]), tak₧e mno₧ina podporovan²ch operacφ je znaΦn∞ omezena. Za druhΘ, jde nßm o to, p°evΘst p°φkaz

 

*kam++ = neco;

 

na volßnφ metody kontejneru pro vlo₧enφ prvku. M∙₧e jφt o metodu insert, push_back, nebo push_front podle toho, jestli chceme vklßdat prvky kamkoli, na konci, nebo na zaΦßtku kontejneru. PopφÜeme si zde konstrukci v²stupnφho iterßtoru, kter² pou₧φvß metodu insert. Je jasnΘ, ₧e takov² iterßtor musφ uchovßvat odkaz na kontejner a iterßtor, kter² urΦuje, kam se budou vklßdat prvky. S pou₧itφm standardu C++, sekce 24.4.2.5 :

 

template <typename Container>áá // (1)

class insert_iterator

á : public iterator<output_iterator_tag, void, void, void, void>á // (2)

{

protected:

áá Container * container;ááá // (3)

áá typename Container::iterator iter;áá // (4)

public:

áá typedef Container container_type;áá // (5)

áá insert_iterator(Container & x,

áááááááááááááááááá typename Container::iterator i);á // (6)

áá insert_iterator<Container> &

ááááá operator =(typename Container::const_reference value);á // (7)

áá insert_iterator<Container> & operator *();á // (8)

áá // ...

};

 

(1)   Metoda insert je povinnou souΦßstφ v∞tÜiny kontejner∙, proto je rozumnΘ parametrizovat vklßdacφ iterßtor typem kontejneru. O rozdφlech mezi vklßdßnφm do r∙zn²ch typ∙ kontejner∙ pohovo°φme za chvφli.

(2)   Jde o v²stupnφ iterßtor. Rysy iterßtoru aktivujeme odvozenφm iterßtoru od t°φdy iterator. Vφce viz [4].

(3)   Odkaz na kontejner.

(4)   Iterßtor, kter² urΦuje, kam se bude vklßdat. Typ iterßtoru zφskßme tak, ₧e se zeptßme kontejneru na jeho typ iterßtoru tj. Container::iterator. KlφΦovΘ slovo typename je zde nutnΘ û napovφ p°ekladaΦi, ₧e jde o typ.

(5)   Abychom se mohli vklßdacφho iterßtoru zeptat na typ kontejneru, do kterΘho vklßdß, je k dispozici tato vno°enß definice typu.

(6)   Konstruktor: zadßme instanci kontejneru a nesingulßrnφ iterßtor (instanci) na tomto kontejneru. Slou₧φ k inicializaci atribut∙ (3) a (4).

 

Nynφ to nejd∙le₧it∞jÜφ: Jak implementovat operßtory (7) a (8)? Jak vφte z Φlßnku [3], operßtor dereferencovßnφ v²stupnφho iterßtoru m∙₧e vrßtit proxy, tj. zßstupnou t°φdu, jejφ₧ p°etφ₧en² operßtor = se postarß o ulo₧enφ prvku. A o to tu jde. Tento operßtor vrßtφ proxy, akorßt ₧e pro jednoduchost touto proxy bude t°φda insert_iterator osobn∞ (to je ale detail implementace, nikoli standardem na°φzenΘ chovßnφ...). Tak₧e t∞lo operßtoru (8) bude obsahovat jedin² p°φkaz

 

return *this;

 

Te∩ je jasnΘ, ₧e operßtor (7) se musφ postarat o vlo₧enφ prvku do kontejneru a aktualizaci atributu iter, nebo¥ vlo₧enφm prvku m∙₧e tento iterßtor ztratit platnost (nap°. kv∙li re-alokaci). Jeho t∞lo bude vypadat takto

 

iter = container->insert(iter, value); // (a)

++iter;áá // (b)

return *this;

 

(a)    Ulo₧φme hodnotu value do kontejneru na pozici, urΦenou iterßtorem iter pomocφ metody insert. P°itom m∙₧e dojφt k re-alokaci, Φφm₧ by p∙vodnφ iterßtor iter ztratil platnost. NaÜt∞stφ metoda insert chyt°e vracφ iterßtor na v²slednou pozici, kam je ulo₧ena hodnota.

(b)   Metoda insert uklßdß novΘ prvky do kontejneru p°ed prvek urΦen² jako mφsto vklßdßnφ. Abychom zajistili toto chovßnφ i pro vklßdacφ iterßtory, musφme postrΦit iter o jeden prvek dop°edu, tak aby odkazoval na p∙vodnφ prvek, p°ed kter² se majφ vklßdat novΘ.

Zb²vajφ jeÜt∞ oba operßtory ++. Jeliko₧ u₧ operßtory (7) a (8) vykryly vÜechnu pot°ebnou Φinnost, budou operßtory ++ hrßt mrtvΘho brouka: ₧ßdn² p°echod na dalÜφ prvek, jen

 

return *this;

 

Zb²vß jeÜt∞ oddiskutovat pou₧itφ metody insert u r∙zn²ch kontejner∙. Stejn∞ jako koncepty iterßtor∙ mßme i koncepty kontejner∙, viz Φlßnek [5]. Po₧adavky vklßdacφho iterßtoru na typ kontejneru spl≥ujφ dva koncepty (a samoz°ejm∞ vÜechny ostatnφ, kterΘ je zjem≥ujφ): posloupnost (Sequence) a set°φd∞n² asociativnφ kontejner (Sorted Associative Container), ka₧d² vÜak po svΘm. Zatφmco u posloupnostφ se nov∞ vklßdanΘ hodnoty v₧dy dostanou na (p°ed) mφsto, kterΘ je urΦeno iterßtorem iter, u set°φd∞n²ch asociativnφch kontejner∙ to neplatφ. Je to celkem pochopitelnΘ: Vklßdanß hodnota musφ padnout tam, kam pat°φ podle t°φdφcφho kritΘria. Parametr iter tam slou₧φ pouze jako pom∙cka (kam asi by to mohlo padnout), ale na v²slednΘm umφst∞nφ hodnoty nemß vliv.

Nynφ zp∞t k funkci copy. S pou₧itφm vklßdacφho iterßtoru bychom mohli napsat (a tentokrßt u₧ to bude v po°ßdku)

 

// spojenφ: k w prikopirujeme v

copy(v.begin(), v.end(),

ááá insert_iterator<vector<int> >(w, w.end()));

 

Ale po°ßd je to moc slo₧itΘ. NaÜt∞stφ, stejn∞ jako u funktor∙, standard definuje p°φsluÜnou vytvo°ujφcφ funkci, kterß s vyu₧itφm pokroΦil²ch vlastnostφ C++ vytvo°φ pot°ebnou instanci vklßdacφho iterßtoru jen na zßklad∞ typ∙ argument∙.

 

template <typename Container, typename Iterator>

inline insert_iterator<Container>

inserter(Container& x, Iterator i)

{

áá return insert_iterator<Container>(x,

ááááááááá typename Container::iterator(i));

}

 

Vytvo°ujφcφ funkce inserter se postarß o vytvo°enφ instance vklßdacφho iterßtoru. Rovn∞₧ se pokusφ o konverzi iterßtoru i na po₧adovan² typ, kter²m je Container::iterator. Pomocφ vytvo°ujφcφ funkce zjednoduÜφme nßÜ k≤d na

 

// spojenφ: k w prikopirujeme v

copy(v.begin(), v.end(), inserter(w, w.end()));

 

Vklßdßnφ na konec

Pou₧ili jsme obecn² vklßdacφ iterßtor aΦkoli nevklßdßme prvky doprost°ed, ale na konec posloupnosti. Proto bychom mohli pou₧φt vklßdacφ iterßtor zalo₧en² na metod∞ push_back. Princip je stejn² jako u t°φdy insert_iterator, ale s t∞mito rozdφly:

Jeliko₧ t°φda vektor je modelem konceptu Back Insertion Sequence a podporuje operaci push_back, m∙₧eme psßt (rovnou s vyu₧itφm vytvo°ujφcφ funkce)

 

// spojenφ: k w prikopirujeme v

copy(v.begin(), v.end(), back_inserter(w));á // OK

 

Vklßdßnφ na zaΦßtek

Obdobn∞ jako na konec, m∙₧eme vklßdat prvky na zaΦßtek posloupnosti metodou push_front. Oproti vklßdßnφ na konec jsou tu tyto rozdφly

Jeden d∙le₧it² rozdφl nakonec: Zatφmco v p°φpad∞ vklßdßnφ na konec nebyl rozdφl mezi pou₧itφm obecnΘho vklßdacφho iterßtoru (insert_iterator) a iterßtoru back_insert_iterator, u vklßdßnφ na zaΦßtek posloupnosti to neplatφ. Ne₧ zaΦnete Φφst dalÜφ °ßdky, zkuste se zamyslet proΦ tomu tak je.

(Nejen) pro ty netrp∞livΘ, zde je vysv∞tlenφ: Iterßtor front_insert_iterator uklßdß prvky, tak jak p°ijdou, v₧dy na zaΦßtek, tak₧e jejich v²slednΘ po°adφ v posloupnosti je obrßcenΘ. P°i pou₧itφ vklßdacφho iterßtoru insert_iterator si tento pamatuje iterßtor na p∙vodnφ prvnφ prvek v posloupnosti po celou dobu vklßdßnφ. To znamenß, ₧e po°adφ vlo₧en²ch prvk∙ v posloupnosti bude odpovφdat po°adφ, v jakΘm byly vlo₧eny.

Shrnutφ

V∞tÜina STL generick²ch algoritm∙ pracuje v p°episovacφm (overwrite) re₧imu. To proto, ₧e p°i pou₧itφ iterßtor∙, kterΘ jim nabφdnou kontejnery, tyto algoritmy nemajφ kredit k modifikaci kontejneru (tj. poΦtu prvk∙ v kontejneru apod.) ale pouze k modifikaci prvk∙, na kterΘ odkazujφ iterßtory. STL vÜak nabφzφ prost°edek, kter² umo₧nφ algoritm∙m pracovat ve vklßdacφm (insert) re₧imu û vklßdacφ iterßtory. Pomocφ nich je mo₧nΘ do kontejner∙ p°idßvat novΘ prvky.

Na zßv∞r povφdßnφ o vklßdacφch iterßtorech se sluÜφ °φct, ₧e je i jejich vytvo°ujφcφ funkce zp°φstupnφme vlo₧enφm standardnφho hlaviΦkovΘho souboru <iterator>. Pro pou₧φvßnφ vklßdacφch iterßtor∙ si staΦφ pamatovat jen ty t°i vytvo°ujφcφ funkce.

A jeÜt∞ jedna rada: NaÜe pou₧itφ funkce copy k p°ipojenφ jednoho vektoru za druh² bylo zvoleno kv∙li vhodnΘ demonstraci funkce vklßdacφch iterßtor∙. Jinak (a lΘpe) lze tuto akci uskuteΦnit pomocφ metody insert

 

w.insert(v.begin(), v.end());

 

Jsou ale situace, kde funkce copy a vklßdacφ iterßtory p°edstavujφ elegantnφ °eÜenφ. Jeden takov² p°φklad poznßme zßhy, a₧ se trochu seznßmφme s iterßtory na vstupn∞/v²stupnφch datov²ch proudech.

Iterßtory na vstupn∞/v²stupnφch proudech

DatovΘ proudy jazyka C++ (iostreams) p°edstavujφ dalÜφ zajφmavou mo₧nost aplikace iterßtor∙. Jednφm z d∙vod∙ zavedenφ koncept∙ vstupnφho a v²stupnφho iterßtoru je prßv∞ mo₧nost dßt STL generick²m algoritm∙m Üanci pracovat p°φmo s datov²mi proudy.

Vstupnφ proud

Zßkladnφ myÜlenkou iterßtoru na vstupnφm proudu je p°evedenφ operace p°φstupu k prvku s p°echodem na dalÜφ prvek *i++ na operaci Φtenφ z datovΘho proudu operßtorem >>. Je jasnΘ, ₧e takov² iterßtor bude modelem (nejv²Üe) vstupnφho iterßtoru. To plyne z toho, ₧e ji₧ p°eΦten² prvek nem∙₧e b²t znovu Φten (byl ji₧ z datovΘho proudu extrahovßn), a tudφ₧ tento iterßtor neumo₧≥uje vφcenßsobn² pr∙chod.

 

template <typename T,ááá // (1)

ááááááááá typename charT = char, // (2)

ááááááááá typename traits = char_traits<charT>,áá // (3)

ááááááááá typename Distance = ptrdiff_t>ááá // (4)

class istream_iteratoráá // (5)

áá : public iterator<input_iterator_tag, T,áá // (6)

áááááááááááááááá Distance, const T*, const T&>

{

áá // ... uvedeny jen specifickΘ slo₧ky

public:

áá typedef charT char_type;áá // (7)

áá typedef traits traits_type;á // (8)

áá typedef basic_istream<charT,traits> istream_type;á // (9)

 

áá istream_iterator();á // (10)

áá istream_iterator(istream_type& s);á // (11)

};

 

(1)   Typ vstupnφch dat, aneb jak mß iterßtor interpretovat vstupnφ data. Pokud chceme z proudu Φφst celß Φφsla, bude T nap°φklad int.

(2)   Typ znaku datovΘho proudu. Obvykle char; pro znaky Unicode by to byl wchar_t.

(3)   T°φda rys∙ popisujφcφ zßkladnφ typy a operace pro prßci se znaky a s posloupnostφ znak∙. Obvykle vystaΦφme s uveden²m implicitnφm argumentem.

(4)   Typ rozdφlu iterßtor∙.

(5)   JmΘno t°φdy

(6)   Odvozenφm od t°φdy iterator aktivujeme rysy iterßtoru (t°φda iterator_traits).

(7)   Definice typu, kterß umo₧≥uje zeptat se iterßtoru na typ znaku datovΘho proudu.

(8)   To samΘ pro typ t°φdy rys∙ znaku datovΘho proudu.

(9)   To samΘ pro typ datovΘho proudu.

(10)                      Implicitnφ konstruktor. Vytvo°φ iterßtor, kter² se bude tvß°it jako konec datovΘho proudu (end-of-stream). To mß v²znam p°i zadßvßnφ rozsahu Φtenφ.

(11)                      Konstruktor, kter²m se iterßtor äp°ipojφô k datovΘmu proudu.

 

Jak tento iterßtor funguje? Zkusme si jednoduch² vstup z p°φkazovΘ °ßdky. Nejd°φve vytvo°φme instanci iterßtoru na vstupnφm datovΘm proudu cin a pak p°eΦteme dv∞ celß Φφsla.

 

istream_iterator<int> i(cin);

int prvni = *i++;

int druhΘ = *i++;

 

JednotlivΘ metody iterßtoru si prßci rozd∞lily takto: konstruktor vytvo°φ instanci iterßtoru, p°ipojφ ji ke standardnφmu vstupnφmu proudu cin a naΦte pomocφ operßtoru >> prvnφ prvek do internφho atributu. Operßtor dereferencovßnφ * vrßtφ prvek ulo₧en² v internφm atributu. Operßtor ++ provede p°echod na dalÜφ prvek, tj. naΦte pomocφ operßtoru >> dalÜφ prvek do internφho atributu. Prvky jsou v datovΘm proudu odd∞leny takzvan²mi bφl²mi znaky (jeden nebo vφce mezer, tabulßtor∙, znak∙ konce °ßdku apod.).

A nynφ ji₧ d°φve slφbenΘ elegantnφ pou₧itφ vklßdacφch iterßtor∙. NaΦteme do vektoru data z datovΘho proudu (jde to i ze souboru, ale my se zde omezφme na standardnφ vstupnφ proud).

 

vector<int> v;

copy(istream_iterator<int>(cin),

áááá istream_iterator<int>(),

áááá back_inserter(v));

 

VÜimn∞te si zadßnφ vstupnφho rozsahu. P°edem nevφme kolik tam bude prvk∙. Vyu₧ijeme ale jednΘ vlastnosti t∞chto iterßtor∙: pokud se Φtenφ nezda°φ z jakΘhokoliv d∙vodu (nap°. konec souboru), pak se iterßtor zaΦne tvß°it jako iterßtor na konec datovΘho proudu, co₧ znamenß ukonΦenφ iterovßnφ. DalÜφ vlastnostφ je nemo₧nost zadat rozsah jinak ne₧ od zaΦßtku do konce datovΘho proudu.

V²stupnφ proud

Iterßtor na v²stupnφm datovΘm proudu je zalo₧en na myÜlence p°evedenφ operace zßpisu prvku *i = a na zßpis do datovΘho proudu pomocφ operßtoru <<. Stejn∞ jako v p°edchozφm p°φpad∞, tento iterßtor nenφ vφcepr∙chodov², tedy je modelem pouze konceptu v²stupnφho iterßtoru.

 

template <typename T,

ááááááááá typename charT = char,

ááááááááá typename traits = char_traits<charT> >

class ostream_iteratoráá //á (1)

áá : public iterator<output_iterator_tag,áá // (2)

áááááááááááááááááááá void, void, void, void>

{

public:

áá // ... uvedeny jen specifickΘ slo₧ky

áá ostream_iterator(ostream_type& s);áá // (3)

áá ostream_iterator(ostream_type& s, const charT * delimiter);á // (4)

 

áá ostream_iterator<T,charT,traits>& operator=(const T& value);á // (5)

};

 

(1)   JmΘno t°φdy.

(2)   Odvozenφm od t°φdy iterator aktivujeme rysy iterßtoru (t°φda iterator_traits). O zvlßÜtnostech rys∙ v²stupnφch iterßtor∙ jsme hovo°ili minule.

(3)   Konstruktor, kter²m se iterßtor äp°ipojφô k datovΘmu proudu. ZapisovanΘ prvky nebudou nijak odd∞leny.

(4)   Konstruktor, kter²m se iterßtor äp°ipojφô k datovΘmu proudu. Zßrove≥ se nastavφ odd∞lovaΦ (°et∞zec), kter² se vypφÜe po ka₧dΘm zapsanΘm prvku.

(5)   Operßtor zßpisu prvku. Tentokrßt, na rozdφl od vstupnφho iterßtoru, mß tento na starosti v²stup prvku a p°φpadn∞ i o v²stup odd∞lovacφho °et∞zce, pokud byl tento zadßn v konstruktoru (4).

Ostatnφ operßtory (++, *) ned∞lajφ nic jinΘho ne₧ pouze vracφ *this. A jak to funguje? Pokud jste sledovali zdrojovΘ k≤dy na Chip CD, jist∞ vφte, jak vypsat na obrazovku (nebo i do souboru) pole prvk∙ bez napsßnφ smyΦky

 

int pole[5] = { 1, 1, 2, 3, 5 };

copy(pole, pole + 5, ostream_iterator<int>(cout, ô ô));

 

Vypisujeme prvky pole do standardnφho v²stupnφho proudu cout. Prvky budou odd∞leny mezerou.

Vstupnφ buffer

Pokud pot°ebujeme neformßtovan² vstup a v²stup znak po znaku, m∙₧eme pou₧φt iterßtory na vyrovnßvacφ pam∞ti datov²ch proud∙. I zde musφme rozliÜit vstup a v²stup. V nßsledujφcφch v²pisech t°φd uvßdφme jen ty slo₧ky, kterΘ vy₧adujφ vysv∞tlenφ.

 

template<typename charT,

áááááááá typename traits = char_traits<charT> >

class istreambuf_iterator

áá : public iterator<input_iterator_tag, charT,

áááááááááááááááááááá typename traits::off_type,

áááááááááááááááááááá charT *, charT &>

{

áá // ... uvedeny jen specifickΘ slo₧ky

public:

áá istreambuf_iterator()á // (1)

áá istreambuf_iterator(istream_type & s) throw();á // (2)

áá istreambuf_iterator(streambuf_type * s) throw();á // (3)

áá bool equal(istreambuf_iterator & j);á // (5)

};

 

(1)   Konstruktor, kter² vytvo°φ iterßtor na konec datovΘho proudu.

(2)   Konstruktor, kter² se p°ipojφ k vyrovnßvacφ pam∞ti datovΘho proudu. V p°φpad∞, ₧e datov² proud je prßzdn² vytvo°φ iterßtor na konec proudu.

(3)   To samΘ jako (2), ale s tφm, ₧e zadßme p°φmo vyrovnßvacφ pam∞¥.

(4)   Rovnost dvou iterßtor∙ typu istreambuf_iterator: rovnajφ se kdy₧ jsou bu∩ oba iterßtorem na konec proudu, nebo ani jeden nenφ iterßtorem na konec proudu.

Narozdφl od formßtovanΘho vstupu, zde konstruktor nenaΦte ₧ßdn² znak. O naΦφtßnφ znak∙ se starß operßtor p°φstupu k prvku *. Ukß₧eme si jeden u₧iteΦn² p°φklad jak nejlΘpe naΦφst obsah (textovΘho) souboru do °et∞zce

 

ifstream in(ôdata.txtö);

string data((istreambuf_iterator<char>(in)),

ááááááá áááááistreambuf_iterator<char>());

 

Je to mnohem rychlejÜφ ne₧ pou₧itφ formßtovanΘho vstupu. ProΦ je prvnφ parametr v zßvorkßch se dozvφte p°φÜt∞.

V²stupnφ buffer

Neformßtovan² v²stup znak po znaku zajistφ nßsledujφcφ v²stupnφ iterßtor

 

template <typename charT,

ááááááááá typename traits = char_traits<charT> >

class ostreambuf_iterator

áá : public iterator<output_iterator_tag,

áááááááááááááááááááá void, void, void, void>

{

áá // ... uvedeny jen specifickΘ slo₧ky

public:

áá ostreambuf_iterator(ostream_type & s);á // (1)

áá ostreambuf_iterator(streambuf_type * s);á // (1)

áá ostreambuf_iterator & operator =(charT c);á // (2)

áá bool failed() const;á // (3)

};

 

(1)   Konstruktory, kterΘ p°ipojφ iterßtor k v²stupnφ vyrovnßvacφ pam∞ti.

(2)   Zde se odehrßvß zßpis znaku do proudu, ale jen v p°φpad∞, ₧e failed() vrßtφ false.

(3)   Vracφ true, pokud se p°i n∞jakΘm p°edchozφm zßpisu (operßtor =) dosßhlo konce proudu; jinak vracφ false.

Ostatnφ operßtory pouze vracφ *this. Navß₧eme na p°edchozφ jednoduch² p°φklad: Kdy₧ u₧ jsme naΦetli textov² soubor, tak si ho te∩ znovu ulo₧φme

 

ofstream out(ômojedata.txtö);

copy(data.begin(), data.end(),

áááá ostreambuf_iterator<char>(out));

 

Deklaraci vÜech t∞chto iterßtor∙ na vstupn∞/v²stupnφch proudech nalezneme v hlaviΦkovΘm souboru <iterator>. Poslednφ dva jmenovanΘ jsou neprßvem podce≥ovßny a p°ehlφ₧eny. Pokud jde o neformßtovan² vstup nebo v²stup, jsou ale tou pravou volbou.

Co zbylo na p°φÜt∞

V p°φÜtφm zßv∞reΦnΘm dφlu dokonΦφme p°ehlφdku STL a vÜimneme si nejΦast∞jÜφch chyb a äpodraz∙ô, kterΘ s sebou pou₧φvßnφ iterßtor∙ p°inßÜφ.

Jaroslav Fran∞k

Infotipy
[1] Dokumentace STL od SGI: www.sgi.com\technology\stl
[2] J. Fran∞k, Iterßtory I, Chip 01/03
[3] J. Fran∞k, Iterßtory II, Chip 01/03
[4] J. Fran∞k, Iterßtory III, Chip 01/03
[5] J. Fran∞k, Nebojte se STL, Chip 12/01
[6] D. Musser et al., STL Tutorial and Reference Guide, 2001
[7] N. Josuttis, The C++ Standard Library, 1999
[8] S. Meyers, Effective STL, 2001
[9] zdrojov² k≤d v rubrice Chip Plus na Chip CD