C的替代品,如C ++标记和转义嵌套循环

问题描述 投票:1回答:3

在C和javascript中,我喜欢写这种东西的能力,并让它工作。

while (a)
{
ctx: while(b)
     {
         while (c)
         {
             if(d) break ctx;
             ...
         }
     }
     ...
}

也许我只是对C ++版本感到困惑,但我在g ++中遇到了这种错误:

error: expected ‘;’ before ‘ctx’
     break ctx;
error: ‘ctx’ was not declared in this scope
warning: label ‘ctx’ defined but not used [-Wunused-label]
 ctx:

C ++似乎拒绝让我编写这段代码。 C ++已经添加了lambdas / closures,可能会让我这样做,但我不太确定它们在这种情况下会如何工作。

使用try throw catch是我能想到的最接近的构造产生这种行为,但是当不需要任何东西时使用错误系统的麻烦关注我(我听到它们也很慢)。

我很想将它包装在extern C中,除非我完全依赖于c ++库来完成整个项目,所以这也感觉很邋..

尝试阻止或只是重写我唯一的选择?

c++ closures try-catch goto
3个回答
3
投票

C和C ++都没有标记的break语句(你可能使用的是语言扩展,而不是标准的C语言)。

相反,您可以使用goto来打破嵌套循环。

while (a)
{
    while(b)
    {
        while (c)
        {
            if(d)
                goto break_b;
        }
    }
    break_b:
    // ...
}

我能够使用goto来解决这个问题...我认为它是c ++中的禁止构造?

没有.goto在C ++中没有被“禁止”。

这是一个使用goto的完美方式。不存在等效的结构化控制语句。


lambdas / closures [...]可能会让我这样做,但我不太确定它们在这种情况下会如何工作。

如果你对goto过敏,那么你确实可以使用lambda,但我不认为它提供任何额外的可读性:

while (a)
{
    [&](){
        while(b)
        {
            while (c)
            {
                if(d)
                    return;
            }
        }
    }();
    // ...
}

您可以使用命名函数代替lambda。但在这种情况下,你需要传递任何变量(如bcd)作为参数(假设它们不是全局变量)。


另一种方式是额外的变量:

while (a)
{
    bool break_b = false;
    while(b)
    {
        while (c)
        {
            if(d) {
                break_b = true;
                break;
            }
        }
        if (break_b)
            break;
    }
    // ...
}

在这三种方法中,我推荐goto,因为它是最具可读性的。除了在示例中省略的实际内循环非常长的情况,在这种情况下,单独的函数可能更好。


1
投票

正如其他人已经指出的那样,goto将是一种完全符合您要求的方式。

话虽这么说,我认为,在提出如何摆脱大规模复杂的控制流结构的问题之前,你应该首先问问自己为什么有一个大规模复杂的流程结构开始。这些循环中发生了什么?如果每个循环中发生的事情都不能更好地转移到它自己的功能中吗?例如,而不是

while (a)
{
ctx: while (b)
     {
         while (c)
         {
             if (d) goto ctx;
             …
         }
     }
     …
}

为什么不

bool doC()
{
    while (c)
    {
        if (d)
            return false;
        …
    }

    return true;
}

void doB()
{
    while (b && doC());
}

然后

while (a)
{
    doB();
    …
}

0
投票

在这里用goto替换断点是不可取的。可能存在未正确调用构造函数和析构函数的问题。虽然goto仍然存在于C ++中,但除非你真的知道自己在做什么,否则它真的不是你想要使用的东西!更安全的选择是使用try-catch块。一个更好的方法是重新计算你的算法(目前它是O(N ^ 3),这应该真的响起一些警钟!)

while (a)
{
  try
  {
    while(b)
    {
      while (c)
      {
        if(d) throw;
      }
    }
  }
  catch(...)
  {
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.