2017-09-04 93 views
3

我需要一種方法幫助我在另一個子字符串中查找字符串,換句話說,在其他字符串的子範圍內查找字符串。此外,我需要以相反的順序找到它,因爲我知道我正在查找的字符串被關閉到用作「haystack」的子字符串的末尾。C++查找子字符串中最後一次發生的字符串

讓我們假設下面的一段代碼,其中rfind_in_substr是我所要求的方法:

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

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)可以被替換但這意味着一個不需要的子串副本。有沒有什麼方法或C++/boost方法可以幫助我做到這一點?

我在看boost::algorithm::string圖書館,但我什麼都沒發現(我已經理解了)。我知道C++ 17有std::string_view類,這將是完美的,但我使用C++ 14。

+3

有什麼不好的[的std :: string :: RFIND(http://en.cppreference.com/w/CPP /串/ basic_string的/ RFIND)? – Ron

+1

http://en.cppreference.com/w/cpp/string/basic_string/rfind我無法找到_unnecessary copies_。 – user0042

+3

@ user0042'rfind'使用整個字符串作爲「乾草堆」,但是我正在查找的字符串必須僅在完整字符串的子範圍中找到。 –

回答

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這樣的索引,但如果不是,則只需使用範圍界面並避免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.

+0

這意味着如果找不到子字符串,搜索到「str」的開頭。我們認爲'str'是一個非常長的'string'(它在'from'之前有一個非常長的前綴)。 –

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 
} 
+2

使用一些string_view +範圍善良使它在我看來更加優雅:** [Live On Coliru](http://coliru.stacked-crooked.com/a/dbe9b5dd0803ec61)** – sehe

相關問題