STL: kontenery C++: STL: kontenery. STL: kontenery. STL: kontenery. STL: kontenery. Fabryka obiektów. Fabryka obiektów

Podobne dokumenty
STL: kontenery. STL: kontenery. STL: kontenery. Typy kontenerów STL. STL: kontenery. STL: kontenery. multimap. Kontener map: przykład zadanie:

STL: implementowanie algorytmów. STL: implementowanie algorytmów. STL: implementowanie algorytmów. STL: implementowanie algorytmów

STL: algorytmy sortujące. STL: algorytmy sortujące. STL: algorytmy sortujące. STL: algorytmy sortujące. STL: algorytmy sortujące

STL: algorytmy sortujące. STL: algorytmy sortujące. STL: algorytmy sortujące. STL: algorytmy sortujące. STL: algorytmy sortujące

STL: kontenery C++: STL: kontenery. STL: kontenery. STL: kontenery. STL: kontenery. Fabryka obiektów. Fabryka obiektów. Fabryka obiektów przykład:

Algorytmy w C++ dla opornych!

Dariusz Brzeziński. Politechnika Poznańska, Instytut Informatyki

Algorytmy, iteratory, kolekcje niestandardowe

obiekty funkcyjne - funktory

STL: implementowanie algorytmów C++: STL. STL: implementowanie algorytmów. STL: implementowanie algorytmów. STL: implementowanie algorytmów

Definicja szablonu klasy. Korzystanie z szablonu. Specjalizacja metody szablonu.

Zaawansowane programowanie w C++ (PCP)

Kurs programowania. Wykład 9. Wojciech Macyna. 28 kwiecień 2016

Programowanie i struktury danych

Wstęp do programowania obiektowego. STL - Standard Template Library

Paradygmaty programowania

STL: kontenery. Typy kontenerów STL. STL: kontenery. STL: kontenery. STL: kontenery. Typy kontenerów STL. deque (double-ended queue) list

Algorytmy i Struktury Danych. Anna Paszyńska

Standard C++0x (C++1x?) Marcin Świderski

Kurs programowania. Wykład 9. Wojciech Macyna

Technologie programowania Wykład 4. Szablony funkcji Notes. Szablony funkcji Notes. Szablony funkcji Notes. Notes. Przemek Błaśkiewicz.

Programowanie w C++ Wykład 6. Katarzyna Grzelak. 1 kwietnia K.Grzelak (Wykład 6) Programowanie w C++ 1 / 43

Szablony klas, zastosowanie szablonów w programach

Szablony funkcji i klas (templates)

Szablony funkcji i szablony klas

2. Klasy cz. 2 - Konstruktor kopiujący. Pola tworzone statycznie i dynamicznie - Funkcje zaprzyjaźnione - Składowe statyczne

Algorytmy i Struktury Danych.

Programowanie w C++ Wykład 7. Katarzyna Grzelak. 23 kwietnia K.Grzelak (Wykład 7) Programowanie w C++ 1 / 40

Programowanie Obiektowo Zorientowane w języku C++ Biblioteka STL

STL: Lekcja 1&2. Filozofia STL

Dla każdej operacji łącznie tworzenia danych i zapisu ich do pliku przeprowadzić pomiar czasu wykonania polecenia. Wyniki przedstawić w tabelce.

Kurs programowania. Wykład 1. Wojciech Macyna. 3 marca 2016

IMIĘ i NAZWISKO: Pytania i (przykładowe) Odpowiedzi

STL Standardt Template Library (wprowadzenie)

Składnia C++ Programowanie Obiektowe Mateusz Cicheński

STL: kontenery. STL: kontenery. STL: kontenery. STL: kontenery. STL: kontenery. STL: kontenery

Technologie cyfrowe semestr letni 2018/2019

Składnia C++ Programowanie Obiektowe Mateusz Cicheński

Operatory na rzecz typu TString

Język ludzki kod maszynowy

Zaawansowane programowanie w języku C++ Biblioteka standardowa

KLASA UCZEN Uczen imię, nazwisko, średnia konstruktor konstruktor Ustaw Wyswietl Lepszy Promowany

wykład IV uzupełnienie notatek: dr Jerzy Białkowski Programowanie C/C++ Język C, a C++. wykład IV dr Jarosław Mederski Spis Język C++ - wstęp

Programowanie współbieżne i rozproszone

8. Wektory. Przykłady Napisz program, który pobierze od użytkownika 10 liczb, a następnie wypisze je w kolejności odwrotnej niż podana.

Aby uzyskać zaliczenie w pierwszym terminie (do 30 stycznia 2018) rozliczyć trzeba co najmniej 8 projektów, po 4 z każdej z części: C++ oraz Python.

Wprowadzenie do szablonów szablony funkcji

Szablony. Szablony funkcji

Wprowadzenie do szablonów klas

Projektowanie klas c.d. Projektowanie klas przykład

Wprowadzenie do szablonów szablony funkcji

