如何在一个c++ 'for'循环中添加两个增量语句?

时间:2022-05-10 11:17:56

I would like to increment two variables in a for-loop condition instead of one.

我想在for循环条件中增加两个变量,而不是一个。

So something like:

所以类似:

for (int i = 0; i != 5; ++i and ++j) 
    do_something(i, j);

What is the syntax for this?

它的语法是什么?

8 个解决方案

#1


124  

A common idiom is to use the comma operator which evaluates both operands, and returns the second operand. Thus:

一个常见的习惯用法是使用逗号运算符来计算两个操作数,并返回第二个操作数。因此:

for(int i = 0; i != 5; ++i,++j) 
    do_something(i,j);

But is it really a comma operator?

Now having wrote that, a commenter suggested it was actually some special syntactic sugar in the for statement, and not a comma operator at all. I checked that in GCC as follows:

写完这篇文章后,一位评论者认为这实际上是for语句中的某种特殊语法糖,而不是逗号运算符。我在GCC中进行了如下检查:

int i=0;
int a=5;
int x=0;

for(i; i<5; x=i++,a++){
    printf("i=%d a=%d x=%d\n",i,a,x);
}

I was expecting x to pick up the original value of a, so it should have displayed 5,6,7.. for x. What I got was this

我希望x取a的原值,所以应该显示5 6 7。对于x,我得到的是这个

i=0 a=5 x=0
i=1 a=6 x=0
i=2 a=7 x=1
i=3 a=8 x=2
i=4 a=9 x=3

However, if I bracketed the expression to force the parser into really seeing a comma operator, I get this

但是,如果我把表达式括起来,迫使解析器真正地看到逗号运算符,我就得到了这个

int main(){
    int i=0;
    int a=5;
    int x=0;

    for(i=0; i<5; x=(i++,a++)){
        printf("i=%d a=%d x=%d\n",i,a,x);
    }
}

i=0 a=5 x=0
i=1 a=6 x=5
i=2 a=7 x=6
i=3 a=8 x=7
i=4 a=9 x=8

Initially I thought that this showed it wasn't behaving as a comma operator at all, but as it turns out, this is simply a precedence issue - the comma operator has the lowest possible precedence, so the expression x=i++,a++ is effectively parsed as (x=i++),a++

最初我认为这表明它根本不是一个逗号运算符,但事实证明,这只是一个优先问题——逗号运算符的优先级可能最低,因此表达式x= I ++,a++ +被有效地解析为(x= I ++ +),a+

Thanks for all the comments, it was an interesting learning experience, and I've been using C for many years!

谢谢大家的评论,这是一次有趣的学习经历,我使用C语言已经很多年了!

#2


51  

Try this

试试这个

for(int i = 0; i != 5; ++i, ++j)
    do_something(i,j);

#3


4  

Try not to do it!

尽量不要这样做!

From http://www.research.att.com/~bs/JSF-AV-rules.pdf:

从http://www.research.att.com/ ~ bs / JSF-AV-rules.pdf:

AV Rule 199
The increment expression in a for loop will perform no action other than to change a single loop parameter to the next value for the loop.

一个for循环中的增量表达式将不执行任何操作,而是将单个循环参数更改为循环的下一个值。

Rationale: Readability.

理由是:可读性。

#4


3  

for (int i = 0; i != 5; ++i, ++j) 
    do_something(i, j);

#5


2  

I came here to remind myself how to code a second index into the increment clause of a FOR loop, which I knew could be done mainly from observing it in a sample that I incorporated into another project, that written in C++.

我来这里是为了提醒自己如何将第二个索引编码到FOR循环的increment子句中,我知道这可以通过观察一个示例来完成,我将这个示例合并到另一个用c++编写的项目中。

Today, I am working in C#, but I felt sure that it would obey the same rules in this regard, since the FOR statement is one of the oldest control structures in all of programming. Thankfully, I had recently spent several days precisely documenting the behavior of a FOR loop in one of my older C programs, and I quickly realized that those studies held lessons that applied to today's C# problem, in particular to the behavior of the second index variable.

今天,我在c#工作,但是我确信在这方面它会遵守同样的规则,因为FOR语句是所有编程中最古老的控制结构之一。值得庆幸的是,我最近花了几天时间,在我以前的一个C程序中精确地记录了FOR循环的行为,我很快意识到,这些研究对今天的c#问题,尤其是第二个索引变量的行为有借鉴意义。

For the unwary, following is a summary of my observations. Everything I saw happening today, by carefully observing variables in the Locals window, confirmed my expectation that a C# FOR statement behaves exactly like a C or C++ FOR statement.

