Я готовлю код:
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
).
Как это сделать?
Я рекомендую преобразовать ваш код в функцию. Тогда вы можете просто вернуть
из этой функции вместо использования 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
. Хотя это еще одно быстрое исправление, я настоятельно не рекомендую его, особенно если вы работаете в строгой среде, где код будет проверяться коллегами и использоваться в течение многих лет.
В , на мой взгляд, подход 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
.
Третье решение - использовать флаг из какого-то типа . По сути, это «более безопасный» 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:
\ (◕ ◡ ◕) /
[]() {
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
{
.
.
.
}
}
}();
Если это уместно, вы можете сделать функцию, содержимым которой будет цикл, и использовать 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;
) и продолжать нарушать, если оно истинно.
Использовать a goto
:
for(int a = 1; a <= 100; a++) //loop a (основной цикл)
{
for(int b = 1000; b <= 2000; b++) //loop b
{
if(b == 1555)
geto done;
}
for(int c = 2001; c <= 3000; c++) //loop c
{
.
.
.
}
}
готово:
установить значение 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
, просто установите 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
или переменных условий, вы можете просто вернуть 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++)
{
.
.
.
}
}