Automatyczne tworzenie operatora = Integer2& operator=(const Integer& prawy) { zdefiniuje. Integer::operator=(ri);

Zaawansowane programowanie w C++ (PCP)

Programowanie Komponentowe Zarządzanie obiektami: kontenery

C++ - przeciążanie operatorów. C++ - przeciążanie operatorów. C++ - przeciążanie operatorów. C++ - przeciążanie operatorów

PARADYGMATY PROGRAMOWANIA Wykład 4

Szablon klasy std::vector

Programowanie obiektowe w C++ Wykład 12

Wykład 3 Składnia języka C# (cz. 2)

EGZAMIN 2 (14 WRZEŚNIA 2015) JĘZYK C++

Instrukcja do pracowni specjalistycznej z przedmiotu. Obiektowe programowanie aplikacji

Programowanie w języku Java. Kolekcje

Automatyczne tworzenie operatora = Integer2& operator=(const Integer& prawy) {

Wykład I. Programowanie II - semestr II Kierunek Informatyka. dr inż. Janusz Słupik. Wydział Matematyki Stosowanej Politechniki Śląskiej

Zaawansowane programowanie w C++ (PCP)

utworz tworzącą w pamięci dynamicznej tablicę dwuwymiarową liczb rzeczywistych, a następnie zerującą jej wszystkie elementy,

KLASA UCZEN Uczen imię, nazwisko, średnia konstruktor konstruktor Ustaw Wyswietl Lepszy Promowany

Technologie cyfrowe semestr letni 2018/2019

Wskaźniki. nie są konieczne, ale dają językowi siłę i elastyczność są języki w których nie używa się wskaźników typ wskaźnikowy typ pochodny:

Programowanie w C++ Wykład 12. Katarzyna Grzelak. 28 maja K.Grzelak (Wykład 12) Programowanie w C++ 1 / 27

Signals + Threads: Qt vs. Boost

Mechanizm dziedziczenia

Język C++ wykład VIII

dr inż. Jarosław Forenc

Obszar statyczny dane dostępne w dowolnym momencie podczas pracy programu (wprowadzone słowem kluczowym static),

Programowanie obiektowe

Programowanie w C++ Wykład 11. Katarzyna Grzelak. 13 maja K.Grzelak (Wykład 11) Programowanie w C++ 1 / 30

PARADYGMATY PROGRAMOWANIA Wykład 3

Automatyczne tworzenie operatora = Integer2& operator=(const Integer& prawy) {

Pojemniki Pojemnik to obiekt, którego zadaniem jest przechowywanie innych obiektów.

Język C++ wykład VII. uzupełnienie notatek: dr Jerzy Białkowski. Programowanie C/C++ Język C++ wykład VII. dr Jarosław Mederski. Spis.

Wstęp do programowania obiektowego, wykład 7

C++11. C++ 11 wybrane elementy. C++11: referencje do rvalue C++ 11: C++11: referencje do rvalue. C++11: referencje do rvalue. Referencje do rvalue

Wykład II. Programowanie II - semestr II Kierunek Informatyka. dr inż. Janusz Słupik. Wydział Matematyki Stosowanej Politechniki Śląskiej

Programowanie obiektowe i C++ dla matematyków

Jzyk C++ cz 3. Jarosław Gramacki Instytut Informatyki i Elektroniki ( $)*)+' *, - ( ' )*'.' '',*/ *, ','*0) 1 / ) %*+ 2'' 2" ( $%%) )'20 )*0) 1 / )

Wstęp do programowania

Programowanie 2. Język C++. Wykład 9.

Kurs programowania. Wykład 2. Wojciech Macyna. 17 marca 2016

Lista, Stos, Kolejka, Tablica Asocjacyjna

C++: STL. STL: kontenery. STL: kontenery. STL: kontenery. STL: kontenery. Programowanie Obiektowe C++: Standard Template Library

Programowanie w języku C++

Identyfikacje typu na etapie. wykonania (RTTI)

Zaawansowane programowanie w C++ (PCP)

Programowanie w językach

Wykład 5 Wybrane zagadnienia programowania w C++ (c.d.)

Stos liczb całkowitych

Słowa kluczowe i nazwy

Techniki programowania INP001002Wl rok akademicki 2018/19 semestr letni. Wykład 5. Karol Tarnowski A-1 p.

Transkrypt:

