2011-12-13 4 views
8

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

/*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», и он будет действителен), но что я могу сделать здесь?

Спасибо, советую!

+1

Если возможно, поместите это внутри отдельного метода, из которого вы можете просто вернуться, что приведет к короткому замыканию петель. –

+8

GOTO! Эй, подождите - куда вы, ребята, идете? Здравствуйте? –

ответ

7

Используйте флаг сигнал завершения:

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; 
} 
+1

Thats подробный способ сделать это. Вы можете просто проверить флаг в условном выражении 'for'. – Jon

+0

Приятная вещь в том, что это очень легко понять для других программистов: нулевой фактор неожиданности. –

+0

@ Jon, я не думаю, что это чистый стиль, чтобы иметь более одного условия внутри. – Tudor

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

-1 для 'goto' ... – IAbstract

+2

Никто не должен использовать' goto' на языке высокого уровня. – Jon

+4

IMO flag-break-checkflag-break даже уродливее, чем goto. Но, конечно, рефакторинг является предпочтительным выбором, где это возможно. – CodesInChaos

3

часто лучше, чтобы поместить это в отдельную функцию, а затем сделать «возвращение»

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; 
      } 
     } 
    } 
} 
+0

В реальных вложенных циклах я что-то вычисляю. Если мне нужно передать их методу, это будет очень уродливо! – Bankin

+0

зависит от того, как вы это делаете ... часто эти вещи становятся беспорядочными, потому что люди имеют множество переменных и не инкапсулировали их в структуру.В идеале вы получаете множество функций, которые работают над структурой. (упрощенный OO). –

4

Некоторые люди застрелить меня, предложившего использование 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 
+0

GOTO ужасны – MethodMan

+4

Они ужасны, когда их используют молодые кодеры и приводят к коду спагетти. В качестве разработчика вы должны использовать доступные вам инструменты, а goto - самый эффективный способ выйти из нескольких вложенных циклов. –

+0

Я согласен с предыдущим кодом спагетти. Я всегда пользуюсь перерывом или возвратом. – MethodMan

0
/*Main loop*/ 
for(int y = 0; y < 100; y+=10) 
{ 
    bool makeMeBreak = false; 

    /*Sub loop*/ 
    for (int x = 0; x < 100; x += 10) 
    { 
     if(x == 56) 
     { 

      //Break the main loop 
      makeMeBreak = true; 
      break; 
     } 
    } 
    if (makeMeBreak) break; 
} 
17

goto!

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

+0

Однажды, когда кто-то вручил вам три десятилетний код FORTRAN, который был набит плохо написанными GOTO, и говорит вам исправить ошибки, и вы обнаружите, что это _impossible_ для рефакторинга, вы поймете. Лучшие программисты могут делать магию с помощью GOTO. Худшее может сделать великое зло. –

+1

Лучшие программисты могут использовать 'goto' без каких-либо печалей и создавать наиболее эффективный код в этом процессе. –

+1

+1, нарушение вложенных циклов является одним из немногих (только?) Допустимых видов использования goto imo. Многое, гораздо чище, чем использование флага. –

2

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

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

0

Нет хорошего общего ответа. «Правильный путь» зависит от реальной проблемы. Лучше всего было бы поместить внешний цикл в функцию, а затем использовать return;, чтобы вырваться из него. Это может быть x=100; y=100;. Это может быть done=true;. Черт, это может быть даже goto (шутка).

2

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

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; 
    } 
} 
+0

Это только так, потому что нет кода после внутреннего цикла и после if. С этим кодом вам нужно добавить два перерыва и чек. – CodesInChaos

0

Не рекомендуется, но вы можете использовать goto. См. this.

public class GotoTest1 
{ 
    static void Main() 
    { 
     int x = 200, y = 4; 
     int count = 0; 
     string[,] array = new string[x, y]; 

     // Initialize the array: 
     for (int i = 0; i < x; i++) 

      for (int j = 0; j < y; j++) 
       array[i, j] = (++count).ToString(); 

     // Read input: 
     Console.Write("Enter the number to search for: "); 

     // Input a string: 
     string myNumber = Console.ReadLine(); 

     // Search: 
     for (int i = 0; i < x; i++) 
     { 
      for (int j = 0; j < y; j++) 
      { 
       if (array[i, j].Equals(myNumber)) 
       { 
        goto Found; 
       } 
      } 
     } 

     Console.WriteLine("The number {0} was not found.", myNumber); 
     goto Finish; 

    Found: 
     Console.WriteLine("The number {0} is found.", myNumber); 

    Finish: 
     Console.WriteLine("End of search."); 


     // Keep the console open in debug mode. 
     Console.WriteLine("Press any key to exit."); 
     Console.ReadKey(); 
    } 
} 
/* 
Sample Input: 44 

Sample Output 
Enter the number to search for: 44 
The number 44 is found. 
End of search. 
*/ 

Не рекомендуется, потому что это затрудняет понимание потока. Другим вариантом, конечно, является установка некоторого флага во внутреннем цикле и проверка его во внешнем цикле, я обесценил это, так как это очевидно, и предположим, что вы это знаете. :)

0

Поскольку, как вы уже упоминали, есть нет метки на команды 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 
     } 
    } 
} 
0

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

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; 
} 

На мой взгляд, это некрасиво в той или иной степени, чтобы иметь несколько операторов возврата из одной функции, используйте дополнительные флаги, или (Дрожь) использовать Гото. Но, иногда, один из них необходим.

Edit: Это демонстрирует, используя этот метод, чтобы вернуть полезный объект какой-то, вы бы «Клиент» или «IDataAccess» или «логическое значение» или что-то другое, чем «объект» в качестве возвращаемых типов при использовании это по-настоящему.

0

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

Смежные вопросы