Metody i języki programowania II

Podobne dokumenty
obiekty funkcyjne - funktory

Programowanie i struktury danych

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

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

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

STL Standardt Template Library (wprowadzenie)

Zaawansowane programowanie w C++ (PCP)

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

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

Zaawansowane programowanie w języku C++ Biblioteka standardowa

Biblioteka standardowa C++

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

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

Paradygmaty programowania

STL: Lekcja 1&2. Filozofia STL

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.

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

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

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

Kurs programowania. Wykład 9. Wojciech Macyna

Kontenery i iteratory. Wykorzystanie kontenerów w praktyce.

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

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

Algorytmy w C++ dla opornych!

Szablon klasy std::vector

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

Zaawansowane programowanie w C++ (PCP)

Język C++ wykład VIII

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

Języki Programowania. Prowadząca: dr inż. Hanna Zbroszczyk. tel: Konsultacje: piątek:

Operatory na rzecz typu TString

10.1 Szablony Szablony funkcji Szablony klas Szablony jako wstęp do biblioteki STL... 10

Podstawy Programowania

Szablony klas, zastosowanie szablonów w programach

Szablony funkcji i szablony klas

Programowanie w języku Java. Kolekcje

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

Strona główna. Strona tytułowa. Programowanie. Spis treści. Sobera Jolanta Strona 1 z 26. Powrót. Full Screen. Zamknij.

Klasy generyczne. ZbiórLiczb. ZbiórCzegokolwiek. Zbiór

Programowanie współbieżne i rozproszone

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

Język ludzki kod maszynowy

C++ Przeładowanie operatorów i wzorce w klasach

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

Szablony funkcji i klas (templates)

Paradygmaty programowania. Paradygmaty programowania

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

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

Podstawy programowania skrót z wykładów:

Algorytmy i Struktury Danych. Anna Paszyńska

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

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

Paradygmaty programowania

PARADYGMATY PROGRAMOWANIA Wykład 4

Szablony. Szablony funkcji

W przypadku STL w specyfikacji nazwy pliku nagłówkowego brak rozszerzenia tj. <string> <string.h> zamiast

1. Wartość, jaką odczytuje się z obszaru przydzielonego obiektowi to: a) I - wartość b) definicja obiektu c) typ oboektu d) p - wartość

Wprowadzenie do szablonów szablony funkcji

Programowanie w języku C++

Wykład 4. Klasa List Kolejki Stosy Słowniki

PARADYGMATY PROGRAMOWANIA Wykład 3

STL Standard Template Library

Wprowadzenie do szablonów szablony funkcji

Lista, Stos, Kolejka, Tablica Asocjacyjna

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

Kiedy potrzebne. Struktura (rekord) Struktura w języku C# Tablice struktur. struktura, kolekcja

Kompletna dokumentacja kontenera C++ vector w -

Biblioteka STL - wstęp. Biblioteka STL - literatura. Biblioteka STL - przegląd. Biblioteka STL - kwestie techniczne

Algorytmy, iteratory, kolekcje niestandardowe

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

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.

Szablon klasy std::list

Kontenery. Wykład 12. Programowanie (język C++) Rodzaje kontenerów. Przegląd kontenerów

Zaawansowane programowanie w języku C++ Funkcje uogólnione - wzorce

Struktury. Przykład W8_1

Język C++ część 9 szablony klas. Jarosław Gramacki Instytut Informatyki i Elektroniki. szablony funkcji

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

Wzorce funkcji (szablony)

Zaawansowane programowanie w C++ (PCP)

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

Programowanie obiektowe Wykład 3. Dariusz Wardowski. dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 1/21

Programowanie w C++ Wykład 14. Katarzyna Grzelak. 3 czerwca K.Grzelak (Wykład 14) Programowanie w C++ 1 / 27

Programowanie Komponentowe Zarządzanie obiektami: kontenery

Wyliczanie wyrażenia obiekty tymczasowe

Programowanie obiektowe w C++ Wykład 11

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

Operacje wejścia/wyjścia (odsłona druga) - pliki

dr inż. Jarosław Forenc

Algorytmy i złożoności. Wykład 3. Listy jednokierunkowe

Ćwiczenia IV - Kontenery (pojemniki)

MATERIAŁY DO ZAJĘĆ II

Wprowadzenie do szablonów klas

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

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

Stos liczb całkowitych

Temat 1: Podstawowe pojęcia: program, kompilacja, kod

Krótkie wprowadzenie do STL. XIV LO im. S. Staszica, K06 D

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

Programowanie obiektowe - Przykładowe zadania egzaminacyjne (2005/2006)

Transkrypt:

Metody i języki programowania II dr inż. Grzegorz Szwarc mgr inż. Andrzej Grosser agrosser@icis.pcz.pl Instytut Informatyki Teoretycznej i Stosowanej

Wstęp Ramowy program zajęć Wzorce funkcji i klas Biblioteka standardowa wzorców Literatura podstawowa Podstawy języka C++, S. B. Lippman, J. Lajoie, Wydawnictwa Naukowo Techniczne, Warszawa, 2003 Język C++, B. Stroustrup, Wydawnictwa Naukowo Techniczne, Warszawa, 2002 Literatura uzupełniaj aca C++. Biblioteka standardowa, N. M. Josuttis, Wydawnictwo Helion, Warszawa, 2003 C++. Szablony. Vademecum profesjonalisty, D. Vandevoorde, N. M. Josuttis, Wydawnictwo Helion, Warszawa, 2003 Dokumentacja STL, https://icis.pcz.pl/docs/stl/index.html C++ bez cholesterolu, http://www.intercon.pl/~sektor/cbx/ g.szwarc mijp-ii - p. 2/114

Wzorce funkcji Wzorce funkcji mechanizm języka służacy do automatycznego generowania (na podstawie ogólnego opisu) wersji konkretnych funkcji, różniacych się typem; wymagane jest określenie parametrów wszystkich lub niektórych typów (argumentów formalnych i wartości przekazywanej) w interfejsie do danej funkcji, której treść pozostaje niezmieniona; deklarację oraz definicję wzorca funkcji poprzedza słowo kluczowe template wraz lista parametrów wzorca ujęta w nawiasy katowe; konkretyzowanie wzorca funkcji odbywa się podczas wywołania funkcji lub pobrania adresu funkcji int max(int a, int b) { return a > b? a : b; } int x = 8, y = 4; double dx = 10.5, dy = 10.0; cout << max(x, y); // 8 cout << max(dx, dy); // 10 double max(double a, double b) { return a > b? a : b; } cout << max(x, y); // 8 cout << max(dx, dy); // 10.5 string sx("alicja"), sy("kot"); cout << max(sx, sy); //???? g.szwarc mijp-ii - p. 3/114

Wzorce funkcji template<typename Typ> Typ max(typ a, Typ b) { return a > b? a : b; } int x = 8, y = 4; double dx = 10.5, dy = 10.0; cout << max(x, y); // 8 cout << max(dx, dy); // 10.5 string sx("alicja"), sy("kot"); cout << max(sx, sy); // Kot g.szwarc mijp-ii - p. 4/114

Wzorce funkcji class A { public: A(const string& p) : p_(p) {} A(const char* p) : p_(p) {} bool operator > (const A& a) const { return count(p_) > count(a.p_); } protected: string p_; int count(const string& s) const; friend ostream& operator << (ostream& os, const A& a); }; g.szwarc mijp-ii - p. 5/114

Wzorce funkcji int A::count(const string& s) const { int tmp = 0; for (int i = 0; i < s.size(); ++i) tmp += s[i]; return tmp; } ostream& operator << (ostream& os, const A& a) { return os << a.p_; } template<typename T> T max(const T& a, const T& b) { return a > b? a : b; } string sx("alicja"), sy("kot"); cout << max(sx, sy); // Kot A ax(sx), ay(sy); cout << max(ax, ay); // Alicja g.szwarc mijp-ii - p. 6/114

Wzorce funkcji Parametr wzorca określenie nazwy typu (parametr typu) zaczyna się od słowa kluczowego typename (dawniej class); parametr wzorca będacy zwykła deklaracja argumentu formalnego (parametr nietypu) reprezentuje pewna (całkowita) wartość stała; nie ma ograniczeń na liczbę parametrów wzorca i liczbę wystapień parametru na liście argumentów formalnych funkcji Poprawne deklaracje wzorca funkcji template<class T> T name(t, T, T); template<class T> void name(t, double); template<typename T> T name(t, T, T); template<class T, class U, typename P> P name(t, U); template<class T> const T& name(const T&, T*); template<class T> inline T name(t, int, T); typedef double U; template<typename U> U name(u*, int); Nieoprawne deklaracje wzorca funkcji template<typename T, class T> T name(t, T, T); inline template<class T> T name(t, int, T); template<typename T, U> T name(u, U); g.szwarc mijp-ii - p. 7/114

