Advertisement
Guest User

Untitled

a guest
Dec 12th, 2017
70
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.21 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <tchar.h>
  3. #include <iostream>
  4. #include <vector>
  5. #include <list>
  6. #include <forward_list>
  7. #include <iterator>
  8.  
  9. // CLASS_06: iteratory
  10.  
  11. // Funkcja drukująca zawartość dowolnego kontenera, korzystająca z iteratorów
  12. template <typename IterT>
  13. void Print(IterT b, IterT e)
  14. {
  15. for (auto it = b; it != e; ++it) {
  16. std::cout << *it << ' ';
  17. }
  18. std::cout << std::endl;
  19. }
  20.  
  21. int _tmain(int argc, _TCHAR* argv[])
  22. {
  23. std::cout << "====== EXAMPLE 1 forward_iterator ======" << std::endl << std::endl;
  24. // tworzymy listę jednokierunkową i inicjalizujemy jej zawartość w pętli
  25. std::forward_list<int> fl;
  26. for (int i = -3; i < 9; ++i) {
  27. fl.push_front(i);
  28. }
  29. // wypisujemy zawartość listy za pomocą pętli używającej iteratorów
  30. // przykład użycia "cbegin" i "cend", które zwracają "const_iterator"
  31. // użycie "begin" i "end" oraz deklaracja "it" za pomocą "auto" nie gwarantują, że "it" będzie "const_iterator"
  32. // jeżeli nie potrzebujemy nadpisywać zawartości kontenera, to dobrą praktyką jest użycie "const_iterator"
  33. std::cout << "forward_list: ";
  34. for (auto pos = fl.cbegin(); pos != fl.cend(); ++pos) {
  35. std::cout << *pos << ' ';
  36. }
  37. std::cout << std::endl << std::endl;
  38. // w przypadku iteratora jednokierunkowego dostępne są operacje:
  39. // - operator dereferencji: * (linia 35)
  40. // - operatory porównania: != == (linia 34)
  41. // - operator inkrementacji: ++ (linia 34)
  42.  
  43. std::cout << "====== EXAMPLE 2 bidirectional_iterator ======" << std::endl << std::endl;
  44. // tworzymy listę i inicjalizujemy jej zawartość w pętli
  45. std::list<int> l;
  46. for (int i = -3; i < 9; ++i) {
  47. l.push_back(i);
  48. }
  49. // wypisujemy zawartość listy za pomocą pętli używającej iteratorów
  50. std::cout << "list: ";
  51. for (auto pos = l.cbegin(); pos != l.cend(); ++pos) {
  52. std::cout << *pos << ' ';
  53. }
  54. std::cout << std::endl << std::endl;
  55. // w przypadku iteratora dwukierunkowego dostępne są operacje jak dla forward_iterator oraz:
  56. // - operator dekrementacji
  57.  
  58. std::cout << "====== EXAMPLE 3 random_access_iterator ======" << std::endl << std::endl;
  59. // tworzymy vektor i inicjalizujemy jego zawartość w pętli
  60. std::vector<int> v;
  61. for (int i = -3; i < 9; ++i) {
  62. v.push_back(i);
  63. }
  64. // wypisujemy co drugi element wektora za pomocą pętli używającej iteratorów
  65. std::cout << "vector: ";
  66. for (auto pos = v.cbegin(); pos < v.cend() && std::next(pos) < v.cend(); pos += 2) {
  67. std::cout << *pos << ' ';
  68. }
  69. std::cout << std::endl << std::endl;
  70. // w przypadku iteratora dwukierunkowego dostępne są operacje jak dla bidirectional_iterator oraz:
  71. // - operatory arytmetyczne: + - += -= (linia 66)
  72. // - operatory mniejszości/większości: < > <= >= (linia 66)
  73. // random_access_iterator ma takie same właściwości jak surowy wskaźnik!
  74.  
  75. // Zamiana deklaracji zmiennej v z "vector" na "list" spowoduje, że kod się nie skompiluje,
  76. // bo iterator listy nie ma właściwości "random_access_iterator".
  77.  
  78. // Pisząc kod dobrą praktyką jest używanie minimalnej wspólnej funkcjonalności iteratorów,
  79. // wtedy kod jest bardziej uniwersalny.
  80. // Wszystkie kontenery STL posiadają iteratory kategorii przynajmniej "forward_iterator".
  81.  
  82. std::cout << "====== EXAMPLE 4 distance/advance/next/prev ======" << std::endl << std::endl;
  83. std::cout << "number/size: " << l.size() << std::endl;
  84. // funkcja "distance" zwraca liczbę elementów między dwoma iteratorami
  85. std::cout << "number/distance: " << std::distance(l.begin(), l.end()) << std::endl;
  86. // Uwaga: musi być możliwe przejście w przód z pierwszego iteratora do drugiego, inaczej zachowanie jest niezdefiniowane!
  87. //std::cout << "number/distance " << std::distance(cont.end(), cont.begin()) << std::endl; BLĄD!
  88.  
  89. // funkcja "advance" pozwala na przesunięcie iteratora żeby pokazywał na inny element
  90. auto it1 = l.begin();
  91. auto it2 = l.end();
  92. std::advance(it1, 3); // przesunięcie o 3 do przodu
  93. std::advance(it2, -2); // przesunięcie o 2 do tyłu
  94. std::cout << "subset number/distance: " << std::distance(it1, it2) << std::endl;
  95.  
  96. std::cout << "sum of adjacent elements: ";
  97. // wersja z dwoma iteratorami pomocniczymi:
  98. auto pos2 = l.begin(); // "pos2" zaincjalizowane jako "begin"
  99. auto pos1 = pos2++; // post-inkrementacja! "pos1" będzie równe "begin", a "pos2" będzie wskazywać na drugi element w sekwencji
  100. while (pos1 != l.end() && pos2 != l.end()) {
  101. std::cout << *pos1 + *pos2 << ' ';
  102. ++pos1;
  103. ++pos2;
  104. }
  105. std::cout << std::endl;
  106.  
  107. std::cout << "sum of adjacent elements: ";
  108. // wersja z funkcją pomocniczą "next", wystarczy tylko jeden iterator
  109. auto pos3 = l.begin();
  110. while (pos3 != l.end() && std::next(pos3) != l.end()) {
  111. std::cout << *pos3 + *std::next(pos3) << ' ';
  112. ++pos3;
  113. }
  114. std::cout << std::endl << std::endl;
  115.  
  116. // Używając funkcji "distance" i "advance" należy pamiętać o tym, że dla różnych kategorii iteratorów mają różną złożoność:
  117. // - dla random_access_iterator - stały czas wykonania
  118. // - dla bidirectional_iterator i forward_iterator - liniowy czas wykonania
  119.  
  120. std::cout << "====== EXAMPLE 5 reverse iterator ======" << std::endl << std::endl;
  121.  
  122. // przykładowy kontener
  123. std::vector<int> coll = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
  124. // wypisujemy zawartość od początku do końca
  125. for (auto it = coll.begin(); it != coll.end(); ++it) {
  126. std::cout << *it << ' ';
  127. }
  128. std::cout << std::endl;
  129.  
  130. // wypisujemy zawartość od końca za pomocą reverse iterator
  131. for (auto it = coll.rbegin(); it != coll.rend(); ++it) {
  132. std::cout << *it << ' ';
  133. }
  134. std::cout << std::endl;
  135.  
  136. // tymczasowy iterator, przechowujący pozycję w kontenerze
  137. std::vector<int>::const_iterator pos;
  138. // wyszukujemy pozycji elementu o wartości 5
  139. pos = std::find(coll.cbegin(), coll.cend(), 5);
  140. std::cout << "pos: " << *pos << std::endl;
  141.  
  142. // zamieniamy iterator "pos" na reverse iterator
  143. std::vector<int>::const_reverse_iterator rpos(pos);
  144. std::cout << "rpos: " << *rpos << std::endl;
  145. // reverse iterator wskazuje na tą samą pozycję fizyczną w kontenerze, ale na sąsiednią pozycję logiczną,
  146. // ponieważ pozwala to zachować definicję zakresu iteratorów jako przedziału jednostronnie domkniętego
  147. // bez ingerencji w kontener
  148.  
  149. // metoda "base()" pozwala na odzyskanie iteratora "do przodu" z iteratora odwrotnego (reverse iterator)
  150. std::vector<int>::const_iterator rrpos;
  151. rrpos = rpos.base();
  152. std::cout << "rrpos: " << *rrpos << std::endl << std::endl;
  153.  
  154. std::cout << "====== EXAMPLE 6 insert iterator ======" << std::endl << std::endl;
  155. // tworzymy przykładowy kontener
  156. std::vector<int> vec = { 1, 2, 3 };
  157. // używamy insertera (insert iterator) w celu wstawienia nowych elementów
  158. // insert iterator zamienia operację nadpisania elementu (przypisania nowej wartości) operacją dodania nowego elementu
  159. // "back_inserter" dodaje nowy element na końcu kontenera, "front_inserter" na początku, a "inserter" w żądanej pozycji
  160. std::back_inserter(vec) = 44;
  161. std::back_inserter(vec) = 55;
  162. Print(vec.begin(), vec.end());
  163.  
  164. // użycie insertera w celu wypełnienia listy w locie elementami z wektora "v"
  165. std::list<int> lst;
  166. std::copy(vec.begin(), vec.end(), std::front_inserter(lst));
  167. Print(lst.begin(), lst.end());
  168.  
  169. return 0;
  170. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement