aalshabaan
aalshabaan

Reputation: 51

Counter in for loop falsely incrementing after execution

I have 3 nested loops in which the code doesn't in anyway modify the counters, I need the value of the topmost-level loop counter to use later in the code. It looks like this

int i;
for( i = 0; !found && i <f_i.size();i++){
    for(unsigned int j = 0; !found && j < f_g.size();j++){
        for(unsigned int k = 0; !found && k < f_g.size();k++){
            ///Do Stuff
            found = (/*Condition that's fulfilled after 2 iterations on k*/);
        }
    }
}

//Stuff that uses i

The condition is fulfilled after 2 iteration of the innermost loop, so i has the value 0 at that point. Using GDB I saw that the value of i jumps to 1 after the condition is checked in the topmost loop, which gives me a wrong later in my program, or worse an out of bounds access.

Thanks in advance

Upvotes: 1

Views: 986

Answers (3)

Adrian Mole
Adrian Mole

Reputation: 51835

As others have said (or, at least, implied): once the (outermost) for loop is entered, the variable, i, will be incremented at the end of that loop, before the condition is tested, to see if another loop should be run ...

... that is, unless you 'jump out' of the loop using a break statement!

So, the following, slightly modified, code will not increment i (at all) if found becomes true during the first iteration of the outermost loop:

    int i;
    for (i = 0; !found && i < f_i.size(); i++) {
        for (unsigned int j = 0; !found && j < f_g.size(); j++) {
            for (unsigned int k = 0; !found && k < f_g.size(); k++) {
                ///Do Stuff
                found = (/*Condition that's fulfilled after 2 iterations on k*/);
            }
        }
        // If "found" becomes true, exit the loop immediately, AVOIDING THE INCREMENT:
        if (found) break;
    }

So, while the other answers are very good, and the code solutions they offer are perfectly valid, the proposal here is a far more 'minimal' adjustment to your code. I hope it helps.

Note: You could, of course, add similar break statements to the inner loops; however, as your j and k variables are declared locally to those loops, it would appear that undesired increments to their values is not relevant. Furthermore, break cannot be used to jump out of multiple, nested loops.

Also, be aware that if the found variable is true before the outermost for loop is encountered, that loop will not be executed (obviously) and, thus, the i variable will not be incremented in that case.

Upvotes: 0

Vlad from Moscow
Vlad from Moscow

Reputation: 310980

The variable i is incremented due to the third expression of the for loop

int i;
for( i = 0; !found && i <f_i.size();i++){
                                    ^^^^  
    for(unsigned int j = 0; !found && j < f_g.size();j++){
        for(unsigned int k = 0; !found && k < f_g.size();k++){
            ///Do Stuff
            found = (/*Condition that's fulfilled after 2 iterations on k*/);
        }
    }
}

To avoid this you can write for example

int i;
for( i = 0; !found && i <f_i.size();){
    for(unsigned int j = 0; !found && j < f_g.size();j++){
        for(unsigned int k = 0; !found && k < f_g.size();k++){
            ///Do Stuff
            found = (/*Condition that's fulfilled after 2 iterations on k*/);
        }

    }
    i += !found;
}

Or instead of the expression statement

i += !found;

you can use the if statement like

if ( !found ) ++i;

Also the code will look more readable if the variable i will be initialized before the loops for example like

int i = 0;
while ( !found && i < f_i.size() ){
    for(unsigned int j = 0; !found && j < f_g.size();j++){
        for(unsigned int k = 0; !found && k < f_g.size();k++){
            ///Do Stuff
            found = (/*Condition that's fulfilled after 2 iterations on k*/);
        }

    }
    i += !found;
}

Upvotes: 2

Jeffrey
Jeffrey

Reputation: 11410

This is how for loops work. The increment is done before the condition is checked.

The proper way (easier to read, easier to maintain) to do what you want is to add a variable, outside the loop.

int index;

And set it when you find the element:

        found = ...
        if (found) index = i;

Upvotes: 2

Related Questions