Fabryka obiektów C++: Fabryka obiektów Klasa, której obiekty pośrednicza przy tworzeniu innych obiektów. Pomagają tworzyć obiekty, jeżeli informacja o typie odnosi się do konkretnego typu, znanego w momencie kompilacji, ale forma jest nieodpowiednia dla kompilatora. Fabryka ukrywa przed użytkownikiem mechanizm zamiany identyfikatora na literał dostarczany do operatora new, upraszczając tworzenie obiektów. 2 Klasa bazowa Figure dostarcza identyfikatorów dla klas konkretnych: class Figure { public: enum Type {SQUARE, CIRLCE, TRIANGLE ; virtual void write(ostream& os) const = 0; virtual void read(istream& is) = 0; ; 3 Klasa pochodna nadpisuje metody wirtualne służące do zapisania obiektu do pliku oraz odczytania z pliku: class Square : public Figure { public: void write(ostream& os) const { os << SQUARE; /* zapis pól */ ; void read(istream& is) { /* odczyt pól */ ; ; 4 Podczas odczytu danych z pliku musimy polegać na informacji dostarczanej w trakcie działania, tj. na identyfikatorze obiektu zapisanym w pliku (zapis do pliku zaczyna się od podania identyfikatora, dopiero potem są zapisywane zawartości pól obiektu) Taki identyfikator to nie jest argument dla new. Potrzebny mechanizm, który tworzy obiekty na podstawie identyfikatora.. Figure* createobj(figure::type type) { switch (type) { case Figure::SQUARE: return new Square(); case Figure::CIRCLE: return new Circle(); case Figure::TRIANGLE: return new Triangle(); default: return NULL; ; ; 5 6 1

Za pomocą tej funkcji oraz metody read można dostarczyć funkcję, która pozwala odczytywać obiekty ze strumienia: Figure* create(ifstream& is) { Figure::Type type; unsigned int t = 0; if(is >> t) { // odczyt wartości typu int type = static_cast<figure::type>(t); // rzutowanie t na Type Figure* obj = createobj(type); obj->read(is); return obj; else return NULL; ;..i to już, wszystko? 7 To rozwiązanie ma wady: kiedy dodamy nowy typ danych, musimy też zmodyfikować funkcję createobj Brakuje kontroli poprawności wiązania identyfikatora z typem. Zestaw identyfikatorów jest zasobem wspólnym dla całej hierarchii, przy modyfikacji zbioru klas musi też podlegać modyfikacji. Potrzeba czegoś więcej.. 8 Fabryka skalowalna obiektów przykład: Fabryka najpierw rejestruje pary: identyfikatory typu i przypisane im funkcje tworzące. Następnie jest gotowa do tworzenia obiektów na podstawie identyfikatora typu. class FigFactory { public: typedef Figure* (*CreateFig)(); // nowy typ: wskaźnik na funkcję tworzącą void registerfig(int id, CreateFig fun); // rejestruje nowy typ Figure* create(int id); // tworzy obiekt na podstawie identyfikatora private: typedef map<int, CreateFig> Creators; // nowy typ: kontener mapa par Creators creators_; // pole: kontener do przechowywania par ; Fabryka skalowalna obiektów przykład: void FigFactory::registerFig(int id, CreateFig fun) { creators_.insert(map<int,createfig>::value_type(id, fun)); ; // typedef pair<const Key, Type> value_type; Figure* FigFactory::create(int id) { //tworzy obiekt danego typu Creators::const_iterator i = creators_.find(id); if(i!= creators_.end() ) //jeżeli znalazł odpowiedni wpis return (i->second)(); //woła metodę fabryczną return 0L; //zwraca pusty wskaźnik, gdy nieznany identyfikator ; 9 10 Fabryka skalowalna obiektów przykład: Autor klasy konkretnej musi też dostarczyć funkcję tworzącą obiekt danej klasy. Funkcja ta ma sygnaturę zdefiniowaną w fabryce i jest dostarczana do fabryki podczas rejestracji typu. Figure* CreateSquare() { return new Square(); ; Figure* CreateCircle() { return new Circle(); ; Figure* CreateTriangle() { return new Triangle(); ; 11 Jeszcze raz tworzymy funkcję, która pozwala odczytywać obiekty ze strumienia: Figure* create(ifstream& is, FigFactory& factory) { unsigned int t = 0; if(is >> t) { Figure* obj = factory.create(t); obj->read(is); return obj; else return NULL; ; 12..i to już, wszystko? 2

Trzeba jeszcze pamiętać, aby na początku programu stworzyć fabrykę i zarejestrować odpowiednie typy int main() { FigFactory factory; factory.registerfig(figure::square, CreateSquare); factory.registerfig(figure::circle, CreateCircle); factory.registerfig(figure::triangle, CreateTriangle); ; /*.. */ To wszystko. Chociaż, może nie.. 13 Fabryka obiektów i wzorzec prototypu: wzorzec prototypu pozwala na tworzenie kopii obiektu, jeżeli mamy dostępny wskaźnik lub referencję do klasy bazowej. Wykorzystuje mechanizm funkcji wirtualnych przenosi odpowiedzialność za tworzenie obiektów do klas konkretnych. Klasa bazowa definiuje tylko czysto wirtualną metodę. 14 Fabryka obiektów i wzorzec prototypu: Dodajemy czysto wirtualną metodę clone do klasy bazowej: class Figure { public: enum Type {SQUARE, CIRCLE, TRIANGLE ; virtual void write(ostream& os) const = 0; virtual void read(istream& is) = 0; virtual Figure* clone() const = 0; ; 15 Fabryka obiektów i wzorzec prototypu: Implementujemy metodę clone w klasach konkretnych: class Square : public Figure { public: void write(ostream& os) const { os << SQUARE; /* zapis pól */ ; void read(istream& is) { /* odczyt pól */ ; Figure* clone() const { return new Square(*this); ; ; Teraz zadaniem fabryki jest przechowywać obiekty wzorcowe, a nie funkcje fabryczne. Można w niej umieścić np. po kilka obiektów tego samego typu, ale w różnym stanie. 16 Fabryka obiektów i wzorzec prototypu: class FigFactory2 { typedef map<int,figure*> Prototypes; Prototypes prototypes_; public: void registerfig(int id, Figure* f){ prototypes_.insert(map<int,figure*>::value_type(id, f)); ; Figure* create(int id){ Prototypes::const_iterator i = prototypes_.find(id); if(i!= prototypes_.end() ) //jeżeli znalazł odpowiedni wpis return (i->second)->clone(); //woła metodę clone return 0L; //zwraca pusty wskaźnik, gdy nieznany identyfikator ; ; Teraz to już naprawdę wszystko o fabrykach obiektów. C++: STL Algorytmy 17 3

STL: algorytmy Wprowadzenie W bibliotece STL znajduje się zbiór funkcji globalnych zwanych algorytmami, które ułatwiają działania na kontenerach Algorytmy dzielą się na cztery grupy: 1. niemodyfikujące (for_each, find, count, equal, search, etc.), 2. modyfikujące (copy, swap, transform, replace, fill, generate, remove, unique, reverse, rotate, random_shuffle), 3. sortujące (partition, sort, merge, operacje na zbiorach i na stercie, min, max), 4. inne, m.in. numeryczne. 1. for_each, 2. find, 3. find_first_of, 4. adjacent_find, 5. count, 6. count_if, 7. mismatch, 8. equal, 9. search, 10.find_end, 11.search_n 19 20 template<typename InputIterator, typename Function> Function for_each( InputIterator _First, InputIterator _Last, Function _Func ); wywołuje podany obiekt funkcyjny na rzecz każdego z obiektów należących do sekwencji określanej przez parę iteratorów. Iterator _Last wskazuje na prawy graniczny element sekwencji pierwszy, z listy zawartej w kontenerze, który do niej nie należy, zwraca kopię obiektu funkcyjnego po jego zastosowaniu. Przykład: Przemnożenie wszystkich elementów w kontenerze przez pewien współczynnik. Obiekt funkcyjny: template <class Type> class MultValue { private: Type Factor; public: MultValue ( const Type& _Val ) : Factor ( _Val ) {; void operator ( ) ( Type& elem ) const { elem *= Factor; ; ; int main( ) { using namespace std; vector <int> v1; vector <int>::iterator Iter1; for ( int i = -4 ; i <= 2 ; i++ ) v1.push_back( i ); for_each ( v1.begin (), v1.end (), MultValue<int> ( -2 ) ); cout << Mnożenie elementów z v1\n " << przez -2 daje:\n" ; for ( Iter1 = v1.begin( ); Iter1!= v1.end( ); Iter1++ ) cout << *Iter1 << " "; cout << endl; 21 22 template<typename InputIterator, typename Type> InputIterator find( InputIterator _First, InputIterator _Last, const Type& _Val ); w sekwencji [_First,_Last) znajduje położenie pierwszego elementu przechowującego określoną wartość _Val, zwraca iterator wskazujący na znaleziony element, a jeżeli takiego elementu nie znaleziono iterator wskazujący na pierwszy element znajdujący się za ostatnim elementem z sekwencji, tj. iterator _Last. Przykład: Należy znaleźć w kontenerze element o wskazanej wartości. int main( ) { list <int> L; list <int>::iterator Iter; list <int>::iterator result; L.push_back( 40 ); L.push_back( 20 ); L.push_back( 10 ); L.push_back( 40 ); L.push_back( 10 ); result = find( L.begin( ), L.end( ), 10 ); if ( result == L.end( ) ) cout << "Nie ma 10 w liście L." << endl; else result++; cout << "Jest 10 w liście L. Po 10 występuje " << *(result) << "." << endl; 23 24 4

template<typename ForwardIterator1, typename ForwardIterator2> ForwardIterator1 find_first_of( ForwardIterator1 _First1, ForwardIterator1 _Last1, ForwardIterator2 _First2, ForwardIterator2 _Last2 ); w sekwencji określanej przez parę iteratorów [_First1,_Last1) poszukuje pierwszego wystąpienia dowolnej z wartości ze zbioru wartości określanego przez parę iteratorów [_First2,_Last2) zwraca iterator wskazujący na znaleziony element, a jeżeli takiego elementu nie znaleziono iterator wskazujący na pierwszy element znajdujący się za ostatnim elementem z sekwencji, tj. iterator _Last1, występuje w dwóch wersjach druga wersja zawiera trzeci argument szablonu reprezentujący obiekt funkcyjny służący do porównań. #include <cctype> // std::find_first_of // std::tolower int mychars[] = {'a','b','c','a','b','c'; std::vector<char> haystack (mychars,mychars+6); std::vector<char>::iterator it; int needle[] = {'A','B','C'; it = find_first_of (haystack.begin(), haystack.end(), needle, needle+3); if (it!=haystack.end()) std::cout << "Pierwszy, który pasuje: " << *it << '\n'; 25 26 // std::find_first_of #include <cctype> // std::tolower bool comp_case_insensitive (char c1, char c2) { return (std::tolower(c1)==std::tolower(c2)); ; int mychars[] = {'a','b','c','a','b','c'; std::vector<char> haystack (mychars,mychars+6); std::vector<char>::iterator it; int needle[] = {'A','B','C'; it = find_first_of (haystack.begin(), haystack.end(), needle, needle+3, comp_case_insensitive); if (it!=haystack.end()) std::cout << "Pierwszy, który pasuje: " << *it << '\n'; 27 template<typename ForwardIterator> ForwardIterator adjacent_find( ForwardIterator _First, ForwardIterator _Last ); w sekwencji określanej przez parę iteratorów [_First,_Last) poszukuje dwóch sąsiadujących ze sobą elementów, które są sobie równe, zwraca iterator wskazujący na pierwszy ze znalezionej pary elementów, a jeżeli takiej pary nie znaleziono iterator wskazujący na pierwszy element znajdujący się za ostatnim elementem z sekwencji, tj. iterator _Last, występuje w dwóch wersjach druga wersja zawiera trzeci argument szablonu reprezentujący obiekt funkcyjny służący do porównań. 28 // std::adjacent_find int myt[] = {5,20,5,30,30,20,10,10,20; std::vector<int> V (myt,myt+8); std::vector<int>::iterator it; it = std::adjacent_find (V.begin(), V.end()); if (it!=v.end()) std::cout << "Pierwsza para duplikatów: " << *it << '\n'; // std::adjacent_find bool myfunction (int i, int j) { return (i==j); // tu miejsce na nasz własny sposób porównywania ; int myt[] = {5,20,5,30,30,20,10,10,20; std::vector<int> V (myt,myt+8); std::vector<int>::iterator it; it = std::adjacent_find (V.begin(), V.end(), myfunction); if (it!=v.end()) std::cout << "Pierwsza para duplikatów: " << *it << '\n'; 29 30 5

template<typename InputIterator, typename Type> typename iterator_traits<inputiterator>::difference_type count( InputIterator _First, InputIterator _Last, const Type& _Val ); w sekwencji określanej przez parę iteratorów [_First,_Last) zlicza elementy których wartości są równe wartości podanej w argumencie _Val, zwraca liczbę znalezionych elementów posługując się typem danych zdefiniowanych w cechach (traits) difference_type (który powinien bezbłędnie konwertować się do int). // std::count using namespace std; int main( ) { using namespace std; vector <int> v1; vector <int>::iterator Iter; v1.push_back( 10 ); v1.push_back( 20 ); v1.push_back( 10 ); v1.push_back( 40 ); v1.push_back( 10 ); 31 int result; result = count( v1.begin( ), v1.end( ), 10 ); cout << "Liczba wystąpień wartości 10 wynosi: " << result << "." << endl; 32 template<typename InputIterator, typename Predicate> typename iterator_traits<inputiterator>::difference_type count_if( InputIterator _First, InputIterator _Last, Predicate _Pred ); w sekwencji określanej przez parę iteratorów zlicza elementy, które spełniają warunek określony w predykacie (obiekt funkcyjny, funkcja), zwraca liczbę znalezionych elementów. 33 // std::count_if using namespace std; bool greater10 ( int value ) { return value > 10; // tu miejsce na nasz własny sposób porównywania int main( ) { vector <int> v1; vector <int>::iterator Iter; v1.push_back( 10 ); v1.push_back( 20 ); v1.push_back( 10 ); v1.push_back( 40 ); v1.push_back( 10 ); int result1 = count_if( v1.begin( ), v1.end( ), greater10 ); cout << "Liczba wystąpień wartości większych od 10 w v1 wynosi: " << result1 << "." << endl; UKSW, WMP. SNS, Warszawa 34 template<typename InputIterator1, typename InputIterator2> pair<inputiterator1, InputIterator2> mismatch( InputIterator1 _First1, InputIterator1 _Last1, InputIterator2 _First2 ); porównuje dwie sekwencje elementów wskazywane przez parę iteratorów [_First1,_Last1) - pierwsza sekwencja, oraz przez iterator _First2 druga sekwencja, odpowiednio element po elemencie poszukując pierwszej takiej pary elementów z obydwu sekwencji, dla których operator porównania zwróci wartość false (obiekty przechowywane w sekwencjach muszą mieć zaimplementowany przeciążony operator porównania), Zwraca parę iteratorów wskazującą na pierwszą znalezioną parę różniących się elementów z dwóch sekwencji, lub na parę pierwszych elementów tuż za sekwencjami, jeżeli sekwencje są identyczne, występuje w dwóch wersjach druga z dodatkowym, ostatnim argumentem szablonu reprezentującym obiekt funkcyjny służący do porównań. // std::mismatch #include <utility> // std::pair for (int i=1; i<6; i++) V.push_back (i*10); // V: 10 20 30 40 50 int myt[] = {10,20,80,320,1024; // myt: 10 20 80 320 1024 std::pair<std::vector<int>::iterator,int*> mypair; mypair = std::mismatch (V.begin(), V.end(), myt); std::cout << " Pierwsza para różnych elementów: " << *mypair.first; std::cout << " oraz " << *mypair.second << '\n'; 35 36 6

// std::mismatch #include <utility> // std::pair bool mypredicate (int i, int j) { return (i==j); // tu miejsce na nasz własny sposób porównywania ; for (int i=1; i<6; i++) V.push_back (i*10); // V: 10 20 30 40 50 int myt[] = {10,20,80,320,1024; // myt: 10 20 80 320 1024 std::pair<std::vector<int>::iterator,int*> mypair; mypair = std::mismatch (V.begin(), V.end(), myt, mypredicate); std::cout << " Pierwsza para różnych elementów: " << *mypair.first; std::cout << " oraz " << *mypair.second << '\n'; 37 template<typename InputIterator1, typename InputIterator2> bool equal( InputIterator1 _First1, InputIterator1 _Last1, InputIterator2 _First2 ); porównuje dwie sekwencje elementów wskazywane przez parę iteratorów [_First1,_Last1) pierwsza sekwencja, oraz iterator _First2 druga sekwencja, odpowiednio element po elemencie zwraca wartość true, jeżeli sekwencje są identyczne, lub false wpp, występuje w dwóch wersjach druga z dodatkowym, ostatnim argumentem szablonu reprezentującym obiekt funkcyjny/funkcję służący do porównań. 38 // std::equal int myt[] = {20,40,60,80,100; // myt: 20 40 60 80 100 std::vector<int>v (myt,myt+5); // V: 20 40 60 80 100 if ( std::equal (V.begin(), V.end(), myt) ) std::cout << "Sekwencje identyczne.\n"; else std::cout << "Sekwencje różne.\n"; // std::equal bool mypredicate (int i, int j) { return (i==j); // tu miejsce na nasz własny sposób porównywania ; int myt[] = {20,40,60,80,100; // myt: 20 40 60 80 100 std::vector<int>v (myt,myt+5); // V: 20 40 60 80 100 if ( std::equal (V.begin(), V.end(), myt, mypredicate) ) std::cout << "Sekwencje identyczne.\n"; else std::cout << "Sekwencje różne.\n"; 39 40 template<class ForwardIterator1, class ForwardIterator2> ForwardIterator1 search( ForwardIterator1 _First1, ForwardIterator1 _Last1, ForwardIterator2 _First2, ForwardIterator2 _Last2 ); w sekwencji określanej przez parę iteratorów [_First1,_Last1) poszukuje pierwszej pod-sekwencji o wartościach identycznych jak sekwencja określana przez parę iteratorów [_First2,_Last2), zwraca iterator na element w sekwencji określanej przez parę iteratorów [_First1,_Last1), który rozpoczyna znalezioną pod-sekwencję, a jeżeli takiej pod-sekwencji nie znaleziono iterator wskazujący na pierwszy element znajdujący się za ostatnim elementem z sekwencji [_First1,_Last1), tj. iterator _Last1, występuje w dwóch wersjach druga z dodatkowym, ostatnim argumentem szablonu reprezentującym obiekt funkcyjny/funkcję służący do porównań. template<class ForwardIterator1, class ForwardIterator2> ForwardIterator1 find_end( ForwardIterator1 _First1, ForwardIterator1 _Last1, ForwardIterator2 _First2, ForwardIterator2 _Last2 ); w sekwencji określanej przez parę iteratorów [_First1,_Last1) poszukuje ostatniej pod-sekwencji o wartościach identycznych jak sekwencja określana przez parę iteratorów [_First2,_Last2) zwraca iterator na element w sekwencji określanej przez parę iteratorów [_First1,_Last1), który rozpoczyna znalezioną pod-sekwencję, a jeżeli takiej pod-sekwencji nie znaleziono iterator wskazujący na pierwszy element znajdujący się za ostatnim elementem z sekwencji [_First1,_Last1), tj. iterator _Last1, występuje w dwóch wersjach druga z dodatkowym, ostatnim argumentem szablonu reprezentującym obiekt funkcyjny/funkcję służący do porównań. 41 42 7

// std::search std::vector<int> haystack; // set some values: haystack: 10 20 30 40 50 60 70 80 90 for (int i=1; i<10; i++) haystack.push_back(i*10); int needle1[] = {40,50,60,70; std::vector<int>::iterator it; it = std::search (haystack.begin(), haystack.end(), needle1, needle1+4); if (it!=haystack.end()) std::cout << "needle1 found at position " <<(it-haystack.begin())<< '\n'; else std::cout << "needle1 not found\n"; 43 // std::search bool mypredicate (int i, int j) { return (i==j); // tu miejsce na nasz własny sposób porównywania std::vector<int> haystack; // set some values: haystack: 10 20 30 40 50 60 70 80 90 for (int i=1; i<10; i++) haystack.push_back(i*10); int needle2[] = {20,30,50; it = std::search (haystack.begin(), haystack.end(), needle2, needle2+3, mypredicate); if (it!=haystack.end()) std::cout << "needle2 found at position " <<(it-haystack.begin())<< '\n'; else std::cout << "needle2 not found\n"; UKSW, WMP. SNS, Warszawa 44 template<class ForwardIterator1, class Diff2, class Type> ForwardIterator1 search_n( ForwardIterator1 _First1, ForwardIterator1 _Last1, Size2 _Count, const Type& _Val ); w sekwencji określanej przez parę iteratorów [_First1,_Last1) szuka pierwszej pod-sekwencji o długości _Count, w której wszystkie elementy mają wartość _Val zwraca iterator na element w sekwencji określanej przez parę iteratorów [_First1,_Last1), który rozpoczyna znalezioną pod-sekwencję, a jeżeli takiej pod-sekwencji nie znaleziono iterator wskazujący na pierwszy element znajdujący się za ostatnim elementem z sekwencji [_First1,_Last1), tj. iteratorem _Last1, występuje w dwóch wersjach druga z dodatkowym, ostatnim argumentem szablonu reprezentującym obiekt funkcyjny/funkcję służący do porównań. 45 // std::search_n int myt[]={10,20,30,30,20,10,10,20; std::vector<int> V (myt,myt+8); std::vector<int>::iterator it; it = std::search_n (V.begin(), V.end(), 2, 30); if (it!=v.end()) std::cout << "two 30s found at position " <<(it-v.begin())<< '\n'; else std::cout << "match not found\n"; 46 // std::search_n bool mypredicate (int i, int j) { return (i==j); // tu miejsce na nasz własny sposób porównywania ; int myt[]={10,20,30,30,20,10,10,20; std::vector<int> V (myt,myt+8); std::vector<int>::iterator it; it = std::search_n (V.begin(), V.end(), 2, 10, mypredicate); if (it!=v.end()) std::cout<<"two 10s found at position "<<int(it-v.begin())<< '\n'; else std::cout << "match not found\n"; Podsumowanie: 1. for_each, 2. find, 3. binary_search, 4. find_first_of, 5. adjacent_find, 6. count, 7. count_if, 8. mismatch, 9. equal, 10.search, 11.find_end, 12.search_n. 47 48 8

1. fill, 2. fill_n, 3. generate, 4. generate_n, 5. copy, 6. copy_backward, 7. swap, 8. swap_ranges, 9. replace, 10.replace_if, 11.replace_copy, 12.replace_copy_if, 13.unique_copy, 14.reverse, 15.reverse_copy, 16.rotate, 17.rotate_copy, 18.random_shuffle, 19.transform template<typename ForwardIterator, typename Type> void fill( ForwardIterator _First, ForwardIterator _Last, const Type& _Val ); w sekwencji określanej przez parę iteratorów [_First,_Last) zmienia wartości przechowywane w elementach tej sekwencji na wartość podaną w argumencie _Val. 49 50 template<typename OutputIterator, typename Size, typename Type> void fill_n( OutputIterator _First, Size _Count, const Type& _Val ); w pierwszych _Count elementach sekwencji, której pierwszy element jest wskazywany przez iterator _First, zmienia wartości przechowywane w tych elementach na wartość podaną w argumencie _Val. // std::fill std::vector<int> V (8); // V: 0 0 0 0 0 0 0 0 std::fill (V.begin(),V.begin()+4,5); // V: 5 5 5 5 0 0 0 0 std::fill (V.begin()+3,3,8); // V: 5 5 5 8 8 8 0 0 std::cout << V zawiera:"; 51 52 template<typename ForwardIterator, typename Generator> void generate( ForwardIterator _First, ForwardIterator _Last, Generator _Gen ); w sekwencji określanej przez parę iteratorów [_First,_Last) zmienia wartości przechowywane w elementach tej sekwencji na wartości wygenerowane przez obiekt funkcyjny _Gen. template<class OutputIterator, class Size, class Generator> void generate_n( OutputIterator _First, Size _Count, Generator _Gen ); w pierwszych _Count elementach sekwencji, której pierwszy element jest wskazywany przez iterator _First, zmienia wartości przechowywane w elementach tej sekwencji na wartości wygenerowane przez obiekt funkcyjny _Gen. 53 54 9

int Fibonacci(void) { static int r; static int f1 = 0; static int f2 = 1; r = f1 + f2 ; f1 = f2 ; f2 = r ; return f1 ; ; // zmienne statyczne // deklarowane są tylko raz int main() { const int VECTOR_SIZE = 8 ; typedef vector<int> IntVector ; typedef IntVector::iterator IntVectorIt ; IntVector Numbers(VECTOR_SIZE) ; IntVectorIt start, end, it ; start = Numbers.begin() ; end = Numbers.end() ; generate(start, end, Fibonacci) ; cout << "Liczby { " ; for(it = start; it!= end; it++) cout << *it << " " ; cout << " \n" << endl ; ; Wyjście: Liczby { 1 1 2 3 5 8 13 21 55 template<typename InputIterator, typename OutputIterator> OutputIterator copy( InputIterator _First, InputIterator _Last, OutputIterator _DestBeg ); Przepisuje wartości elementów z sekwencji źródłowej określanej przez parę iteratorów [_First,_Last) do sekwencji docelowej, której pierwszy element wskazywany jest przez iterator _DestBeg Uwaga: przedziały muszą być poprawnie zdefiniowane, w przedziale docelowym musi być dostatecznie dużo elementów; ponieważ algorytm kopiuje sekwencyjnie zaczynając od pierwszego elementu, przedziały mogą się nakładać ważne, aby element wskazywany przez _First nie należał do przedziału docelowego. 56 template< typename BidirectionalIterator1, typename BidirectionalIterator2> BidirectionalIterator2 copy_backward( BidirectionalIterator1 _First, BidirectionalIterator1 _Last, BidirectionalIterator2 _DestEnd ); przepisuje wartości elementów z sekwencji źródłowej określanej przez parę iteratorów [_First,_Last) do sekwencji docelowej, dla której pierwszy element znajdujący się za ostatnim z sekwencji docelowej wskazywany jest przez iterator _DestEnd Uwaga: wszystkie iteratory muszą być dwukierunkowe; przedziały muszą być poprawnie zdefiniowane, w przedziale docelowym musi być dostatecznie dużo elementów; ponieważ algorytm kopiuje sekwencyjnie zaczynając od pierwszego elementu, przedziały mogą się nakładać ważne, aby element wskazywany przez _First UKSW, WMP. nie SNS, należał Warszawado przedziału docelowego. 57 Aby przesunąć sekwencję elementów np. o jeden w lewo należy użyć copy, natomiast o jeden w prawo copy_backward, np.: string s("abcdefghihklmnopqrstuvwxyz"); vector<char> vector1(s.begin(), s.end()); copy(vector1.begin() + 1, vector1.end(), vector1.begin()); copy_backward(vector1.begin(), vector1.end() - 1, vector1.end()); 58 // std::copy_backward template< typename ForwardIterator1, typename ForwardIterator2> void iter_swap( ForwardIterator1 _Left, ForwardIterator2 _Right ); zamienia miejscami dwie wartości wskazywane przez dwa iteratory. for (int i=1; i<=5; i++) V.push_back(i*10); // V: 10 20 30 40 50 V.resize(V.size()+3); // allocate space for 3 more elements std::copy_backward ( V.begin(), V.begin()+5, V.end() ); std::cout << "V zawiera: "; W oknie konsoli: V zawiera: 10 20 30 10 20 30 40 50 59 60 10

template< typename ForwardIterator1, typename ForwardIterator2> ForwardIterator2 swap_ranges( ForwardIterator1 _First1, ForwardIterator1 _Last1, ForwardIterator2 _First2 ); zamienia miejscami wartości z dwóch zakresów, jeden wskazywany przez parę iteratorów [_First,_Last), a drugi zaczynający się od elementu wskazywanego przez iterator _First2. #include <deque> // std::swap_ranges // std::deque std::vector <int> v1; std::deque <int> d1; for ( int i = 0 ; i <= 5 ; i++ ) v1.push_back( i ); for ( int ii =4 ; ii <= 9 ; ii++ ) d1.push_back( 6 ); std::swap_ranges ( v1.begin ( ), v1.end ( ), d1.begin ( ) ); 61 62 template<class ForwardIterator, class Type> void replace( ForwardIterator _First, ForwardIterator _Last, const Type& _OldVal, const Type& _NewVal ); w sekwencji określanej przez parę iteratorów [_First,_Last) zamienia wszystkie wystąpienia wartości _OldVal wartością _NewVal. // std::replace int myt[] = { 10, 20, 30, 30, 20, 10, 10, 20 ; std::vector<int> V(myT, myt+8); // 10 20 30 30 20 10 10 20 std::replace (V.begin(), V.end(), 20, 99); // 10 99 30 30 99 10 10 99 63 64 template<class ForwardIterator, class Predicate, class Type> void replace_if( ForwardIterator _First, ForwardIterator _Last, Predicate _Pred, const Type& _Val ); w sekwencji określanej przez parę iteratorów [_First,_Last) zamienia wszystkie elementy spełniające predykat _Pred wartością _NewVal. // std::replace_if bool Nieparzysty (int i) { return ((i%2)==1); for (int i=1; i<10; i++) V.push_back(i); // 1 2 3 4 5 6 7 8 9 std::replace_if (V.begin(), V.end(), Nieparzysty, 0); // 0 2 0 4 0 6 0 8 0 65 66 11

template<class InputIterator, class OutputIterator, class Type> OutputIterator replace_copy( InputIterator _First, InputIterator _Last, OutputIterator _Result, const Type& _OldVal, const Type& _NewVal ); z sekwencji określanej przez parę iteratorów [_First,_Last) kopiuje do sekwencji, której pierwszy element jest wskazywany przez _Result, wszystkie elementy, ale po drodze zamienia elementy o wartości _OldVal elementami o wartości _NewVal // std::replace_copy int myt[] = { 10, 20, 30, 30, 20, 10, 10, 20 ; std::vector<int> V(8); std::replace_copy (myt, myt+8, V.begin(), 20, 99); 67 68 template<class InputIterator, class OutputIterator, class Predicate, class Type> OutputIterator replace_copy_if( InputIterator _First, InputIterator _Last, OutputIterator _Result, Predicate _Pred, const Type& _Val ); z sekwencji określanej przez parę iteratorów [_First,_Last) kopiuje do sekwencji, której pierwszy element jest wskazywany przez _Result, wszystkie elementy, ale po drodze zamienia elementy spełniające predykat _Pred wartością _NewVal. 69 // std::replace_copy_if bool Nieparzysty (int i) { return ((i%2)==1); std::vector<int> V, W; for (int i=1; i<10; i++) V.push_back(i); // 1 2 3 4 5 6 7 8 9 W.resize(V.size()); // allocate space std::replace_copy_if (V.begin(), V.end(), W.begin(), Nieparzysty, 0); // 0 2 0 4 0 6 0 8 0 std::cout << "W zawiera:"; for (std::vector<int>::iterator it=w.begin(); it!=w.end(); ++it) 70 template<class InputIterator, class OutputIterator> OutputIterator unique_copy( InputIterator _First, InputIterator _Last, OutputIterator _Result ); z sekwencji określanej przez parę iteratorów [_First,_Last) kopiuje do sekwencji, której pierwszy element jest wskazywany przez _Result, wartości bez powtórzeń, tj. tak, aby każda wartość w sekwencji wynikowej była unikalna (występowała w niej tylko raz), występuje w dwóch wersjach druga z dodatkowym, ostatnim argumentem szablonu reprezentującym obiekt funkcyjny/funkcję służący do porównań. // std::unique_copy, std::sort, std::distance int myt[] = {10,20,20,20,30,30,20,20,10; std::vector<int> V (9); // V: 0 0 0 0 0 0 0 0 0 std::vector<int>::iterator it; it=std::unique_copy (myt,myt+9,v.begin()); // V: 10 20 30 20 10 0 0 0 0 // ^ for (it=v.begin(); it!=v.end(); ++it) 71 72 12

// std::unique_copy, std::sort, std::distance bool myfunction (int i, int j) { return (i==j); ; int myt[] = {10,20,20,20,30,30,20,20,10; std::vector<int> V (9); // V: 0 0 0 0 0 0 0 0 0 std::vector<int>::iterator it; it=std::unique_copy (myt,myt+9,v.begin(), myfunction); // V: 10 20 30 20 10 0 0 0 0 // ^ for (it=v.begin(); it!=v.end(); ++it) template<class BidirectionalIterator> void reverse( BidirectionalIterator _First, BidirectionalIterator _Last ); odwraca kolejność elementów w sekwencji określanej przez parę iteratorów [_First,_Last). 73 74 // std::reverse for (int i=1; i<10; ++i) V.push_back(i); // 1 2 3 4 5 6 7 8 9 std::reverse(v.begin(),v.end()); // 9 8 7 6 5 4 3 2 1 template<class BidirectionalIterator, class OutputIterator> OutputIterator reverse_copy( BidirectionalIterator _First, BidirectionalIterator _Last, OutputIterator _Result ); z sekwencji określanej przez parę iteratorów [_First,_Last) kopiuje do sekwencji, której pierwszy element jest wskazywany przez _Result, wszystkie elementy ale w odwrotnej kolejności. 75 76 int myt[] ={1,2,3,4,5,6,7,8,9; // std::reverse_copy V.resize(9); // allocate space std::reverse_copy (myt, myt+9, V.begin()); template<class ForwardIterator> void rotate( ForwardIterator _First, ForwardIterator _Middle, ForwardIterator _Last ); obraca elementy w sekwencji określanej przez parę iteratorów [_First,_Last) zamieniając lewą i prawą połowę elementów sekwencji miejscami, przy czym iterator _Middle wskazuje środek. std::cout << "V contains:"; 77 78 13

// std::rotate for (int i=1; i<10; ++i) V.push_back(i); // 1 2 3 4 5 6 7 8 9 std::rotate(v.begin(),v.begin()+3,v.end()); // 4 5 6 7 8 9 1 2 3 template<class ForwardIterator, class OutputIterator> OutputIterator rotate_copy( ForwardIterator _First, ForwardIterator _Middle, ForwardIterator _Last, OutputIterator _Result ); do sekwencji wskazywanej przez _Result kopiuje elementy z sekwencji określanej przez parę iteratorów [_First,_Last) w innym porządku, tj. zamieniając lewą i prawą połowę elementów sekwencji miejscami, przy czym iterator _Middle wskazuje środek. 79 80 // std::rotate_copy int myints[] = {10,20,30,40,50,60,70; std::vector<int> V (7); std::rotate_copy(myints,myints+3,myints+7,v.begin()); template <class RandomAccessIterator, class RandomNumberGenerator> void random_shuffle ( RandomAccessIterator first, RandomAccessIterator last); template <class RandomAccessIterator, class RandomNumberGenerator> void random_shuffle ( RandomAccessIterator first, RandomAccessIterator last, RandomNumberGenerator& rand ) miesza kolejność elementów w sekwencji. 81 82 // std::random_shuffle Jak miesza random_shuffle #include <ctime> // std::time #include <cstdlib> // std::rand, std::srand int myrandom (int i) { return std::rand()%i; std::srand ( unsigned ( std::time(0) ) ); for (int i=1; i<10; ++i) V.push_back(i); // 1 2 3 4 5 6 7 8 9 std::random_shuffle ( V.begin(), V.end() ); std::random_shuffle ( V.begin(), V.end(), myrandom); template <class RandomAccessIterator, class RandomNumberGenerator> void random_shuffle ( RandomAccessIterator first, RandomAccessIterator last, RandomNumberGenerator& gen) { iterator_traits<randomaccessiterator>::difference_type i, n; n = (last-first); for (i=n-1; i>0; --i) { swap (first[i],first[gen(i+1)]); 83 84 14

template < class InputIterator, class OutputIterator, class UnaryOperator > OutputIterator transform ( InputIterator first1, InputIterator last1, OutputIterator result, UnaryOperator op ) modyfikuje elementy z sekwencji operatorem jednoargumentowym i wynik modyfikacji zapisuje do innej sekwencji. 85 // std::transform int op_increase (int i) { return ++i; std::vector<int> W; for (int i=1; i<6; i++) V.push_back (i*10); // V: 10 20 30 40 50 W.resize(V.size()); // allocate space std::transform (V.begin(), V.end(), W.begin(), op_increase); // W: 11 21 31 41 51 std::cout << W zawiera:"; for (std::vector<int>::iterator it=w.begin(); it!=w.end(); ++it) 86 template<class InputIterator1, class InputIterator2, class OutputIterator, class BinaryFunction> OutputIterator transform( InputIterator1 _First1, InputIterator1 _Last1, InputIterator2 _First2, OutputIterator _Result, BinaryFunction _Func ); transformuje elementy pochodzące z dwóch sekwencji operatorem dwuargumentowym, pierwsza sekwencja jest wskazywana przez iteratory [_First1, _Last1), drugiej pierwszy element jest wskazywany przez iterator _First2, wynik zapisywany jest do sekwencji, której pierwszy element jest wskazywany przez _Result, natomiast obiekt funkcyjny jest wskazywany przez _Func. 87 // std::transform #include <functional> // std::plus int op_increase (int i) { return ++i; std::vector<int> W; for (int i=1; i<6; i++) V.push_back (i*10); // V: 10 20 30 40 50 W.resize(V.size()); // allocate space std::transform (V.begin(), V.end(), W.begin(), op_increase); // W: 11 21 31 41 51 // std::plus adds together its two arguments: std::transform (V.begin(), V.end(), W.begin(), V.begin(), std::plus<int>()); // V: 21 41 61 81 101 88 Podsumowanie: 1. fill, 2. fill_n, 3. generate, 4. generate_n, 5. copy, 6. copy_backward, 7. swap, 8. swap_ranges, 9. replace, 10.replace_if, 11.replace_copy, 12.replace_copy_if, 13.unique_copy, 14.reverse_copy, 15.rotate, 16.rotate_copy, 17.random_shuffle, 18.transform 89 15