【问题标题】:How to use something like a continue statement in nested for loops?如何在嵌套的 for 循环中使用 continue 语句之类的东西?
【发布时间】:2017-05-01 23:15:16
【问题描述】:

我有一类对象,需要将每个对象的一个​​属性与所有其他对象的相同属性进行比较。如果它们匹配,则代码需要做一些事情。这导致两个“for 循环”遍历对象以获取该属性,并且在第二个“for 循环”中,有第三个“for 循环”遍历属性的元素(它是一个向量)以比较它们.如果它们匹配,我需要最外层的“for 循环”来中止当前迭代并继续下一个迭代(我只想考虑与另一个对象的第一个匹配)。

我研究了“goto”语句并创建了一个 do{}while() 结构,但无法以某种方式实现它们以获得所需的结果。我需要的是基于最内层循环中条件语句中发生的情况的最外层循环的“继续”语句。

实现这一点的好方法是什么?如何实现?

编辑:在我接受的答案旁边,我还推荐 Martin Bonner 的答案,它也可以正常工作并且不依赖 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
            }
        }
    }
}

因此,如果满足“k”循环中的条件语句,我希望“i”循环中止当前迭代并继续进行下一个迭代。

另外,由于我是新手,代码可能不优雅,但请在您的回答中关注这个特定问题!除非对代码进行一般重组可能是解决问题的方法:)

【问题讨论】:

  • 我需要最外层的循环进行一次迭代你的意思是增加 i 吗?如果 object_property1 的大小与 object_property2 的大小不同,您是否也想过会发生什么?
  • 旁白:直到我说到“我缺乏英语词汇……”之前,我一直以为你和我一样是母语为英语的人。你的英语很好。
  • do {...} while(false); hack 用于避免嵌套 if-else 的非嵌套循环,因为它还使用 break 跳出开关。
  • @stijn 是的,但它们的大小相同,因为它们是同一类的成员,所以不会产生问题!
  • @stefaanv 谢谢你的信息!

标签: c++ loops conditional nested-loops continue


【解决方案1】:

解决这个经典问题的最易读的方法几乎总是将嵌套循环放在一个函数中。我不知道具体的代码是做什么的,但这里有一些伪代码可以作为解决方案的基础:

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 是这样的:

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

【讨论】:

    【解决方案2】:

    您可以使用 lambda 并使用 return 语句来更改控件。如果您返回 true,则 lambda 将结束并且外部“for”将“继续”。

    精简版:

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

    更通用的模板:

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

    对于这种情况:

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

    【讨论】:

    • 聪明,但可读性堪比古代楔形文字碑文,该碑文由当时食用蘑菇的有阅读障碍的抄写员雕刻而成。
    • 我没有对此进行测试,因为我对如何根据您提供的代码实现它有点困惑!我应该在 if() 之后将括号留空吗?
    • 只是一个模板,在if()中加入条件
    • 如果内循环 lambda 可以有一个有意义的名称并且可以重复使用,则可以将其移动到常规函数中。
    • 这只是毫无意义的元编程,丝毫不会增加可读性。事实上,恰恰相反。
    【解决方案3】:

    我强烈推荐@alexeykuzmin0 的方法,但如果您必须在禁止goto 的环境中工作,那么替代方案(带有烦人的标志)是:

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

    【讨论】:

    • 我不认为在这种情况下这很烦人,因为您可能确实想知道属性是否匹配。
    • @stefaanv:是的,如果你想模拟像 python for ... else ... 这样的东西,那么这个标志很有用。另一方面,在标签情况下,您可以将处理“不匹配”的代码直接放在中间 for(可能带有 continue)之后,将处理“匹配”的代码放在标签之后。跨度>
    • @MartinBonner 还有一个问题:虽然这工作正常,但我收到编译器警告:“警告:标签‘property_matched’已定义但未使用”。我怎样才能避免这种情况?
    • 啊“label property_matched not used”。如果您使用标志,只需删除标签!你当然不想要两者。
    • 傻我。从标签选项切换到标志选项时我忽略了它并忘记删除。请忽略那个愚蠢的评论。
    【解决方案4】:

    这可以用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:;
    }
    

    这是使用goto 真正简化代码的罕见情况之一。

    【讨论】:

    • 我会让标签有一个有意义的名字,比如property_matched
    • @MartinBonner 我的意思是cntcontinue 的首字母缩略词
    • @alexeykuzmin0 还不清楚,因为它不能继续自己,所以让它类似于goto_continue注意: 大括号是必须这样做,否则由于某种原因它会破坏变量范围x)
    • 除非绝对必要,否则不要使用goto - 你可能知道自己在做什么,但其他人进来并用它彻底破坏你的应用程序并可能破坏数据!
    猜你喜欢
    • 2015-01-18
    • 1970-01-01
    • 2016-08-09
    • 2016-01-14
    • 1970-01-01
    • 2019-06-05
    • 1970-01-01
    • 2020-11-25
    • 2013-01-01
    相关资源
    最近更新 更多