Language agnostic 测试循环在顶部还是底部?(while vs.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 { ...

当我在大学(80年代中期)学习CS时,一个不断重复的想法就是总是编写循环,在循环的顶部(while…)而不是底部(do…while)进行测试。这些概念经常得到研究的支持,研究表明,在顶部测试的回路在统计上比在底部测试的回路更可能是正确的

因此,我几乎总是编写在顶部测试的循环。如果它在代码中引入额外的复杂性,我不会这样做,但这种情况似乎很少见。我注意到一些程序员倾向于只编写在底层测试的循环。当我看到这样的结构时:

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 );