Переход break

Оператор break предназначен для досрочного прерывания циклов for, while, do, а также выхода из инструкции выбора switch. Оператор может применяться только внутри указанных инструкций и влияет только на одну, непосредственно содержащую break, если их несколько вложенных. После обработки оператора break выполнение программы продолжается на инструкции, следующей за прерванным циклом или switch.

Синтаксис очень простой — ключевое слово break и точка с запятой:

break ;

При использовании внутри циклов break обычно помещается в одну из веток условного оператора if/else.

Рассмотрим скрипт, который выводит текущий счетчик системного времени раз в секунду, но не более 100 раз. В нем предусмотрена обработка прерывания процесса пользователем: для этого производится опрос функции IsStopped в условном операторе if и в его зависимой инструкции имеется break (StmtJumpBreak.mq5).

int count = 0;
while(++count < 100)
{
   Comment(GetTickCount());
   Sleep(1000);
   if(IsStopped())
   {
      Print("Terminated by user");
      break;
   }
}

В следующем примере заполняется диагональная матрица с таблицей умножения (верхний правый угол останется заполнен нулями).

int a[10][10] = {0};
for(int i = 0i < 10; ++i)
{
   for(int j = 0j < 10; ++j)
   {
      if(j > i)
         break;
      a[i][j] = (i + 1) * (j + 1);
   }
}
ArrayPrint(a);

Когда переменная внутреннего цикла j больше переменной наружного цикла i, оператор break прерывает внутренний цикл. Разумеется, это не лучший способ заполнить диагонально матрицу: проще было бы запустить цикл по j от 0 до i без всякого break, но здесь это демонстрирует наличие эквивалентных конструкций с break и без break.

Хотя в рабочих проектах всё может быть не столь очевидно, рекомендуется по возможности избегать оператора break и заменять его на дополнительные переменные (например, логическую переменную с "говорящим" названием needAbreak), которые использовать в терминальных выражениях в заголовках циклов, чтобы прерывать их стандартным путем.

Представим, что два вложенных цикла используются для поиска повторяющихся символов в строке. Первый цикл последовательно делает каждый символ строки текущим, второй — пробегает по оставшимся (стоящим справа) символам.

string s = "Hello, " + Symbol();
ushort d = 0;
const int n = StringLen(s);
for(int i = 0i < n; ++i)
{
   for(int j = i + 1j < n; ++j)
   {
      if(s[i] == s[j])
      {
         d = s[i];
         break;
      }
   }
}

При совпадении символов на позициях i и j, запоминаем символ-дубликат и выходим из цикла по break.

Можно было бы предположить, что переменная d должна после выполнения этого фрагмента содержать букву 'l'. Однако если разместить скрипт на самом популярном инструменте "EURUSD", ответ будет 'U'. Дело в том, что break прерывает только внутренний цикл, и после нахождения первого дубликата ('ll' в слове "Hello"), цикл по i продолжается. Поэтому для выхода сразу из нескольких вложенных циклов необходимо принимать дополнительные меры.

Наиболее популярный способ — это включение в условие внешнего цикла (или всех внешних циклов) некой переменной, заполняемой во внутреннем цикле. В нашем случае такая переменная уже есть: d.

for(int i = 0i < n && d == 0; ++i)
{
   for(int j = i + 1j < n; ++j)
   {
      if(s[i] == s[j])
      {
         d = s[i];
         break;
      }
   }
}

Проверка d на 0 теперь остановит внешний цикл по нахождению первого дубликата. Но точно такая же проверка может быть добавлена и во внутренний цикл, что избавит нас от необходимости применять break.

for(int i = 0i < n && d == 0; ++i)
{
   for(int j = i + 1j < n && d == 0; ++j)
   {
      if(s[i] == s[j])
      {
         d = s[i];
      }
   }
}