C ++查找子字符串中字符串的最后一次出现

时间:2017-09-04 01:09:53

标签: c++ boost range string-algorithm

我需要一个方法来帮助我在另一个子字符串中找到一个字符串,换句话说,在其他字符串的子范围内找到一个字符串。此外,我需要以相反的顺序找到它,因为我知道我正在寻找的字符串关闭到用作" haystack"的子字符串的末尾。

让我们假设以下代码,其中rfind_in_substr是我要求的方法:

std::string sample("An example with the example word example trice");

// substring "ample with the example wo"
std::size_t substr_beg = 5;
std::size_t substr_size = 24;

// (1)
std::size_t pos = rfind_in_substr(sample, substr_beg,
                                  substr_size, "example");

// pos == 20, because its the index of the start of the second
// "example" word inside the main string. 

当然,第(1)行可以替换为:

std::size_t pos = substr_beg + sample.substr
            (substr_beg, substr_size).rfind("example");

但这意味着子串的不必要副本。是否有任何方法或C ++ / boost方法可以帮助我做到这一点?

我在看boost::algorithm::string图书馆,但我一无所获(我已经理解了)。我知道C ++ 17有std::string_view类,这是完美的,但我使用的是C ++ 14。

3 个答案:

答案 0 :(得分:3)

您可以通过组合API来限制原始字符串中的搜索长度,并进行额外检查以查看最终结果是否在substr_beg之前找到答案:

std::size_t rfind_in_substr(
    const std::string& str
,   const std::size_t from
,   const std::size_t len
,   const std::string& sub
) {
    std::size_t res = str.rfind(sub, from+len-sub.size());
    return res != string::npos && res >= from ? res : string::npos;
}
  • from+len-sub.size()计算子字符串可以开始的最后位置。
  • res >= from拒绝答案,如果它出现在子字符串的初始字符之前。

Demo.

答案 1 :(得分:3)

来自Boost.StringAlgo:

#include <boost/algorithm/string/find.hpp>

auto haystack = boost::make_iterator_range(str.begin() + from, str.begin() + from + len);
auto found = boost::algorithm::find_last(haystack, needle);

现在,如果您需要将其与std::string中的其他成员函数一起使用,则需要执行额外的步骤,将结果范围转换为this answer does之类的索引,但如果您不是t,然后只需使用范围界面,避免std::string&#34;有用&#34;方法

另一种选择是使用boost::string_refstd::string_view基本上是基于:

#include <iostream>
#include <boost/utility/string_ref.hpp>


std::size_t rfind_in_substr(std::string const& str, std::size_t from,
                            std::size_t len, std::string const& s)
{

    return from + boost::string_ref(str).substr(from, len).rfind(s);
}

int main()
{
    std::string sample("An example with the example word example trice");

    // substring "ample with the example wo"
    std::size_t substr_beg = 5;
    std::size_t substr_size = 24;

    // (1)
    std::size_t pos = rfind_in_substr(sample, substr_beg,
                                      substr_size, "example");

    // pos == 20, because its the index of the start of the second
    // "example" word inside the main string. 
    std::cout << pos << "\n";
}

答案 2 :(得分:2)

使用std::find_end可以有效地解决问题而不需要使用超过需要的问题,但我希望有任何方法已经解决了这个问题:

#include <iostream>
#include <string>
#include <algorithm>

std::size_t rfind_in_substr(std::string const& str, std::size_t from,
                            std::size_t len, std::string const& s)
{
    auto sub_beg = str.begin() + from;
    auto sub_end = sub_beg + len;

    auto found_it = std::find_end(sub_beg, sub_end, s.begin(), s.end());

    if (found_it == sub_end)
        return str.npos;
    else
        return found_it - str.begin();
}

int main()
{
    std::string sample("An example with the example word example trice");

    // substring "ample with the example w"
    std::size_t substr_beg = 5;
    std::size_t substr_size = 24;

    std::size_t pos = rfind_in_substr(sample, substr_beg,
                                      substr_size, "example");

    std::cout << pos << std::endl; // Prints 20
}