2008-11-04 7 views
5

Ich würde gerne zwei aufeinanderfolgende Elemente in einer std :: list vergleichen, während ich durch die Liste iteriere. Was ist der richtige Weg, um auf Element i + 1 zuzugreifen, während sich mein Iterator auf Element i befindet? Dank CobeVergleichen Sie zwei aufeinanderfolgende Elemente in std :: list

+0

Wenn es möglich ist, möchten Sie vielleicht den Fragetitel in "Wie vergleiche ich zwei aufeinanderfolgende Elemente in Std :: Liste?" Ändern. Ich würde es selbst machen, aber nicht den Ruf haben ;-) –

Antwort

10

-Boost hat ein Dienstprogramm next (und seine Umkehrung, prior) genannt für genau diesen Zweck.

*itr == *next(itr) 

Edit: Aber wenn wir einen Schritt zurück in den Wald zu sehen, die echte Frage ist, warum benutzerdefinierte schreiben Sie Ihre adjacent_find Funktion? (Ich empfehle die Antwort von Nicola Bonelli zu akzeptieren.) Das ist Teil der STL, und erfordert nicht Boost, wenn Ihr Code Boost nicht verwendet (dank der Kommentatoren für das Aufzeigen).

+0

Es macht Spaß, wie fast jede C++ - Frage auf der Seite völlig anders lautet "wenn du Boost hast" und "wenn du auf Standard-C++ beschränke" Antworten. Fast so, als ob sie verschiedene Sprachen wären ... –

+0

Ich habe das gleiche gedacht :) – warren

+0

Es ist wie verschiedene Sprachen! Boost ist, was C++ für mich sinnvoll macht. :-P Die Verwendung von Boost ist nicht so, wie wenn SRFIs beim Schreiben von Programmcode nicht verwendet werden. :-P –

8

Der einfachste Weg wäre, zwei Iteratoren zu halten (da Sie sowieso beim vorletzten stoppen müssen).

std::list<int>::const_iterator second = list.begin(), 
           end = list.end(); 

if (second != end) // Treat empty list 
    for(std::list<int>::const_iterator first = second++; // Post-increment 
     second != end; 
     ++first, ++second) 
    { 
     //... 
    } 

anzumerken, dass mit dem firstpost-incrementation von second so initialisiert wird, wenn die Schleife beginnt firstlist.begin() ist und die zweite ist list.begin()+1.

Chris Jester-Young points out die next und prior Funktionen steigern kann, auch wenn ich mit diesen Funktionen nicht vertraut bin (für meine Sünden) deren Umsetzung ist trivial (besonders wenn man bedenkt, dass list bidirektionale Iteratoren hat).

template <class Iterator> 
Iterator next(Iterator i) // Call by value, original is not changed 
{ 
    return ++i; 
} 
// Implementing prior is left as an exercise to the reader ;o) 

Mein Gefühl ist, dass die Verwendung von next dieses Problem nicht Suite sowie die beiden Iteratoren beibehalten, da Sie sich daran erinnern müssen, um sicherzustellen, next(i) nicht gleich end() bei jedem Gebrauch.


Edits:

  • Fehler behoben, wenn die Liste leer dank Luc Touraille ‚s Kommentar.
  • Hinzufügen Verweis auf next und warum ich denke, es passt nicht zu diesem Anwendungsfall.
+0

Ups nach dem Schreiben der Implementierung von nächsten sehe ich, dass es genau das gleiche wie in dem Link Chris in Hallo Post enthalten ist. – Motti

+0

Ahh, die Kraft der einfachen, offensichtlichen Lösungen! :-P denke ich immer noch neben_find ist die einfachste Lösung der Partie, aber ja. –

10

STL stellt den boundary_find() - Algorithmus zur Verfügung, mit dem zwei aufeinanderfolgende gleiche Elemente gefunden werden können. Es gibt auch eine Version mit einem benutzerdefinierten Prädikat.

Dies sind die Prototypen:

template <class ForwardIterator> 
    ForwardIterator adjacent_find (ForwardIterator first, ForwardIterator last); 

template <class ForwardIterator, class BinaryPredicate> 
    ForwardIterator adjacent_find (ForwardIterator first, ForwardIterator last, 
            BinaryPredicate pred); 
+0

Ihre Antwort ist die Antwort, die ich selbst geschrieben habe; Ich hoffe, das OP akzeptiert Ihre Antwort. Gutes Zeug! +1 (naja ich würde +5, aber die Seite erlaubt das nicht) –

1

Liste ist ein Wende Container, so seine Iteratoren Bidirektionale Iteratoren sind, die ein Modell der Vorwärts Iterator ist, die ich ziemlich sicher bin, bedeutet, dass Sie dies tun können (oder etwas Gleichwertiges, wenn Sie das Ausbrechen aus der Mitte einer Schleife usw. allergisch sind):

if (!l.empty()) { 
    for (list<T>::const_iterator i = l.begin();;) { 
     const T &a = *i; 
     ++i; 
     if (i == l.end()) break; 
     do_comparison(a, *i); 
    } 
} 

Sie konnten das nicht tun, mit einem InputIterator, denn mit denen die Werte nur „existieren“, so lange wie Sie einen Iterator bei ihnen haben. Aber Sie können mit einem Forward Iterator.

0
for (list<int>::iterator it = test.begin(); it!=test.end(); it++) { 
     cout<<*it<<":\t"; 
     list<int>::iterator copy = it; 
     for(list<int>::iterator it2 = ++copy; it2!=test.end();it2++){ 
      cout<<*it2<<"\t"; 
     } 
     cout<<endl; 
    }