Русский

Учебник по MQL4  Операторы  Оператор continue

Оператор continue


Иногда при использовании цикла возникает необходимость досрочно закончить обработку текущей итерации и перейти к следующей, не выполняя при этом все оставшиеся операторы, составляющие тело цикла. В таких случаях используется оператор continue.

Формат оператора continue


Оператор continue состоит из одного слова, заканчивается знаком ";" (точка с запятой).

   continue;                                         // Оператор continue

Правило исполнения оператора continue


Оператор continue прекращает исполнение текущей итерации ближайшего оператора цикла while или for. Результатом выполнения оператора continue является переход к следующей итерации ближайшего оператора цикла while или for. Оператор continue может использоваться только в составе тела указанных операторов цикла.

Рассмотрим вариант практического использования оператора continue.

Задача 16. На первой ферме имеется 1000 овец. Ежедневно количество овец на первой ферме увеличивается на 1%. Если в конце месяца на первой ферме количество овец превышает 50 000, то 10% овец переводят на вторую ферму. Через какое время количество овец на второй ферме достигнет численности 35 000? (Считать, что в месяце 30 рабочих дней.)

Алгоритм решения задачи очевиден: необходимо организовать цикл, в котором рассчитывалась бы сумма общего количества овец на первой ферме. По условию задачи перевод части овец на вторую ферму происходит в конце месяца, значит необходимо создать ещё один (внутренний) цикл, в котором вычислялось бы накопление в текущем месяце. По окончании месяца необходимо выяснить: превышен ли пороговый уровень в 50 000? И если это так, то нужно рассчитать количество овец, переводимых на вторую ферму в конце месяца, и общее количество овец на второй ферме.

Рассматриваемый алгоритм реализован в скрипте sheep.mq4. Здесь оператор continue используется для расчётов во внешнем цикле.

//--------------------------------------------------------------------
// sheep.mq4
// Предназначен для использования в качестве примера в учебнике MQL4.
//--------------------------------------------------------------------
int start() // Специальная ф-ия start()
{
//--------------------------------------------------------------------
int
day, // Текущий день месяца
Mons; // Искомое количест. месяцев
double
One_Farm =1000.0, // Количество на 1 ферме
Perc_day =1, // Ежедневный подъём, %
One_Farm_max=50000.0, // Пороговое значение
Perc_exit =10, // Ежемесячный вывод, %
Purpose =35000.0, // Необх. колич. на 2 ферме
Two_Farm; // Количество на 2 ферме
//--------------------------------------------------------------------
while(Two_Farm < Purpose) // Внешний цикл по истории
{ // Начало тела внешн. цикла
//--------------------------------------------------------------
for(day=1; day<=30; day++) // Цикл по дням месяца
One_Farm=One_Farm*(1+Perc_day/100);//Накопление на 1й ферме
//--------------------------------------------------------------
Mons++; // Считаем месяцы
if (One_Farm < One_Farm_max) // Если меньше допустимого,.
continue; // .. то овец не переводим
Two_Farm=Two_Farm+One_Farm*Perc_exit/100;//Количес. на 2 ферме
One_Farm=One_Farm*(1-Perc_exit/100);// Остаток на 1 ферме
} // Конец тела внешнего цикла
//--------------------------------------------------------------------
Alert("Цель будет достигнута через ",Mons," мес.");//Вывод на экран
return; // Выход из функции start()
}
//--------------------------------------------------------------------

В начале программы, как обычно, описаны и прокомментированы переменные. Собственно расчёт выполняется в цикле while, а после его окончания выводится соответствующее сообщение. Расчёты во внешнем цикле while будут происходить до тех пор, пока не будет достигнута цель, а именно, пока общее количество овец на второй ферме не достигнет ожидаемого значения 35 000.

Внутренний цикл for очень прост: значение баланса увеличивается ежедневно на 1%. Никакого анализа суммы в этом цикле не выполняется, потому что по условию задачи перевод овец может происходить только в конце месяца. Таким образом, после выхода из цикла for переменная One_Farm имеет значение, равное количеству овец на первой ферме. Сразу после этого вычисляется значение переменной Mons, увеличивающееся на единицу при выполнении каждой итерации внешнего цикла while.

В зависимости от текущего количества овец на первой ферме выполняется одно из двух вычислений:

  • если количество овец на первой ферме превышает пороговое значение 50 000, то необходимо 10% овец с первой фермы перевести на вторую ферму;
  • в противном случае - овец с первой фермы на вторую не переводить и продолжать разведение овец на первой ферме.

