3

我需要一种方法来帮助我在另一个子字符串中找到一个字符串,或者换句话说,在另一个字符串的子范围内找到一个字符串。此外,我需要以相反的顺序找到它,因为我知道我要查找的字符串接近用作“干草堆”的子字符串的末尾。

让我们假设以下一段代码,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。

4

3 回答 3

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,您需要执行额外的步骤将结果范围转换为索引,就像这个答案一样,但如果您不是,那么只需使用范围接口并避免std::string' s “有用”的方法。

另一种选择是使用boost::string_ref基本上std::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";
}
于 2017-09-04T04:30:43.657 回答
3

您可以通过组合一个 API 来找到答案,该 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如果答案在子字符串的初始字符之前,则拒绝答案。

演示。

于 2017-09-04T02:03:55.557 回答
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
}
于 2017-09-04T02:53:25.457 回答