2009-08-22 3 views
43

Beim Iterieren eines Strings (oder eines aufzählbaren Objekts) interessiert uns nicht nur der aktuelle Wert, sondern auch die Position (Index). Um dies zu erreichen, indem string::iterator verwenden, haben wir einen separaten Index halten:Wie kann ich durch einen String iterieren und weiß auch den Index (aktuelle Position)?

string str ("Test string"); 
    string::iterator it; 
    int index = 0; 
    for (it = str.begin() ; it < str.end(); it++ ,index++) 
    { 
     cout << index << *it; 
    } 

Above Stil scheint nicht überlegen scheinen die 'c-style'

string str ("Test string"); 
    for (int i = 0 ; i < str.length(); i++) 
    { 
     cout << i << str[i] ; 
    } 

In Ruby können wir sowohl Inhalte erhalten und Index in einer eleganten Art und Weise:

"hello".split("").each_with_index {|c, i| puts "#{i} , #{c}" } 

Also, was ist die beste Praxis in C++ durch ein zählbares Objekt iterieren und auch den Überblick über den aktuellen Index halten?

Antwort

34

ich noch nie gehört habe einer Best Practice für diese spezifische Frage. Eine bewährte Methode im Allgemeinen besteht jedoch darin, die einfachste Lösung zu verwenden, die das Problem löst. In diesem Fall ist der array-artige Zugriff (oder c-style, wenn Sie es so nennen wollen) die einfachste Möglichkeit zum Iterieren, während der Indexwert verfügbar ist. Also würde ich es auf jeden Fall empfehlen.

+0

ein Beispiel wäre nett: P –

42

So:


    std::string s("Test string"); 
    std::string::iterator it = s.begin(); 

    //Use the iterator... 
    ++it; 
    //... 

    std::cout << "index is: " << std::distance(s.begin(), it) << std::endl; 
1

Für Strings, können Sie string.c_str() verwenden, die Ihnen eine const char * zurück, die als ein Array, beispielsweise behandelt werden können:

const char* strdata = str.c_str(); 

for (int i = 0; i < str.length(); ++i) 
    cout << i << strdata[i]; 
+0

Diese Frage ist ähnlich wie meine eigene, also würde ich lieber hier fragen, wie vergleichen Sie den Wert von stardata [i] zu ""? Gibt es eine Möglichkeit, es in char umzuwandeln? – frogeyedpeas

6

Eine gute Praxis würde auf Lesbarkeit, zB:

string str ("Test string"); 
for (int index = 0, auto it = str.begin(); it < str.end(); ++it) 
    cout << index++ << *it; 

Oder:

string str ("Test string"); 
for (int index = 0, auto it = str.begin(); it < str.end(); ++it, ++index) 
    cout << index << *it; 

Oder Ihr original:

string str ("Test string"); 
int index = 0; 
for (auto it = str.begin() ; it < str.end(); ++it, ++index) 
    cout << index << *it; 

Etc. Was auch immer am einfachsten und saubersten zu Ihnen ist.

Es ist nicht klar, es gibt eine Best Practice, da Sie irgendwo eine Counter-Variable benötigen. Die Frage scheint zu sein, ob, wo Sie es definieren und wie es inkrementiert, gut für Sie arbeitet.

+0

Meine vorherige Bearbeitung ist korrekt, @Alex Reynolds. Überprüfen Sie [Es ist nicht möglich, zwei Variablen unterschiedlicher Typen im Initialisierungskörper einer 'for' -Schleife in' C++ 'zu deklarieren.] (Https://stackoverflow.com/questions/2687392/is-it-possible-to-declare -zwei Variablen verschiedener Typen in einer Schleife) und [dies] (https://ideone.com/lngBfo). – Bateman

19

können Sie Standard-STL-Funktion Abstand verwenden wie zuvor erwähnt

index = std::distance(s.begin(), it); 

Außerdem können Sie String und einige andere Behälter mit dem c-ähnliche Schnittstelle zugreifen:

for (i=0;i<string1.length();i++) string1[i]; 
+2

BTW, in meiner Implementierung Indizes arbeiten viel schneller, dass Iteratoren (5x und mehr) – Andrew

3

Ich würde it-str.begin() verwenden In diesem speziellen Fall sind std :: Abstand und Operator gleich. Aber wenn container zu etwas ohne zufälligen Zugriff wechselt, wird std :: distance das erste Argument inkrementieren, bis es die Sekunde erreicht, was somit lineare Zeit ergibt und operator - wird nicht kompiliert. Mir persönlich gefällt das zweite Verhalten - es ist besser informiert zu werden, wenn Sie von O-Algorithmus (n) wurde O (n^2) ...

1

Da std::distance ist nur konstante Zeit für Random-Access-Iteratoren, würde ich wahrscheinlich bevorzugen explizite Iteratorarithmetik. Da wir hier C++ - Code schreiben, glaube ich, dass eine C++ - idiomatische Lösung einem C-ähnlichen Ansatz vorzuziehen ist.