对于粗心的人,以下是我的观察总结。通过仔细观察局部变量窗口中的变量,我今天看到的一切都证实了我的预期,即c# FOR语句的行为与C或c++ FOR语句的行为完全相同。

  1. The first time a FOR loop executes, the increment clause (the 3rd of its three) is skipped. In Visual C and C++, the increment is generated as three machine instructions in the middle of the block that implements the loop, so that the initial pass runs the initialization code once only, then jumps over the increment block to execute the termination test. This implements the feature that a FOR loop executes zero or more times, depending on the state of its index and limit variables.
  2. 当FOR循环第一次执行时,将跳过增量子句(它的三个子句中的第三个)。在Visual C和c++中,增量在实现循环的块中间以三个机器指令的形式生成,这样初始传递只运行一次初始化代码,然后跳过增量块执行终止测试。这实现了FOR循环执行0或更多次的特性,这取决于其索引的状态和限制变量。
  3. If the body of the loop executes, its last statement is a jump to the first of the three increment instructions that were skipped by the first iteration. After these execute, control falls naturally into the limit test code that implements the middle clause. The outcome of that test determines whether the body of the FOR loop executes, or whether control transfers to the next instruction past the jump at the bottom of its scope.
  4. 如果执行循环的主体,它的最后一条语句将跳转到第一次迭代跳过的三个增量指令中的第一个。在这些执行之后,控制自然地落入实现中间子句的极限测试代码中。该测试的结果决定了FOR循环的主体是否执行,或者控制是否通过其作用域底部的跳转转移到下一个指令。
  5. Since control transfers from the bottom of the FOR loop block to the increment block, the index variable is incremented before the test is executed. Not only does this behavior explain why you must code your limit clauses the way you learned, but it affects any secondary increment that you add, via the comma operator, because it becomes part of the third clause. Hence, it is not changed on the first iteration, but it is on the last iteration, which never executes the body.
  6. 由于控制从FOR循环块的底部转移到递增块,所以在执行测试之前,索引变量将递增。这种行为不仅解释了为什么必须按照所学的方式编写limit子句,而且还会影响通过逗号运算符添加的任何二次增量,因为它是第三子句的一部分。因此,它在第一次迭代中没有改变,但是在最后一次迭代中,它从不执行主体。

If either of your index variables remains in scope when the loop ends, their value will be one higher than the threshold that stops the loop, in the case of the true index variable. Likewise, if, for example, the second variable is initialized to zero before the loop is entered, its value at the end will be the iteration count, assuming that it is an increment (++), not a decrement, and that nothing in the body of the loop changes its value.

如果在循环结束时,您的任何一个索引变量仍然在范围内,那么它们的值将会比停止循环的阈值高一个,在真实索引变量的情况下。同样,如果在输入循环之前将第二个变量初始化为0,那么它在最后的值将是迭代计数,假设它是一个增量(++),而不是递减,并且循环主体中的任何东西都不会改变它的值。

#6


1  

I agree with squelart. Incrementing two variables is bug prone, especially if you only test for one of them.

我同意squelart。增加两个变量是容易出错的,特别是如果您只测试其中一个变量。

This is the readable way to do this:

这是一种可读的方法:

for(int i = 0; i < 5; ++i) {
    ++j;
    do_something(i, j);
}

For loops are meant for cases where your loop runs on one increasing/decreasing variable. For any other variable, change it in the loop.

For循环指的是循环在一个递增/递减变量上运行的情况。对于任何其他变量,在循环中更改它。

If you need j to be tied to i, why not leave the original variable as is and add i?

如果需要将j与i绑定,为什么不保留原始变量原样并添加i呢?

for(int i = 0; i < 5; ++i) {
    do_something(i,a+i);
}

If your logic is more complex (for example, you need to actually monitor more than one variable), I'd use a while loop.

如果您的逻辑更复杂(例如,实际上需要监视多个变量),我将使用while循环。

#7


0  

int main(){
    int i=0;
    int a=0;
    for(i;i<5;i++,a++){
        printf("%d %d\n",a,i);
    } 
}

#8


0  

Use Maths. If the two operations mathematically depend on the loop iteration, why not do the math?

使用数学。如果这两个操作在数学上依赖于循环迭代,为什么不进行数学运算呢?

int i, j;//That have some meaningful values in them?
for( int counter = 0; counter < count_max; ++counter )
    do_something (counter+i, counter+j);

Or, more specifically referring to the OP's example:

或者,更具体地指OP的例子:

for(int i = 0; i != 5; ++i)
    do_something(i, j+i);

