如果我在continue
循环中使用while
,为什么它会进入无限循环,但在for
循环中工作正常?
如果我在i++
之后使用循环计数器增量while
,则会在continue
循环中忽略它,但如果它在for
循环中则有效。
如果continue
忽略后续语句,那么为什么它不会忽略for
循环的第三个语句,其中包含计数器增量i++
?不是for
循环后续到continue
的第三个语句,并且应该被忽略,因为执行了for
循环的第三个语句在循环体之后?
while(i<10) //causes infinite loop
{
...
continue
i++
...
}
for(i=0;i<10;i++) //works fine and exits after 10 iterations
{
...
continue
...
}
答案 0 :(得分:23)
因为continue
回到循环的开头。对于for
,操作后i++
是循环控件的积分部分,并在循环体重新启动之前执行。
使用while
,i++
只是循环体中的另一个语句(与a = b
没有区别),如果你continue
之前跳过了{{1}}到达它。
答案 1 :(得分:10)
原因是因为continue
语句会使循环体中跟随它的语句短路。由于您编写while
循环的方式在continue
语句后面有增量语句,因此它会被短路。您可以通过更改while
循环来解决此问题。
很多教科书声称:
for (i = 0; i < N; ++i) {
/*...*/
}
相当于:
i = 0;
while (i < N) {
/*...*/
++i;
}
但实际上,它真的很像:
j = 0;
while ((i = j++) < N) {
/*...*/
}
或者,更迂腐:
i = 0;
if (i < 10) do {
/*...*/
} while (++i, (i < 10));
这些更相同,因为现在如果while
的正文具有continue
,则增量仍会发生,就像在for
中一样。后一种方法仅在迭代完成后执行增量,就像for
一样(前者在迭代之前执行增量,推迟将其保存在i
中直到迭代之后)。
答案 2 :(得分:3)
i
的增量在继续之后,因此永远不会被执行
while(i<10) //causes infinite loop
{
.........
continue
i++
......
}
答案 3 :(得分:2)
在任何循环中,继续将执行移回循环的顶部,在执行continue语句后不执行任何其他指令。
在这种情况下,for循环的定义总是执行(按标准C),而i ++;语句未执行,因为它出现在continue语句之后。
答案 4 :(得分:0)
因为for的第三部分总是被执行。
答案 5 :(得分:0)
continue
语句将控件跳转到当前循环迭代语句的末尾,即它跳过当前迭代中语句的执行并移动到循环的下一次迭代。
使用while
循环,continue
语句使控制到达语句的结尾(包括递增语句),从而导致循环永远继续。
使用for
循环,continue
语句将控件跳转到语句的结尾并执行递增语句(在for
循环中,递增语句被认为与在正文中写入的语句分开循环)。
答案 6 :(得分:0)
for循环保存条件语句和递增,所以当条件满足时,它继续执行for循环中的语句,但是如果写继续语句,它将再次到达for循环的第一行,即增加和检查条件语句,如果满意再次进来执行。 对于while循环,它只检查条件语句,如果条件满足,它将在while循环中执行语句。 所以继续不会在它之后执行任何行。因此你的条件每次都满足并且进入无限循环。
答案 7 :(得分:0)
continue
绕过块的其余部分,如果满足循环的条件,则再次从块的顶部开始。
接下来的问题是:“那我该怎么办?” 我能想到两个答案。
示例:的
void foo ()
{
size_t i = 0;
do
{
/*...*/
if ( /*...*/ )
{
/*...*/
continue;
}
/*...*/
i++;
} while ( /* loop conditional */ );
}
解决方案#1:手动增加
void foo ()
{
size_t i = 0;
do
{
/*...*/
if ( /*...*/ )
{
/*...*/
i++;
continue;
}
/*...*/
i++;
} while ( /* loop conditional */ );
}
解决方案#2: goto
*
void foo ()
{
size_t i = 0;
do
{
/*...*/
if ( /*...*/ )
{
/*...*/
goto foo_next;
}
/*...*/
foo_next:
i++;
} while ( /* loop conditional */ );
}
goto
在这种情况下有效,因为两个地方的增量在技术上是相同的指令。当每次迭代 - 易变量变量更复杂时,此解决方案尤其重要;例如,设置多个变量或用等式或函数修改值。
如果出现单一的递增或递减声明,解决方案#1可能会证明是有利的;但是,应该注意:如果代码在这样的实现之后被修改,则必须记住更新语句的两个实例(这可能容易出错,特别是如果修改发生在一段延长的时间之后** )。因此,我高度推荐解决方案#2。
*有些人会考虑使用goto
不良做法。我建议你自己决定,并留下这个:google for "c goto bad"
**提醒这种必要性的评论可能就足够了,但是 - 如果我的建议已被遵循 - 每次迭代 - 易变变量仅限于一个语句。我引述:
从不是评论单行的理由
-Linus Torvalds(来源:http://yarchive.net/comp/linux/coding_style.html)