Разрывать вложенные циклы - PullRequest
8 голосов
/ 14 декабря 2011

Может кто-нибудь сказать мне, как разорвать основной цикл, когда у меня есть вложенные циклы?
Пример *:

/*Main loop*/
for(int y = 0; y < 100; y+=10)
{
    /*Sub loop*/
    for (int x = 0; x < 100; x += 10)
    {
        if(x == 60) 
        { 
            //Break the main loop 
        }
    }
}

* Этот код ничего не делает, это просто пример

Что я должен поставить вместо комментария "Разорвать основной цикл"? В Java есть метки, которые я могу разбить (когда я устанавливаю метку для основного цикла с именем "MainLoop", я могу написать "break MainLoop;", и она будет действительной), но что я могу сделать здесь?

Спасибо за совет!

Ответы [ 13 ]

17 голосов
/ 14 декабря 2011

goto!

Я не понимаю этого постоянного мема, который говорит, что goto считается "вредным". При правильном использовании он очень мощный, и это именно тот случай.

10 голосов
/ 14 декабря 2011
  • рефакторинг, поэтому вам не нужно выходить из вложенных циклов таким образом.
    Использование return часто возможно путем помещения циклов в отдельную функцию.
  • используйте goto.
  • Используйте флаг (некрасиво)
7 голосов
/ 14 декабря 2011

Используйте флаг, чтобы сигнализировать об окончании:

for(int y = 0; y < 100; y+=10)
{
     bool flag = false;
     for(int x = 0; x < 100; x += 10)
     {
        if (x == 56)
        {
           flag = true;
           break;
        }
     }

     if(flag) break;
}
5 голосов
/ 14 декабря 2011

Некоторые люди стреляют в меня за предложение использовать оператор goto, но разрыв нескольких циклов - одно из мест, где оно может быть очень полезным (и эффективным):

/*Main loop*/
for(int y = 0; y < 100; y+=10)
{
    /*Sub loop*/
    for (int x = 0; x < 100; x += 10)
    {
        if(x == 56) 
        { 
            goto MainLoopDone;
        }
    }
}

MainLoopDone:
// carry on here
3 голосов
/ 14 декабря 2011

часто лучше поместить это в отдельную функцию, а затем выполнить 'return'

void loop_de_loop()
{
  for(int y = 0; y < 100; y+=10)
  {
      /*Sub loop*/
      for (int x = 0; x < 100; x += 10)
      {
          if(x == 56) 
          { 
              return;
          }
      }
  }
}
2 голосов
/ 14 декабря 2011

Флаги, как предлагается в комментариях, вероятно, лучший метод:

boolean someFlag = true;

for(int y = 0; i < 100 && someFlag; y += 10) {
  for(int x = 0; x < 100 && somFlag; x += 10) {
    if(x == 56)
      someFlag = false;
  }
}
2 голосов
/ 14 декабря 2011

Я не знаю, есть ли способ вырваться из вложенных циклов в C #, но позвольте мне предложить обходной путь.

Вы можете бросить основной цикл в функцию и вернуться из этой функции,Вы можете return false; указать на преждевременный разрыв и return true; указать, что цикл прошел весь путь, если это имеет значение.

0 голосов
/ 27 августа 2015

Сначала я использовал LINQ для сбора интересных объектов, а затем выполнил операции с результатами запроса LINQ. Тем самым удаляя вложенные циклы и заменяя их одним циклом.

0 голосов
/ 14 декабря 2011

Как уже говорили другие, «правильный» ответ зависит от проблемы, которую вы решаете.Если вы можете, разбить его на более мелкие части является предпочтительным маршрутом.Что-то вроде этой модели:

object MainLoop ()
{
    object result = null;
    for(int y = 0; y < 100; y+=10)
    {
        result = SubLoop(y);
        if (result != null)
        {
            break;
        }
    }
    return result;
}

object SubLoop (int y)
{
    object result = null;
    for (int x = 0; x < 100; x += 10)
    {
        if(x == 56)
        {
            result = objectInstance;
            break;
        }
    }
    return result;
}

На мой взгляд, в разной степени уродливо иметь несколько операторов return из одной функции, использовать дополнительные флаги или ( shudder ) использовать goto's.Но иногда один из них необходим.

Редактировать: Это демонстрация использования этого метода для возврата какого-либо полезного объекта, у вас будет "Customer" или "IDataAccess" или "bool "или что-то отличное от" object "в качестве возвращаемых типов, если используется это для реального.

0 голосов
/ 14 декабря 2011

Поскольку, как вы упомянули, в команде break нет меток, вы можете сделать что-то вроде этого:

/*Main loop*/
bool fFound;
for(int y = 0; y < 100 && !fFound; y+=10)
{
    /*Sub loop*/
    for (int x = 0; x < 100; x += 10)
    {
        if(x == 56) 
        { 
            //Break the main loop 
            fFound = true;
            break; //Break inner loop
        }
    }
}
...