使用!=与计数器控制的循环

iwa*_*ram 6 c++ java

今天的最后一个问题...明天我会回来的......我有很多要跟进...

我正在寻找Reilly Java文本 - 谈论反控制循环模式..(无论什么语言......)

用于计数器控制循环(for,while等)和嵌套循环的作者...使用!=进行测试...现在我意识到!=用于某些具有事件控制循环的情况 - 如Sentinel或EOF类型循环 - 但对我来说 - 使用它与计数器控制循环是一个坏主意...很容易出错...

例子:

x = 0;
while (x != 100) {
   y = 0;
  while (y != 100) {

   ...
   y++;
 }
  x++;
}
Run Code Online (Sandbox Code Playgroud)

如果说...使用其他关系运营商会更好吗?

x = 0;
while (x < 100) {   //or even better some defined constant...
   y = 0;
  while (y < 100) {

   ...
   y++;
 }
  x++;
} 
Run Code Online (Sandbox Code Playgroud)

从我所看到的通常是文本中提出的方式..classes.etc ..

再一次 - 你是否会认为这很糟糕 - 或者只是采取不同的方式......谢谢......

Bil*_*ard 6

我只会用

while (x != 100)
Run Code Online (Sandbox Code Playgroud)

如果我希望循环在x 正好为 100 时终止.所以在绝大多数情况下我都会使用

while (x < 100)
Run Code Online (Sandbox Code Playgroud)

这对于反控制循环来说更常见.

编辑:第二个想法,我总是在一个反控制循环中使用for语法,所以这个例子应该是

for(int i=0; i < 100; ++i)
Run Code Online (Sandbox Code Playgroud)

  • +1这在Java中是惯用的; 不要搞砸不破的东西. (3认同)

S.L*_*ott 6

您希望循环条件与所需的后置条件完全相反.

i= 0;
while( i != 100 ) {
    i += 1;
}
assert i == 100;
Run Code Online (Sandbox Code Playgroud)

您可以简单地看到循环后置条件与循环终止条件完全匹配.没有神秘感.

此外,您可以从初始条件和身体证明它将达到100,而不会"以某种方式"神奇地跳过一个值.

在你有一个非常复杂的循环体的情况下,这个简单的并行结构是必不可少的.

如果使用最弱前置条件技术从后置条件导出循环,则循环条件将是如上所示的简单匹配条件.

i < 100是一个坏主意,因为你的循环可能有一个不正确的主体,使变量严重增加并仍然"出现"工作.

  • 关键是如果100"以某种方式"被跳过,你就会有一个错误.循环需要崩溃并严重崩溃.无限循环是另一个bug的症状,你必须找到并修复它.不解决. (2认同)

Tom*_*ine 6

使用<在Java中更常见.现代C++使用!=.

!=更有可能在代码中捕获错误.在大多数情况下,这是一件好事.如果由于某种原因,计数器不仅已达到但超过了界限(通常在第一次迭代时),那么正文将以非法值执行.只要循环体不隐藏错误,那么你将得到一个例外.如果正文隐藏错误,循环将执行数十亿次,显然存在错误.

例如,去年Adobe Flash的实施中发现了一个有趣的漏洞.可以使用作为数组的指针初始化为null.通常不是问题 - 只要首次取消引用,该过程就会安全地崩溃.但是,使用了循环<,允许从不执行主体,然后允许执行继续.之后,可以在攻击者指定的位置写入内存.因为值null始终是0,攻击者确切地知道正在写入哪些内存位置.如果使用循环,则不会发生这种情况!=.


Car*_*ers 5

正如其他答案所示,
while(i < 100)是安全的*,
while(i != 100)准确的**.

顺便说一下,你可能想尝试while(i++ < 100)或者for(i = 0; i < 100; ++i)代替你所展示的更简单的while循环 - 忘记在循环结束时增加计数器是一个真正的痛苦.注意,如果i=0,i++将等于0,然后下一次递增i,++i并将增加i然后等于1,因此while(i++ < 100),必须使用postfix ++运算符.

还要注意,如果i在条件中进行测试时为0,那么它在循环体中将为1(对于while示例),因此如果i是数组的索引或其他东西,而不仅仅是跟踪循环迭代,你最好坚持使用for循环(每次迭代后增加i).


*:这里的安全意味着不太可能进入无限循环.如果循环不是微不足道的话,它也可以隐藏潜在的错误也是不安全的

**:确切地说,如果它没有完全符合你的预期,它就会失败,你会注意到.其他一些答案也描述了如何在这种循环中更加保护您免受错误的影响.