C 的替代方案,例如为 C++ 标记和转义嵌套循环
Alternitives to C like labling and escaping nested loops for C++
在 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 是我能想到的最接近的构造,它会产生这种行为,但是当需要 none 时使用错误系统的草率让我担心(而且我听说它们很慢)。
我很想将它包装在 extern C 中,除非我在整个项目中完全依赖 C++ 库,所以这也让人感到草率。
是 try 块还是只是重写我唯一的选项?
C 和 C++ 都没有带标签的 break 语句(您可能使用的是语言扩展,而不是标准 C)。
相反,您可以使用 goto
来跳出嵌套循环。
while (a)
{
while(b)
{
while (c)
{
if(d)
goto break_b;
}
}
break_b:
// ...
}
I was able to use goto to solve this... I though it was a banned construct in c++?
没有。 goto
在 C++ 中不是 "banned"。
这是使用 goto
的完美方式。不存在等效的结构化控制语句。
lambdas/closures [...] potentially would let me do this but I'm not quite sure how they would work in this case.
如果您对 goto
过敏,那么您确实可以使用 lambda,但我认为它不会提供任何额外的可读性:
while (a)
{
[&](){
while(b)
{
while (c)
{
if(d)
return;
}
}
}();
// ...
}
您可以使用命名函数来代替 lambda。但在那种情况下,您需要将任何变量(例如 b
、c
和 d
)作为参数传递(假设它们不是全局变量)。
另一种方法是一个额外的变量:
while (a)
{
bool break_b = false;
while(b)
{
while (c)
{
if(d) {
break_b = true;
break;
}
}
if (break_b)
break;
}
// ...
}
在这三种方法中,我推荐 goto
,因为它的可读性最高。除非示例中省略的实际内部循环非常长,在这种情况下,单独的函数可能会更好。
这里不建议用 goto 代替 break。可能存在构造函数和析构函数未被正确调用的问题。虽然 goto 仍然存在于 C++ 中,但除非您 真的 知道自己在做什么,否则您真的不想使用它!一个更安全的选择是使用 try-catch 块。更好的方法是重构你的算法 (目前它是 O(N^3),这真的应该敲响警钟!)
while (a)
{
try
{
while(b)
{
while (c)
{
if(d) throw;
}
}
}
catch(...)
{
}
}
正如其他人已经指出的那样,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();
…
}
在 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 是我能想到的最接近的构造,它会产生这种行为,但是当需要 none 时使用错误系统的草率让我担心(而且我听说它们很慢)。
我很想将它包装在 extern C 中,除非我在整个项目中完全依赖 C++ 库,所以这也让人感到草率。
是 try 块还是只是重写我唯一的选项?
C 和 C++ 都没有带标签的 break 语句(您可能使用的是语言扩展,而不是标准 C)。
相反,您可以使用 goto
来跳出嵌套循环。
while (a)
{
while(b)
{
while (c)
{
if(d)
goto break_b;
}
}
break_b:
// ...
}
I was able to use goto to solve this... I though it was a banned construct in c++?
没有。 goto
在 C++ 中不是 "banned"。
这是使用 goto
的完美方式。不存在等效的结构化控制语句。
lambdas/closures [...] potentially would let me do this but I'm not quite sure how they would work in this case.
如果您对 goto
过敏,那么您确实可以使用 lambda,但我认为它不会提供任何额外的可读性:
while (a)
{
[&](){
while(b)
{
while (c)
{
if(d)
return;
}
}
}();
// ...
}
您可以使用命名函数来代替 lambda。但在那种情况下,您需要将任何变量(例如 b
、c
和 d
)作为参数传递(假设它们不是全局变量)。
另一种方法是一个额外的变量:
while (a)
{
bool break_b = false;
while(b)
{
while (c)
{
if(d) {
break_b = true;
break;
}
}
if (break_b)
break;
}
// ...
}
在这三种方法中,我推荐 goto
,因为它的可读性最高。除非示例中省略的实际内部循环非常长,在这种情况下,单独的函数可能会更好。
这里不建议用 goto 代替 break。可能存在构造函数和析构函数未被正确调用的问题。虽然 goto 仍然存在于 C++ 中,但除非您 真的 知道自己在做什么,否则您真的不想使用它!一个更安全的选择是使用 try-catch 块。更好的方法是重构你的算法 (目前它是 O(N^3),这真的应该敲响警钟!)
while (a)
{
try
{
while(b)
{
while (c)
{
if(d) throw;
}
}
}
catch(...)
{
}
}
正如其他人已经指出的那样,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();
…
}