Materiały dodatkowe zadanie 4
Transkrypt
Materiały dodatkowe zadanie 4
Paradygmaty programowania Programowanie generyczne w C++ Dr inż. Andrzej Grosser Czestochowa, 2014 , 2 Spis treści 1. Zadanie 4 5 1.1. Wprowadzenie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 1.2. Wskazówki do zadania . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 3 4 Spis treści 1. Zadanie 4 1.1. Wprowadzenie Dzisiejsze zadanie jest dość proste do zrobienia wymagaja, jedynie (przynajmniej w niektórych przypadkach) przygotowania odpowiedniego dla danego algorytmu funktora. Można tutaj wyróżnić: 1. generate() - funktor nieprzyjmujacy żadnych argumentów i zwracajacy element , , sekwencji np. (nie podaje, definicji klasy Osoba, ale latwo można ja, wydedukować): c l a s s Gen { public : Osoba operator ( ) ( ) { return Osoba ( ”Nowak ” , ”A l e k s a n d e r ” , 1 8 ) ; } }; // . . . s t d : : v e c t o r <Osoba> vec ( 1 0 ) ; s t d : : g e n e r a t e ( vec . b e g i n ( ) , vec . end ( ) , Gen ( ) ) ; 2. sort(), unique() - predykat dwuargumentowy (zwraca wartość logiczna, i pobiera elementy sekwencji) np.: c l a s s Pred { public : bool operator ( ) ( const Osoba& o1 , const Osoba& o2 ) const { return o1 . nazwisko ( ) > o2 . nazwisko ( ) ; } }; // . . . s t d : : v e c t o r <Osoba> vec ( 1 0 ) ; // . . . Operacje na w e k t o r z e np . w c z y t y w a n i e z p l i k u // S o r t o w a n i e s t d : : s o r t ( vec . b e g i n ( ) , vec . end ( ) , Pred ( ) ) ; 3. remove_if(), remove_copy_if() - predykat jednoargumentowy (zwaraca wartość logiczna, i pobiera elemnt sekwencji) np.: c l a s s Pred2 { 5 6 1. Zadanie 4 public : bool operator ( ) ( const Osoba& o ) const { return o . nazwisko ( ) [ 0 ] == ’A ’ ; } }; // . . . s t d : : v e c t o r <Osoba> vec ( 1 0 ) ; // . . // Dopiero w po l a, c z e n i u z metod a, e r a s e ( ) e l e m e n t y s a, f i z y c z n i e usuwane vec . e r a s e ( s t d : : r e m o v e i f ( vec . b e g i n ( ) , vec . end ( ) , Pred2 ( ) ) , vec . end ( ) ) ; 4. accumulate() - funktor dwuagrumentowy np.: c l a s s Fun { public : // Prev t o p o p r z e d n i a warto ś ć z l i c z a n e j w i e l k o ś c i , // p r z e d u w z g l e, dnieniem b i e ż a, cego elementu double operator ( ) ( double prev , const Osoba& o ) { return prev + o . wiek ( ) ; } }; // . . . s t d : : v e c t o r <Osoba> vec ( 1 0 ) ; // . . . double sum = accumulate ( vec . b e g i n ( ) , vec . end ( ) , 0 . 0 , Fun ( ) ) ; 5. transform() - wymaga funkcji dwuargumentowej lub jednoargumentowej w zależności od użytej wersji np.: c l a s s Fun2 { public : int operator ( ) ( const Osoba& o ) { return o . wiek ( ) ; } }; // . . . s t d : : v e c t r o <Osoba> vec ( 1 0 ) ; s t d : : v e c t o r <int> wiek ( 1 0 ) ; // . . . // Tutaj transformowana j e s t w e k t o r os ó b na w e k t o r // z a w i e r a j a, cy t y l k o wiek os ó b ( i n t −y ) s t d : : t r a n s f o r m ( vec . b e g i n ( ) , vec . end ( ) , wiek . b e g i n ( ) , Fun2 ( ) ) ; 1.2. Wskazówki do zadania 7 Uwaga - podana lista nie wyczerpuje wszystkich możliwości, niektóre wersje algorytmów nie wymagaja, podawania funktorów, wystarcza zapewnienie dla określonego typu stosownego operatora (np. istnieje wersja sort, dla której wystarczy dostarczyć operator mniejszości (<), podobnie istnieje wersja unique, która korzysta z operator równości (==) itd.). Po szczególy implementacyjne odsylam Was do dokumentacji. 1.2. Wskazówki do zadania 1. Algorym unique() podobnie jak remove_if nie usuwa fizycznie elementów, dlatego wymagane jest polaczenie z metoda, erase(). Do poprawnego użycia tego algorytmu , wymagane jest także wcześniejsze posorotwanie sekwencji (usuwa powtórzone elementy, które sasiaduj a, ze soba). , , 2. Przenoszenie elementów polega na skopiowaniu ich z orginalnej sekwencji do sekwencji wynikowej a nastepnie wymagane jest fizyczne usuniecie elementów z oryginalnego , , zasobnika. Do tego celu można użyć algorytmów remove_if i remove_copy_if - należy sobie jednak zdać sprawe, gdyż tak , że nazwa drugiego algorytmu jest mylaca, , naprawde, sluży do kopiowania elemntów, dla których predyka nie jest spelniony (musi wykonywać odwrotność tego co dla remove if). 3. Algorytmy same nie przydziela, dodatkowej pamieci o , - programista musi pamietać , jej wcześniejszym przydzieleniu lub skorzystać z dodatkowych mechanizmów np. z back inseretera): v e c t o r <int> v1 ( 1 0 ) , v2 ; copy ( v1 . b e g i n ( ) , v1 . end ( ) , b a c k i n s e r t e r ( v2 ) ) ; W podanym powyżej przykladzie elementy sa, kopiowane z wektora v1 do wektora v2, kolejne elementy sa, dostawiane na koniec wektora v2 - dzieki użycia back inseretera , nie byl potrzebny przydzial pamieci , dla v2 - ta metoda jest szczególnie użyteczna dla algorytmów, dla których nie wiadomo z góry ile elementów trzeba bedzie przenieść , (np. remove_copy_if()). 4. Algorytm accumulate() wymaga dolaczenia naglówka numeric. ,