daniel451
daniel451

Reputation: 11002

C++: looping over a string - iterator?

Let us assume I have different functions accessing a single String str (getting a single character of it) and I want to loop through this string with every access...how could I achieve this?

For example:

string str = "abc";
function1(); // returns "a"
function2(); // returns "b"
function3(); // returns "c"
function4(); // returns "a" again
function2(); // returns "b" again
...

So basically I have different functions accessing this string str and I need some kind of iterator which gets back to the first character of str if the end of str is reached.

Upvotes: 0

Views: 185

Answers (3)

Frought
Frought

Reputation: 116

I don't know how many times you need this to work, but here you are(You can edit it to fit with your needs):

#include <iostream>
#include <string>

int main()
{
   std::string str = "abc";

    bool bAgain = true;

    int Max = str.length() + 1;

    for(int i = 0; i < Max; i++)
    {
        std::cout << str[i] << "\n";

        if(bAgain)
        {
            if(i == Max - 1)
            {
                i = -1;
                bAgain = false;
                continue;
            }
        }
    }
}

`

Output

 a 
 b 
 c 
 a 
 b 
 c 

Upvotes: 0

Jerry Coffin
Jerry Coffin

Reputation: 490108

If you really want to use an iterator instead of indexing, you could use a cyclic_iterator, something like this:

#ifndef CYCLIC_ITERATOR_H_INC_
#define CYCLIC_ITERATOR_H_INC_
#include <iterator>

template <class FwdIt>
class cyclic_iterator_t : public std::iterator<std::input_iterator_tag, typename FwdIt::value_type> {
    FwdIt begin;
    FwdIt end;
    FwdIt current;
public:
    cyclic_iterator_t(FwdIt begin, FwdIt end) : begin(begin), end(end), current(begin) {}

    cyclic_iterator_t operator++() { 
        if (++current == end) 
            current = begin; 
        return *this; 
    }
    typename FwdIt::value_type operator *() const { return *current; }
};

template <class Container>
cyclic_iterator_t<typename Container::iterator> cyclic_iterator(Container &c) { 
    return cyclic_iterator_t<typename Container::iterator>(c.begin(), c.end());
}

#endif

This is quite minimal as iterators go--for example, it currently only supports pre-increment, not post-increment (and it's a forward iterator, so about all you can do with the iterator is increment it and dereference it).

Nonetheless, for the job you envision, it seems to be adequate.

Upvotes: 3

Cory Kramer
Cory Kramer

Reputation: 117856

I would just index out of the string using the % modulus operator. This will get you the wraparound behavior you want.

#include <iostream>
#include <string>

int main()
{
    std::string str = "abc";
    for (int i = 0; i < 10; ++i)
    {
        std::cout << str[i % str.size()] << " ";
    }
}

Output

a b c a b c a b c a

Upvotes: 2

Related Questions