0

ここで質問に答えました: https://stackoverflow.com/a/28862668/2642059繰り返しを使用してstring. 各関数のパラメーターとしてa を使用したかったconst string&のですが、再帰ごとに文字列を再構築したい場合を除き、それ自体だけでなく astartfinish位置を渡す必要があることがわかりました。そのため、合格することはまったくstring無意味になりました。string

start最後に、とfinishへのポインターを渡すだけにしましたchar[]


例として、ネストされた括弧を含む文字列が与えられたとします(ただし、括弧の挿入は並んでいません)。したがって、次のようになります。

(abc(def(ghi((j)klm)nop)qrs)tuv)wxyz

しかし、このようではありません:

(abc(def)(ghi)(j)(klm)(nop)(qrs)tuv)wxyz

最も深くネストされた括弧内の文字列を抽出する再帰プログラムを作成したいと考えています。何かのようなもの:

string foo(const string& bar){
    auto start = bar.find('(') + 1;

    return start == string::npos + 1 ? bar : foo(bar.substr(start, bar.find_last_of(')') - start));
}

ただし、stringの繰り返しごとに を再構築するのは不満ですfoo。別の方法は、リンクされた例のようにstartandfinishポインターを渡すことです (またはstring::const_iterators を渡すこともできます)。

string機能を使用できるが、再構築できないラッパーまたは何かがありstringますか?

4

2 に答える 2

1

自分で書いてくださいarray_view<T>。数十行のコードです。

std::find両方のアルゴリズムを置き換えるために使用します。場合によっては、逆反復子を使用します。(または範囲ベースの検索と範囲ベースのを書くbackwards

{T*,T*}ctor を使用して再帰します。

array_view<const char> foo(array_view<const char> bar)

ここにプリミティブがありarray_view<T>ます:

template<class T>
struct array_view {
  using mutable_T = typename std::remove_reference<T>::type;
  // 3 primitive functions:
  T* begin() const { return b; }
  T* end() const { return e; }
  array_view(T* s, T* f):b(s), e(f) {};
  // everything else based on them:
  size_t size() const { return end()-begin(); }
  array_view(T* s, size_t l):array_view(s,s+l) {}
  array_view():array_view(nullptr,  nullptr) {}
  // repeat next 3 for string, array, initializer list, C array as required:
  template<class A>
  array_view( std::vector<T,A>& v ):array_view(v.data(), v.size()) {}
  // may not compile for non-const T, but that is ok  you get an error:
  template<class A>
  array_view( std::vector<mutable_T,A>const & v ):array_view(v.data(), v.size()) {}
  // in a better world, you'd SFINAE remove the above from consideration
  // consider it for your next iteration of array_view.
  // conversion to containers:
  template<class A>
  explicit operator std::vector<mutable_T,A>() const {
    return convert_to< std::vector<mutable_T, A> >();
  }
  template<class C>
  C convert_to() const {
    C retval(begin(), end());
    return retval;
  }

  // utility functions:
  T& front() const { return *begin(); }
  T& back() const { return std::prev(*end()); }
  // Also rbegin, rend, and whatever else you find you are missing

  // inspired by std::experimental:
  void pop_front() { *this = {std::next(begin()), end()}; }
  void pop_back() { *this = {begin(), std::prev(end())}; }
  // but I find direct use of `view = {x,y}` almost as good
  // these kind of operations are the ONLY ones that are non-const
  // remember this is a view.  If you want a view of const data, make it
  // an array_view<const T>, not a const array_view<T>.  It really works
  // out better.
private:
  T* b
  T* e;
};

上記のサンプル コードはテストされていません。

于 2015-03-12T12:29:45.933 に答える