0

the following two programs are supposed to produce all three digit combinations of 1, 2, 3 (with repetition). They are identical in every way, other that where the loop counters are being initialized

#include <stdio.h>
int main(void)
{
        short i, j, k;
        i = j = k = 1;
        for (; i <= 3; i++) {
                for (; j <= 3; j++) {
                        for (; k <= 3; k++)
                                fprintf(stdout, "%hi %hi %hi\n", i, j, k);
                }
        }
        return 0;
}

...This one where the counters for the three loops are being initialized outside them doesn't produce the desired output. It prints.

1 1 1
1 1 2
1 1 3

The second one...

#include <stdio.h>
int main(void)
{
        short i, j, k;
        for (i = 1; i <= 3; i++) {
                for (j = 1; j <= 3; j++) {
                        for (k = 1; k <= 3; k++)
                                fprintf(stdout, "%hi %hi %hi\n", i, j, k);
                }
        }
        return 0;
}

...where the counters are being initialized within each loop, produces the desired output

1 1 1
1 1 2
1 1 3
1 2 1
1 2 2
1 2 3
1 3 1
1 3 2
1 3 3
2 1 1
2 1 2
2 1 3
2 2 1
2 2 2
2 2 3
2 3 1
2 3 2
2 3 3
3 1 1
3 1 2
3 1 3
3 2 1
3 2 2
3 2 3
3 3 1
3 3 2
3 3 3

Read in a book that a for loop can be written in several forms--all of which are identical--and that the counter can be initialized, incremented, tested either inside or outside the for statement. Then why the different behavior here?

4 Answers 4

4

Because you don't initialize the variables i, j, k inside the loop but define them in the outer scope, their values remain saved.

In particular k remains 4, after the first loop finishes to run, then the condition k<=3 is always false and the print statement is never reached.

To write the code in the equivalent way to your book meant is that way:

#include <stdio.h>
int main(void)
{
        short i, j, k;
        i = 1;
        for (; i <= 3; i++) {
                j = 1;
                for (; j <= 3; j++) {
                       k = 1;
                        for (; k <= 3; k++)
                                fprintf(stdout, "%hi %hi %hi\n", i, j, k);
                }
        }
        return 0;
}
Sign up to request clarification or add additional context in comments.

Comments

2

In the second one, the variables j and k are reinitialised to 1 each time the for loop is encountered.

In the first one, they are always just left with the value that they had - which means that the second time round (when i == 2 or 3), j is left at 4 from the first time round, which immediately fails the j <= 3 condition.

Comments

2

it's not about how you initialize the for loop, but the fact that each time that you start the for loop you don't initialize it.

        for (; i <= 3; i++) {
            for (; j <= 3; j++) {
                    for (; k <= 3; k++)

so for the first time it's fine since the values are correct, but after the 2nd and 3rd for loop finished their iterations and the first for loop reached the 2nd index the other for loops are not being initialized so their values remain 4 and the condition isn't being met, so the loops stop there. you still need to use the initialization inside the nested for loops regardless to fix the issue.

Comments

2

If you initialize your variables just once, outside the for loops, then their values will never get re-initialized in the nested loops (something you need in order to generate every combination starting with 1xx, 2xx and 3xx).

In the case of the outside initialization: After you've generated all the 11x combinations, your k variable will have the value 4, regardless of what the enclosing loops do.

So when either j or i increments to 2 and 3, your k will already be 4, hence the innermost for loop will not execute anymore.

Needless to say, the second variant of your code, re-initializes k and j every time i increments, which will then make your code reach the printf every time like you intended.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.