Wzorce funkcji template<typename U, int size> U max(u (&tab)[size]) { U tmp = tab[0]; for (int i = 1; i < size; ++i) if (tab[i] > tmp) tmp = tab[i]; return tmp; } int tabi[] = {3, 5, 1, 4}; cout << max(tabi); // 5 int tabi2[] = {30, 52, 31, 64, 21}; cout << max(tabi2); // 64 string tabs[] = {"Ala", "ma", "kota"}; cout << max(tabs); // ma A taba[] = {"Ala", "ma", "kota"}; cout << max(taba); // kota g.szwarc mijp-ii - p. 8/114

Wzorce funkcji Jawne argumenty wzorców funkcji unikanie dedukcji argumentów wzorca funkcji; dopuszczenie niejawnego przekształcenia typu argumentów aktualnych; cout << max(10, 20.0); // błąd cout << max<double>(10, 20.0); const char* a1 = "Kot"; const char* a2 = "Alicja"; string s1(a1), s2(a2); cout << max(s1, s2); // Kot cout << max(a1, a2); // Alicja cout << max<string>(a1, a2); // Kot g.szwarc mijp-ii - p. 9/114

Wzorce funkcji Jawna specjalizacja wzorców funkcji możliwość wykorzystania specjalnej właściwości typu do zaprogramowania wydajniejszej wersji algorytmu; ominięcie nieodpowiedniej wersji algorytmu generowanego z ogólnego wzorca; template<> const char* max<const char*> (const char* const& a, const char* const& b) { return strcmp(a, b) > 0? a : b; } const char* a1 = "Kot"; const char* a2 = "Alicja"; string s1(a1), s2(a2); cout << max(s1, s2) // Kot cout << max(a1, a2) // Kot Materiał do samodzielnego opanowania Przeciażanie wzorców funkcji g.szwarc mijp-ii - p. 10/114

Wzorce klas Wzorzec klasy mechanizm automagicznego generowania klas zwiazanych z konkretnym typem danych; zasady tworzenia analogiczne jak dla wzorców funkcji; konkretyzowanie wzorca klasy generowanie klasy na podstawie wzorca klasy; brak zwiazków między wersjami klasy skonkretyzowanymi dla różnych parametrów; w nazwie skonkretyzowanej klasy musza być jawnie specyfikowane argumenty wzorca g.szwarc mijp-ii - p. 11/114

Wzorce klas class Stosik { public: Stosik() : pozycja(-1) {} void dodaj(const int& elem); void zdejmij() { if (!pusty()) --pozycja; } bool pelny() { return pozycja == 2; } bool pusty() { return pozycja < 0; } const int& element() const { return pusty()? wartosci[0] : wartosci[pozycja]; } protected: int wartosci[3]; int pozycja; }; g.szwarc mijp-ii - p. 12/114

