Language agnostic 测试循环在顶部还是底部?(while vs.do while)
当我在大学(80年代中期)学习CS时,一个不断重复的想法就是总是编写循环,在循环的顶部(while…)而不是底部(do…while)进行测试。这些概念经常得到研究的支持,研究表明,在顶部测试的回路在统计上比在底部测试的回路更可能是正确的 因此,我几乎总是编写在顶部测试的循环。如果它在代码中引入额外的复杂性,我不会这样做,但这种情况似乎很少见。我注意到一些程序员倾向于只编写在底层测试的循环。当我看到这样的结构时:Language agnostic 测试循环在顶部还是底部?(while vs.do while),language-agnostic,loops,while-loop,do-while,Language Agnostic,Loops,While Loop,Do While,当我在大学(80年代中期)学习CS时,一个不断重复的想法就是总是编写循环,在循环的顶部(while…)而不是底部(do…while)进行测试。这些概念经常得到研究的支持,研究表明,在顶部测试的回路在统计上比在底部测试的回路更可能是正确的 因此,我几乎总是编写在顶部测试的循环。如果它在代码中引入额外的复杂性,我不会这样做,但这种情况似乎很少见。我注意到一些程序员倾向于只编写在底层测试的循环。当我看到这样的结构时: if (condition) { do { ...
if (condition)
{
do
{
...
} while (same condition);
}
或者相反(if
在中,而中),这让我怀疑他们是否真的是这样写的,或者当他们意识到循环没有处理空情况时,他们是否添加了if
语句
我在谷歌上搜索了一下,但没有找到关于这个主题的任何文献。你们这些家伙(和女孩)是如何编写循环的?我写的循环几乎完全是在顶部测试。它的代码更少,所以至少对我来说,它不太可能出错(例如,复制粘贴条件使两个地方总是需要更新它)我总是遵循这样的规则,如果它应该运行零次或多次,则在开始时测试,如果它必须运行一次或多次,则在结束时测试。我看不出使用示例中列出的代码的任何逻辑原因。它只会增加复杂性。为了可读性,在顶部进行测试似乎是明智的。它是一个循环这一事实很重要;阅读代码的人在试图理解循环体之前应该了解循环条件。它实际上是用于不同的目的。在C语言中,您可以使用do-while构造来实现这两种场景(至少运行一次,并且在为true时运行)。但是PASCAL对于每个场景都有<强> >直到和, ,如果我没有记错的话,艾达有另一个结构让你在中间退出,当然这不是你要问的。
我对你的问题的回答是:我喜欢顶部有测试的循环。两者的用例不同。这不是一个“最佳实践”问题
如果希望基于条件执行循环,而不是使用
用于或而
若您想在不考虑条件的情况下执行某项操作一次,然后根据条件评估继续执行该操作。
<>强> >/P>>P>>这确实取决于你想在顶部测试的情况,当你想在底部测试的时候,还有其他的,当你想在中间测试时。
然而,给出的例子似乎很荒谬。如果要在顶部进行测试,不要使用If语句,而要在底部进行测试,只需使用while语句,这就是它的用途。您应该首先将测试视为循环代码的一部分。如果测试在逻辑上属于循环处理的开始,那么它就是循环的顶部测试。如果测试逻辑上属于循环的末尾(即,它决定循环是否应该继续运行),那么它可能是循环测试的底部
如果测试在逻辑上属于它们,您将不得不做一些奇特的事情。:-) 对于那些想不出理由进行一次或多次循环的人:
try {
someOperation();
} catch (Exception e) {
do {
if (e instanceof ExceptionIHandleInAWierdWay) {
HandleWierdException((ExceptionIHandleInAWierdWay)e);
}
} while ((e = e.getInnerException())!= null);
}
这同样适用于任何层次结构
类内节点:
public Node findSelfOrParentWithText(string text) {
Node node = this;
do {
if(node.containsText(text)) {
break;
}
} while((node = node.getParent()) != null);
return node;
}
不同之处在于,do循环执行“do something”一次,然后检查该条件以确定是否应重复“do something”,而while循环在执行任何操作之前检查该条件。如果条件为false,则首先可能根本不执行该条件。另一个将至少执行一次,然后检查条件。第一个在执行之前测试条件,以便您的代码可能永远不会进入下面的代码。第二个将在测试条件之前在中执行代码 while循环将首先检查“条件”;如果为false,它将永远不会“做某事”。但是do…while循环将首先“做某事”,然后检查“条件”。Awhile()在每次执行循环体之前检查条件,Ado…while()在每次执行循环体之后检查条件
因此,**do…while()**s将始终至少执行一次循环体
从功能上讲,while()相当于
startOfLoop:
if (!condition)
goto endOfLoop;
//loop body goes here
goto startOfLoop;
endOfLoop:
startOfLoop:
//loop body
//goes here
if (condition)
goto startOfLoop;
do…while()相当于
startOfLoop:
if (!condition)
goto endOfLoop;
//loop body goes here
goto startOfLoop;
endOfLoop:
startOfLoop:
//loop body
//goes here
if (condition)
goto startOfLoop;
请注意,实现可能比这更有效。但是,do…while()比while()少进行一次比较,因此速度稍快。如果出现以下情况,请使用do…while()
- 你知道这个条件在第一次出现时总是正确的,或者
- 您希望循环执行一次,即使条件一开始为false
在计算机科学中的一个典型离散结构类中,很容易证明两者之间存在等价映射
风格上,我更喜欢while(easy-expr){},因为easy-expr是预先知道的,并且准备好了,而且循环没有太多重复的开销/初始化。我更喜欢做{}while(稍微不太容易的expr);当有更多的重复开销时,提前设置条件可能不是那么简单。如果我写一个无限循环,我总是使用while(true){}。我无法解释原因,但我只是不喜欢为(;;){}写作。以下是翻译:
do { y; } while(x);
同
{ y; } while(x) { y; }
注意:额外的大括号用于在y
中有变量定义的情况。它们的范围必须像do循环一样保持在本地。因此,do while循环只执行其主体至少一次。除此之外,这两个循环是相同的。所以如果我们把这个规则应用到你的代码中
do {
// do something
} while (condition is true);
对应
do {
a++;
} while (a < n)
while (++a < n) {}
begin loop
<Code block A>
loop condition
<Code block B>
end loop
func();
while (condition) {
func();
}
//or:
while (true){
func();
if (!condition) break;
}
do{
func();
} while(condition);
do {
get_tasks_for_core();
launch_thread();
} while (cores_remaining());
while( someConditionMayBeFalse ){
// this will never run...
}
// then the alternative
do{
// this will run once even if the condition is false
while( someConditionMayBeFalse );