Разветвление алгоритма осуществляется с помощью оператора if:

      if (One_Farm < One_Farm_max)        // Если меньше допустимого,.
continue; // .. то овец не переводим

Эти строки кода можно охарактеризовать так: если количество овец на первой ферме меньше порогового значения 50 000, то исполнить оператор, составляющий тело оператора if. При первой итерации количество овец на первой ферме оказывается меньше порогового значения, поэтому управление будет передано в тело оператора if, т.е. оператору continue. Исполнение оператора continue означает следующее: закончить текущую итерацию ближайшего выполняемого цикла (в данном случае это цикл в операторе while ) и передать управление в заголовок оператора цикла. При этом следующие программные строки, также являющиеся составной частью тела оператора цикла while, выполняться не будут:

      Two_Farm = Two_Farm+One_Farm*Perc_exit/100;//Количес. на 2 ферме
One_Farm = One_Farm*(1-Perc_exit/100); // Остаток на 1 ферме

В этих строках осуществляется расчёт достигнутого количества овец на второй ферме и остаточное количество овец на первой ферме. На первой итерации выполнять эти расчёты нельзя, т.к. ещё не достигнуто пороговое количество овец 50 000 на первой ферме. Сущность оператора continue как раз и состоит в том, чтобы "переступить" через эти строки, не исполнять их в текущей итерации.

В результате исполнения оператора continue управление передаётся в заголовок оператора цикла while. Далее происходит проверка условия в операторе цикла и начинается следующая итерация. Выполнение цикла будет продолжаться по тому же алгоритму до тех пор, пока количество овец на первой ферме не достигнет порогового значения. При этом на каждой итерации накапливается значение Mons.

На некотором этапе расчётов количество овец на первой ферме достигнет или превысит пороговое значение 50 000 голов. В этом случае, при исполнении оператора if условие (One_Farm < One_Farm_max) окажется ложным, поэтому управление в тело оператора if передано не будет. Это значит, что оператор continue не исполнится, а управление будет передано на первую из двух последних строк тела цикла while: сначала будет вычислено количество овец на второй ферме, а затем остаточное количество овец на первой ферме. После этих вычислений очередная итерация цикла while закончится, и управление снова будет передано в заголовок цикла. Ниже представлена функциональная схема алгоритма, реализованного в скрипте sheep.mq4.


Рис. 47. Функциональная схема программы, в которой оператор continue прерывает итерации внешнего цикла (sheep.mq4).

На схеме наглядно видно, что в зависимости от исполнения условия в операторе if, управление либо сразу передаётся в заголовок цикла while (в результате исполнения continue ), либо сначала выполняются некоторые операторы, а потом управление всё равно передаётся в заголовок цикла while. В обоих случаях выполнение цикла при этом не заканчивается.

Обратите внимание, наличие оператора continue в теле цикла не обязательно приводит к окончанию текущей итерации. Это происходит только в том случае, если он исполняется, т.е. если ему передано управление.

На каждой очередной итерации в операторе цикла while, будет рассчитываться новое достигнутое значение переменой Two_Farm. Как только это значение превысит заданную величину (35 000), условие в операторе цикла while окажется ложным, поэтому вычисления в теле цикла while больше выполняться не будут, а управление будет передано ближайшему оператору, следующему за оператором цикла:

    Alert("Цель будет достигнута через ",Mons," мес.");//Вывод на экран

Результатом исполнения функции Alert() будет строка следующего вида:

Цель будет достигнута через 17 мес.

Оператор return заканчивает исполнение специальной функции start(), в результате чего управление будет передано клиентскому терминалу, а исполнение скрипта заканчивается - он будет выгружен из окна финансового инструмента.

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

В правиле исполнения оператора continue используется выражение "ближайшего оператора". Ошибочно полагать, что это означает близость программных строк. Посмотрим на код скрипта sheep.mq4. Оператор for находится "ближе" к оператору continue, чем заголовок цикла while. Однако это не имеет никакого значения: оператор continue никак не связан с циклом for, потому что находится за его пределами, вне его тела. В общем случае программа может содержать множество вложенных операторов цикла. Оператор continue всегда находится в теле какого-то из них. Но одновременно с этим оператор continue, являясь составной частью внутреннего оператора цикла, естественно, находится и внутри внешнего оператора цикла. Выражение "прекращает исполнение текущей итерации ближайшего оператора цикла" следует понимать так, что его действие распространяется на ближайший оператор цикла, внутри тела которого он находится. Чтобы проиллюстрировать это, несколько изменим условия задачи.


