可以基于范围的循环知道结束
Can range-based for loops be aware of the end?
给定最小C++11 STL示例:
set<int> S = {1,2,3,4};
for(auto &x: S) {
cout << x;
cout << ",";
}
有没有办法检查x
是否就是结尾前的那个?本例的目标是输出1,2,3,4
,而不是末尾的最后一个逗号。目前,我使用了一个带有两个迭代器的标准循环,
set<int>::const_iterator itr;
set<int>::const_iterator penultimate_end_itr = --S.end();
for(itr=S.begin(); itr!=penultimate_end_itr;++itr)
cout << (*itr) << ',';
cout << (*penultimate_end_itr);
这很有效,但非常麻烦。有没有办法在基于for循环的范围内进行检查?
编辑:问题的重点是而不是打印出逗号分隔的列表。我想知道基于范围的for循环是否知道列表中倒数第二个元素(即,它是否在末尾之前)。给出了一个最小的例子,所以我们都有一个共同的代码块可以讨论。
基于范围的for循环的目的就是忘记迭代器。因此,它们只允许您访问当前值,而不允许您访问迭代器。下面的代码能帮你吗?
set<int> S = {1,2,3,4};
std::string output;
for(auto &x: S) {
if (!output.empty())
output += ",";
output += to_string(x);
}
cout << output;
编辑
另一种解决方案:您可以比较值的地址,而不是比较迭代器(就像对循环的"正常"所做的那样):
set<int> S = {1,2,3,4};
auto &last = *(--S.end());
for (auto &x : S)
{
cout << x;
if (&x != &last)
cout << ",";
}
Boost.Range可以在这里提供帮助:
if (std::begin(S) != std::end(S)) {
std::cout << *std::begin(S);
for (const auto &x: boost::make_iterator_range(std::next(std::begin(S)), std::end(S))) {
std::cout << ", " << x;
}
}
一种更灵活的方法是使用boost::adaptors::indexed
(自Boost 1.56以来)对范围进行索引:
for (const auto &element: boost::adaptors::index(S)) {
std::cout << (element.index() ? ", " : "") << element.value();
}
在1.56之前的Boost版本中,boost::adaptors::indexed
不起作用,但你可以很容易地写出类似的作品:
template <typename... T>
auto zip(const T&... ranges) -> boost::iterator_range<boost::zip_iterator<decltype(boost::make_tuple(std::begin(ranges)...))>>
{
auto zip_begin = boost::make_zip_iterator(boost::make_tuple(std::begin(ranges)...));
auto zip_end = boost::make_zip_iterator(boost::make_tuple(std::end(ranges)...));
return boost::make_iterator_range(zip_begin, zip_end);
}
template<typename T>
auto enumerate(const T &range) -> boost::iterator_range<boost::zip_iterator<boost::tuple<
boost::counting_iterator<decltype(boost::distance(range))>, decltype(std::begin(range))>>>
{
return zip(boost::make_iterator_range(boost::make_counting_iterator(0),
boost::make_counting_iterator(boost::distance(range))), range);
}
for (const auto &tup: enumerate(S)) {
std::cout << (tup.get<0>() ? ", " : "") << tup.get<1>();
}
这是在使用c++11的Sequence-zip函数中的zip
函数吗?
相关文章:
- 为什么在这个代码结束循环中没有得到结束
- 当调用switch语句中的函数时(即使函数不包含循环),似乎是永不结束的循环的问题
- 使用 shared_ptr 在中断时结束多线程循环
- 如何使用循环结束 c++ 上的行
- 具有迭代器和自定义步长的循环结束条件
- 为什么这个 while 循环在下面的代码中没有结束?
- 为什么在使用不相关的宏时会阻止 while 循环结束?
- 为什么我的 while 循环永远不会在 C++ 中的数字猜测游戏中结束?
- while 循环 C++ 结束,但不继续到其余语句
- 为什么循环结束时不这样做?
- 向量中指针的前半部分在循环结束后被重新分配
- For 循环结束自身并终止正在运行的程序,但在删除斜率计算语句时正常运行
- 有没有一个C++版本在循环结束后将在for循环初始化中声明的变量保留在作用域中
- 数组循环在循环结束后输出垃圾
- C++ - 如果在循环中声明对象,是否在循环结束时调用其析构函数
- Dlsym以无限循环结束
- 为什么我总是以无限循环结束
- 崩溃控制台应用程序,在循环结束时.寻求建议.(图片在里面)
- 在while循环结束时清除c++字符串
- Vector迭代器+偏移量超出范围,在while循环结束时给出错误