Especially if you're passing into a function by value, then you should get something that does exactly what you want.

特别是当你通过值传递到一个函数时,你应该得到一个完全符合你要求的东西。

#1


124  

A common idiom is to use the comma operator which evaluates both operands, and returns the second operand. Thus:

一个常见的习惯用法是使用逗号运算符来计算两个操作数,并返回第二个操作数。因此:

for(int i = 0; i != 5; ++i,++j) 
    do_something(i,j);

But is it really a comma operator?

Now having wrote that, a commenter suggested it was actually some special syntactic sugar in the for statement, and not a comma operator at all. I checked that in GCC as follows:

写完这篇文章后,一位评论者认为这实际上是for语句中的某种特殊语法糖,而不是逗号运算符。我在GCC中进行了如下检查:

int i=0;
int a=5;
int x=0;

for(i; i<5; x=i++,a++){
    printf("i=%d a=%d x=%d\n",i,a,x);
}

I was expecting x to pick up the original value of a, so it should have displayed 5,6,7.. for x. What I got was this

我希望x取a的原值,所以应该显示5 6 7。对于x,我得到的是这个

i=0 a=5 x=0
i=1 a=6 x=0
i=2 a=7 x=1
i=3 a=8 x=2
i=4 a=9 x=3

However, if I bracketed the expression to force the parser into really seeing a comma operator, I get this

但是,如果我把表达式括起来,迫使解析器真正地看到逗号运算符,我就得到了这个

int main(){
    int i=0;
    int a=5;
    int x=0;

    for(i=0; i<5; x=(i++,a++)){
        printf("i=%d a=%d x=%d\n",i,a,x);
    }
}

i=0 a=5 x=0
i=1 a=6 x=5
i=2 a=7 x=6
i=3 a=8 x=7
i=4 a=9 x=8

Initially I thought that this showed it wasn't behaving as a comma operator at all, but as it turns out, this is simply a precedence issue - the comma operator has the lowest possible precedence, so the expression x=i++,a++ is effectively parsed as (x=i++),a++

最初我认为这表明它根本不是一个逗号运算符,但事实证明,这只是一个优先问题——逗号运算符的优先级可能最低,因此表达式x= I ++,a++ +被有效地解析为(x= I ++ +),a+

Thanks for all the comments, it was an interesting learning experience, and I've been using C for many years!

谢谢大家的评论,这是一次有趣的学习经历,我使用C语言已经很多年了!

#2


51  

Try this

试试这个

for(int i = 0; i != 5; ++i, ++j)
    do_something(i,j);

#3


4  

Try not to do it!

尽量不要这样做!

From http://www.research.att.com/~bs/JSF-AV-rules.pdf:

从http://www.research.att.com/ ~ bs / JSF-AV-rules.pdf:

AV Rule 199
The increment expression in a for loop will perform no action other than to change a single loop parameter to the next value for the loop.

一个for循环中的增量表达式将不执行任何操作,而是将单个循环参数更改为循环的下一个值。

Rationale: Readability.

理由是:可读性。

#4


3  

for (int i = 0; i != 5; ++i, ++j) 
    do_something(i, j);

#5


2  

I came here to remind myself how to code a second index into the increment clause of a FOR loop, which I knew could be done mainly from observing it in a sample that I incorporated into another project, that written in C++.

我来这里是为了提醒自己如何将第二个索引编码到FOR循环的increment子句中,我知道这可以通过观察一个示例来完成,我将这个示例合并到另一个用c++编写的项目中。

Today, I am working in C#, but I felt sure that it would obey the same rules in this regard, since the FOR statement is one of the oldest control structures in all of programming. Thankfully, I had recently spent several days precisely documenting the behavior of a FOR loop in one of my older C programs, and I quickly realized that those studies held lessons that applied to today's C# problem, in particular to the behavior of the second index variable.

今天,我在c#工作,但是我确信在这方面它会遵守同样的规则,因为FOR语句是所有编程中最古老的控制结构之一。值得庆幸的是,我最近花了几天时间,在我以前的一个C程序中精确地记录了FOR循环的行为,我很快意识到,这些研究对今天的c#问题,尤其是第二个索引变量的行为有借鉴意义。

For the unwary, following is a summary of my observations. Everything I saw happening today, by carefully observing variables in the Locals window, confirmed my expectation that a C# FOR statement behaves exactly like a C or C++ FOR statement.

