【问题标题】:Whats wrong with this while loop? [duplicate]这个while循环有什么问题? [复制]
【发布时间】:2011-02-06 07:54:31
【问题描述】:
boolean r = false ; int s = 0 ;
while (r == false) ; 
{
    s = getInt() ; 
    if (!(s>=0 && s<=2)) System.out.println ("try again not a valid response") ; 
    else r = true ; 
}

即使输入 3 或 123 并且循环永远不会终止,文本也不会显示自己。这里有什么问题?

【问题讨论】:

  • 另外这不是一个无限循环,所以infinite-loop 标签没有意​​义。
  • 其实是一个无限循环。 while (r == false) ; 是一个不做任何事情的无限循环,因为 r 被初始化为 false。
  • 停止尝试将多个东西放在一条线上。最重要的是,这就是导致您的问题的原因。一旦你养成了写清楚的习惯,你会发现这种事情发生的少得多。还将您在 Eclipse 中的警告设置得更高——它应该向您指出空语句。不要只解决这个问题,要解决根本原因。
  • GAAAAAAAHH!我的眼睛!!!请考虑对该 if 语句进行缩进。即使是最简单的控制语句也可以通过将所有内容都放在单行中而变得不可读,没有缩进,也没有打开/关闭大括号。此外,重新处理该 if 语句中的表达式,使其不使用否定 (!) 您很少希望使用复合布尔表达式的否定。
  • 在调试器中单步执行此代码以查找问题不是更简单吗?

标签: java while-loop infinite-loop


【解决方案1】:

条件后面有一个分号。当您使用大括号为 while 指定一个块时,您不要使用分号。

【讨论】:

  • 呵呵...while (r==false) /*DO NOTHING*/ ;
【解决方案2】:

去掉';'过了一会儿。

【讨论】:

    【解决方案3】:

    其他人已经指出了这个错误,但你的代码在其他方面很可怕,最终会让你绊倒:

    if (!(s>=0 && s<=2)) System.out.println ("try again not a valid response") ; 
    else r = true ; 
    

    这很糟糕,因为在 ifelse 子句的情况下,您可以轻松地打算运行多个语句。使用花括号并避免将条件语句放在一行:

    if (!(s>=0 && s<=2))
    {
        System.out.println ("try again not a valid response");
    }
    else
    {
        r = true;
    }
    

    它更容易阅读,并且不太可能引入难以发现的错误。

    【讨论】:

    • 我不同意使用花括号。如果它是一个单一的语句,它是一个单一的语句。就风格而言,我会缩进,但不会在单个语句中使用花括号……但是这是一场宗教斗争。
    • @Atomiton 绝对,我更喜欢一直使用它们,因为我可能会在某个时候回来更改它,如果我不放它们我会搞砸的首先在那里。至少把它们放在不同的线上——我希望我们能就这一点达成一致:)
    • 我从不在单个语句中使用大括号,而且我经常回来添加更多内容,而且我从来没有不小心忘记添加大括号并搞砸了我的控制流......除非我有写了一阵子python,然后回到C,也就是。
    • 虽然我经常将大括号放在单行上,但我无法捍卫这种做法。事实是,在那里戴上牙套几乎没有任何成本,即使它们以某种方式让你有点失望,再看一眼也不到一秒钟。另一方面,把它们关掉——比如一千个“if”语句中的一个(假设你已经写了一段时间python然后回到C),如果你碰巧把它搞砸了,可能需要几分钟或几个小时来修复——这是站不住脚的,而且很明显是错误的。然而,我仍然经常离开它们......
    • 我喜欢人们说“我永远不会回来犯那个错误”之类的话。因为可能不是你回到代码中,而且无论如何,几个月前写的代码很可能是别人写的。
    【解决方案4】:

    而(r == 假)

    应该是

    while(!r)

    尽管其他人都说分号,但这就是我认为它的错误:)

    【讨论】:

    • while(r == false) 更加明确和可读。我想人们也可能会争辩说应该是while(false == r),但我讨厌这样。无论如何,并不是他“应该”将其更改为!r,因为r 是一个布尔值,因此无论哪种方式都无关紧要,这意味着这只是风格问题。
    • 始终遵循约定 r!r 而不是 r == falser == true 避免了 r = falser = true 的错误(这不会导致 java 中的编译错误) .如果您想让它更明确和可读,请将r 重命名为continuefound
    • continue 是一个关键字,因此会产生一个糟糕的变量名。不过,你是对的,像 r 和 s 这样的东西是可怕的变量名。使用具有自动完成功能的现代 IDE,并将其称为合理的东西,例如 done 或 found。
    • @Myers 我不同意。我认为 r == false 代码很臭,我永远不想看到有人在我正在使用的代码中使用它。
    【解决方案5】:

    +1 给丹尼尔·迪保罗。我想我会发布一个单独的答案来澄清为什么会出现这种情况。

    Java 中的循环可以用以下两种方式之一编写。如果循环体只有一行,可以简写:

    while (true)
        System.out.println("While loop");
    

    这将在控制台上打印出“While loop”,直到程序结束。另一个选项是在大括号之间指定一个循环体,就像你在上面所做的那样:

    int i = 0;
    while (i < 10) {
        System.out.println("i = " + i);
        i++;
    }
    

    这将在单独的行上分别打印出“i = 0”、“i = 1”、...、“i = 9”。

    您发布的代码会将两者混淆。在简写的 while 循环中,Java 解析器期望在 while 循环条件和分号之间找到一条语句。因为这里没有找到语句,所以while循环运行,但什么也不做;它没有身体。此外,由于循环没有主体,因此您的变量 r 没有机会采用新值;条件总是计算为真,循环永远不会退出。

    如果您要在示例中否定 while 循环中的条件,即,

    boolean r = false ; int s = 0 ;
    while (r != false) ; 
    {
        s = getInt() ; 
        if (!(s>=0 && s<=2)) System.out.println ("try again not a valid response") ; 
        else r = true ; 
    }
    

    (注意我把错误的分号放在那里),你会发现你想要的循环体将精确执行一次,因为循环永远不会运行。

    【讨论】:

      【解决方案6】:

      除了其他的cmets,还应该把if改成

      if (s < 0 || s > 2)
      

      这样更容易理解。

      【讨论】:

      • +1 当然,否定使阅读本应简单的内容变得很麻烦。
      【解决方案7】:

      不相关的答案,我真的很推荐你遵循 Sun 的风格指南。

      boolean r = false ; 
      int s = 0 ;
      while (r == false) {
          s = getInt() ; 
          if (!(s>=0 && s<=2)) {
              System.out.println ("try again not a valid response") ; 
          } else {
            r = true ;
          } 
      }
      

      如果您在自己的循环中评估结果,您可以摆脱 r 变量和 if/else 条件。

      int s = 0;
      
      while( ( s = getInt() ) < 0 || s > 2 ) {
          System.out.println( "Try again, not a valid response");
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-01-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多