for 循环的简写 - C++中的语法糖(11)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/29512963/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Shorthand for for-loop - syntactic sugar in C++(11)
提问by dingalapadum
Actually these are two related questions.
其实这是两个相关的问题。
I know there is a new syntax in C++11 for range-based for
loops of the form:
我知道 C++11 中有一种新语法用于for
以下形式的基于范围的循环:
//v is some container
for (auto &i: v){
// Do something with i
}
First question: how can I infer at which iteration I am in this loop? (Say I want to fill a vector with value j at position j).
第一个问题:我如何推断我在这个循环中的哪个迭代?(假设我想在位置 j 用值 j 填充向量)。
Second question: I wanted to know if there also is some other way to write a loop of the form
第二个问题:我想知道是否还有其他方法可以编写表单的循环
for (int i=0; i<100; i++) { ... }
I find this way of writing it a bit cumbersome, and I do this so often and I would love to have a more concise syntax for it. Something along the lines:
我发现这种写法有点麻烦,而且我经常这样做,我希望有一个更简洁的语法。沿线的东西:
for(i in [0..99]){ ... }
would be great.
会很好。
For both questions I would like to avoid having to use additional libraries.
对于这两个问题,我都希望避免使用额外的库。
回答by Mike Seymour
First answer: you don't. You've used a simple construct for a simple purpose; you'll need something more complicated if you have more complicated needs.
第一个答案:你没有。您已经为一个简单的目的使用了一个简单的构造;如果您有更复杂的需求,您将需要更复杂的东西。
Second answer: You could make an iterator type that yields consecutive integer values, and a "container" type that gives a range of those. Unless you have a good reason to do it yourself, Boost has such a thing:
第二个答案:您可以创建一个生成连续整数值的迭代器类型,以及一个给出这些值范围的“容器”类型。除非你有充分的理由自己做,否则 Boost 有这样的东西:
#include <boost/range/irange.hpp>
for (int i : boost::irange(0,100)) {
// i goes from 0 to 99 inclusive
}
回答by Peter K
回答by Angew is no longer proud of SO
For the first question, the answer is pretty simple: if you need the iteration count, don't use the syntactic construct which abstracts away the iteration count. Just use a normal for
loop and not the range-based one.
对于第一个问题,答案非常简单:如果您需要迭代计数,请不要使用抽象出迭代计数的句法结构。只需使用普通for
循环而不是基于范围的循环。
For the second question, I don't think there's anything currently in the standard library, but you could use a boost::irange
for it:
对于第二个问题,我认为标准库中目前没有任何内容,但您可以使用 a boost::irange
:
for (int i : boost::irange(0, 100))
回答by onqtam
For the second question - if Boostis too heavy, you could always use this library:
对于第二个问题 - 如果Boost太重,你总是可以使用这个库:
for(auto i : range(10, 15)) { cout << i << '\n'; }
will print 10 11 12 13 14
for(auto i : range(10, 15)) { cout << i << '\n'; }
将打印 10 11 12 13 14
for(auto i : range(20, 30, 2)) { cout << i << '\n'; }
will print 20 22 24 26 28
for(auto i : range(20, 30, 2)) { cout << i << '\n'; }
将打印 20 22 24 26 28
Doubles and other numeric types are supported too.
也支持双精度和其他数字类型。
It has other pythonic iteration tools and is header-only.
它有其他 pythonic 迭代工具,并且只有头文件。
回答by Matt
You can do both of these things with Boost.Range: http://boost.org/libs/range
你可以用 Boost.Range 做这两件事:http://boost.org/libs/range
boost::adaptors::indexed
: element value & indexboost::irange
: integer range
boost::adaptors::indexed
: 元素值和索引boost::irange
: 整数范围
For brevity (and to spice things up a little, since boost::irange
has been already demonstrated in isolation), here's a sample code demonstrating these features working together:
为简洁起见(为了让事情更有趣,因为boost::irange
已经单独演示了),这里有一个示例代码,演示了这些功能一起工作:
// boost::adaptors::indexed
// http://www.boost.org/doc/libs/master/libs/range/doc/html/range/reference/adaptors/reference/indexed.html
#include <boost/range/adaptor/indexed.hpp>
// boost::irange
// http://www.boost.org/doc/libs/master/libs/range/doc/html/range/reference/ranges/irange.html
#include <boost/range/irange.hpp>
#include <iostream>
#include <vector>
int main()
{
std::vector<int> input{11, 22, 33, 44, 55};
std::cout << "boost::adaptors::indexed" << '\n';
for (const auto & element : input | boost::adaptors::indexed())
{
std::cout << "Value = " << element.value()
<< " Index = " << element.index()
<< '\n';
}
endl(std::cout);
std::cout << "boost::irange" << '\n';
for (const auto & element : boost::irange(0, 5) | boost::adaptors::indexed(100))
{
std::cout << "Value = " << element.value()
<< " Index = " << element.index()
<< '\n';
}
return 0;
}
Sample output:
示例输出:
boost::adaptors::indexed
Value = 11 Index = 0
Value = 22 Index = 1
Value = 33 Index = 2
Value = 44 Index = 3
Value = 55 Index = 4
boost::irange
Value = 0 Index = 100
Value = 1 Index = 101
Value = 2 Index = 102
Value = 3 Index = 103
Value = 4 Index = 104
回答by Stuck
For the 2nd question:
对于第二个问题:
There is another way, but I would not use or recommend it. However, for quickly setting up a test you could write:
还有另一种方式,但我不会使用或推荐它。但是,为了快速设置测试,您可以编写:
if you do not want to use a library and you are fine with only providing the top bound of the range you can write:
如果您不想使用库并且只提供可以编写的范围的上限就可以了:
for (auto i:vector<bool>(10)) {
cout << "x";
}
This will create a boolean vector of size 10, with uninitialized values. Looping through these unitialized values using i
(so do notuse i
) it will print 10 times "x".
这将创建一个大小为 10 的布尔向量,其中包含未初始化的值。通过使用这些未初始化值循环i
(所以千万不能使用i
),将打印10次“×”。
回答by Yakk - Adam Nevraumont
If v
is a vector (or any std
contiguous container), then
如果v
是向量(或任何std
连续的容器),则
for(auto& x : v ) {
size_t i = &x-v.data();
x = i;
}
will set the ith entry to the value i
.
将第 i 个条目设置为 value i
。
An output iterator that counts is reasonably easy to write. Boosthas one and has an easy-to-generate range of them called irange
.
一个计数的输出迭代器相当容易编写。Boost有一个,并且有一个易于生成的范围,称为irange
.
Extracting the indexes of a container is relatively easy. I have written a function called indexes
that can take a container, or a range of integers, and produces random output iterators over the range in question.
提取容器的索引相对容易。我编写了一个名为的函数indexes
,它可以接受一个容器或一个整数范围,并在所讨论的范围内产生随机输出迭代器。
That gives you:
这给你:
for (size_t i : indexes(v) ) {
v[i] = i;
}
There probably is an equivalent container-to-index range function in Boost.
Boost 中可能有一个等效的容器到索引范围函数。
If you need both, and you don't want to do the work, you can write a zipper.
如果两者都需要,又不想做这个工作,可以写一个zipper。
for( auto z : zip( v, indexes(v) ) ) {
auto& x = std::get<0>(z);
size_t i = std::get<1>(z);
x = i;
}
where zip
takes two or more iterable ranges (or containers) and produces a range view over tuples of iterator_traits<It>::reference
s to the elements.
wherezip
需要两个或多个可迭代范围(或容器),并生成iterator_traits<It>::reference
s元组到元素的范围视图。
Here is Boost zip iterator: http://www.boost.org/doc/libs/1_41_0/libs/iterator/doc/zip_iterator.html-- odds are there is a Boost zip range that handles syntax like the above zip
function.
这是 Boost zip 迭代器:http: //www.boost.org/doc/libs/1_41_0/libs/iterator/doc/zip_iterator.html—— 可能有一个 Boost zip 范围可以处理类似上述zip
函数的语法。
回答by Sheen
For the second question, if you are using the latest Visual Studio versions, type 'if' then Tab, Tab, and Tabto fill in init value, step-up and so on.
对于第二个问题,如果您使用的是最新的 Visual Studio 版本,请键入 'if' then Tab、Tab、 并Tab填写 init 值、step-up 等。