How can I iterate through a string and also know the index (current position)?

173,950

Solution 1

I've never heard of a best practice for this specific question. However, one best practice in general is to use the simplest solution that solves the problem. In this case the array-style access (or c-style if you want to call it that) is the simplest way to iterate while having the index value available. So I would certainly recommend that way.

Solution 2

Like this:


    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;

Solution 3

You can use standard STL function distance as mentioned before

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

Also, you can access string and some other containers with the c-like interface:

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

Solution 4

A good practice would be based on readability, e.g.:

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

Or:

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

Or your original:

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

Etc. Whatever is easiest and cleanest to you.

It's not clear there is any one best practice as you'll need a counter variable somewhere. The question seems to be whether where you define it and how it is incremented works well for you.

Solution 5

I would use it-str.begin() In this particular case std::distance and operator- are the same. But if container will change to something without random access, std::distance will increment first argument until it reach second, giving thus linear time and operator- will not compile. Personally I prefer the second behaviour - it's better to be notified when you algorithm from O(n) became O(n^2)...

Share:
173,950
pierrotlefou
Author by

pierrotlefou

Software Developer

Updated on September 07, 2020

Comments

  • pierrotlefou
    pierrotlefou over 3 years

    Often when iterating through a string (or any enumerable object), we are not only interested in the current value, but also the position (index). To accomplish this by using string::iterator we have to maintain a separate index:

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

    The style shown above does not seem superior to the 'c-style':

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

    In Ruby, we can get both content and index in a elegant way:

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

    So, what is the best practice in C++ to iterate through an enumerable object and also keep track of the current index?