web-dev-qa-db-fra.com

Comment utiliser quelque chose comme une instruction continue dans des boucles imbriquées?

J'ai une classe d'objets et j'ai besoin de comparer une propriété de chaque objet à la même propriété de tous les autres objets. S'ils correspondent, le code doit faire quelque chose. Il en résulte deux boucles for pour parcourir les objets pour obtenir cette propriété, et dans la seconde boucle for, une troisième boucle for traverse les éléments de la propriété (qui est un vecteur) pour les comparer. . S'ils correspondent, j'ai besoin de la boucle la plus externe pour abandonner l'itération actuelle et passer à la suivante (je veux seulement que la première correspondance avec un autre objet soit prise en compte).

J'ai étudié les instructions 'goto' et créé une structure do {} while (), mais je n'ai pas pu les implémenter de manière à obtenir le résultat souhaité. Ce dont j'ai besoin, c'est quelque chose comme une instruction 'continue' pour la boucle la plus externe basée sur ce qui se passe dans l'instruction conditionnelle dans la boucle la plus interne.

Quelle serait la bonne méthode pour y parvenir et comment devrait-elle être mise en œuvre?

Edit: à côté de la réponse que j'ai acceptée, je recommanderais également la réponse de Martin Bonner, qui fonctionne également parfaitement et ne repose pas sur goto.

for (int i = 0; i < max; i++){
Object & object1 = system.getAgent(i);
VectorOfStrings object_property1 = object1.getProperty();

    for (int j = i + 1; j < max; j++){
    Object & object2 = system.getObject(j);
    VectorOfStrings object_property2 = object2.getProperty();

        for (unsigned int k = 0; k < object_property1.size(); k++){

            if (object_property1[k] == object_property2[k]){

            //do something

            break; //this aborts the inner most loop
            //Additionally, I need the outer most loop to move on one iteration
            }
        }
    }
}

Donc, si l'instruction conditionnelle dans la boucle "k" est remplie, je veux que la boucle "i" abandonne l'itération en cours et passe à la suivante.

De plus, comme je suis nouveau, le code peut être inélégant, mais veuillez vous concentrer sur ce problème spécifique dans vos réponses! À moins qu'une restructuration générale du code ne soit la solution au problème bien sûr :)

14
faranzki

Cela peut être implémenté avec goto:

for (int i = 0; i < max; i++){
    Object & object1 = system.getAgent(i);
    VectorOfStrings object_property1 = object1.getProperty();

    for (int j = i + 1; j < max; j++){
        Object & object2 = system.getObject(j);
        VectorOfStrings object_property2 = object2.getProperty();
        for (unsigned int k = 0; k < object_property1.size(); k++){
            if (object_property1[k] == object_property2[k]){
                //do something
                goto cnt; //this aborts the inner most loop
                //Additionally, I need the outer most loop to move on one iteration
            }
        }
    }
    cnt:;
}

C'est l'un des rares cas où l'utilisation de goto simplifie vraiment le code.

23
alexeykuzmin0

La façon la plus lisible de résoudre ce problème classique est presque toujours de mettre les boucles imbriquées dans une fonction. Je ne sais pas ce que le code spécifique est censé faire, mais voici un pseudo-code sur lequel vous pouvez baser une solution:

bool keep_going = true;
for (int i = 0; i < max && keep_going; i++)
{
  Object& object1 = system.getAgent(i);
  keep_going = !compare_objects(object1.getProperty(), i+1, max);
}

compare_objects est quelque chose comme ceci:

inline bool compare_objects (const VectorOfStrings& obj_prop1, size_t begin, size_t end)
{
  for(size_t i=begin; i<end; i++)
  { 
    Object& obj2 = system.getObject(j);
    VectorOfStrings obj_prop2 = obj2.getProperty();

    for size_t j = 0; j < obj_prop1.size(); j++)
    {
      ifobj_prop1[j] == obj_prop2[j])
      {
        do_something();
        return true;
      }
    }
  }

  return false;
}
5
Lundin

Je recommande fortement l'approche de @ alexeykuzmin0, mais si vous devez travailler dans un environnement où goto est interdit, alors l'alternative (avec un drapeau ennuyeux) est:

for (int i = 0; i < max; i++){
    Object & object1 = system.getAgent(i);
    VectorOfStrings object_property1 = object1.getProperty();

    bool property_matched = false;
    for (int j = i + 1; j < max && !property_matched; j++){
        Object & object2 = system.getObject(j);
        VectorOfStrings object_property2 = object2.getProperty();
        for (unsigned int k = 0; k < object_property1.size(); k++){
            if (object_property1[k] == object_property2[k]){
                //do something
                property_matched = true; // This will break the "j" loop
                break; //this aborts the inner most loop
            }
        }
    }
}

Vous pouvez utiliser lambda et utiliser return stament pour changer le contrôle. Si vous revenez vrai, le lambda se terminera et outter "pour" continuera ".

Version compacte:

for(;;) {
    [&]() {
        for(;;) {
            if(/*break condition here*/)
                return;
        }
    }();
}

Un modèle plus général:

for(;;) {
    auto innerLoop = [&]() {
        for(;;) {
            if(/*break condition here*/)
                return true;
        }
        return false;
    };

    if(innerLoop())
        continue;
}

Pour ce cas:

for (int i = 0; i < max; i++){
    Object & object1 = system.getAgent(i);
    VectorOfStrings object_property1 = object1.getProperty();

    auto innerLoop = [](){
        for (int j = i + 1; j < max; j++){
        Object & object2 = system.getObject(j);
        VectorOfStrings object_property2 = object2.getProperty();

            for (unsigned int k = 0; k < object_property1.size(); k++){

                if (object_property1[k] == object_property2[k]){
                    //do something
                    return true;
                }
            }
        }
        return false;
    };

    if(innerLoop())
        continue;
}
3
Bediver