boost — C ++ Найти последнее вхождение строки внутри подстроки

Мне нужен метод, который помогает мне найти строку внутри другой подстроки или, другими словами, найти строку внутри поддиапазона другой строки. Кроме того, мне нужно найти его в обратном порядке, потому что я знаю, что искомая строка закрыта до конца подстроки, используемой как «стог сена».

Давайте предположим следующий фрагмент кода, где 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

Решение

От 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«полезные» методы.

Другой вариант заключается в использовании 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";
}
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.

3

С 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
}
2
По вопросам рекламы [email protected]