J'ai 3 boucles imbriquées dans lesquelles le code ne modifie en aucun cas les compteurs, j'ai besoin de la valeur du compteur de boucle de niveau supérieur à utiliser plus tard dans le code. Ça ressemble à ça

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

La condition est remplie après 2 itérations de la boucle la plus interne, donc i a la valeur 0 à ce point. En utilisant GDB, j'ai vu que la valeur de i passe à 1 après que la condition est vérifiée dans la boucle supérieure, ce qui me donne une erreur plus tard dans mon programme, ou pire un accès hors limites.

Merci d'avance

1
Abed Alrahman Shabaan 20 avril 2020 à 18:31

3 réponses

Meilleure réponse

Voici comment fonctionnent les boucles for. L'incrémentation est effectuée avant que la condition ne soit vérifiée.

La bonne façon (plus facile à lire, plus facile à maintenir) de faire ce que vous voulez est d'ajouter une variable, en dehors de la boucle.

int index;

Et réglez-le lorsque vous trouvez l'élément:

        found = ...
        if (found) index = i;
2
Jeffrey 20 avril 2020 à 15:37

Comme d'autres l'ont dit (ou, du moins, implicite ): une fois que la boucle (la plus externe) for est entrée , la variable, i , sera incrémenté à la fin de cette boucle, avant le test de la condition, pour voir si une autre boucle doit être exécutée ...

... c'est-à-dire, à moins que vous ne «sautiez» de la boucle en utilisant un {{X0 }} déclaration!

Ainsi, le code suivant, légèrement modifié, n'incrémentera pas i (du tout) si found devient true lors de la première itération de la boucle la plus externe:

    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;
    }

Ainsi, alors que les autres réponses sont très bonnes et que les solutions de code qu'elles proposent sont parfaitement valables, la proposition ici est un ajustement beaucoup plus «minimal» de votre code. J'espère que cela aide.

Remarque: Vous pouvez, bien sûr, ajouter des instructions break similaires aux boucles internes; cependant, comme vos variables j et k sont déclarées localement dans ces boucles, il semblerait que les incréments indésirables de leurs valeurs ne soient pas pertinents. De plus, break ne peut pas être utilisé pour sauter hors de plusieurs boucles imbriquées.

De plus, sachez que si la variable found est true avant la boucle for la plus externe, cette boucle ne sera pas être exécutée (évidemment) et, par conséquent, la variable i ne sera pas incrémentée dans ce cas.

0
Adrian Mole 20 avril 2020 à 16:06

La variable i est incrémentée en raison de la troisième expression de la boucle for

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*/);
        }
    }
}

Pour éviter cela, vous pouvez écrire par exemple

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;
}

Ou au lieu de l'instruction d'expression

i += !found;

Vous pouvez utiliser l'instruction if comme

if ( !found ) ++i;

De plus, le code paraîtra plus lisible si la variable i sera initialisée avant les boucles, par exemple comme

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;
}
2
Vlad from Moscow 20 avril 2020 à 15:40