检查减少迭代器是否指向有效元素

时间:2014-05-09 17:44:15

标签: c++

我需要知道我是否可以减少迭代器并拥有一个有效的对象。以下错误因为我将迭代器减少1而不存在。我怎么知道所以我没有得到错误?

ticks.push_front(Tick(Vec3(0, 0, 5), 0));
ticks.push_front(Tick(Vec3(0, 0, 8), 100));
ticks.push_front(Tick(Vec3(0, 0, 10), 200));

bool found = false;
    list<Tick, allocator<Tick>>::iterator iter;
    for (iter = ticks.begin(); iter != ticks.end(); ++iter)
    {
        Tick t = (*iter);

        if (214>= t.timestamp)
        {
            prior = t;
            if (--iter != ticks.end())
            {
                next = (*--iter);
                found = true;
                break;
            }
        }
    }

我正在尝试直接在“上方”找到条目,并直接在“下方”列表中的值214。如果只有1存在那么我不在乎。我需要在上面和下面存在。

3 个答案:

答案 0 :(得分:1)

在您对问题进行编辑后,我认为我可以写出比以前更好的答案。

首先,为使用其时间戳的Tick编写一个比较函数:

bool CompareTicks(const Tick& l, const Tick& r)
{
   return l.timestamp < r.timestamp;
}

现在使用std::upper_bound的函数:

// Get an iterator pointing to the first element in ticks that is > 214
// I'm assuming the second parameter to Tick's ctor is the timestamp
auto itAbove = std::upper_bound(ticks.begin(), ticks.end(), Tick(Vec3(0, 0, 0), 214), CompareTicks);
if(itAbove == ticks.end())
   ; // there is nothing in ticks > 214. I don't know what you want to do in this case.

这将为您提供刻度线中的第一个元素&gt; 214.接下来,您可以使用lower_bound查找第一个元素&gt; = 214:

// get an iterator pointing to the first element in ticks that is >= 214
// I'm assuming the second parameter to Tick's ctor is the timestamp
auto itBelow = std::lower_bound(ticks.begin(), ticks.end(), Tick(Vec3(0, 0, 0), 214), CompareTicks);

你现在必须用itBelow做一个额外的步骤才能获得214之前的第一个元素,注意不要超过列表的开头:

if(itBelow == ticks.begin())
   ; // there is nothing in ticks < 214. I don't know what you want to do in this case.
else
   --itBelow;

现在,假设您没有遇到任何错误情况,itAbove指向第一个元素&gt; 214,itBelow指向最后一个元素&lt; 214。

这假定您的Tick按时间顺序排列,这似乎就是这种情况。另请注意,即使列表中有多个214,此技术也能正常工作。最后,你说这个列表很短,所以它并不值得担心时间复杂度,但如果你还用list代替vector,这种技术可以让你获得对数性能迭代方法的线性。

答案 1 :(得分:1)

您的核心问题的答案很简单。如果你在最后,不要增加。如果你刚开始就不要减少。

在递增之前,请检查。

if ( iter == ticks.end() )

在降级之前,请检查。

if ( iter == ticks.begin() )

您的特定示例

看看你想要完成什么,我怀疑你打算使用:

        if (iter != ticks.begin())

而不是

        if (--iter != ticks.end())

<强>更新

您似乎依赖于按时间戳排序的列表内容。

在您发表评论后,我认为您需要的是:

    if (214>= t.timestamp)
    {
        prior = t;
        if (++iter != ticks.end())
        {
            next = *iter;
            if ( 214 <= next.timestep )
            {
               found = true;
               break;
            }
        }
    }

更新2

我同意@crashmstr的评论。你的逻辑可以是:

    if (214 <= t.timestamp)
    {
        next = t;
        if ( iter != ticks.begin())
        {
            prior = *--(iter);
            found = true;
            break;
        }
    }

答案 2 :(得分:1)

我认为您可以使用标准库std::adjacent_find中的<algorithm>执行所需操作。默认情况下,std::adjacent_find会查找两个连续的相同的元素,但您可以提供自己的函数来定义您感兴趣的关系。

这是一个简单的例子:

#include <algorithm>
#include <iostream>
#include <list>

struct matcher
{
    matcher(int value) : target(value) {}
    bool operator()(int lo, int hi) const {
        return (lo < target) && (target < hi);
    }
    int target;
};

int main()
{
    std::list<int> ticks = { 0, 100, 200, 300 };

    auto it = std::adjacent_find(ticks.begin(), ticks.end(), matcher(214));

    if (it != ticks.end()) {
        std::cout << *it << ' ' << *std::next(it) << '\n';
    } else {
        std::cout << "not found\n";
    }
}

这会输出200 300,两个&#34;周围&#34;它找到的价值。