Iterator, Schleifen und Schleifen"index"
-
Ich bin gerade dabei den C++-Primer durchzuarbeiten. Dort steht nun, dass man auf alle möglichen Container der Standardbibliothek am besten per Iterator (Generator?) zugreifen soll. Häufig will man ja aber neben dem eigentlich Element des Containers noch die Nummer des Schleifendurchlaufs zu wissen.
Ist das hier dann die übliche Lösung, oder gibt es da einen "eleganteren" Weg ?
#include <iostream> #include <vector> #include <string> using namespace std; int main() { vector<string> animals(1, "rabbit"); animals.push_back("horse"); animals.push_back("bird"); int i = 0; for (vector<string>::const_iterator iter = animals.begin(); iter != animals.end(); iter++) { cout << i << ' ' << *iter << endl; i++; } return 0; }
0 rabbit 1 horse 2 bird
-
noch_unwissender schrieb:
Ich bin gerade dabei den C++-Primer durchzuarbeiten. Dort steht nun, dass man auf alle möglichen Container der Standardbibliothek am besten per Iterator (Generator?) zugreifen soll. Häufig will man ja aber neben dem eigentlich Element des Containers noch die Nummer des Schleifendurchlaufs zu wissen.
Das Problem ist hierbei, das nicht bei allen Containertypen ein Index existiert, oder der Weg diesen zu bestimmen sehr aufwändig wäre. Bei einen Vektor mag der Aufwand gering sein, da die Elemente in direkter Folge liegen, bei einer Liste (Einzelelemente die mit Zeigern verbunden sind) oder einer Map (in der Regel binärer Suchbaum oder ähnliches) ist dies aber nicht gegeben.
Davon abgesehen ist die Nummer des Schleifendurchlaufes sehr selten relevant (In der Praxis zumindestens war dieser Fall so selten, das ein Mitschleppen eines Indexes [der sich bei jeder Änderung je nach Containertyp ändern kann!] dann nicht den Aufwand darstellt).
Daher: Nein, eine leichtere Art ist mir nicht (zumindestens nicht Containerneutral) bekannt.
-
Ok, vielen Dank.
-
? Im Falle eines std::vector
for (int i=0;i<animals.size();++i) { std::cout<<i<<" "<<animals[i]; }
oder habe ich was falsch verstanden? Kürzer und übersichtlicher.
-
bloo schrieb:
Kürzer und übersichtlicher.
Vor allem aber weniger flexibel.
Man kennt den Iterator nicht (der aber gerade für STL-Algorithmen von Bedeutung sein könnte) und muss den ganzen Code umschreiben, wenn man dann plötzlich einen anderen Container wählt, der keinen Random Access unterstützt.
Deshalb: Solange man nur von Anfang bis Ende durchiteriert, sollte man Iteratoren einsetzen. Es hat schon einen Grund, warum diese so heissen.
-
bloo schrieb:
? Im Falle eines std::vector
for (int i=0;i<animals.size();++i) { std::cout<<i<<" "<<animals[i]; }
oder habe ich was falsch verstanden? Kürzer und übersichtlicher.
Naja, wirklich schön ist das auch nicht, 2 verschiedene Sorten von Schleifen zu benutzen. Irgendwann machst du vielleicht aus dem Vektor eine Liste, und schon mußt du an zig verschiedenen Stellen irgendwelche Schleifen komplett umkrempeln, weil es so dann eben doch nicht mehr geht.
Den aktuellen Index kriegt man übrigens auch mit
std::distance(animals.begin(), i);
Bei einem Vektor ist das kein Problem, bei anderen Containern kann das allerdings sehr ineffizient sein.
-
dooooomi schrieb:
Bei einem Vektor ist das kein Problem, bei anderen Containern kann das allerdings sehr ineffizient sein.
Man kann auch
operator-
verwenden, der wird nur von Random-Access-Iteratoren unterstützt.
-
Auch nicht bei jedem Container ist der operator[] const. Kann auch zu Problemen führen. Bei einer std::map muss man zB find() verwenden (oder eben const_iterator).