2017-03-23 5 views
1

私は現在、ベクトルの範囲内に留まることにいくつか問題があります。私がチェックされている数がベクトル範囲内での滞在方法?

#include <iostream> 
#include <vector> 
#include <stdexcept> 

bool fun(std::vector<int> v) 
{ 
    for(int i = 0; i < v.size(); i++) 
    { 
     if(v.at(i) <= v.at(i+1)) 
     { 
      // code 
     } 
    } 
    return true; 
} 

int main() 
{  
    std::vector<int> v { 1,2,3,4,5,6,7,8,9 }; 

    try 
    { 
     std::cout << fun(v); 
    } 
    catch(std::out_of_range range_problem) 
    { 
     std::cout << "EXCEPTION: " << range_problem.what(); 
    } 
    return 0; 
} 

によりat()への後の数字に小さい又は等しいかどうかを確認しようとしていた次のコードで

、関数は例外ので、出力上記のコードを投げていますこの:

EXCEPTION: vector::_M_range_check

私は、forループでif(i+1 == v.size() - 1) break;を追加することを考えたが、それは私がそのベクトルの最後の2つの要素を比較することができないであろうことを意味します。

誰でもこの問題の解決策をお勧めしますか?

おかげで、コードのこのセクションでは

+4

どのようにfor'ループ 'の条件の変更について' i)が(v.sizeを< - 1; '? – songyuanyao

+0

ありがとうございました代替ソリューションはありませんか?チェックした値の一部をベクトルに保存したい場合は、それを返します。私は – noobcoder

+1

に必要ならば、最後の要素を特別に保存するif文をチェックする必要があります。最後の要素で特別なことをする必要があるなら 'if if i == v.size()-1) 'for'ループの中にあります。 – songyuanyao

答えて

2

for(int i = 0; i < v.size(); i++) 
    { 
     if(v.at(i) <= v.at(i+1)) 
     { 
      // code 
     } 
    } 

v.at(i+1)は、ループの最後の反復では、ベクターの末尾を越えて行きます。ループ内の条件をi < v.size()-1に変更すると、問題が解決されます。以下は

1

私はこのコードを記述する方法を次のとおりです。

auto prev = begin(v); 
auto it = prev; 
if(it == end(v)) 
    return; 
it ++; 
for(; it != end(v); it++, prev++) 
{ 
    if(*prev <= *it) 
    { 
     //code 
    } 
} 

いくつかのメリットがあります。

  1. それはlistと、このようなint v[] = {10,20,30,40,50};array<int, 5>として配列を含むコンテナの複数のタイプで動作しますが、

  2. イテレータは転送のみ可能であり、ランダムアクセスである必要はありません。

  3. あなたはインデックスが必要な場合は、まだdistance(begin(v), it)

デモからそれを得ることができます。link

1

いくつかの提案。

ベクトルに要素が1つしかない場合はどうなりますか?

これは決して起こり得ないかもしれませんが、とにかくそれをチェックします。

次に、後で2つの要素を操作する必要がある場合に備え、2つのインデックス変数を使用する方が簡単です。

bool fun(std::vector<int> v) 
{ 
    if (v.size() == 1) 
     return true; // Perhaps you would return false? 

    for(int i = 0, j = 1; i < v.size() && j < v.size() - 1; i++, j++) 
    { 
     if(v.at(i) <= v.at(j)) 
     { 
      // code 
     } 
    } 
    return true; 
} 
0

私はコメントに入れても、これを回答として投稿します。

成長する配列を行列に格納することについての説明がある場合、std::is_sorted_untilを使用する次のコード例は、単純なdo-whileループで使用できます。

#include <vector> 
#include <algorithm> 

bool fun(std::vector<int>& v) 
{ 
    // our matrix 
    std::vector<std::vector<int>> matrix; 

    // initially point to beginning of vector 
    auto startIter = v.begin(); 
    auto iter = startIter; 
    do 
    { 
     // return first item that is out of order 
     iter = std::is_sorted_until(startIter, v.end()); 

     // save everything as a matrix row, 
     // starting from beginning up to the item that's out of order 
     matrix.push_back({ startIter, iter }); 

     // set new starting position to the position of the 
     // item out-of-order 
     if (iter != v.end()) 
      startIter = iter; 
    } while (iter != v.end()); // keep going until we reach the end 

    return true; 
} 

Live Example

上記の例のコメントが発生しているかを説明するのに十分でなければなりません。

重要なことは、一連のデータで動作するループを書くときは常に、アルゴリズムや一連のSTLアルゴリズム関数があると考えています。この場合、そのアルゴリズムはstd::is_sorted_untilでした。


あなたは純粋にイテレータを使用して上記のより一般的なを行うことができます。

#include <vector> 
#include <algorithm> 

template <typename Iter> 
bool fun(Iter iter1, Iter iter2) 
{ 
    // our matrix 
    std::vector<std::vector<int>> matrix; 

    // initially point to beginning of vector 
    auto startIter = iter1; 
    auto iter = startIter; 
    do 
    { 
     // return first item that is out of order 
     iter = std::is_sorted_until(startIter, iter2); 

     // save everything as a matrix row, 
     // starting from beginning up to the item that's out of order 
     matrix.push_back({ startIter, iter }); 

     // set new starting position to the position of the 
     // item out-of-order 
     if (iter != iter2) 
      startIter = iter; 
    } while (iter != iter2); // keep going until we reach the end 

    return true; 
} 

int main() 
{ 
    int arr [] = { 1,2,3,2,5,6,4,8,3 }; 
    fun(arr, std::end(arr)); 
} 

Live Example

関連する問題