如何将两个增量语句放入 C++“for”循环中?
-
22-07-2019 - |
题
我想增加两个变量 for
-循环条件而不是一个。
所以像这样:
for (int i = 0; i != 5; ++i and ++j)
do_something(i, j);
这个的语法是什么?
解决方案
一个常见的习惯用法是使用 逗号运算符 它计算两个操作数,并返回第二个操作数。因此:
for(int i = 0; i != 5; ++i,++j)
do_something(i,j);
但这真的是逗号运算符吗?
现在写完后,一位评论者表示这实际上是 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);
}
我期望 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
但是,如果我将表达式括起来以强制解析器真正看到逗号运算符,我会得到这个
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
最初我认为这表明它根本不是逗号运算符,但事实证明,这只是一个优先级问题 - 逗号运算符有 尽可能低的优先级, ,因此表达式 x=i++,a++ 被有效解析为 (x=i++),a++
感谢所有的评论,这是一次有趣的学习经历,而且我已经使用 C 多年了!
其他提示
尝试此
for(int i = 0; i != 5; ++i, ++j)
do_something(i,j);
尽量不要这样做!
从 http://www.research.att.com/~bs/JSF-AV-rules.pdf:
AV 规则 199
A for循环中的增量表达式除了将单个循环参数更改为循环的下一个值外,不会执行任何动作。理由:可读性。
for (int i = 0; i != 5; ++i, ++j)
do_something(i, j);
我来这里是为了提醒自己如何将第二个索引编码到 FOR 循环的增量子句中,我知道这主要可以通过在我合并到另一个用 C++ 编写的项目中的示例中观察来完成。
今天,我使用 C# 工作,但我确信它在这方面会遵循相同的规则,因为 FOR 语句是所有编程中最古老的控制结构之一。值得庆幸的是,我最近花了几天时间精确记录了我的一个旧 C 程序中 FOR 循环的行为,我很快意识到这些研究提供了适用于当今 C# 问题的经验教训,特别是第二个索引变量的行为。
对于粗心的人来说,以下是我的观察总结。通过仔细观察“局部变量”窗口中的变量,我今天所看到的一切都证实了我的预期:C# FOR 语句的行为与 C 或 C++ FOR 语句完全相同。
- 第一次执行 FOR 循环时,将跳过增量子句(三个子句中的第三个)。在 Visual C 和 C++ 中,增量是在实现循环的块中间生成为三个机器指令,因此初始阶段仅运行一次初始化代码,然后跳过增量块来执行终止测试。这实现了 FOR 循环执行零次或多次的功能,具体取决于其索引和限制变量的状态。
- 如果执行循环体,则其最后一条语句将跳转到第一次迭代跳过的三个增量指令中的第一个指令。在这些执行之后,控制自然落入实现中间子句的限制测试代码中。该测试的结果确定 FOR 循环的主体是否执行,或者控制是否转移到经过其范围底部的跳转的下一条指令。
- 由于控制从 FOR 循环块的底部转移到增量块,因此索引变量在执行测试之前递增。这种行为不仅解释了为什么您必须按照您学到的方式编码限制子句,而且它会影响您通过逗号运算符添加的任何辅助增量,因为它成为第三个子句的一部分。因此,它在第一次迭代时没有改变,但在最后一次迭代时改变,它从不执行主体。
如果循环结束时任一索引变量仍在范围内,则在真正的索引变量的情况下,它们的值将比停止循环的阈值高。同样,例如,如果在进入循环之前将第二个变量初始化为零,则其最后的值将是迭代计数,假设它是增量 (++),而不是减量,并且其中没有任何内容循环体改变了它的值。
我同意斯奎拉特的观点。增加两个变量很容易出现错误,特别是如果您只测试其中之一。
这是执行此操作的可读方法:
for(int i = 0; i < 5; ++i) {
++j;
do_something(i, j);
}
For
循环适用于循环在一个递增/递减变量上运行的情况。对于任何其他变量,请在循环中更改它。
如果你需要 j
被束缚于 i
, ,为什么不保留原始变量并添加 i
?
for(int i = 0; i < 5; ++i) {
do_something(i,a+i);
}
如果您的逻辑更复杂(例如,您需要实际监视多个变量),我会使用 while
环形。
int main(){
int i=0;
int a=0;
for(i;i<5;i++,a++){
printf("%d %d\n",a,i);
}
}
使用数学。如果两个操作数学取决于循环迭代,为什么不能做数学题?
int i, j;//That have some meaningful values in them?
for( int counter = 0; counter < count_max; ++counter )
do_something (counter+i, counter+j);
或者,更具体地指的是OP的示例:
for(int i = 0; i != 5; ++i)
do_something(i, j+i);
特别是如果你传递由值的函数,那么你应该得到的东西,你想要做什么。