C++/Iteratory: Różnice pomiędzy wersjami
Usunięta treść Dodana treść
→Podział iteratorów: styl. |
+< source>, poprawki |
||
Linia 5:
Istnieją pewne analogie między iteratorem a wskaźnikiem. Przede wszystkim znajomo wyglądają wyrażenia:
<source lang="cpp">
*nasz_iterator = wart // podstawienie wartości zmiennej w miejsce pojemnika wskazane przez nasz_iterator
</source>
Umożliwia nam to przeciążony '''operator*''' , jak i '''operator=''' dzięki któremu możemy pod iterator podstwiać inne wartości.
Linia 14 ⟶ 16:
* '''Iteratory wejścia:'''
Taki iterator może odczytać wartość elementu, na który wskazuje, o ile nie wskazuje przekroczenia zakresu – end(). Musi posiadać domyślny konstruktor, konstruktor kopiujący oraz operatory =, ==, !=, ++. Odczytać wartość można:
<source lang="cpp">
wart = *iterator; // '' poprawne użycie iteratora wejścia''▼
▲
</source>
Można inkrementować iterator – aby wskazywał następny składnik:
<source lang="cpp">
</source>
Linia 23 ⟶ 30:
Ten typ iteratora umożliwia tylko zapis wartości do danego składnika – odczyt jest niemożliwy. Musi posiadać domyślny konstruktor, konstruktor kopiujący oraz operatory =, ++.
np.
<source lang="cpp">
wartosc = *iterator; // błędnie – próbujemy odczytać
</source>
Linia 39 ⟶ 48:
Sposób użycia iteratora bezpośredniego dostępu;
załóżmy ze nasz iterator wskazuje już składnik n-ty
<source lang="cpp">
iterator+=5; // '' teraz wskazuje (n+5)-ąty składnik▼
</source>
== Użycie w poszczególnych kontenerach (z przykładami) ==
Linia 47 ⟶ 58:
Przedstawimy teraz metody poszczególnych kontenerów, które umożliwiają operowanie na iteratorach. Należy podkreślić, że nazwy niektórych metod powtarzają się w różnych pojemnikach a także pełnią te same funkcje, dlatego nie będziemy ich za każdym razem dokładnie opisywać - podobnie jak przeładowanych operatorów.
Poruszanie się za pomocą iteratorów po kolejnych składowych może odbywać się na dwa sposoby:<br>
1) '''w przód''' - czyli od początku do końca np.:
<source lang="cpp">
</source>
początek struktury wyznacza metoda begin(); zaś koniec end();
2) '''od końca''' - czyli od końca do początku np.:
<source lang="cpp">
skanować możemy od rbegin(); do rend(); , co można utożsamiać z odwróconym początkiem i odwróconym końcem. ▼
</source>
▲skanować możemy od <tt>rbegin();</tt> do <tt>rend();
{cout<<*iter<<endl;}▼
Użycie zostanie zobrazowane na przykładzie kontenera <tt>vector</tt>.
=== Wektor ===
▲Aby użyć iteratora należy najpierw nadać mu wartość. Dlatego gdy chcemy powtarzać pewną operacje w pętli dla każdego elementu wektora – od początku do końca – inicjujemy iterator wartością bezparametrowej funkcji '''begin()'''. Metoda ta zwraca iterator wskazujący na pierwszy element pojemnika wektor. Jest to iterator bezpośredniego dostępu. Nie mamy jednak możliwości porównywania iteratora z wartością NULL (bo iterator zwykłym wskaźnikiem nie jest) musi istnieć metoda która pokazuje koniec naszego wektora. Tak też jest – metoda '''end()''' zwraca iterator za ostatnim elementem. To także jest iterator bezpośredniego dostępu.
Przykład:
<source lang="cpp">
vector<int> tab;▼
▲ #include <iostream>
▲ #include <vector>
▲ using namespace std;
▲ int main ()
▲ {
▲ vector<int> tab;
▲ ''//inicjujemy wektor kolejnymi liczbami naturalnymi''
tab.push_back(1);
tab.push_back(2);
tab.push_back(3);
vector<int>::iterator i;
for( i=tab.begin(); i
{
cout<< *i <<
}
return 0;
</source>
1
2
Linia 98 ⟶ 106:
Metody begin() i end() skonstruowane są do przeglądania wektora od początku do końca. Co jeśli chcemy działać na składowych wektora w odwrotnej kolejności? Nie ma problemu. Istnieje bowiem metoda '''rbegin()''', która zwraca odwrócony iterator wskazujący na ostatni element pojemnika (mówi się także, że jest to odwrócony początek). Odwołuje się on do elementu bezpośrednio poprzedzającego iterator wskazywany przez end. Jest to odwrócony iterator bezpośredniego dostępu. Mamy także metode '''rend()''', która zwraca odwrócony iterator do elementu odwołującego się do elementu bezpośrednio poprzedzającego pierwszy element kontenera wector (zwany także odwróconym końcem). rend() wskazuje miejsce bezpośrednio poprzedzające składnik do którego odwoływałby się begin(). Oto przykład:
<source lang="cpp">
vector<int> tab;
tab.push_back(1);
tab.push_back(2);
tab.push_back(3);
vector<int>::reverse_iterator i;
for( i=tab.rbegin(); i
{
cout<<*i<<
}
return 0;
</source>
3
2
Linia 129 ⟶ 137:
=== Listy jedno- i dwukierunkowe ===
Na liście dwukierunkowej działamy bardzo podobnie jak na wektorze. Tu także dysponujemy metodami '''begin()''' i '''end()''' zwracającymi wartość iteratora odpowiednio: na początek listy i tuż za koniec. Jest to iterator dwukierunkowy i możemy na nim działać zarówno do przodu (dzięki ++) jak i do tyłu (przez --). Mamy także analogiczne '''rbegin()''' i '''rend()''' zwracające odwrócony iterator do listy.
Przykład:
<source lang="cpp">
#include <iostream>▼
list<char> lista;
lista.push_back('a');
lista.push_back('b');
lista.push_back('c');
list<char>::iterator i;
cout<<"lista po kolei: ";
for( i=lista.begin(); i!=lista.end(); ++i )
{
cout<<*i<<" ";
}
cout<<"\nLista od tylu: ";
for( i = lista.end(); i!=lista.begin(); --i )
{
cout<<*i<<" ";
}
list<char>::reverse_iterator i2;
cout
for( i2=lista.rbegin(); i2 != lista.rend(); i2++ )
{
cout<<*i2<<" ";
}
cout<<
return 0;
</source>
Wynikiem działania programu będzie:
lista po kolei: a b c
Linia 181 ⟶ 192:
Iterator w zbiorach działa jak w innych kontenerach. Iterator działający na zbiorze jest dwukierunkowy – możemy więc korzystać ze wszystkich operatorów przeciążonych dla iteratora dwukierunkowego. Dodatkowo (jak z własności zbioru wynika) należy wspomnieć, że metoda '''begin()''' daje dostęp iteratorowi do pierwszego elementu zbioru, który równocześnie posiada najniższy klucz. W zbiorach możemy także korzystać z odwróconych iteratorów.
<source lang="cpp">
int o;
set<int> zbior;
Linia 193 ⟶ 204:
zbior.insert(1);
zbior.insert(11);
set<int>::iterator i; // teraz i jest wskaznikiem do zbioru▼
for(i=zbior.begin();i!=zbior.end();++i)▼
return 0;▼
}▼
▲ set<int>::iterator i; // teraz i jest wskaznikiem do zbioru
▲ for( i=zbior.begin(); i!=zbior.end(); ++i )
▲ return 0;
</source>
Wynikiem pracy programu będzie wypisanie cyfr:
1
|