代码之家  ›  专栏  ›  技术社区  ›  iwanttoprogram

使用!=带计数器控制回路

  •  6
  • iwanttoprogram  · 技术社区  · 17 年前

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

    我在看Reilly Java文本-谈论计数器控制的循环模式…(不管是哪种语言…)

    计数器控制循环(for、while等)和嵌套循环的作者…使用!=为了测试…现在我意识到了!=用于事件控制循环(如sentinel或EOF类型的循环)的某些情况,但对我来说,将其用于计数器控制循环是一个坏主意…非常容易出错。。

    示例:

    x = 0;
    while (x != 100) {
       y = 0;
      while (y != 100) {
    
       ...
       y++;
     }
      x++;
    }
    

    如果只说..使用其他关系运算符。。。

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

    再一次-你会认为这一切都不好-或只是一个不同的方式做它。。。 谢谢

    10 回复  |  直到 17 年前
        1
  •  6
  •   S.Lott    17 年前

    您希望循环条件与所需的post条件完全相反。

    i= 0;
    while( i != 100 ) {
        i += 1;
    }
    assert i == 100;
    

    您可以很容易地看到,循环post条件与循环终止条件完全匹配。没有秘密。

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

    如果你使用 Weakest Precondition techniques 为了从post条件导出循环,循环条件将是如上所示的简单匹配条件。

    这个 i < 100 这是一个坏主意,因为您的循环可能有一个不正确的主体,该主体严重增加了变量,并且仍然“看起来”正常工作。

        2
  •  6
  •   Bill the Lizard    17 年前

    while (x != 100)
    

    如果我希望循环在x为 确切地

    while (x < 100)
    

    这在计数器控制的循环中更常见。

    编辑:再想一想,我总是在计数器控制的循环中使用语法,所以这个例子应该是

    for(int i=0; i < 100; ++i)
    
        3
  •  6
  •   Tom Hawtin - tackline    17 年前

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

    更可能捕获代码中的错误。在大多数情况下,这是一件好事。如果由于某种原因,计数器不仅达到了界限,而且超过了界限(通常在第一次迭代时),那么主体将使用非法值执行。只要循环体没有隐藏错误,就会得到一个异常。如果主体隐藏错误,循环将执行数十亿次,显然存在错误。

    null . 通常不是问题-只要第一次取消引用,进程就会安全地崩溃。但是,使用 < 已使用,允许主体从不执行,然后允许继续执行。之后,可以在攻击者指定的位置写入内存。因为 无效的 总是 0 != .

        4
  •  5
  •   Carson Myers    17 年前


    while(i < 100) 是安全的 * ,
    while(i != 100) ** .

    顺便说一句,你可能想试试 while(i++ < 100) 或 for(i = 0; i < 100; ++i) 与您所展示的更简单的while循环不同,忘记在循环结束时增加计数器是一件非常痛苦的事情。注意,如果 i=0 , i++ 将等于0,然后为下一次增加i,并且 ++i 将增加i,然后等于1,对于 ,后缀++运算符是必需的。

    i 在条件中测试时为0,那么在循环体中为1(例如while),因此如果 我


    * :此处安全意味着不太可能进入无限循环。它也不安全,因为它可以隐藏潜在的错误,如果循环不是琐碎的

    **

        5
  •  4
  •   James Curran    17 年前

    使用“!=”over“<”的主要优点是,有些东西会失败,它应该失败 大的 .

    例如,如果某个bug导致x进入设置为110的循环,那么 x < 100 将永远不会进入循环,这是调试过程中可能会遗漏的一个事实。奥托,如果你用 x!=100 ,它将永远不会退出循环--这是调试过程中不能缺少的。

        6
  •  3
  •   cdmckay    17 年前

    我不认为<一定比!=为您提供更多的保护。如果你有一个案例 i 如果以您意想不到的方式递增,您应该抛出一个异常,而不是用<将其扫到地毯下;。

    x = 0;
    while (x != 100) 
    {
       assert x >= 0;
       assert x < 100;
    
       y = 0;
       while (y != 100) 
       {    
         assert y >= 0;
         assert y < 100;
    
         ...
         y++;
       }
       x++;
    }
    

    这样,当循环超出边界时,您的程序就会立即死亡(过早崩溃,频繁崩溃),并且您知道您的代码是一团糟的。

        7
  •  2
  •   David Thornley    17 年前

    我怀疑这可能与C++迭代器有关。

    如果使用整数或指针, < < 可能未定义,或可能难以计算。

    例如,在运行列表时,C++方式将是:

    for(std::list<foo>::const_iterator i = bar.begin(); i != bar.end(); ++i)
    

        8
  •  1
  •   kscott    17 年前

    我相信它们在语义上是相同的,唯一的区别在于!=超过100的数字显然也会满足以下条件,即<将阻止任何大于100的数字通过。

    但是,在给定的情况下,两个运算符将产生相同的输出。现在,如果x和y变量在该代码之外以某种方式起作用,“<”将是一种更好的方法,可以确保在100处有一个截止点,即使输入值为90,并且如果输入值为4000,则根本无法继续。显然,你当时所做的事情的意图决定了你选择了哪一个操作符,通常有几种方法来实现相同的结果,但并不总是一种“正确”的方法。

        9
  •  0
  •   b.roth    17 年前

    对它们在语义上是相同的。

    使用“<”运算符的第二种语法是人们在本例中通常使用的语法,看起来更直观(因为变量的值在循环中递增)。

        10
  •  -1
  •   Kieveli    17 年前

    最好使用小于<消息灵通的代码中的错误可能会导致计数器增加两次。这意味着循环将突然变成一个无限循环(或者直到你吹MAXINT)。