Ist es möglich, einen Vektor vom Ende bis zum Anfang zu iterieren?
for (vector<my_class>::iterator i = my_vector.end();
i != my_vector.begin(); /* ?! */ ) {
}
Oder ist das nur mit so etwas möglich:
for (int i = my_vector.size() - 1; i >= 0; --i) {
}
Antworten:
Der beste Weg ist:
rbegin()
Ichrend()
wurde speziell für diesen Zweck entwickelt. (Und ja, wenn Sie areverse_interator
erhöhen, wird es rückwärts verschoben.)Theoretisch würde Ihre Methode (mit
begin()
/end()
&--i
) funktionieren, dastd::vector
der Iterator bidirektional ist. Denken Sie jedoch daran, dass diesend()
nicht das letzte Element ist - es ist eines, das über das letzte Element hinausgeht. Sie müssten also zuerst dekrementieren, und Sie sind es erledigt, wenn Sie erreichenbegin()
- aber Sie müssen noch Ihre Verarbeitung durchführen.UPDATE: Ich war anscheinend zu aggressiv beim Umschreiben der
for()
Schleife in einewhile()
Schleife. (Der wichtige Teil ist, dass das--i
am Anfang ist.)quelle
--i
dass dies ein großes Problem verursachen wird, wenn der Container leer ist ... Bevor Sie in diedo - while
Schleife gehen, ist es sinnvoll, dies zu überprüfen(my_vector.begin() != my_vector.end())
.do-while
Schleife anstelle einerwhile
Schleife? Dann brauchen Sie keine spezielle Prüfung für leere Vektoren.auto
um sie besser lesbar zu machen?Wenn Sie C ++ 11 haben, können Sie davon Gebrauch machen
auto
.quelle
Das gut etablierte "Muster" für die Rückwärtsiteration durch geschlossen-offene Bereiche sieht wie folgt aus
oder, wenn Sie es vorziehen,
Dieses Muster ist beispielsweise nützlich, um ein Array mithilfe eines vorzeichenlosen Index rückwärts zu indizieren
(Personen, die mit diesem Muster nicht vertraut sind, bestehen häufig darauf, vorzeichenbehaftete Ganzzahltypen für die Array-Indizierung zu verwenden, da sie fälschlicherweise glauben, dass vorzeichenlose Typen für die umgekehrte Indizierung irgendwie "unbrauchbar" sind.)
Es kann zum Iterieren über ein Array unter Verwendung einer "Gleitzeiger" -Technik verwendet werden
oder es kann für die umgekehrte Iteration über einen Vektor unter Verwendung eines gewöhnlichen (nicht umgekehrten) Iterators verwendet werden
quelle
--end()
end()
. Obwohl sie anscheinend bei beginnenend()
, stellen sie immer sicher, dass der Iterator vor dem ersten Zugriff dekrementiert wird.auto a = vector<int>{0,1,2}; bool reversed = 0; auto it = (!reversed?a.begin():a.end()); auto end = (reversed?a.begin():a.end());
while(it != end) { if(reversed)--it; cout << *it << endl; if(!reversed)++it; }
reversed
vier Mal - zwei davon in einer Schleife. Natürlich ist das Testen eines Booleschen Werts sehr schnell, aber warum müssen Sie nicht arbeiten, um zu arbeiten? Zumal der einzige Zweck darin zu bestehen scheint, den Code unlesbar zu machen. Wie wäre es, wenn wir zwei separate Schleifen verwenden?if (reversed) for (auto it = my_vector.rbegin(); it != my_vector.rend(); ++it) {doStuff(*it);} else for (auto it = my_vector.begin(); it != my_vector.end(); ++it) {doStuff(*it);}
if
aber ich wollte die Vorlage auf der Seite loswerdendoStuff()
. Immer noch machbar mit den beidenif
s, die Sie haben, indem Sie den ersten umgekehrt drehen.Ab c ++ 20 können Sie eine
std::ranges::reverse_view
und eine bereichsbasierte for-Schleife verwenden:Oder auch
Leider implementiert zum Zeitpunkt des Schreibens (Januar 2020) kein großer Compiler die Bereichsbibliothek, aber Sie können auf Eric Nieblers Bereiche-v3 zurückgreifen :
quelle
Benutzeriteratoren
rend() / rbegin()
:for (vector<myclass>::reverse_iterator it = myvector.rbegin(); it != myvector.rend(); it++)
quelle
Dann:
Alternativ können Sie in C ++ 14 auch Folgendes tun:
In C ++ 03/11 haben die meisten Standardcontainer auch eine
.rbegin()
und.rend()
-Methode.Schließlich können Sie den Bereichsadapter
backwards
wie folgt schreiben :und jetzt können Sie dies tun:
was ich ziemlich hübsch finde.
quelle
Verwenden Sie umgekehrte Iteratoren und eine Schleife von
rbegin()
bisrend()
quelle
Hier ist eine supereinfache Implementierung, die die Verwendung von für jedes Konstrukt ermöglicht und nur auf der C ++ 14-Standardbibliothek basiert:
Dies funktioniert mit Dingen, die ein rbegin () und ein rend () liefern, sowie mit statischen Arrays.
quelle
Ich mag den Rückwärtsiterator am Ende von Yakk - Adam Nevraumonts Antwort, aber es schien kompliziert für das, was ich brauchte, also schrieb ich Folgendes:
Ich kann einen normalen Iterator wie diesen verwenden:
und ändern Sie es in dieses, um es in umgekehrter Reihenfolge zu wiederholen:
quelle
Wenn Sie The Boost Library verwenden können, gibt es den Boost.Range , der den
reverse
Bereichsadapter bereitstellt , indem er Folgendes enthält :In Kombination mit der Range-
for
Schleife eines C ++ 11 können Sie dann einfach Folgendes schreiben:Da dieser Code kürzer ist als der, der das Iteratorpaar verwendet, ist er möglicherweise besser lesbar und weniger fehleranfällig, da weniger Details zu beachten sind.
quelle
Verwenden Sie diesen Code
quelle
Da ich die neue Syntax von Alien Mars überhaupt nicht einführen möchte und einfach auf vorhandenen Grundelementen aufbauen möchte, scheinen die folgenden Ausschnitte zu funktionieren:
quelle