对于粗心的人,以下是我的观察总结。通过仔细观察局部变量窗口中的变量,我今天看到的一切都证实了我的预期,即c# FOR语句的行为与C或c++ FOR语句的行为完全相同。

  1. The first time a FOR loop executes, the increment clause (the 3rd of its three) is skipped. In Visual C and C++, the increment is generated as three machine instructions in the middle of the block that implements the loop, so that the initial pass runs the initialization code once only, then jumps over the increment block to execute the termination test. This implements the feature that a FOR loop executes zero or more times, depending on the state of its index and limit variables.
  2. 当FOR循环第一次执行时,将跳过增量子句(它的三个子句中的第三个)。在Visual C和c++中,增量在实现循环的块中间以三个机器指令的形式生成,这样初始传递只运行一次初始化代码,然后跳过增量块执行终止测试。这实现了FOR循环执行0或更多次的特性,这取决于其索引的状态和限制变量。
  3. If the body of the loop executes, its last statement is a jump to the first of the three increment instructions that were skipped by the first iteration. After these execute, control falls naturally into the limit test code that implements the middle clause. The outcome of that test determines whether the body of the FOR loop executes, or whether control transfers to the next instruction past the jump at the bottom of its scope.
  4. 如果执行循环的主体,它的最后一条语句将跳转到第一次迭代跳过的三个增量指令中的第一个。在这些执行之后,控制自然地落入实现中间子句的极限测试代码中。该测试的结果决定了FOR循环的主体是否执行,或者控制是否通过其作用域底部的跳转转移到下一个指令。
  5. Since control transfers from the bottom of the FOR loop block to the increment block, the index variable is incremented before the test is executed. Not only does this behavior explain why you must code your limit clauses the way you learned, but it affects any secondary increment that you add, via the comma operator, because it becomes part of the third clause. Hence, it is not changed on the first iteration, but it is on the last iteration, which never executes the body.
  6. 由于控制从FOR循环块的底部转移到递增块,所以在执行测试之前,索引变量将递增。这种行为不仅解释了为什么必须按照所学的方式编写limit子句,而且还会影响通过逗号运算符添加的任何二次增量,因为它是第三子句的一部分。因此,它在第一次迭代中没有改变,但是在最后一次迭代中,它从不执行主体。

If either of your index variables remains in scope when the loop ends, their value will be one higher than the threshold that stops the loop, in the case of the true index variable. Likewise, if, for example, the second variable is initialized to zero before the loop is entered, its value at the end will be the iteration count, assuming that it is an increment (++), not a decrement, and that nothing in the body of the loop changes its value.

如果在循环结束时,您的任何一个索引变量仍然在范围内,那么它们的值将会比停止循环的阈值高一个,在真实索引变量的情况下。同样,如果在输入循环之前将第二个变量初始化为0,那么它在最后的值将是迭代计数,假设它是一个增量(++),而不是递减,并且循环主体中的任何东西都不会改变它的值。

#6


1  

I agree with squelart. Incrementing two variables is bug prone, especially if you only test for one of them.

我同意squelart。增加两个变量是容易出错的,特别是如果您只测试其中一个变量。

This is the readable way to do this:

这是一种可读的方法:

for(int i = 0; i < 5; ++i) {
    ++j;
    do_something(i, j);
}

For loops are meant for cases where your loop runs on one increasing/decreasing variable. For any other variable, change it in the loop.

For循环指的是循环在一个递增/递减变量上运行的情况。对于任何其他变量,在循环中更改它。

If you need j to be tied to i, why not leave the original variable as is and add i?

如果需要将j与i绑定,为什么不保留原始变量原样并添加i呢?

for(int i = 0; i < 5; ++i) {
    do_something(i,a+i);
}

If your logic is more complex (for example, you need to actually monitor more than one variable), I'd use a while loop.

如果您的逻辑更复杂(例如,实际上需要监视多个变量),我将使用while循环。

#7


0  

int main(){
    int i=0;
    int a=0;
    for(i;i<5;i++,a++){
        printf("%d %d\n",a,i);
    } 
}

#8


0  

Use Maths. If the two operations mathematically depend on the loop iteration, why not do the math?

使用数学。如果这两个操作在数学上依赖于循环迭代,为什么不进行数学运算呢?

int i, j;//That have some meaningful values in them?
for( int counter = 0; counter < count_max; ++counter )
    do_something (counter+i, counter+j);

Or, more specifically referring to the OP's example:

或者,更具体地指OP的例子:

for(int i = 0; i != 5; ++i)
    do_something(i, j+i);

Especially if you're passing into a function by value, then you should get something that does exactly what you want.

特别是当你通过值传递到一个函数时,你应该得到一个完全符合你要求的东西。