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

C++ Find last ocurrence of a string inside a substring

我需要一种方法来帮助我在另一个子字符串中找到一个字符串,或者换句话说,在其他字符串的子范围内找到一个字符串。此外,我需要以相反的顺序找到它,因为我知道我要查找的字符串已关闭到用作 "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 class,那将是完美的,但我使用的是 C++14。

您可以通过组合 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 如果答案出现在子字符串的初始字符之前,则拒绝答案。

Demo.

使用 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
}

来自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 的其他成员函数一起使用,则需要执行额外的步骤将结果范围转换为索引,例如 ,但如果您不是t,然后简单地使用范围接口并避免使用 std::string 的 "helpful" 方法。

另一种选择是使用 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";
}