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 ).

Как это сделать?

9
задан Peter Mortensen 29 August 2010 в 10:53
поделиться

11 ответов

Я рекомендую преобразовать ваш код в функцию. Тогда вы можете просто вернуть из этой функции вместо использования 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 перед любым другим членом команды, который случайно наткнется на код.

20
ответ дан 4 December 2019 в 05:51
поделиться

Используйте 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:
34
ответ дан 4 December 2019 в 05:51
поделиться

Выполните одно из четырех действий: используйте goto , используйте throw , использовать флаг или рефакторинг.

Многие не согласятся с , использующим goto , но иногда это чистое решение. (В большинстве случаев это не так, но оно существует по определенной причине.) Однако я считаю, что использование goto требует рефакторинга.

Второе решение - вызвать какое-то особое исключение, а затем перехватить его сразу за пределами основного цикла. Это злоупотребление системой исключений и, по сути, еще хуже goto ; используйте вместо него goto .

Третье решение - использовать флаг из какого-то типа . По сути, это «более безопасный» goto , но некоторые могут поспорить, что это немного уродливее. (Особенно с многоуровневыми. Хотя в таком случае вас беспокоит то, насколько уродливым является ваш код.)

Решение, которое я бы порекомендовал, - это рефакторинг . Что бы вы ни делали, это уже слишком. Вы должны переместить внутренние циклы в функцию и вызвать эту функцию. Возврат к основному циклу - это просто возврат из этой функции. (Другими словами: «Моя работа сделана».)

23
ответ дан 4 December 2019 в 05:51
поделиться
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:
4
ответ дан 4 December 2019 в 05:51
поделиться

\ (◕ ◡ ◕) /

[]() {
    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
        {
           .
           .
           .
        }
    }
}();
4
ответ дан 4 December 2019 в 05:51
поделиться

Если это уместно, вы можете сделать функцию, содержимым которой будет цикл, и использовать 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
4
ответ дан 4 December 2019 в 05:51
поделиться

Единственный способ выйти из двух таких циклов одновременно - это goto или throw или return и throw и return могут не подходить (особенно throw , если условие не является исключительным). В качестве альтернативы вы можете установить какое-то условие ( bool breakout; ) и продолжать нарушать, если оно истинно.

4
ответ дан 4 December 2019 в 05:51
поделиться
  1. Использовать 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
     {
     .
     .
     .
     }
    }
    готово:
    
  2. установить значение 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
     {
     .
     .
     .
     }
    }
    
3
ответ дан 4 December 2019 в 05:51
поделиться

Одна простая стратегия - поместить цикл в отдельную функцию и выполнить возврат в выбранной точке:

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
        {
           .
           .
           .
        }
    }
}

Любой результат также может быть возвращен с возвращаемым значением или с параметром ссылки для функции.

2
ответ дан 4 December 2019 в 05:51
поделиться

Идеальным способом было бы рефакторить ваш код так, чтобы вам больше не требовалась такая сложная структура вложенных циклов. В зависимости от того, как выглядит остальная часть вашего кода, циклы 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;.

2
ответ дан 4 December 2019 в 05:51
поделиться

Используйте этот тип шаблона

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++)
    {
       .
       .
       .
    }
}
1
ответ дан 4 December 2019 в 05:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: