2017-10-10 7 views
2

与えられた署名を持つ関数では、シーケンスの要素を最初のものから最後のものに並べ替えたい、その述語を満たすすべての要素がそうでない要素の前に置かれ、与えられた述語を満たさない最初の要素。イテレータを使って述語で再編成する

同じ位置に新しい要素がそれを満たしている場合に存在する元素は、述語が再び最後の1つの

  • チェックに置き換える満たしていない場合は私のアルゴリズムは、シーケンス
  • に反復

    • スタートです
    • (last-1)と置き換えない場合は、さらに進むようにしてください。
    • 既に交換した要素の1つに到達するまで繰り返す

    私のコード

    template<class Iterator, class Predicate> 
    Iterator Rearrange(Iterator first, Iterator last, Predicate pred) { 
        auto res = first; 
        if (first == last) { 
        ; 
        } 
        else { 
        auto run = first; 
        auto end = last; 
        auto tmp = *first; 
        while (run != end) { 
         if (pred(*run) == false) { 
         again: tmp = *(--end); 
        *end = *run; 
        *run = tmp; 
        if (pred(*run) == false) { 
         goto again; 
        } 
         } 
         ++run; 
        } 
        } 
        return res; 
    } 
    

    それは私に私が見つけ、理解することはできません

    terminate called after throwing an instance of 'std::range_error' 
        what(): dereferencing end of sequence 
    Aborted 
    

    を与えます。つまり、私はどこかでコンテナの外の要素を間接参照しようとしていますが、私のプログラムでそれを見ることはできません。誰も私がコーディングエラーを修正するか、私のアルゴリズムのロジックを改善するのを助けることができますか?

  • +1

    私は18年前に仕事がVB6からC++に移行してからC#に移行し、再び「goto」に取り組む必要はないと思っていました。 – Steve

    答えて

    3

    入力範囲が空でなく、その中の要素が述語を満たしていない場合、コードはgotoループにスタックされ、whileに再び到達しません。最終的に--endfirstの前にendになります。

    これは学習の練習であれば、gotoを取り除くことをお勧めします。 gotoはまれな正当な用途を持つことができますが、ループを置き換えることはその1つではありませんが、悪い習慣を学ぶことは望ましくありません。また、tmpのダンスはstd::swapに置き換えることができます。

    これは学習の練習ではない場合は、ちょうどあなたが望むものを実行するstd::partitionを使用してください。

    関連する問題