Задача 17. На первой ферме имеется 1000 овец. Ежедневно количество овец на первой ферме увеличивается на 1%. В тот день, когда количество овец на первой ферме достигает 50 000, 10% овец переводят на вторую ферму. Через какое время количество овец на второй ферме достигнет численности 35 000? (Считать, что в месяце 30 рабочих дней.)

Решение задачи 17 реализовано в скрипте othersheep.mq4. В данном случае оператор continue используется для расчётов во внешнем и внутреннем циклах.

//--------------------------------------------------------------------
// othersheep.mq4
// Предназначен для использования в качестве примера в учебнике MQL4.
//--------------------------------------------------------------------
int start() // Специальная ф-ия start()
{
//--------------------------------------------------------------------
int
day, // Текущий день месяца
Mons; // Искомое количест. месяцев
double
One_Farm =1000.0, // Количество на 1 ферме
Perc_day =1, // Ежедневный подъём, %
One_Farm_max=50000.0, // Пороговое значение
Perc_exit =10, // Разовый вывод, %
Purpose =35000.0, // Необх. колич. на 2 ферме
Two_Farm; // Количество на 2 ферме
//--------------------------------------------------------------------
while(Two_Farm < Purpose) // До достижения цели
{ // Начало тела внешн. цикла
//--------------------------------------------------------------
for(day=1; day<=30 && Two_Farm < Purpose; day++)// Цикл по дням
{
One_Farm=One_Farm*(1+Perc_day/100);//Накопл. на 1 ферме
if (One_Farm < One_Farm_max) // Если меньше допустимого,.
continue; // .. то овец не переводим
Two_Farm=Two_Farm+One_Farm*Perc_exit/100;//Накопл. на 2 ферме
One_Farm=One_Farm*(1-Perc_exit/100); //Остаток на 1 ферме
}
//--------------------------------------------------------------
if (Two_Farm>=Purpose) // Если цель достигнута,..
continue; // .. то месяцы не считаем
Mons++; // Считаем месяцы
} // Конец тела внешнего цикла
//--------------------------------------------------------------------
Alert("Цель будет достигнута через ",Mons," мес. и ",day," дн.");
return; // Выход из функции start()
}
//--------------------------------------------------------------------

Для решения задачи необходимо анализировать количество овец для каждого дня. С этой целью строки:

   if (One_Farm < One_Farm_max)             // Если меньше допустимого,.
continue; // .. то овец не переводим
Two_Farm=Two_Farm+One_Farm*Perc_exit/100;//Накопл. на 2 ферме
One_Farm=One_Farm*(1-Perc_exit/100); //Остаток на 1 ферме

перенесены во внутренний цикл, организованный по дням месяца. Очевидно, что перевод некоторого количества овец на вторую ферму в данном случае происходит не в конце месяца, а в тот день, когда количество овец на первой ферме достигает заданного значения. Смысл использования здесь оператора continue тот же: "переступить" через строки, в которых выполняются вычисления, связанные с переводом овец с одной фермы на другую, т.е. не выполнять эти строки. Обратите внимание, цикл while, построенный по дням месяца, не прерывается независимо от факта перевода овец, потому что действие оператора continue распространяется на ближайший оператор цикла, в данном случае - на оператор цикла for.

В качестве Условия в операторе цикла for используется сложное выражение:

   for(day=1; day<=30 && Two_Farm<Purpose; day++)// Цикл по дням

Использование операции && ("и") означает, что цикл будет выполняться до тех пор, пока будут справедливы оба условия:

  • месяц ещё не закончился, т.е. переменная day остаётся в пределах от 1 до 30 включительно;
  • количество овец на второй ферме не достигло заданного, т.е. переменная Two_Farm меньше Purpose (35 000).

Если же хотя бы одно из условий не выполняется (становится ложным), цикл прекращается. Когда выполнение цикла for закончено (по любой из причин), управление передаётся оператору if:

   if (Two_Farm >= Purpose)            // Если цель достигнута,..
continue; // .. то месяцы не считаем
Mons++; // Считаем месяцы

Использование в этом месте кода оператора continue имеет простой смысл: продолжать считать месяцы только в том случае, если количество овец на второй ферме меньше ожидаемого. Если же цель уже достигнута, то значение переменной Mons не изменяется, а управление (в результате исполнения continue) передаётся в заголовок ближайшего оператора цикла, в этом случае - оператора цикла while.

Использование операторов continue во вложенных циклах отражено на рис. 48.


Рис. 48. Функциональная схема алгоритма, построенного на вложенных циклах. В теле каждого из циклов имеется свой оператор continue (othersheep.mq4).

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