2017-09-04 11 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 ::文字列:: RFIND](http://en.cppreference.com/w/cpp/string/basic_string/rfind)? – Ron

+1

http://en.cppreference.com/w/cpp/string/basic_string/rfind私は_不要なコピーを見つけることはできません。 – user0042

+3

@ user0042 'rfind'は文字列全体を" haystack "として使いますが、探している文字列は完全な文字列の部分範囲内になければなりません。 –

答えて

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の「有用な」方法を避けてください。

別のオプションは、std::string_viewは基本的に基づいているものであるboost::string_refを使用することです:

#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

あなたは長さと最終的な結果は、前substr_begに来るかどうかを確認するための追加のチェックによって、元の文字列内の検索を制限APIを組み合わせることで答えを見つけることができます。

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は、部分文字列の最初の文字の前に来ると回答を拒否します。 std::find_end

Demo.

+0

これは、部分文字列が見つからない場合、 'str'の先頭まで検索することを意味します。 'str'は非常に長い' string'(これは 'from'の前に非常に長い接頭辞があります)ということです。 –

2

問題は、必要以上に使用することなく、効率的に解くことができますが、私はすでにそれを解決する任意の方法があった望んだ:

#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 + range goodnessを使用すると、私の意見ではより洗練されたものになりました。** [Live On Coliru](http://coliru.stacked-crooked.com/a/dbe9b5dd0803ec61)** – sehe

関連する問題