Starting loop at specific index of a std::string?

Viewed 225

I wrote the following function:

std::regex r("");

for (std::sregex_iterator i = words_begin; i != words_end; ++i) {}

It starts looking for regex matches from the beginning of the given string (str) But how may I tell it to exclude everything before specific index?

For example I want it to delete with all of what comes after index number 4 (Not including it).

Note: I am calling this code from another function so I tried something like str + 4 in the string parameter but I got an error that it's not l-value.

2 Answers

If I understand your question correctly you can pass a parameter to the function with the position where you'd like to start the search, and use it to set the iterator:

void print_str(const std::string& str, int pos)
{
    std::regex r("\\{[^}]*\\}");

    auto words_begin =
        std::sregex_iterator(str.begin() + pos, str.end(), r);
    //...
}
int main()
{
    std::string str = "somestring";
    func_str(str, 4);
}

Or pass the iterators themselves, one to the position you'd like to start the search and one to the end of the string:

void func_str(std::string::iterator it_begin, std::string::iterator it_end)
{
    std::regex r("\\{[^}]*\\}");

    auto words_begin =
        std::sregex_iterator(it_begin, it_end, r);
    //...
}
int main()
{
    std::string str = "somestring";
    func_str(str.begin() + 4, str.end());
}

As @bruno correctly stated, you may use str.substr(4) not str + 4, as an argument instead of the original string, the downside of the method is that it will create unnecessary copies of the string to be searched, as @Marek also correctly pointed out, thus the options of passing a position or begin and end iterators is less expensive. The upside is that you would not have to change anything in the function.

I suggest checking the std::smatch#position() to determine if the match is to be taken or discarded:

#include <iostream>
#include<regex>

int main() {
    std::regex r("\\{[^}]*\\}");
    std::string str("{1}, {2} and {3}");
    auto words_begin =
            std::sregex_iterator(str.begin(), str.end(), r);
    auto words_end = std::sregex_iterator();
    for (std::sregex_iterator i = words_begin; i != words_end; ++i) {
        std::smatch m = *i;
        if (m.position() > 4) {
          std::cout << m.str() << std::endl;
        }
    }
    return 0;
}

See the C++ demo online. Adjust the if condition as you need.

Here, the first {1} match is discarded since its position was less or equal than 4.

Related