简体   繁体   中英

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

I am working on an exercise where a small piece of code based on a for-loop is converted to preform the same operation with a while loop. The conversion is wrong by purpose, and looks like this:

int sum = 0;

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

This is converted into:

int i = 0, sum = 0;

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

In the exercise, I am asked to explain why the conversion is wrong and then fix it. My thoughts are:

  1. With the initial value of i = 0 , this will trigger continue instantly after entering the will loop, since (0 % 3 == 0) will make the if-statement true. As long as the initial value is 0, this will execute the loop, for so to skip it an endless amount of times. I tried changing the initial value of i = 1 , but noe sum is printed. Then I tried to increment i before executing the if-statement , and the program now prints the sum 7. The question here is; why won't the program print if i incremented after the if statement, even if the initial value of i = 1 suggests (in my head) that program should run properly?

  2. I made a table for each program to compare the summing.

The for-loop version:

i = 0, sum += i not preformed (continue), i++

i = 1, sum = 1, i++

i = 2, sum = 3, i++

i = 3, sum += i not preformed (continue), i++

i = 4, i < 4 false, loop stopped

The while-loop version:

i = 0, i++, sum = 1

i = 1, i++, sum = 3

i = 2, i++, sum += i not preformed (continue)

i = 3, i++, sum = 7

i = 4, i < 4 false, loop stopped

In the while-loop , sum += i is preformed once more than in the for-loop . Is this the right way to convert the for-loop into a while-loop ?

int i = 0, sum = 0;

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

        System.out.println(sum);

Your 1 is focussing on it being the initial value, but that's not the point. The point is that i is never incremented when i % 3 == 0 is true, not that 0 is the initial value. So the while loop loops forever.

Your 2 doesn't make any sense: The while version will loop forever, never summing anything.

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

No, you're incrementing i at the wrong time.

Think bout how a for loop works:

  1. Initialization - First it sets the variables to the values in the first expression.

  2. Test - Then it tests the values using the second expression.

  3. Execute - If the value is true, it executes the loop body.

  4. Increment - When the loop body is complete, it executes the third (increment) expression. Note that this is after the loop body.

Make your while loop do what the for loop is doing. (I'm intentionally not doing that for you; this is a learning exercise. I'll note that the best way to convert that for loop will not use continue , however. "Best," of course, is subjective.)

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

The conversion is wrong simply because when you will reach a i value that modulo 3 equals 0 (the first iteration in that case), you will skip to the next iteration and re-validate. However, since you skipped directly without incrementing i , you will re-validate the same condition and re-validate ad-infinitum .

You could fix it easily by getting rid of the continue and negating the condition :

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

    i++;    
}

The for-loop given by the question if converted to plain English , it means sum up from 0 to 3 and exclude all multiples of 3 . (0+1+2=3)

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

So now, we ask ourselves, how do we sum up 0 to x and exclude all multiples of 3 using a while-loop . We will do this without looking at the original for-loop . ( Sometimes it is easier to do it this way since we already know the intention of the for-loop )

To sum up a number from 0 to 3:

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

To sum a number from 0 to 3, excluding multiples of 3:

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

To sum a number from 0 to 3, excluding multiples of 3 (using continue):

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

Since after the continue , all statements below it will be skipped, you have to remember to do an increment i++ before calling continue . There will be another i++ since you branch out into 2 conditions now.

According to the while loop logic, increment of variable i is conditional where as for for-loop it is unconditional. To make the increment logic uniform, you should increment in both cases.

I think the proper converting would be -

int i = 0, sum = 0;

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

Normally the increment would be on the last line of a while loop. However, in this "disaster waiting to happen" code, there is a condition to skip to the end of the while block without incrementing i. If you are relying on i to increment, make sure it is always executed on any iteration. And also, at the end, because you want it to iterate the first time.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM