C++: разорвать основной цикл
Я готовлю код:
for(int a = 1; a <= 100; a++) //loop a (main loop)
{
for(int b = 1000; b <= 2000; b++) //loop b
{
if(b == 1555)
break;
}
for(int c = 2001; c <= 3000; c++) //loop c
{
.
.
.
}
}
Я хочу разорвать основной цикл (переменная цикла int a
) С помощью break;
оператор в цикле b (переменная цикла int b
).
как я могу это сделать?
11 ответов
Я рекомендую рефакторинг кода в функцию. Тогда вы можете просто return
из этой функции, вместо использования break
:
void myFunc()
{
for(int a = 1; a <= 100; a++) //loop a (main loop)
{
for(int b = 1000; b <= 2000; b++) //loop b
{
if(b == 1555) // Logic is just an example,
return; // since it will always return
}
.
.
.
}
}
это - или, возможно, даже более сложный рефакторинг вашего кода - должно поддаваться чистому, элегантному решению. Кроме того, если вы просто хотите быстро исправить, вы можете использовать переменную условия:
for(int a = 1; a <= 100; a++) //loop a (main loop)
{
bool cond = false;
for(int b = 1000; b <= 2000; b++) //loop b
{
if(b == 1555){
cond = true;
break;
}
}
if (cond) break;
.
.
.
}
другие предложили использовать goto
. Хотя это еще одно быстрое исправление, я настоятельно рекомендую против него, особенно, если вы работаете в строгой среде, где код будет рецензироваться и использоваться в течение многих лет.
на мое мнение the goto
подход немного сложнее поддерживать, чем рефакторинг функции/возврата, особенно позже, когда кто-то другой вносит изменения в код. Плюс вам придется оправдать goto
для всех остальных членов команды, которые случайно наткнулись на код.
использовать goto
.
for(int a = 1; a <= 100; a++) //loop a (main loop)
{
for(int b = 1000; b <= 2000; b++) //loop b
{
if(b == 1555)
goto loopDone;
}
for(int c = 2001; c <= 3000; c++) //loop c
{
.
.
.
}
}
loopDone:
либо сделайте одну из четырех вещей: используйте goto
используйте throw
, используйте флаг или рефакторинг.
многие не согласятся с используя goto
, а иногда это чистое решение. (В большинстве случаев это не так, но оно существует по какой-то причине.) Тем не менее, я нахожу использование goto
требует рефакторинга.
второй вариант бросить некоторые специальные исключения, а затем поймать его только вне основного цикла. Это злоупотребление система исключений и в основном хуже goto
; использовать goto
вместо этого.
третьим решением было бы использовать флаг of какой-то. Это в основном "безопаснее"goto
, но некоторые могут возразить, что это немного уродливее. (Особенно с несколькими уровнями. Хотя в таком случае вас беспокоит, насколько уродлив ваш код.)
решение, которое я бы рекомендовал, это рефакторинг. Что бы ты ни делал, это слишком. Ты должен двигаться. внутренняя петля переходит в функцию и вызывает эту функцию. Возврат к основному циклу-это просто возврат из этой функции. (Другими словами "Моя работа сделана.")
for(int a = 1; a <= 100; a++) //loop a (main loop)
{
for(int b = 1000; b <= 2000; b++) //loop b
{
if(b == 1555)
goto end;
}
for(int c = 2001; c <= 3000; c++) //loop c
{
.
.
.
}
}
end:
если это уместно, вы можете сделать функцию, содержимое которой является циклом a, и использовать return.
public void bigLoop()
{
for(int a = 1; a <= 100; a++)
{
for(int b = 1000; b <= 2000; b++)
{
if(b == 1555)
return;
}
for(int c = 2001; c <= 3000; c++)
{
.
.
.
}
}
}//bigLoop
единственный способ выйти из двух таких петель за раз-это goto
или throw
или return
и throw
и return
может быть не подходит (особенно throw
, если условие не является исключительным). В качестве альтернативы вы можете установить какое-то условие (bool breakout;
), и продолжайте ломать, если это правда.
\ (◡ ◕ ◕) /
[]() {
for(int a = 1; a <= 100; a++) //loop a (main loop)
{
for(int b = 1000; b <= 2000; b++) //loop b
{
if(b == 1555)
return;
}
for(int c = 2001; c <= 3000; c++) //loop c
{
.
.
.
}
}
}();
-
использовать
goto
:for(int a = 1; a <= 100; a++) //loop a (main loop) { for(int b = 1000; b <= 2000; b++) //loop b { if(b == 1555) goto done; } for(int c = 2001; c <= 3000; c++) //loop c { . . . } } done:
-
установите значение sentinel, проверенное каждым циклом:
bool sentinel = true ; for(int a = 1; a <= 100 && sentinel ; a++) //loop a (main loop) { for(int b = 1000; b <= 2000 && sentinel; b++) //loop b { if(b == 1555) sentinel = false; } for(int c = 2001; c <= 3000 && sentinel; c++) //loop c { . . . } }
одна простая стратегия-поместить цикл в отдельную функцию и сделать возврат в выбранной точке:
void func()
{
for(int a = 1; a <= 100; a++) //loop a (main loop)
{
for(int b = 1000; b <= 2000; b++) //loop b
{
if(b == 1555)
return;
}
for(int c = 2001; c <= 3000; c++) //loop c
{
.
.
.
}
}
}
любой результат может быть возвращен с возвращаемым значением или со значением параметра ссылку на функцию.
идеальным способом было бы повторно-фактор ваш код, так что вам больше не нужна столь сложная вложенного цикла структуры. В зависимости от того, как выглядит остальная часть вашего кода, ваш b
и c
петли могут быть кандидатами на то, чтобы стать отдельными функциями, если не все a
петли.
так как это выглядит как петли b
и c
итерация по смежным диапазонам, почему бы не объединить их и немного уменьшить вложенность цикла?
for (int a = 1; a <= 100; a++) //loop a (main loop)
{
int count = 1000;
while (count <= 3000) // combined loops 'b' and 'c'
{
if (count <= 2000)
{
// Old loop 'b' code
if (b == 1555)
goto fullbreak;
}
else
{
// Old loop 'c' code
...
}
count++;
}
}
fullbreak:
вы также можете использовать переменная условия вместо goto
. Если вы хотите вырваться из старого b
цикл, но все еще обрабатывать старый c
loop, просто установите count = 2001
внутри старого b
код цикла.
в идеале, вы, по крайней мере, сможете перефразировать это на что-то вроде
for (int a = 1; a <= 100; a++) //loop a (main loop)
{
if (process_inner_loop(pass, required, args))
break;
}
где функция process_inner_loop
обертывает исходные два цикла и возвращает ненулевое значение, если вы хотите вырваться из замкнутого цикла. Теперь вместо использования goto
или условие переменные, вы можете просто return 1;
.
используйте такой шаблон
for(int a = 1; a <= 100; a++)
{
int breakMain = 0;
for(int b = 1000; b <= 2000; b++)
{
if(b == 1555)
{
breakMain = 1;
break;
}
}
if(breakMain)
break;
for(int c = 2001; c <= 3000; c++)
{
.
.
.
}
}