将带有 continue 语句的 for 循环转换为 while 循环

Converting a for-loop with continue statement to while-loop

我正在做一个练习,将一小段基于 for 循环的代码转换为使用 while 循环执行相同的操作。转换是故意错误的,看起来像这样:

int sum = 0;

    for (int i = 0; i < 4; i++) {
        if (i % 3 == 0) continue;
        sum += i;   
    }
System.out.println(sum); // prints 3

这样转换成:

int i = 0, sum = 0;

        while (i < 4) {
            if (i % 3 == 0) continue;
            sum += i;   
            i++;    
        }
System.out.println(sum); // will not print

在练习中,我被要求解释为什么转换错误然后修复它。我的想法是:

  1. 初始值为i = 0,这会在进入will循环后立即触发continue,因为 (0 % 3 == 0) 将使 if 语句 为真。只要初始值为 0,这将执行循环,因此可以无限次地跳过它。我尝试更改 i = 1 的初始值,但没有打印总和。然后我尝试在执行 if 语句 之前增加 i,程序现在打印总和 7。这里的问题是;如果我在 if 语句之后递增,为什么程序不打印,即使 i = 1 的初始值表明(在我的脑海中)程序应该 运行 正确?

  2. 我给每个程序做了一个table来比较求和

for-loop版本:

i = 0, sum += i 未执行(继续),i++

i = 1, 总和 = 1, i++

i = 2, 总和 = 3, i++

i = 3, sum += i 未执行(继续),i++

i = 4, i < 4 false, 循环停止

while-loop版本:

i = 0, i++, 总和 = 1

i = 1, i++, 总和 = 3

i = 2, i++, sum += i 未执行(继续)

i = 3, i++, 总和 = 7

i = 4, i < 4 false, 循环停止

while-loop中,sum += i 比在for-loop中多执行一次。这是将 for-loop 转换为 while-loop 的正确方法吗?

int i = 0, sum = 0;

        while (i < 3) {
            i++;
            if (i % 3 == 0) continue;
            sum += i;           
        }

        System.out.println(sum);

您的 1 关注的是它是初始值,但这不是重点。关键是当 i % 3 == 0 为真时 i 永远不会递增,而不是 0 是初始值。所以 while 循环永远循环。

你的 2 没有任何意义:while 版本将永远循环,永远不会总结任何东西。

Is this the right way to convert the for-loop into a while-loop?

不,您在错误的时间递增 i

想想 for 循环是如何工作的:

  1. 初始化 - 首先将变量设置为第一个表达式中的值。

  2. Test - 然后使用第二个表达式测试值。

  3. Execute - 如果值为真,则执行循环体。

  4. Increment - 当循环体完成时,它执行第三个(递增)表达式。请注意,这是 after 循环体。

让您的 while 循环执行 for 循环正在执行的操作。 (我故意 而不是 为您做那件事;这是一个学习练习。我会注意到转换 for 循环的最佳方法不会使用 continue,但是。"Best,"当然是主观的。)

根据while循环逻辑,变量i的递增是有条件的,而for循环是无条件的。为了使自增逻辑统一,两种情况都应该自增。

我认为正确的转换应该是 -

int i = 0, sum = 0;

while (i < 4) {
    if (i % 3 == 0) {i++;continue;}
    sum += i;   
    i++;   
}
System.out.println(sum);

In the exercise, I am asked to explain why the conversion is wrong and then fix it

转换是错误的,因为当您达到模 3 等于 0 的 i 值时(在这种情况下是第一次迭代),您将跳到下一次迭代并重新验证。但是,由于您直接跳过而没有递增 i ,因此您将重新验证相同的条件并重新验证 ad-infinitum.

您可以通过删除 continue 并否定条件来轻松修复它:

while (i < 4) {
    if (i % 3 != 0)
        sum += i;

    i++;    
}

通常增量会在 while 循环的最后一行。然而,在这个 "disaster waiting to happen" 代码中,有一个条件可以跳到 while 块的末尾而不增加 i。如果您依赖 i 来递增,请确保它始终在任何迭代中执行。而且,最后,因为您希望它第一次迭代。

    while (i < 4) {
        if (i % 3 == 0) {
          // skip!
        } else {
          sum += i;   
        }
        i++;    
    }

题中给出的for-loop转换成普通的English,表示sum up0 到 3 并排除 所有 3 的倍数。 (0+1+2=3)

   for (int i = 0; i < 4; i++) {
        if (i % 3 == 0) continue;
        sum += i;   
    }

所以现在,我们问自己,我们如何使用 while 循环 将 0 加到 x 并排除所有 3 的倍数。我们将在不查看原始 for-loop 的情况下执行此操作。 (有时这样做更容易,因为我们已经知道 for 循环的意图

求和一个从0到3的数:

int i = 0;
while(i < 4){
    sum += i;
    i++;
}

计算 0 到 3 之间的数,不包括 3 的倍数:

int i = 0;
while(i < 4){
    if(i % 3 != 0)
        sum += i;
    i++;
}

对 0 到 3 的数求和,不包括 3 的倍数(使用 continue):

int i = 0;
while(i < 4){
    if(i % 3 == 0){
        i++;       //Remember to increase i before continue
        continue;
    }
    else
        sum += i;
    i++;
}

因为在continue之后,它下面的所有语句都会被跳过,你必须记得在调用continue之前做一个增量i++。将有另一个 i++ 因为你现在分支到 2 个条件。