Előadást letölteni
Az előadás letöltése folymat van. Kérjük, várjon
1
Haladó C++ Programozás SzJ/IV
Haladó C++ Programozás SzJ/IV. Az STL sablonkönyvtár Iterátorok, műveletek intervallumokkal 2013. október Előadó: Szigeti János
2
Témáink copy függvény iterátorok algoritmusok iterator tags
speciális iterátorok insert_iterator output_iterator input_iterator algoritmusok halmazműveletek bejárás, keresés, lecserélés STL
3
copy fv. template <class InputIterator, class OutputIterator>
OutputIterator copy(InputIterator first, InputIterator last, OutputIterator result); [first, last) szakaszból [result, result + (last - first))-ba másolja az elemeket *result = *first, *(result + 1) = *(first + 1), ..., *(result + n) = *(first + n) Pl. copy_demo.cc pontosabban: a bemeneti intervallum elejétől kezdve x=*first++; művelettel olvassa az adatokat; a kimenetre *result++=x; művelettel ír; mindaddig, amíg first==last nem lesz. Így nemcsak kész konténerekre, hanem elvont intervallumokra is használható (ld. [i|o]stream_iterator, insert_iterator) STL
4
Iterator tags Az iterátorral kapcsolatos információk kinyerésére
pl.: distance_type, value_type Használata: segédfüggvény sablonokban gyakori példa: algoritmus definiálása intervallumra (iterátor pár) az intervallum elemeinek megfogása iter_traits.cc STL
5
insert_iterator STL Típusa: kimeneti iterátor
csak írhatunk bele eredményintervallum elejét definiálhatjuk vele (pl. copy algoritmusban) Konténerekre definiálható tipizálás konténerrel typedef insert_iterator<vector<int> > IntVII; inicializálás (konstruktorban) konténerrel és iterátorral vector<int> i0_v; IntVII i0_vii(i0_v,i0_v.begin()); makró a tároló ::insert(it,dat) függvényére speciálisan ha az iterátor begin() vagy end() lenne, és a konténernek létezik a push_*() függvénye: front_insert_iterator -> push_front() back_insert_iterator -> push_back() Pl. insert_vector.cc, insert_iterator_demo.cc egyszerűbb megadási mód: inserter(Container,iterator); inserter_demo.cc front_inserter(Container); back_inserter(Container); Mi a különbség az alábbiak között? copy(a.begin();a.end(),b.begin()); copy(a.begin();a.end(),inserter(b,b.begin())); STL
6
ostream_iterator Szintén kimeneti iterátor kétféle konstruktor:
ostream_iterator(ostream& s) s << t ostream_iterator(ostream& s, const char* delim) s << t << delim A definiált operátorok (++,*,=) felüldefiniálásával lehet trükközni! Pl. ostreamiter_demo.cc és MyOstreamIterator.h STL
7
istream_iterator Bemeneti iterátor kétféle konstruktor:
csak olvasunk alóla: dat=*it++; kétféle konstruktor: istream_iterator(istream& s) ez a szokványos istream_iterator() ez pedig utolsó utáni iterátorral egyezik meg (operator==: true) - for ciklus lezárásához kell! Pl. istreamiter_demo.cc és halmaz4_demo.cc STL
8
Algoritmusok csoportosítása
Belső vagy külső fv. belső fv. a struktúrára optimalizált Rendezett bemenettel dolgozik-e igen: unique(), merge(), set_union() stb. Tartalmon módosít-e nem: find(), count(), search(), equal() stb. igen: sort(), unique(), merge(), copy(), replace() stb. igen: külön kimeneti intervallummal dolgozik-e Hány bemeneti intervallummal dolgozik 1-gyel 2-vel Kimenete iterator intervallum-vég pozíció érték (pl. aggregátum) vectorlist_demo.cc STL
9
Algoritmusok – belső v. külső fv.
vector list set map size b empty find k count merge unique - sort remove reverse automatikusan egyedi automatikusan rendezve erase! Külső fv. előnyei: különböző konténertípusokra működik. Pl. merge list<int>+set<int> intervallum rugalmasan definiálható hátrányok: nem használhatóak ki a konténer struktúrája által adott előnyei intervallum mérete nem módosítható. Pl. remove, unique STL
10
Halmazműveletek (1) rendezett adatsorokon végezhetőek
set, map alapból rendezett vector, list: előbb sort(), aztán hajrá megadási szintaxis: template <class InputIterator1, class InputIterator2, class OutputIterator> OutputIterator set_op(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result); vagy: template <class InputIterator1, class InputIterator2, class OutputIterator, class StrictWeakOrdering> OutputIterator result, StrictWeakOrdering comp); lásd less<T> STL
11
Halmazműveletek (2) unió/metszet: azonos elemek többször (max(m,n) ill. min(m,n)) is megjelennek a kimeneten Pl. halmaz1_demo.cc, halmaz2_demo.cc különbség: azonos elemek max(m-n,0)- szor jelennek meg a kimeneten Pl. halmaz3_demo.cc szimmetrikus különbség: azonos elemek abs(m-n)-szer jelennek meg a kimeneten Pl. halmaz4_demo.cc STL
12
Algoritmusok közelebbről
Értéket nem változtató algoritmusok for_each find_if search equal Értéket módosító algoritmusok copy replace replace_if STL
13
InputIterator, vagyis csak olvasásra szánt
for_each sablon Az intervallum összes tagját egyenként argumentumul véve végrehajt egy függvényt template <class InputIterator, class UnaryFunction> UnaryFunction for_each(InputIterator first, InputIterator last, UnaryFunction f); definiálandó: void f::operator() (T x); x típusa T vagy const T&, de nem T& - nem módosítható void (*function)(const T&) típusú fv.ptr. is megadható példa: foreach1_demo.cc, foreach2_demo.cc, foreach3_demo.cc InputIterator, vagyis csak olvasásra szánt STL
14
Házi feladat Melyik operátora hányszor hívódott meg az OutputIteratornak? Egészítsd ki a hf07_oiCnt.cc-ben megadott ostream_iterator-t, hogy az számolja a függvényhívásokat Használd a copy fv.-ben ezt a saját OstreamIteratorCnt iterátort a mostani ostream_iterator helyett A copy lefutása után írd ki, mi hányszor hívódott meg (külső objektum elérése ld. foreach2_demo.cc) Szorgalmi módosítsd az OstreamIteratorCnt-t sablonná, hogy ne csak int-ekre működjön az egyes függvények hívásának sorrendjét is jegyezze meg (counter helyett history változó) STL
15
find_if függvény find()-dal ellentétben nem értékre keres, hanem az első olyan objektumra, melyre igaz egy állítás (Predicate). template<class InputIterator, class Predicate> InputIterator find_if(InputIterator first, InputIterator last, Predicate pred); Az állítás típusa unary_function<T,bool> példa: findif_demo.cc arg return STL
16
Search függvény intervallumot keres egy másik intervallumban
template <class ForwardIterator1, class ForwardIterator2, class BinaryPredicate> ForwardIterator1 search(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate binary_pred); példa: search1_demo.cc, search2_demo.cc Megj.: ForwardIterator vs. InputIterator: a search a megadott intervallumok elemeit (op*-gal) többször is ki akarja olvasni. Az InputIterator nem garantálja, hogy az iterátor alatt op*-gal elért elem mindig ugyanaz lesz – lásd: istream_iterator! STL
17
equal függvény megnézi, hogy a két intervallum megegyezik- e
sorrend is számít egyezőség vizsgálata predicate alapján történhet template <class InputIterator1, class InputIterator2, class BinaryPredicate> bool equal(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, BinaryPredicate binary_pred); STL
18
replace függvény az intervallum összes old_value-val egyező elemét new_value-ra cseréli template <class ForwardIterator, class T> void replace(ForwardIterator first, ForwardIterator last, const T& old_value,const T& new_value) párja: replace_if old_value helyett feltétel adható meg példa: replace_demo.cc, replace_if_demo.cc STL
19
replace_copy A replace függvény sem képes const T& típusú elemeket (pl. const T& set<T>::iterator::operator*()) felülírni Lehetséges megoldás: while ciklusban: find/find_if, erase, insert veszély: iterálás közben erase/insert (ld. később) új tároló létrehozása, s bele már a módosított adatok töltése template <class InputIterator, class OutputIterator, class T> OutputIterator replace_copy(InputIterator first, InputIterator last, OutputIterator result, const T& old_value, const T& new_value); Pl: replace_copy_demo.cc STL
20
transform Mi van akkor, ha a régi értéktől függő új értékkel akarjuk megoldani a replace()-t? if (pred(old_val)==true) new_val=func(old_val) Ez ekvivalens azzal, hogy és func(val) {if (pred(val)==true) return val; /eredeti func body/ } különbség: a replace az irreleváns elemeket békén hagyja, a transform őket is "birizgálja" teendő: az irreleváns adatok miatti járulékos feladatok minimalizálása. (Pl. pointer szerinti adatátadás) STL
21
transform Általánosan: vagy kéttagú műveletekre:
template <class InputIterator, class OutputIterator, class UnaryFunction> OutputIterator transform(InputIterator first, InputIterator last, OutputIterator result, UnaryFunction op); vagy kéttagú műveletekre: template <class InputIterator1, class InputIterator2, class OutputIterator, class BinaryFunction> OutputIterator transform(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, OutputIterator result, BinaryFunction binary_op); Pl.: transform_demo.cc STL
Hasonló előadás
© 2024 SlidePlayer.hu Inc.
All rights reserved.