是否可以使用break
函数退出多个嵌套的for
循环?如果是这样,你会怎么做呢?你还可以控制休息退出的循环次数吗?
答案 0 :(得分:249)
不,不要用break
破坏它。这是使用goto
的最后一个据点。
答案 1 :(得分:211)
AFAIK,C ++不支持命名循环,就像Java和其他语言一样。您可以使用goto,或创建您使用的标志值。在每个循环结束时检查标志值。如果设置为true,那么您可以跳出该迭代。
答案 2 :(得分:52)
打破嵌套循环的另一种方法是将两个循环分解为单独的函数,并在要退出时将该函数return
分解。
当然,这提出了另一个论点,即你是否应该从最后的任何地方的函数中明确return
。
答案 3 :(得分:46)
只是使用lambdas添加一个明确的答案:
for (int i = 0; i < n1; ++i) {
[&] {
for (int j = 0; j < n2; ++j) {
for (int k = 0; k < n3; ++k) {
return; // yay we're breaking out of 2 loops here
}
}
}();
}
当然这种模式有一定的局限性,显然只有C ++ 11,但我认为它非常有用。
答案 4 :(得分:32)
中断将仅退出包含它的最内层循环。
您可以使用转到来突破任意数量的循环。
当然转到通常是Considered Harmful。
使用break函数[...]是否合适?
使用break和goto会使得更难以推断程序的正确性。请参阅此处以获取对此的讨论:Dijkstra was not insane。
答案 5 :(得分:19)
虽然这件衣服已经出现了,但我认为一个好方法是做到以下几点:
for(unsigned int z = 0; z < z_max; z++)
{
bool gotoMainLoop = false;
for(unsigned int y = 0; y < y_max && !gotoMainLoop; y++)
{
for(unsigned int x = 0; x < x_max && !gotoMainLoop; x++)
{
//do your stuff
if(condition)
gotoMainLoop = true;
}
}
}
答案 6 :(得分:14)
这个怎么样?
for(unsigned int i=0; i < 50; i++)
{
for(unsigned int j=0; j < 50; j++)
{
for(unsigned int k=0; k < 50; k++)
{
//Some statement
if (condition)
{
j=50;
k=50;
}
}
}
}
答案 7 :(得分:12)
使用goto
的代码示例和打破嵌套循环的标签:
for (;;)
for (;;)
goto theEnd;
theEnd:
答案 8 :(得分:9)
打破几个嵌套循环的一个好方法是将代码重构为函数:
void foo()
{
for(unsigned int i=0; i < 50; i++)
{
for(unsigned int j=0; j < 50; j++)
{
for(unsigned int k=0; k < 50; k++)
{
// If condition is true
return;
}
}
}
}
答案 9 :(得分:5)
goto对破坏嵌套循环非常有用
for (i = 0; i < 1000; i++) {
for (j = 0; j < 1000; j++) {
for (k = 0; k < 1000; k++) {
for (l = 0; l < 1000; l++){
....
if (condition)
goto break_me_here;
....
}
}
}
}
break_me_here:
// Statements to be executed after code breaks at if condition
答案 10 :(得分:3)
我知道这是一个老话题,但是我觉得这确实需要说,没有其他地方要说。对于这里的每个人,请使用 goto。。我刚刚使用过。
几乎所有内容都一样,goto不是“或”或“不好”的100%。至少有两种用法,我要说的是,如果您将goto用于它们-而不用于其他任何用途-您不仅应该100%可以,而且与没有它相比,您的程序将更具可读性,因为它使您的意图更加清晰(有多种方法可以避免这种情况,但是我发现它们都比较笨拙):
与其仅仅教条地接受诸如“ so-so is'evil'”之类的规则,不如理解为什么主张情感,并遵循“ why”而不是情书。不知道这也会给我带来很多麻烦,以至于我要说,断断续续地称呼事物“邪恶”比事物本身有害得多。最糟糕的是,您只会得到错误的代码-然后您知道只要听到警惕就不会使用它,但是如果您为满足教条主义而竭尽全力,那会更糟。 >
为什么之所以将“ goto”称为“邪恶”是因为您永远不要使用它来代替普通的ifs,fors和whiles 。那为什么呢?尝试一下,一直尝试使用“ goto”代替普通的控制逻辑语句,然后尝试再次使用控制逻辑编写相同的代码,并告诉我哪个看起来更好,更容易理解,哪个看起来更糟。 。妳去(奖金:现在尝试在仅goto的代码中添加新功能。)这就是为什么它是“邪恶的”,并且围绕“邪恶”具有适当的范围限定。使用它来缩短C的“ break
”命令的缺点不是是有问题的用法,只要您从代码中清楚地知道goto应该完成什么(例如使用“ nestedBreak”之类的标签)。打破嵌套循环是很自然的。
(或者更简单地说:使用goto打破循环。我想说这是更可取的。请勿使用goto来 create 循环。那是“邪恶”。)
又怎么知道自己是教条的?如果遵循“ xyz是邪恶的”规则,则代码会使您的代码变得 less 容易理解,因为您正试图绕过它(例如,通过在每个循环中添加额外的条件或某些标记变量),或类似的其他技巧),那么您很有可能会教条主义。
除了良好的编码习惯以外,没有什么可以替代学习良好的思考习惯。前者在后者之前,而后者通常会在前者被采用后跟随。但问题是,我发现的次数太多了,后者不够复杂。太多的人只是简单地说“这很不好”和“这需要更多的思考”,而没有说要想什么,想什么关于和为什么 。太可惜了。
(FWIW,在C ++中,仍然需要打破嵌套循环,但是对错误代码的需求却不存在:在这种情况下,请始终使用异常来处理错误代码,除非如此,否则绝不返回它们异常抛出和捕获经常会导致性能问题,例如在高需求服务器代码中的紧密循环中,也许[有人可能说“例外”应该“很少使用”,但这是思想欠缺的另一部分。摆脱教条主义:不,至少在我反驳这种教条之后,根据我的经验,我发现它们使事情变得更加清晰-只是不要滥用它们来进行错误处理以外的其他操作,例如将它们用作控制流;实际上与“ goto”相同。如果将它们全部使用并且仅用于错误处理,那就是它们的用途。]。
答案 11 :(得分:2)
我确实认为goto
在这种情况下有效:
要模拟break
/ continue
,您需要:
for ( ; ; ) {
for ( ; ; ) {
/*Code here*/
if (condition) {
goto theEnd;
}
}
}
theEnd:
for ( ; ; ) {
for ( ; ; ) {
/*Code here*/
if (condition) {
i++;
goto multiCont;
}
}
multiCont:
}
答案 12 :(得分:2)
break
语句终止执行它出现的最近的封闭do
,for
,switch
或while
语句。控制传递给终止语句后面的语句。
来自msdn。
答案 13 :(得分:1)
我不确定是否值得,但是您可以使用一些简单的宏来模拟Java的命名循环:
#define LOOP_NAME(name) \
if ([[maybe_unused]] constexpr bool _namedloop_InvalidBreakOrContinue = false) \
{ \
[[maybe_unused]] CAT(_namedloop_break_,name): break; \
[[maybe_unused]] CAT(_namedloop_continue_,name): continue; \
} \
else
#define BREAK(name) goto CAT(_namedloop_break_,name)
#define CONTINUE(name) goto CAT(_namedloop_continue_,name)
#define CAT(x,y) CAT_(x,y)
#define CAT_(x,y) x##y
用法示例:
#include <iostream>
int main()
{
// Prints:
// 0 0
// 0 1
// 0 2
// 1 0
// 1 1
for (int i = 0; i < 3; i++) LOOP_NAME(foo)
{
for (int j = 0; j < 3; j++)
{
std::cout << i << ' ' << j << '\n';
if (i == 1 && j == 1)
BREAK(foo);
}
}
}
另一个例子:
#include <iostream>
int main()
{
// Prints:
// 0
// 1
// 0
// 1
// 0
// 1
int count = 3;
do LOOP_NAME(foo)
{
for (int j = 0; j < 3; j++)
{
std::cout << ' ' << j << '\n';
if (j == 1)
CONTINUE(foo);
}
}
while(count-- > 1);
}
答案 14 :(得分:0)
其他语言(例如PHP)接受一个break参数(即break 2;)来指定你想要突破的嵌套循环级别的数量,但C ++却没有。您必须使用在循环之前设置为false的布尔值,如果要中断,在循环中设置为true,加上嵌套循环后的条件中断,检查布尔值是否设置为true如果是的话会打破。
答案 15 :(得分:0)
我知道这是老帖子。但我会建议一点逻辑和简单的答案。
for(unsigned int i=0; i < 50; i++)
{
for(unsigned int j=0; j < conditionj; j++)
{
for(unsigned int k=0; k< conditionk ; k++)
{
// If condition is true
j= conditionj;
break;
}
}
}
答案 16 :(得分:0)
仅用一个bool
变量中断任意数量的循环,如下所示:
bool check = true;
for (unsigned int i = 0; i < 50; i++)
{
for (unsigned int j = 0; j < 50; j++)
{
for (unsigned int k = 0; k < 50; k++)
{
//Some statement
if (condition)
{
check = false;
break;
}
}
if (!check)
{
break;
}
}
if (!check)
{
break;
}
}
在这段代码中,我们break;
所有循环。
答案 17 :(得分:-1)
while (i<n) {
bool shouldBreakOuter = false;
for (int j=i + 1; j<n; ++j) {
if (someCondition) {
shouldBreakOuter = true;
}
}
if (shouldBreakOuter == true)
break;
}
答案 18 :(得分:-2)
你可以使用try ... catch。
try {
for(int i=0; i<10; ++i) {
for(int j=0; j<10; ++j) {
if(i*j == 42)
throw 0; // this is something like "break 2"
}
}
}
catch(int e) {} // just do nothing
// just continue with other code
如果你必须同时打破几个循环,那么它通常是一个例外。
答案 19 :(得分:-3)
断开for循环对我来说有点奇怪,因为for循环的语义通常表明它将执行指定的次数。但是,在所有情况下都不错;如果你正在寻找一个集合中的东西,并想在你找到它之后破解它,那么它很有用。但是,在C ++中不可能打破嵌套循环;通过使用标记的中断,它是其他语言。你可以使用标签和goto,但这可能会让你在晚上胃灼热..?看起来似乎是最好的选择。