Wzorce klas void Stosik::dodaj(const int& elem) { if (!pelny()) wartosci[++pozycja] = elem; } Stosik k; int i = 1; while (!k.pelny()) { k.dodaj(2*i+1); cout << k.element() << ; // 3 5 7 ++i; } while (!k.pusty()) { cout << k.element() << ; // 7 5 3 k.zdejmij(); } g.szwarc mijp-ii - p. 13/114

Wzorce klas template<typename T = int, int ile = 3> class Stosik { public: Stosik() : pozycja(-1) {} void dodaj(const T& elem); void zdejmij() { if (!pusty()) --pozycja; } bool pelny() { return pozycja == (ile - 1); } bool pusty() { return pozycja < 0; } const T& element() { return pusty()? wartosci[0] : wartosci[pozycja]; } protected: T wartosci[ile]; int pozycja; }; g.szwarc mijp-ii - p. 14/114

Wzorce klas template<typename T, int ile> void Stosik<T, ile>::dodaj(const T& elem) { if (!pelny()) wartosci[++pozycja] = elem; } int i = 1; Stosik<double, 4> sd; while (!sd.pelny()) { sd.dodaj(3*(i++)/2.0); cout << sd.element() << ; // 1.5 3 4.5 6 } while (!sd.pusty()) { cout << sd.element() << ; // 6 4.5 3 1.5 sd.zdejmij(); } g.szwarc mijp-ii - p. 15/114

Wzorce klas Stosik<string> ss; ss.dodaj("ala"); ss.dodaj("ma"); ss.dodaj("koty"); ss.dodaj("dwa"); while (!ss.pusty()) { cout << ss.element() << ; // koty ma ala ss.zdejmij(); } Stosik<> si; i = 0; while (!si.pelny()) { si.dodaj(2*(i++)+1); cout << si.element() << ; // 1 3 5 } g.szwarc mijp-ii - p. 16/114

Wzorce klas enum wymiar {d1 = 1, d2, d3}; template<wymiar d, typename U = float> class Punkt { public: typedef U wsp; Punkt(); Punkt(int nr, U (&x)[d] ); U& x(int i) { assert(i>-1 && i < d); return x_[i]; } int& nr() { return nr_; } protected: U x_[d]; int nr_; template<wymiar w, typename T> friend ostream& operator << (ostream& os, const Punkt<w, T>& p); }; g.szwarc mijp-ii - p. 17/114

Wzorce klas template<wymiar d, typename U> Punkt<d, U>::Punkt() : nr_(0) { for (int i = 0; i < d; ++i) x_[i] = 0; } template<wymiar d, typename U> Punkt<d, U>::Punkt(int nr, U (&x)[d] ) : nr_(nr) { for (int i = 0; i < d; ++i) x_[i] = x[i]; } template<wymiar d, typename U> ostream& operator << (ostream& os, const Punkt<d, U>& p) { os << p.nr_ << ; for (int i = 0; i < d; ++i) os << p.x_[i] << ; return os; } g.szwarc mijp-ii - p. 18/114

Wzorce klas Stosik<Punkt<d2> > sp; for (int i = 0; i < 5; ++i) { Punkt<d2> t; t.nr() = i; t.x(0) = i/2.0; t.x(1) = i/3.0; sp.dodaj(t); } while (!sp.pusty()) { cout << sp.element() << \n ; sp.zdejmij(); } // 2 1 0.666667 // 1 0.5 0.333333 // 0 0 0 g.szwarc mijp-ii - p. 19/114

Wzorce klas Pola statyczne wzorców klas pole statyczne wzorca klasy jest też wzorcem; z każda skonkretyzowana wersja klasy jest zwiazany jej własny zbiór pól statycznych (jeśli takie były deklarowane); definicja pól statycznych musi występować na zewnatrz definicji wzorca klasy template<typename T> class A { public: A(T p) : p0(p) { --p1; ++p2; } void pokaz(t p) { cout << p << << p0 << << p1 << << p2 << \n ; } protected: T p0; static T p1; static int p2; }; g.szwarc mijp-ii - p. 20/114

Wzorce klas template<typename T> T A<T>::p1 = 20; // ograniczenie template<typename T> int A<T>::p2 = 0; A<double> d1(1); d1.pokaz(2); // 2 1 19 1 A<double> d2(3); d2.pokaz(4); // 4 3 18 2 A<int> i1(5); i1.pokaz(6); // 6 5 19 1 A<int> i2(7); i2.pokaz(8); // 8 7 18 2 A<string> s("ala"); //błąd g.szwarc mijp-ii - p. 21/114

Dziedziczenie a wzorce klas BazT < > PochT template<typename T> class BazT { public: BazT(T a) : p0(a) { } virtual void pokaz() { cout << p0 << \n ; } protected: T p0; }; PochT<int> i(1, 2); BazT<int>* wi = &i; wi->pokaz(); // 1 2 PochT<char> c( a, b ); wi = &c; //błąd template<typename T> class PochT : public BazT<T> { public: PochT(T a0, T a1) : BazT<T>(a0), p1(a1) { } void pokaz() { cout << this->p0 << << p1 << \n ; } protected: T p1; }; g.szwarc mijp-ii - p. 22/114

Dziedziczenie a wzorce klas BazT < > Poch template<typename T> class BazT { public: BazT(T a) : p0(a) { } virtual void pokaz() { cout << p0 << \n ; } protected: T p0; }; Poch d(3,4); BazT<double>* wd = &d; wd->pokaz(); // 3 4 BazT<int>* wii = &d; // błąd class Poch : public BazT<double> { public: Poch(double a0, double a1) : BazT<double>(a0), p1(a1) { } void pokaz() { cout << p0 << << p1 << \n ; } protected: double p1; }; g.szwarc mijp-ii - p. 23/114

Dziedziczenie a wzorce klas Baz < > PochT class Baz { public: Baz(int a) : p0(a) {} virtual void pokaz() { cout << p0 << \n ; } protected: int p0; }; PochT<char> a(2, a ); Baz* wb = &a; wb->pokaz(); // 2 a PochT<float> f(4, 3.14); wb = &f; wb->pokaz(); // 4 3.14 template<typename T> class PochT : public Baz { public: PochT(int a0, T a1) : Baz(a0), p1(a1) { } void pokaz() { cout << p0 << << p1 << \n ; } protected: T p1; }; g.szwarc mijp-ii - p. 24/114

Pole składowe klasy Składowa klasy utworzona ze wzorca klasy template<typename T> class Sklad { public: Sklad(T a) : p0(a) {} void pokaz() { cout << p0 << ; } protected: T p0; }; class Calosc { public: Calosc(int i, float f) : pi(i), pf(f) { } void pokaz() { pi.pokaz(); pf.pokaz(); } protected: Sklad<int> pi; Sklad<float> pf; }; Calosc c(2, 3.14); c.pokaz(); // 2 3.14 g.szwarc mijp-ii - p. 25/114

Pole składowe klasy template<typename T, typename U> class CaloscT { public: CaloscT(T i, U f, char c) : pi(i), pf(f), pc(c) { } void pokaz() { pi.pokaz(); pf.pokaz(); pc.pokaz(); } protected: Sklad<T> pi; Sklad<U> pf; Sklad<char> pc; }; CaloscT<float, int> ct(3.14, 2, a ); ct.pokaz(); // 3.14 2 a g.szwarc mijp-ii - p. 26/114

Jawna specjalizacja wzorca klasy Specjalizacja wzorców klas template<typename T> class Jakas { public: Jakas(T a) : p0(new T(a)) { } ~Jakas() { delete p0; } void pokaz() { cout << "ogólny " << *p0 << \n ; } Jakas(const Jakas<T>& j) : p0(new T(*j.p0)) { } const Jakas<T>& operator = (const Jakas<T>& j) { *p0 = *j.p0; return *this; } protected: T* p0; }; g.szwarc mijp-ii - p. 27/114

Specjalizacja wzorców klas Jakas<int> i(2); i.pokaz(); // ogólny 2 Jakas<string> s("ala"); s.pokaz(); // ogólny Ala Jakas<char> c( B ); c.pokaz(); // ogólny B char kot[10] = "Kot"; Jakas<char*> tc(kot); tc.pokaz(); // ogólny Kot strcpy(kot, "Pies"); tc.pokaz(); // ogólny Pies g.szwarc mijp-ii - p. 28/114

Specjalizacja wzorców klas template<> class Jakas<char*> { public: Jakas(char* a) : p0(new char[strlen(a)+1]) { strcpy(p0, a); } ~Jakas() { delete [] p0; } void pokaz() { cout << "specjalny " << p0 << \n ; } Jakas(const Jakas<char*>& j) : p0(new char[strlen(j.p0)+1]) { strcpy(p0, j.p0); } const Jakas<char*>& operator = (const Jakas<char*>& j) { if (this == &j) return *this; delete [] p0; p0 = new char[strlen(j.p0)+1]; strcpy(p0, j.p0); return *this; } protected: char* p0; }; g.szwarc mijp-ii - p. 29/114

Częściowa specjalizacja wzorca klasy template<typename T, int ile> class Stosik<T*, ile> { public: Stosik() : pozycja(-1) {} ~Stosik(); void dodaj(const T& elem); void dodaj(t* elem); void zdejmij(); bool pelny() { return pozycja == (ile - 1); } bool pusty() { return pozycja < 0; } const T& element(); protected: T* wartosci[ile]; int pozycja; }; Specjalizacja wzorców klas g.szwarc mijp-ii - p. 30/114

Specjalizacja wzorców klas template<typename T, int ile> const T& Stosik<T*, ile>::element() { return pusty()? *wartosci[0] : *wartosci[pozycja]; } template<typename T, int ile> Stosik<T*, ile>::~stosik() { while (!pusty()) zdejmij(); } template<typename T, int ile> void Stosik<T*, ile>::dodaj(const T& elem) { if (!pelny()) wartosci[++pozycja] = new T(elem); } template<typename T, int ile> void Stosik<T*, ile>::dodaj(t* elem) { if (!pelny()) wartosci[++pozycja] = elem; } template<typename T, int ile> void Stosik<T*, ile>::zdejmij() { if (!pusty()) delete wartosci[pozycja--]; } g.szwarc mijp-ii - p. 31/114

Specjalizacja wzorców klas typedef Punkt<d2, double> Punkt2D; Stosik<Punkt2D*, 6> sp1; for (int i = 0; i < 5; ++i) { Punkt2D t; t.nr() = i; t.x(0) = i/2.0; t.x(1) = i/3.0; sp1.dodaj(t); } Stosik<Punkt2D*, 6> sp0; for (int i = 0; i < 5; ++i) { Punkt2D::wsp t[d2] = {i/2.0, i/3.0}; sp0.dodaj(new Punkt2D(i, t)); } g.szwarc mijp-ii - p. 32/114

Materiał do samodzielnego opanowania (nieobowi azkowe) Typy zagnieżdżone we wzorcach klas Rozstrzyganie znaczenia nazw we wzorcach klas Wzorce klas w przestrzeniach nazw Deklaracje zaprzyjaźnienia w wzorcach klas Jawna deklaracja konkretyzowania wzorców Modele kompilacji wzorców (inkluzywny i separatywny) Wzorce klas g.szwarc mijp-ii - p. 33/114

Elementy STL Standardowa biblioteka wzorców Standard Template Library (STL) zasobniki iteratory algorytmy obiekty funkcji Zasobniki kolekcje, zbiorniki, kontenery sekwencyjne porzadkowe, liniowe, ciagi vector wektor; szybkie wstawianie i usuwanie na końcu; bezpośredni dostęp do dowolnego elementu deque kolejka dwustronna; szybkie wstawianie i usuwanie na poczatku i końcu; bezpośredni dostęp do dowolnego elementu list szybkie wstawianie i usuwanie w dowolnym miejscu; brak bezpośredniego dostępu do dowolnego elementu g.szwarc mijp-ii - p. 34/114

Zasobniki asocjatywne skojarzeniowe set zbiór; duplikaty zabronione multiset wielozbiór; duplikaty dozwolone map słownik; duplikaty zabronione multimap wielosłownik; duplikaty dozwolone adaptery łaczniki stack stos; LIFO queue kolejka; FIFO priority_queue kolejka priorytetowa; element o najwyższym priorytecie jest zawsze pierwszym elementem do wyjścia g.szwarc mijp-ii - p. 35/114

Zasobniki Metody wspólne dla wszystkich zasobników empty zwraca prawdę, jeśli zasobnik jest pusty max_size zwraca maksymalna liczbę elementów dla zasobnika size zwraca bieżac a liczbę elementów operator= przypisanie zasobników operator<, operator<=, operator>, operator>=, operator==, operator!= zwraca prawdę, jeśli relacja między zasobnikami jest spełniona (nieobsługiwane przez priority_queue) swap wymienia elementy dwóch zasobników erase usuwa jeden lub więcej elementów zasobnika clear usuwa wszystkie elementy zasobnika g.szwarc mijp-ii - p. 36/114

Zasobniki begin zwraca iterator lub const_iterator, które odwołuja się do pierwszego elementu zasobnika end zwraca iterator lub const_iterator, które odwołuja się do następnej pozycji po ostatnim elemencie zasobnika; element za ostatni rbegin zwraca reverse_iterator lub const_reverse_iterator, które odwołuja się do ostatniego elementu w zasobniku rend zwraca reverse_iterator lub const_reverse_iterator, które odwołuja się do pozycji zasobnika znajdujacej przed pierwszym elementem zasobnika; element przed pierwszy g.szwarc mijp-ii - p. 37/114

Zasobniki Definicje typedef wspólne dla zasobników sekwencyjnych i asocjatywnych value_type typ elementu przechowywanego w zasobniku reference typ referencji do elementu przechowywanego w zasobniku const_reference typ referencji do stałego elementu przechowywanego w zasobniku pointer typ wskaźnika do elementu przechowywanego w zasobniku iterator iterator, który wskazuje na element przechowywany w zasobniku const_iterator iterator, który wskazuje na element przechowywany w zasobniku; tylko do odczytu reverse_iterator odwrotny iterator, który wskazuje na element przechowywany w zasobniku const_reverse_iterator odwrotny iterator, który wskazuje na element przechowywany w zasobniku; tylko do odczytu size_type typ używany do liczenia pozycji i indeksowania w zasobnikach sekwencyjnych (nie ma indeksacji dla list) g.szwarc mijp-ii - p. 38/114

Iteratory Iterator uogólniony wskaźnik; używany (przede wszystkim) do wskazywania na elementy zasobników sekwencyjnych i asocjatywnych; arytmetyka iteratorów zgodna z arytmetyka wskaźników; dostęp do wartości wskazywanej przez iterator przez operator dereferencji Hierarchia iteratorów input output տ ր forward bidirectional random access g.szwarc mijp-ii - p. 39/114

Iteratory wejściowy (input) odczytywanie elementu z zasobnika; przesuwanie tylko do przodu o jeden element; użyteczny dla algorytmów jedno-przejściowych wyjściowy (output) zapis elementu do zasobnika; przesuwanie tylko do przodu o jeden element; użyteczny dla algorytmów jedno-przejściowych do przodu (forward) odczytywanie i zapisywanie elementu w zasobniku; przesuwanie tylko do przodu o jeden element; użyteczny dla algorytmów wielo-przejściowych dwukierunkowy (bidirectional) łaczy możliwości iteratora do przodu z możliwościa poruszania się o jedna pozycję w kierunku wstecznym o dostępie bezpośrednim (random access) łaczy możliwości iteratora dwukierunkowego z możliwościa poruszania się o dowolna liczbę pozycji w obu kierunkach; dostęp do dowolnego elementu g.szwarc mijp-ii - p. 40/114

Iteratory Typy iteratorów obsługiwane przez zasobniki o dostępie bezpośrednim - vector, deque dwukierunkowy - list, set, multiset, map, multimap brak obsługi iteratorów - stack, queue, proirity_queue Działania na iteratorze iterator wejściowy ++p, p++ pre- i postinkrementacja *p p-wartość elementu wskazywanego iteratorem p = p1 przypisanie wartości innego iteratora p == p1 porównanie iteratorów pod względem równości p!= p1 porównanie iteratorów pod względem nierówności iterator wyjściowy ++p, p++ pre- i postinkrementacja *p l-wartość elementu wskazywanego iteratorem p = p1 przypisanie wartości innego iteratora g.szwarc mijp-ii - p. 41/114

Iteratory iterator do przodu pełna funkcjonalność iteratora wyjściowego i wejściowego iterator dwukierunkowy pełna funkcjonalność iteratora do przodu oraz --p, p-- pre- i postdekrementacja iterator o dostępie bezpośrednim pełna funkcjonalność iteratora dwukierunkowego oraz p += i, p -= i inkrementacja i dekrementacja iteratora o i pozycji p + i, p - i w wyniku daje iterator przesunięty o i pozycji (p pozostaje nie zmienione) p[i] w wyniku daje referencję do elementu umieszczonego na pozycji p przesuniętej o i p < p1, p <= p1, p > p1, p >= p1 w wyniku zwraca prawdę gdy dana relacja jest spełniona g.szwarc mijp-ii - p. 42/114

Iteratory Kierunek inkrementacji oraz wyłuskiwanie predefiniowanych iteratorów dla zasobników sekwencyjnych i asocjatywnych iterator do przodu odczyt/zapis const_iterator do przodu odczyt reverse_iterator do tyłu odczyt/zapis const_reverse_iterator do tyłu odczyt Iterator strumienia strumień jako zasobnik istream_iterator dla strumienia wejściowego ostream_iterator dla strumienia wyjściowego // co robi ten program? istream_iterator<int> ii(cin); int l = *ii++; ostream_iterator<int> io(cout); *io = l + *ii; g.szwarc mijp-ii - p. 43/114

Iteratory Iteratory wstawiajace adaptery iteratorów specjalizowane iteratorem zasobnika; nie używa się ich bezpośrednio, lecz za pomoca pomocniczych funkcji back_inserter() w miejscu operatora przypisania następuje wywołanie operacji stawiajacej push_back() int t[] = {1, 2, 3}; list<int> v(2, 5); ostream_iterator<int> io(cout, " "); // copy(t, t+3, v.end()); // błąd copy(t, t+3, back_inserter(v)); copy(v.begin(), v.end(), io); // 5 5 1 2 3 g.szwarc mijp-ii - p. 44/114

Iteratory front_inserter() w miejscu operatora przypisania następuje wywołanie operacji stawiajacej push_front() copy(t, t+3, front_inserter(v)); copy(v.begin(), v.end(), io); // 3 2 1 5 5 inserter() w miejscu operatora przypisania następuje wywołanie operacji stawiajacej insert(); wartość iteratora nie jest stała jest zwiększana dla każdego wstawianego elementu list<int>::iterator p = v.begin(); copy(t, t+3, inserter(v, ++p)); copy(v.begin(), v.end(), io); // 5 1 2 3 5 g.szwarc mijp-ii - p. 45/114

Zasobniki sekwencyjne Metody wspólne dla zasobników sekwencyjnych front() zwraca referencję do pierwszego elementu w zasobniku back() zwraca referencję do ostatniego elementu w zasobniku push_back() wstawianie elementu do zasobnika na ostatnim miejscu pop_back() usuwanie elementu z ostatniego miejsca w zasobniku Zasobnik sekwencyjny vector<t, Alloc> szybki dostęp do danych przez operator indeksowania; wydajne dodawanie i usuwanie elementów na końcu sekwencji; automatyczne rozszerzanie dostępnego obszaru pamięci; plik nagłówkowy <vector>; dodatkowe metody składowe: insert(), capacity(), resize(), reserve(), assign(), at(), operator[] g.szwarc mijp-ii - p. 46/114

Zasobniki sekwencyjne typedef vector<int> Vi; Vi v; cout << v.size() << << v.capacity() << \n ; // 0 0 v.push_back(12); v.push_back(23); v.push_back(34); cout << v.size() << << v.capacity() << \n ; // 3 4 Vi::iterator p = v.begin(); cout << *p << \n ; // 12 cout << *(p+2) << \n ; // 34 cout << *++p << \n ; // 23 cout << (p == v.begin()) << \n ; // 0 cout << (p > v.begin()) << \n ; // 1 g.szwarc mijp-ii - p. 47/114

Zasobniki sekwencyjne for (p = v.begin(); p!= v.end(); ++p) cout << *p << ; // 12 23 34 cout << \n ; Vi::reverse_iterator q; for (q = v.rbegin(); q!= v.rend(); ++q) cout << *q << ; // 34 23 12 cout << \n ; v.push_back(112); v.push_back(123); v.push_back(134); cout << v.front() << \n ; // 12 cout << v.back() << \n ; // 134 v.pop_back(); cout << v.back() << \n ; // 123 g.szwarc mijp-ii - p. 48/114

Zasobniki sekwencyjne cout << v.size() << << v.capacity() << \n ; // 5 8 v.erase(v.begin(), v.begin()+3); ostream_iterator<int> io(cout, " "); copy(v.begin(), v.end(), io); // 112 123 v.clear(); cout << v.size() << << v.capacity() << \n ; // 0 8 g.szwarc mijp-ii - p. 49/114

Zasobniki sekwencyjne Vi w(2, 10); cout << w.size() << << w.capacity() << \n ; // 2 2 copy(w.begin(), w.end(), io); // 10 10 w.resize(5); cout << w.size() << << w.capacity() << \n ; // 5 5 copy(w.begin(), w.end(), io); // 10 10 0 0 0 w.reserve(9); cout << w.capacity() << \n ; // 9 w.reserve(3); cout << w.capacity() << \n ; // 9 g.szwarc mijp-ii - p. 50/114

Zasobniki sekwencyjne w.resize(7, 6); cout << w.size() << \n ; // 7 copy(w.begin(), w.end(), io); // 10 10 0 0 0 6 6 w.at(1) = 2; w[1] = 2; w.insert(w.begin()+3, 4); copy(w.begin(), w.end(), io); // 10 2 0 4 0 0 6 6 w.clear(); cout << "w" << (w.empty()? " " : " nie ") << "jest pusty\n"; // w jest pusty g.szwarc mijp-ii - p. 51/114

Zasobniki sekwencyjne int t[] = {1, 3, 5, 7, 9, 12}; Vi v1(t, t + 6); Vi v2(t, t + 4); Vi v3(v2); v3[2] = 4; copy(v1.begin(), v1.end(), io); // 1 3 5 7 9 12 copy(v2.begin(), v2.end(), io); // 1 3 5 7 copy(v3.begin(), v3.end(), io); // 1 3 4 7 cout << boolalpha; cout << (v1 < v2); // false cout << (v1 > v3); // true cout << (v2 == v3); // false cout << (v3 <= v2); // true g.szwarc mijp-ii - p. 52/114

Zasobniki sekwencyjne Zasobnik sekwencyjny list<t, Alloc> wydajne dodawanie i usuwanie elementów w dowolnym miejscu sekwencji; implementowany jako lista z dwukierunkowymi odnośnikami (do poprzedniego i do następnego); dostępny iterator dwukierunkowy; plik nagłówkowy <list>; dodatkowe metody składowe: insert(), splice(), push_front(), pop_front(), remove(), unique(), merge(), reverse(), sort(), resize(), remove_if() typedef list<int> Li; int t[] = {2, 6, 4, 8}; Li w(t, t + 4); w.push_back(4); w.push_back(3); w.push_front(1); w.push_front(2); copy(w.begin(), w.end(), io); // 2 1 2 6 4 8 4 3 w.sort(); copy(w.begin(), w.end(), io); // 1 2 2 3 4 4 6 8 g.szwarc mijp-ii - p. 53/114

Zasobniki sekwencyjne w.unique(); copy(w.begin(), w.end(), io); // 1 2 3 4 6 8 Li wi(t, t + 4); w.swap(wi); copy(w.begin(), w.end(), io); // 2 6 4 8 copy(wi.begin(), wi.end(), io); // 1 2 3 4 6 8 w.splice(w.end(), wi); copy(w.begin(), w.end(), io); // 2 6 4 8 1 2 3 4 6 8 copy(wi.begin(), wi.end(), io); // <pusto> wi.insert(wi.begin(), t, t+4); copy(wi.begin(), wi.end(), io); // 2 6 4 8 g.szwarc mijp-ii - p. 54/114

Zasobniki sekwencyjne wi.sort(); w.sort(); w.merge(wi); copy(w.begin(), w.end(), io); // 1 2 2 2 3 4 4 4 6 6 6 8 8 8 copy(wi.begin(), wi.end(), io); // <pusto> w.unique(); copy(w.begin(), w.end(), io); // 1 2 3 4 6 8 w.assign(t, t+4); copy(w.begin(), w.end(), io); // 2 6 4 8 wi.assign(5, 7); copy(wi.begin(), wi.end(), io); // 7 7 7 7 7 // w.splice(w.begin()+2, wi); // błąd Li::iterator p = w.begin(); p++; p++; w.splice(p, wi); copy(w.begin(), w.end(), io); // 2 6 7 7 7 7 7 4 8 g.szwarc mijp-ii - p. 55/114

Zasobniki sekwencyjne w.reverse(); copy(w.begin(), w.end(), io); // 8 4 7 7 7 7 7 6 2 w.remove(4); w.remove(7); copy(w.begin(), w.end(), io); // 8 6 2 w.pop_front(); copy(w.begin(), w.end(), io); // 6 2 w.insert(w.end(), t, t+4); copy(w.begin(), w.end(), io); // 6 2 2 6 4 8 //bool mniej5(int v) { return v < 5; } w.remove_if(mniej5); copy(w.begin(), w.end(), io); // 6 6 8 g.szwarc mijp-ii - p. 56/114

Zasobniki sekwencyjne Zasobnik sekwencyjny deque<t, Alloc> szybki dostęp do danych przez operator indeksowania; wydajne dodawanie i usuwanie elementów na poczatku i końcu sekwencji; automatyczne rozszerzanie dostępnego obszaru pamięci; plik nagłówkowy <deque>; dodatkowe metody składowe: insert(), resize(), assign(), at(), operator[], push_front(), pop_front() int t[] = {9, 3, 5}; deque<int> dq(t, t + 3); for (int i = 0; i < dq.size(); ++i) cout << dq[i] << ; // 9 3 5 dq.push_back(4); dq.push_back(3); dq.push_front(1); dq.push_front(2); copy(dq.begin(), dq.end(), io); // 2 1 9 3 5 4 3 g.szwarc mijp-ii - p. 57/114

Zasobniki skojarzeniowe Zasobniki skojarzeniowe implementowane jako czerwono czarne drzewa przeszukiwania binarnego; minimalizacja średniego czasu wyszukania elementu; metody wspólne: count(), find(), lower_bound(), upper_bound(), equal_range() Zasobniki skojarzeniowe set<key, Compare, Alloc> i multiset<key, Compare, Alloc> szybkie zapamiętywanie i odzyskiwanie kluczy (dla multiset dopuszczalne duplikaty); elementy porzadkowane zgodnie z obiektem funkcji (drugi parametr szablonu domyślnie less<t>); elementy musza obsługiwać odpowiednie operatory porównania; obsługa iteratorów dwukierunkowych; plik nagłówkowy <set> g.szwarc mijp-ii - p. 58/114

Zasobniki skojarzeniowe ostream_iterator<int> out(cout, " "); int t[] = {6, 8, 2, 4, 8, 2}; set<int> s(t, t+6); s.insert(2); copy(s.begin(), s.end(), out); // 2 4 6 8 cout << s.count(10); // 0 cout << s.count(4); // 1 set<int>::const_iterator q; q = s.find(6); if (q!= s.end()) copy(q, s.end(), out); // 6 8 g.szwarc mijp-ii - p. 59/114

Zasobniki skojarzeniowe typedef multiset<int> Muls; Muls ms(t, t+6); ms.insert(2); ms.insert(1); copy(ms.begin(), ms.end(), out); // 1 2 2 2 4 6 8 8 cout << ms.count(2); // 3 copy(ms.lower_bound(2), ms.upper_bound(4), out); // 2 2 2 4 pair<muls::const_iterator, Muls::const_iterator> range; range = ms.equal_range(2); ms.erase(range.first, range.second); copy(ms.begin(), ms.end(), out); // 1 4 6 8 8 g.szwarc mijp-ii - p. 60/114

Zasobniki skojarzeniowe Zasobniki skojarzeniowe map<key, Data, Compare, Alloc> i multimap<key, Data, Compare, Alloc> szybkie zapamiętywanie i odzyskiwanie par wartości (klucz, wartość) (dla multimap dopuszczalne duplikaty); elementy porzadkowane zgodnie z obiektem funkcji (drugi parametr szablonu domyślnie less<t>) uwzględniajacym wartość klucza; elementy musza obsługiwać odpowiednie operatory porównania; obsługa iteratorów dwukierunkowych; plik nagłówkowy <map>; dla zasobnika map dostępny jest operator[] typedef map<int, string> Mis; Mis m; m.insert(mis::value_type(15, "Ala")); m.insert(pair<int, string>(11, "kota")); //m.insert(make_pair(12, "ma")); m.insert(make_pair<int, string>(12, "ma")); g.szwarc mijp-ii - p. 61/114

Zasobniki skojarzeniowe m[14] = "a"; m[13] = "Boguś"; m[16] = "psa"; Mis::const_iterator p = m.begin(); for(; p!= m.end(); ++p) cout << p->first << << p->second << ; // 11 kota 12 ma 13 Boguś 14 a 15 Ala 16 psa cout << m.count(90); // 0 string tmp = m[90]; cout << m.count(90); // 1 typedef multimap<int, string> Mulmis; Mulmis mm(m.lower_bound(11), m.upper_bound(13)); mm.insert(m.lower_bound(11), m.upper_bound(13)); g.szwarc mijp-ii - p. 62/114

Zasobniki skojarzeniowe Mulmis::iterator mp = mm.begin(); for(; mp!= mm.end(); ++mp) cout << mp->first << << mp->second << ; // 11 kota 11 kota 12 ma 12 ma 13 Boguś 13 Boguś mp = mm.find(12); if (mp!= mm.end()) (--mp)->second = "psa"; pair<mulmis::iterator, Mulmis::iterator> r; r = mm.equal_range(13); mm.erase(r.first, r.second); mm.erase(12); for(mp = mm.begin(); mp!= mm.end(); ++mp) cout << mp->first << << mp->second << ; //11 kota 11 psa g.szwarc mijp-ii - p. 63/114

Łaczniki zasobników Łaczniki zasobników nie dostarczaja implementacji struktury danych, wykorzystuja do tego zasobniki sekwencyjne; nie obsługuja iteratorów; pliki nagłówkowe: <stack>, <queue>; metody wspólne: push(), pop() stack<double> sdq; // domyślnie na deque stack<double, vector<double> > sdv; // może też być list for (int i = 5; i < 10; ++i) { sdq.push(i/3.0); sdv.push(i/2.0); } template <typename T> void view_and_pop(t& v) { while (!v.empty()) { cout << v.top() << ; v.pop(); } } cout.setf(ios::showpoint); cout.precision(3); view_and_pop(sdq); //3.00 2.67 2.33 2.00 1.67 view_and_pop(sdv); //4.50 4.00 3.50 3.00 2.50 g.szwarc mijp-ii - p. 64/114

Łaczniki zasobników queue<double> qd; // domyślnie na deque qd.push(1.6); qd.push(9.8); qd.push(0.8); qd.push(2.7); cout << qd.back(); // 2.7 while (!qd.empty()) { cout << qd.front() << ; qd.pop(); } // 1.60 9.80 0.800 2.70 priority_queue<double> pqd; // domyślnie na vector i z less pqd.push(1.6); pqd.push(9.8); pqd.push(0.8); pqd.push(2.7); view_and_pop(pqd); // 9.80 2.70 1.60 0.800 priority_queue<double, deque<double>, greater<double> > pqdd; pqdd.push(1.6); pqdd.push(9.8); pqdd.push(0.8); pqdd.push(2.7); view_and_pop(pqdd); // 0.800 1.60 2.70 9.80 g.szwarc mijp-ii - p. 65/114

Obiekty funkcyjne Obiekty funkcyjne funktory; obiekt klasy dla której przeciażono operator wywołania funkcji; wykorzystywane głównie jako orzeczniki (predykaty) w algorytmach ogólnych; alternatywa dla funkcji orzekajacych przekazywanych przez wskaźnik; jeśli operator() zadeklarowano jako funkcję rozwijana w miejscu poprawa wydajności, moga przechowywać dodatkowe dane pomocnicze ważne do poprawnego realizowania bieżacej operacji Obiekty funkcyjne zdefiniowane w bibliotece STL wzorce klas; plik nagłówkowy <functional> arytmetyczne dodawanie plus<t> odejmowanie minus<t> mnożenie multiplies<t> dzielenie divides<t> modulo modulus<t> negacja negate<t> g.szwarc mijp-ii - p. 66/114

relacyjne równe equal_to<t> nierówne not_equal_to<t> większe niż greater<t> większe niż lub równe greater_equal<t> mniejsze niż less<t> mniejsze niż lub równe less_equal<t> logiczne koniunkcja logical_and<t> alternatywa logical_or<t> negacja logical_not<t> plus<float> p; negate<double> n; greater<char> g; logical_and<int> a; Obiekty funkcyjne cout << p(3.14, 2.73) << << n(-1.23) << << g( z, a ) << << a(1, 0); // 5.87 1.23 1 0 g.szwarc mijp-ii - p. 67/114

Obiekty funkcyjne int t[] = {11, 2, 13, 1, 7, 9, -1}; list<int> l(t, t+7); l.sort(greater<int>()); ostream_iterator<int> out(cout, " "); copy(l.begin(), l.end(), out); // 13 11 9 7 2 1-1 bool mniej_niz_7(int y) { return y < 7; } struct mniej_niz { mniej_niz(int x_) : x(x_) { } bool operator () (int y) const { return y < x; } private: int x; }; l.remove_if(mniej_niz(7)); copy(l.begin(), l.end(), out); // 13 11 9 7 g.szwarc mijp-ii - p. 68/114

Obiekty funkcyjne struct pair_si { int first; string second; bool operator < (const pair_si& p) const { return first == p.first? second < p.second : first < p.first; } }; istream& operator >> (istream& ifs, pair_si& s) { static int licznik = 0; s.first = ++licznik; return ifs >> s.second; } typedef istream_iterator<pair_si> is; ifstream file("test.txt"); if (!file) return -1; list<pair_si> w; copy(is(file), is(), back_inserter(w)); g.szwarc mijp-ii - p. 69/114

Obiekty funkcyjne template<typename T> struct output_pair { output_pair(ostream& o, string e = "") : out(o), end(e) { } void operator () (const T& p) { out << p.first << \t << p.second << end; } private: ostream& out; string end; }; template <typename T> void view(t con) { for_each(con.begin(), con.end(), output_pair<typename T::value_type>(cout, " ")); } g.szwarc mijp-ii - p. 70/114

Obiekty funkcyjne view(w); // 1 Tanie 2 wino 3 jest 4 dobre, 5 bo // 6 jest 7 dobre 8 i 9 tanie. class ffoe { public: ffoe(const string& e) : extra(e) { } pair_si& operator () (pair_si& w) { string::size_type p; while ((p = w.second.find_first_of(extra))!= string::npos) w.second.erase(p, 1); return w; } protected: string extra; }; g.szwarc mijp-ii - p. 71/114

Obiekty funkcyjne transform(w.begin(), w.end(), w.begin(), ffoe(".,")); view(w); // 1 Tanie 2 wino 3 jest 4 dobre 5 bo // 6 jest 7 dobre 8 i 9 tanie class ssort { public: bool operator () (const pair_si& l, const pair_si& r) { return l.second < r.second; } }; w.sort(ssort()); view(w); // 1 Tanie 5 bo 4 dobre 7 dobre 8 i // 3 jest 6 jest 9 tanie 2 wino g.szwarc mijp-ii - p. 72/114

Obiekty funkcyjne typedef map<string, int> stat_map; class stat { public: stat(stat_map& msi_) : msi(msi_) {} void operator () (const pair_si& s) { msi[s.second]++; } protected: stat_map& msi; }; stat_map st; for_each(w.begin(), w.end(), stat(st)); view(st); // Tanie 1 bo 1 dobre 2 i 1 jest 2 tanie 1 wino 1 g.szwarc mijp-ii - p. 73/114

Obiekty funkcyjne Adaptory obiektów funkcyjnych wzorce klas pozwalajace na zmianę funkcjonalności obiektów funkcyjnych; nie używa się ich bezpośrednio, lecz za pomoca funkcji zwracajacych obiekty tych klas; dwa podstawowe typy wiazadło przekształca dwuargumentowy funktor w jednoargumentowy, zwiazuj ac jeden z argumentów z konkretna wartościa; funkcja bind1st wiaże pierwszy argument, funkcja bind2nd wiaże drugi ostream_iterator<int> os(cout, " "); int t[] = {11, 2, 13, 1, -7, 9, -1}; list<int> l(t, t+7); l.remove_if(bind2nd(less<int>(), 1)); copy(l.begin(), l.end(), os); // 11 2 13 1 9 negator zmienia wartość logiczna funktora na wartość przeciwna: funkcja not1 odwraca wartość funktora jednoargumentowego, funkcja not2 dwuargumentowego l.sort(not2(less<int>())); copy(l.begin(), l.end(), os); // 13 11 9 2 1 g.szwarc mijp-ii - p. 74/114

Obiekty funkcyjne struct mniej_niz : public unary_function <int, bool> { mniej_niz(int x_) : x(x_) { } bool operator () (int y) const { return y < x; } private: int x; }; l.remove_if(mniej_niz(5)); copy(l.begin(), l.end(), os); // 13 11 9 l.remove_if(not1(mniej_niz(10))); copy(l.begin(), l.end(), os); // 9 g.szwarc mijp-ii - p. 75/114

Obiekty funkcyjne class E { public: E(int e) : e_(e) { } void foo() { cout << e_; } void bar() const { cout << 10+e_; } private: int e_; }; template<typename T> struct pointer { T* operator() (T& t) { return &t; } }; E t[] = {9, 1, 8, 2, 7, 3, 6, 4, 5, 0}; for_each(t, t+10, mem_fun_ref(&e::foo)); // 9182736450 list<const E*> l; transform(t, t+10, back_inserter(l), pointer<e>()); for_each(l.begin(), l.end(), mem_fun(&e::bar)); // 19111812171316141510 g.szwarc mijp-ii - p. 76/114

Obiekty funkcyjne const char* a[] = {"ala", "ma", "kota", ""}; const char** a_end = a+4; ostream_iterator<int> o(cout); transform(a, a_end, o, strlen); // 3240 cout << boolalpha; cout << (find_if(a, a_end, strlen)!= a_end); // true cout << (find_if(a, a_end, not1(ptr_fun(strlen)))!= a_end); // true g.szwarc mijp-ii - p. 77/114

Algorytmy ogólne Algorytmy ogólne algorytmy uogólnione wzorce funkcji implementujace podstawowe operacje na elementach zasobników; działaja na elementach pośrednio przez iteratory; w większości przypadków jako dwa pierwsze argumenty pobieraja parę iteratorów wyznaczajacy zakres działania algorytmu; para iteratorów musi spełniać warunek powtarzajac wykonanie operatora inkrementacji można przejść od poczatku zakresu do jego końca; deklaracja każdego algorytmu zawiera określenie minimalnej kategorii wymaganych iteratorów brak gwarancji wychwycenia przez kompilator iteratora nieodpowiedniej kategorii; niektóre algorytmy występuja w kilku wersjach przeciażenie oraz zmiana nazwy; końcówka _if możliwość podania orzecznika (funktora); końcówka _copy odróżnienie od wersji algorytmu działajacej w miejscu; pliki nagłówkowe: <algorithm>, <numeric> Nieformalny podział algorytmów ogólnych : niezmieniajace, zmieniajace, sortujace, operujace na zbiorach, operujace na stertach, numeryczne g.szwarc mijp-ii - p. 78/114

Algorytmy ogólne Użyte oznaczenia : OutIt iterator wyjściowy (output), InIt iterator wejściowy (input), FwdIt iterator do przodu (forward) BidIt iterator dwukierunkowy (bidirectional), RanIt iterator o dostępie swobodnym (random-access) Algorytmy niezmieniajace for_each template<typename InIt, typename Fn1> Fn1 for_each(init first, InIt last, Fn1 func); dla każdego elementu z zakresu [first, last) wywołaj funkcję jedoargumentowa func find, find_if template<typename InIt, typename Ty> InIt find(init first, InIt last, const Ty& val); template<typename InIt, typename Pr> InIt find_if(init first, InIt last, Pr pred); znajduje w podanym zakresie wartość równa val (wersja _if wartość spełniajac a pred); zwraca iterator wskazujacy na znaleziony element lub last jeśli nie znalazł g.szwarc mijp-ii - p. 79/114

Algorytmy ogólne adjacent_find template<typename FwdIt [, typename Pr]> FwdIt adjacent_find(fwdit first, FwdIt last [, Pr pred]); znajduje taki element, że jego następnik jest mu równy; jeśli podano pred znajduje taki element i, że pred(*i, *i+1) jest spełniony; jeśli element nie zostanie znaleziony, zwracany jest last find_first_of template<typename FwdIt1, typename FwdIt2 [, typename Pr]> FwdIt1 find_first_of(fwdit1 first1, FwdIt1 last1, FwdIt2 first2, FwdIt2 last2 [, Pr pred]); znajduje w zakresie [first1, last1) którykolwiek z elementów z zakresu [first2, last2); jeśli podano pred, jest on użyty do porównywania elementów, jeśli nie, używa się operatora == equal template<typename InIt1, typename InIt2 [, typename Pr]> bool equal(init1 first1, InIt1 last1, InIt2 first2 [, Pr pred]); porównuje dwa zakresy (operatorem == lub pred); zwraca wartość logiczna wynikajaca z porównania g.szwarc mijp-ii - p. 80/114

count, count_if template<typename InIt, typename Ty, typename Dist> typename iterator_traits<init>::difference_type count(init first, InIt last, const Ty& val); template<typename InIt, typename Pr, typename Dist> typename iterator_traits<init>::difference_type count_if(init first, InIt last, Pr pred); Algorytmy ogólne zlicza elementy równe val (wersja _if elementy spełniajace warunek pred) w podanym zakresie; zwraca liczbę wystapień mismatch template<typename InIt1, typename InIt2 [, typename Pr]> pair<init1, InIt2> mismatch(init1 first1, InIt1 last1, InIt2 first2 [, Pr pred]); porównuje dwa zakresy (operatorem == lub pred); zwraca odpowiednio iterator z pierwszego zakresu i iterator symetrycznie mu odpowiadajacy z drugiego; jeśli na jakiejś pozycji podane zakresy się różnia, zwracana jest para iteratorów, których dereferencje się różnia, jeśli zakresy okaża się identyczne - pierwszym ze zwracanej pary jest last1 g.szwarc mijp-ii - p. 81/114

Algorytmy ogólne lexicographical_compare template<typename InIt1, typename InIt2 [, typename Pr]> bool lexicographical_compare(init1 first1, InIt1 last1, InIt2 first2, InIt2 last2 [, Pr pred]); porównuje elementy dwóch zakresów (operatorem < lub pred); zwraca wartość porównania elementów różniacych się; w przypadku gdy zakresy sa różnej długości i posiadaja elementy o tych samych wartościach zostanie zrócona prawda tylko w wypadku gdy zakres pierwszy będzie krótszy search template<typename FwdIt1, typename FwdIt2 [, typename Pr]> FwdIt1 search(fwdit1 first1, FwdIt1 last1, FwdIt2 first2, FwdIt2 last2 [, Pr pred]); wyszukuje w zakresie [first1, last1) ciag [first2, last2); zwraca wartość iteratora z pierwszego zakresu, na którym szukany ciag się zaczyna; jeśli nie znaleziono - zwraca last1 g.szwarc mijp-ii - p. 82/114

Algorytmy ogólne search_n template<typename FwdIt1, typename Diff2, typename Ty [, typename Pr]> FwdIt1 search_n(fwdit1 first1, FwdIt1 last1, Diff2 count, const Ty& val [, Pr pred]); szuka w podanym zakresie ciagu count elementów równych val lub spełniajacych z nia pred; jeśli wartość nie zostanie znaleziona, zwracana jest wartość last1 find_end template<typename FwdIt1, typename FwdIt2 [, typename Pr]> FwdIt1 find_end(fwdit1 first1, FwdIt1 last1, FwdIt2 first2, FwdIt2 last2 [, Pr pred]); funkcja robi to samo co search z tym tylko że od końca; jeśli ci ag nie zostanie znaleziony, zwracana jest wartość last1 g.szwarc mijp-ii - p. 83/114

Algorytmy zmieniajace copy template<typename InIt, typename OutIt> OutIt copy(init first, InIt last, OutIt dest); Algorytmy ogólne kopiuje elementy z podanego zakresu do dest wywołujac kolejno operator przypisania; powoduje nadpisanie, a nie wstawianie elementów, nie można więc użyć jej do wstawiania elementów do pustego zasobnika; jeśli zakresy się na siebie nakładaja copy nie może zostać użyte copy_backward template<typename BidIt1, typename BidIt2> BidIt2 copy_backward(bidit1 first, BidIt1 last, BidIt2 dest); jak copy, ale kopiuje od tyłu; dest jest górnym zakresem docelowym (wartościa za-ostatnia zakresu docelowego) g.szwarc mijp-ii - p. 84/114

swap template<typename Ty> void swap(ty& left, Ty& right); Algorytmy ogólne zamienia miejscami left i right; argumenty musza obsługiwać operator przypisania iter_swap template<typename FwdIt1, typename FwdIt2> void iter_swap(fwdit1 left, FwdIt2 right); identyczne z swap(*left, *right), istnieje ze względu na to, że niektóre kompilatory nie radza sobie z wydedukowaniem typów argumentów przy wywołaniu jako swap swap_ranges template<typename FwdIt1, typename FwdIt2> FwdIt2 swap_ranges(fwdit1 first1, FwdIt1 last1, FwdIt2 first2); zamienia miejscami podane zakresy g.szwarc mijp-ii - p. 85/114

replace template<typename FwdIt, typename Ty> void replace(fwdit first, FwdIt last, const Ty& oldval, const Ty& newval); Algorytmy ogólne zamienia w podanym przedziale wszystkie znalezione wartości oldval na newval replace_if template<typename FwdIt, typename Pr, typename Ty> void replace_if(fwdit first, FwdIt last, Pr pred, const Ty& val); jak replace, ale dla elementów spełniajacych pred g.szwarc mijp-ii - p. 86/114

Algorytmy ogólne replace_copy template<typename InIt, typename OutIt, typename Ty> OutIt replace_copy(init first, InIt last, OutIt dest, const Ty& oldval, const Ty& newval); jak copy, ale jeśli w źródłowym zakresie wartość jest równa oldval, wstawiane jest tam newval replace_copy_if template<typename InIt, typename OutIt, typename Pr, typename Ty> OutIt replace_copy_if(init first, InIt last, OutIt dest, Pr pred, const Ty& val); jak replace_copy, ale sprawdzany jest pred g.szwarc mijp-ii - p. 87/114

Algorytmy ogólne transform template<typename InIt1, typename OutIt, typename Fn1> OutIt transform(init1 first1, InIt1 last1, OutIt dest, Fn1 func); template<typename InIt1, typename InIt2 typename OutIt, typename Fn2> OutIt transform(init1 first1, InIt1 last1, InIt2 first2, OutIt dest, Fn2 func); przekształca przy pomocy funkcji func podany zakres elementów; pierwsza wersja pobiera argumenty z zakresu [first1, last), przetwarza przy pomocy func i wstawia wynik poprzez dest; druga wersja pobiera pierwszy argument z pierwszego zakresu, a drugi - z drugiego random_shuffle template<typename RanIt [, typename Fn1]> void random_shuffle(ranit first, RanIt last [, Fn1& func]); losowo zmienia uporzadkowanie elementów zakresu; opcyjne func jest generatorem liczb psełdolosowych z zakresu [0,N], gdzie N jest (całkowitym) argumentem func g.szwarc mijp-ii - p. 88/114

fill template<typename FwdIt, typename Ty> void fill(fwdit first, FwdIt last, const Ty& val); Algorytmy ogólne wypełnia podany zakres wartościa val korzystajac z operatora przypisania fill_n template<typename OutIt, typename Diff, typename Ty> void fill_n(outit first, Diff count, const Ty& val); jak fill, ale górny zakres jest równy first + count generate template<typename FwdIt, typename Fn0> void generate(fwdit first, FwdIt last, Fn0 func); jak fill, ale wartość uzyskuje z generatora func generate_n template<typename OutIt, typename Diff, typename Fn0> void generate_n(outit first, Diff count, Fn0 func); jak generate, ale górny zakres jest równy first + count g.szwarc mijp-ii - p. 89/114

remove template<typename FwdIt, typename Ty> FwdIt remove(fwdit first, FwdIt last, const Ty& val); Algorytmy ogólne usuwa z podanego zakresu elementy o wartości val; w rzeczywistości nic nie jest usuwane (tzn. nie zmienia się rozmiar zasobnika), a jedynie następuje nadpisanie elementów tak, aby nie było wśród nich podanej wartości oraz kolejność elementów została zachowana; otrzymujemy nowy zakres, gdzie poczatek jest taki sam, natomiast koniec zakresu jest zwracany jako rezultat; jeśli nie ma w podanym zakresie szukanej wartości rezultat jest równy last; zakres wyznaczany od nowego końca zakresu do poprzedniego pozostaje niezmieniony remove_if template<typename FwdIt, typename Pr> FwdIt remove_if(fwdit first, FwdIt last, Pr pred); jak remove, ale elementy zakresu sprawdzane sa orzecznikiem pred g.szwarc mijp-ii - p. 90/114

remove_copy template<typename InIt, typename OutIt, typename Ty> OutIt remove_copy(init first, InIt last, OutIt dest, const Ty& val); jak remove, ale wykonuje kopiowanie do dest remove_copy_if template<typename InIt, typename OutIt, typename Pr> OutIt remove_copy_if(init first, InIt last, OutIt dest, Pr pred); jak remove_if, ale wykonuje kopiowanie do dest unique template<typename FwdIt [, typename Pr]> FwdIt unique(fwdit first, FwdIt last [, Pr pred]); Algorytmy ogólne działa identycznie jak remove, z tym że usuwa wszystkie elementy, które sa sobie równe z wyjatkiem jednego z nich (tzn. po wykonaniu każdy element jest unikalny); jeśli podano pred, testuje się nim dwa sasiednie elementy, w przeciwnym wypadku używa się operatora == g.szwarc mijp-ii - p. 91/114

Algorytmy ogólne unique_copy template<typename InIt, typename OutIt [, typename Pr]> OutIt unique_copy(init first, InIt last, OutIt dest [, Pr pred]); kopiuje elementy do dest, pomijajac powtarzajace się reverse template<typename BidIt> void reverse(bidit first, BidIt last); odwraca kolejność elementów w zakresie; wymagane sa iteratory dwukierunkowe reverse_copy template<typename BidIt, typename OutIt> OutIt reverse_copy(bidit first, BidIt last, OutIt dest); jak reverse, ale wykonuje kopiowanie do dest rotate template<typename FwdIt> void rotate(fwdit first, FwdIt mid, FwdIt last); zamienia zakres [mid, last) z [first, mid) g.szwarc mijp-ii - p. 92/114

rotate_copy template<typename FwdIt, typename OutIt> OutIt rotate_copy(fwdit first, FwdIt mid, FwdIt last, OutIt dest); jak rotate, ale wykonuje kopiowanie do dest partition template<typename BidIt, typename Pr> BidIt partition(bidit first, BidIt last, Pr pred); Algorytmy ogólne dzieli przedział na dwie części, gdzie wcześniejsza zawiera elementy spełniajace podany warunek, a dalsza nie; iterator rozpoczynajacy ten drugi zakres jest zwracany; nie gwarantuje się tej samej (względnej) kolejności elementów po operacji stable_partition template<typename BidIt, typename Pr> BidIt stable_partition(bidit first, BidIt last, Pr pred); jak partition, ale gwarantuje zachowanie tej samej (względnej) kolejności elementów po operacji g.szwarc mijp-ii - p. 93/114

Sortowanie oraz algorytmy zwiazane z sortowaniem sort template<typename RanIt [, typename Pr]> void sort(ranit first, RanIt last [, Pr pred]); Algorytmy ogólne sortowanie niestabilne, tzn. jeśli elementy sa sobie równe, nie gwarantuje się, że pozostana względem siebie ułożone tak samo; sortowanie jest rosnace, porównania dokonuje się operatorem < lub podanym orzecznikiem pred stable_sort template<typename BidIt [, typename Pr]> void stable_sort(bidit first, BidIt last [, Pr pred]); jak sort, ale stabilne g.szwarc mijp-ii - p. 94/114

partial_sort template<typename RanIt [, typename Pr]> void partial_sort(ranit first, RanIt mid, RanIt last [, Pr pred]); Algorytmy ogólne sortowanie częściowe według algorytmu sortowania sterty (heapsort); polega to na tym, że elementy w efekcie sa posortowane, ale tylko na pierwszych mid - first pozycjach; pozostałe sa ułożone w nieokreślonym porzadku partial_sort_copy template<typename InIt, typename RanIt [, typename Pr]> RanIt partial_sort_copy(init first1, InIt last1, RanIt first2, RanIt last2 [, Pr pred]); jak partial_sort, ale wynik sortowania umieszczany jest w zakresie [first2, last2) g.szwarc mijp-ii - p. 95/114

nth_element template<typename RanIt [, typename Pr]> void nth_element(ranit first, RanIt nth, RanIt last [, Pr pred]); Algorytmy ogólne dokonuje podziału zakresu [first, last), że wszystko, co jest mniejsze (operator < lub podany orzecznik) niż wartość pod nth znajduje się zakresie [first, nth) lower_bound template<typename FwdIt, typename Ty [, typename Pr]> FwdIt lower_bound(fwdit first, FwdIt last, const Ty& val [, Pr pred]); zwraca iterator wskazujacy na najwcześniejsze miejsce w zakresie poszukiwanej wartości val; miejsce przed którym można wstawić val nie zaburzajac uporzadkowania zakresu upper_bound template<typename FwdIt, typename Ty [, typename Pr]> FwdIt upper_bound(fwdit first, FwdIt last, const Ty& val [, Pr pred]); jak lower_bound, ale najpóźniejsze miejsce g.szwarc mijp-ii - p. 96/114