2011-06-21 61 views
15

我现在有for循环以下:迭代对于第二到最后一个元素列表中的

for(list<string>::iterator jt=it->begin(); jt!=it->end()-1; jt++) 

我有字符串这是一个更大的列表(list<list<string> >)的列表。我想遍历内部列表的内容,直到到达第二个到最后一个元素。这是因为我已经处理了最后一个元素的内容,没有理由再次处理它们。

但是,使用it->end()-1是无效的 - 我不能在这里使用-运算符。虽然我可以使用运算符--,但这会在每个循环中递减最后的迭代器。

我相信一个STL列表是一个双向链表,所以从我的角度来看,应该可以做到这一点。

建议?在此先感谢

回答

9

使用标准库所需的建议:

std::for_each(lst.begin(), --lst.end(), process); 

如果你不想创建一个仿函数[我几乎没做]费尽口舌,而不能使用反向迭代器,葫芦结束检查出循环:

for(iterator i = lst.begin(), j = --lst.end(); i != j; ++i) { 
    // do 
    // stuff 
} 

或者,你可以信任优化承认,它没有继续重建结束条件,并做了提升本身。它的可靠程度取决于列表实现,循环代码的复杂程度以及优化器的性能。

无论如何,只要做一件最容易理解的事情,并在完成后担心性能。

+0

我很欣赏这个解决方案的简单性。是的,使用反向迭代器的其他解决方案非常好 - 但是您的解决方案在不使用特殊迭代器的情况下教会了我一种方法。 – BSchlinker

+0

“如果你不想为创建一个仿函数而烦恼” - 今天我会建议只在那里粘贴一个lambda – Paladin

6

列表迭代器不是随机迭代器。你应该做到以下几点:

if (! it->empty()) 
{ 
    list<string>::iterator test = it->end(); 
    --test; 
    for(list<string>::iterator jt = it->begin(); jt != test; ++jt) 
    { 
    ... 
    } 
} 

一件事:使用++jtjt++jt++源代码通常看起来是这样的:

iterator operator++ (int i) 
{ 
    iterator temp = (*this); 
    ++(*this); 
    return temp; 
}; 
4

虽然我可以使用 - 运营商,这将减小在每个周期这最后的迭代器。

不,它不会。它会得到一个复制结束迭代器并将其递减。就这样。它不会更改存储在列表中的结束迭代器。

您的主要问题应该是验证列表是而不是为空,从而确保存在--it-> end()。

4

逆向迭代器呢?

for(list<string>::reverse_iterator jt=++(it->rbegin()); jt!=it->rend(); jt++) 
+0

这实际上是由于使用了“!”会导致错误运算符在语句“jt!= it-> rend();” – BSchlinker

+0

该类型应该是'list :: reverse_iterator',而不仅仅是'list :: iterator'。 –

+0

不知道反向迭代器 - 谢谢! – BSchlinker

1

在C++ 11后,最好的答案似乎是对http://en.cppreference.com/w/cpp/iterator/prev说使用std::prev

for(iterator i = lst.begin(); i != std::prev(lst.end()); ++i) { 
    // do 
    // stuff 
} 

的文档的std ::分组,

虽然表达 - c.end()经常编译,但不保证这样做:c.end()是一个右值表达式,并且没有迭代器要求指定右值的递减保证工作。特别是,当迭代器实现为指针时,--c.end()不会编译,而std :: prev(c.end())会执行。

相信的std ::上一个()的空名单上是不确定的,所以你可能需要在!i.empty()条件来包装这个

相关问题