如何保持在矢量范围内?

时间:2017-03-23 01:51:07

标签: c++ vector

我目前在向量中保持一个范围时遇到一些问题。

在下面的代码中,我试图检查正在检查的数字是否小于或等于数字

#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;,但这意味着我无法比较该向量中的最后两个元素。

有人可以推荐这个问题的解决方案吗?

谢谢

4 个答案:

答案 0 :(得分: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 :(得分: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)
  4. 获取索引

    演示link

答案 2 :(得分:1)

一些建议。

如果你的矢量只有一个元素怎么办?

这可能永远不会发生,但无论如何我会检查它。

然后我发现在这些情况下使用两个索引变量更容易,以防我以后需要操作这两个元素。

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;
}

答案 3 :(得分: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