Русский

Учебник по MQL4  Операторы  Оператор циклa for

Оператор циклa for


Вторым оператором цикла является оператор for.

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


Полноформатный оператор цикла for состоит из заголовка, содержащего Выражение_1, Условие и Выражение_2, и исполняемого тела цикла, обрамлённого фигурными скобками.

  for (Выражение_1; Условие; Выражение_2)            // Заголовок оператора цикла
{ // Открывающая фигурная скобка
Блок операторов, // Тело цикла может состоять ..
составляющих тело цикла //.. из нескольких операторов
} // Закрывающая фигурная скобка

Если в операторе for тело цикла составляет один оператор, то фигурные скобки можно опустить.

  for (Выражение_1; Условие; Выражение_2)            // Заголовок оператора цикла
Один оператор, тело цикла // Тело цикла - один оператор

Допускается отсутствие Выражения_1, Условия и Выражения_2. При этом наличие разделяющего знака ; (точка с запятой) обязательно.

  for ( ; Условие; Выражение_2)                       // Отсутствует Выражение_1
{ // Открывающая фигурная скобка
Блок операторов, // Тело цикла может состоять ..
составляющих тело цикла //.. из нескольких операторов
} // Закрывающая фигурная скобка
// - ---------------------------------------------------------------------------------
for (Выражение_1; ; Выражение_2) // Отсутствует Условие
{ // Открывающая фигурная скобка
Блок операторов, // Тело цикла может состоять ..
составляющих тело цикла //.. из нескольких операторов
} // Закрывающая фигурная скобка
// - ---------------------------------------------------------------------------------
for ( ; ; ) // Отсутств. Выражения и Условие
{ // Открывающая фигурная скобка
Блок операторов, // Тело цикла может состоять ..
составляющих тело цикла //.. из нескольких операторов
} // Закрывающая фигурная скобка

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


При передаче управления оператору for исполнить Выражение_1. Пока Условие оператора for является истинным: передать управление первому оператору тела цикла, а после выполнения всех операторов тела цикла исполнить Выражение_2 и передать управление в заголовок для проверки истинности Условия. Если Условие оператора for является ложным, то: передать управление оператору, следующему за оператором for.

Посмотрим, как работает оператор цикла for. Для этого решим задачу.

Задача 13. Дана последовательность целых чисел: 1 2 3 4 5 6 7 8 9 10 11 ...Составить программу, вычисляющую сумму элементов этой последовательности, начиная с номера N1, заканчивая номером N2.

С точки зрения математики эта задача решается просто. Предположим, необходимо высчитать сумму элементов с третьего по седьмой. Решением будет сумма: 3 + 4 + 5 + 6 + 7 = 25. Такое решение годится только для частного случая, когда номера первого и последнего элементов, составляющих сумму, равны соответственно 3 и 7. Программа должна быть составлена так, чтобы при необходимости вычисления суммы в другом интервале последовательности (например, от 15-го до 23-го элемента) можно было легко заменить численные значения номеров элементов в одном месте, не меняя программные строки в других местах. Вот один из вариантов такой программы (скрипт sumtotal.mq4):

//--------------------------------------------------------------------
// sumtotal.mq4
// Предназначен для использования в качестве примера в учебнике MQL4.
//--------------------------------------------------------------------
int start() // Специальная функция start()
{
//--------------------------------------------------------------------
int
Nom_1, // Номер первого элемента
Nom_2, // Номер второго элемента
Sum, // Сумма чисел
i; // Формальн параметр (счётчик)
//--------------------------------------------------------------------
Nom_1=3; // Задаём численное значение
Nom_2=7; // Задаём численное значение
for(i=Nom_1; i<=Nom_2; i++) // Заголовок оператора цикла
{ // Скобка начала тела цикла
Sum=Sum + i; // Сумма накапливается
Alert("i=",i," Sum=",Sum); // Сообщение на экран
} // Скобка конца тела цикла
//--------------------------------------------------------------------
Alert("После выхода из цикла i=",i," Sum=",Sum);// Вывод на экран
return; // Выход из start()
}
//--------------------------------------------------------------------

В первых строках программы объявлены переменные (с комментариями, поясняющими смысл каждой переменной). В строках

   Nom_1 = 3;                           // Задаём численное значение
Nom_2 = 7; // Задаём численное значение

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

   for(i=Nom_1; i<=Nom_2; i++)          // Заголовок оператора цикла
{ // Скобка начала тела цикла
Sum = Sum + i; // Сумма накапливается
Alert("i=",i," Sum=",Sum); // Сообщение на экран
} // Скобка конца тела цикла

Ключевая фраза - правило исполнения оператора for такая: "Начиная с .., до тех пор пока.., с шагом.. выполнять следующее: ..". Употребление слов "с шагом" уместно в том случае, если в качестве Выражения_2 используется накопительный счётчик, например, i++ или i=i+2. В данном примере ключевая фраза звучит так: начиная с i, равного Nom_1, до тех пор, пока i меньше или равно Nom_2, с шагом 1 выполнять следующее: (и далее - анализ тела цикла).

В соответствии с правилом исполнения оператора for в этом блоке программы будет выполнено следующее:

1. Исполнение Выражения_1:

   i=Nom_1

Переменная i получит численное значение переменной Nom_1, т.е. целое число 3. Выражение_1 выполняется один раз, - в тот момент, когда управление передаётся оператору for и ни в каких последующих событиях Выражение_1 не участвует.

2. Выполняется проверка Условия:

   i<=Nom_2

Значение переменной Nom_2 на первой итерации - целое число 7, а значение переменной i равно 3. Это значит, что Условие является истинным (т.к. 3 меньше 7), а значит, управление будет передано в тело цикла для его исполнения.

3. В данном примере тело цикла составляют два оператора, которые будут последовательно исполнены:

   Sum = Sum + i;                    // Сумма накапливается
Alert("i=",i," Sum=",Sum); // Сообщение на экран

Переменная Sum не получила при инициализации какое-либо начальное значение, поэтому до начала первой итерации её значение равно нулю. В процессе вычислений значение переменной Sum увеличивается на величину i и по окончании первой итерации равно 3. Это значение можно увидеть в окне функции Alert() :

i=3 Sum=3

4. Последним событием, которое происходит при выполнении оператора цикла, является исполнение Выражения_2:

   i++

Значение переменной i увеличивается на единицу. На этом заканчивается первая итерация, и управление передаётся на проверку Условия.

Далее начинается вторая итерация, пункты 2 - 4. В процессе вычислений переменные получают новые значения. В частности, на второй итерации значение переменной i будет равно 4, а Sum будет равно 7, о чём появится соответствующее сообщение. В целом, события в этой программе будут развиваться в соответствии со схемой:


Рис. 43. Функциональная схема исполнения оператора цикла for в программе sumtotal.mq4.


Программа будет циклически повторять исполнение оператора цикла, до тех пор, пока Условие не окажется ложным. Это произойдёт, когда значение переменной i будет равно 8, т.е. больше заданного значения переменной Nom_2, равного 7. В этом случае управление будет передано за пределы оператора for, а именно в строку:

   Alert("После выхода из цикла i=",i,"  Sum=",Sum);// Вывод на экран

и дальше, на исполнение оператора return, завершающего работу специальной функции start().

Можно использовать эту программу для вычислений суммы любого другого интервала значений. Например, если заменить константы 3 и 7 на 10 и 15, то в результате исполнения этой же программы будет вычислена сумма значений для указанного интервала.


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

Обратите внимание на 2 последние строки сообщений, оставшиеся после завершения всех вычислений и выгрузки скрипта:

i=7 Sum=25
После выхода из цикла i=8 Sum=25

Первое из этих сообщений появилось на стадии последней итерации, ещё до завершения цикла, а последнее сообщение выдано последней функцией Alert() перед завершением программы. Примечательно, что в этих строках отображаются разные значения переменной i. Ещё при выполнении цикла это значение равно 7, а после завершения цикла равно 8. Чтобы понять, почему это произошло, обратимся ещё раз к рис. 43.

Последняя (в данном случае - пятая) итерация начинается с проверки Условия. Значение i в этот момент равно 7. Поскольку 7 не больше, чем значение переменной Nom_2, то Условие истинно, а значит, будет выполняться тело цикла. По окончании выполнения операторов, составляющих тело цикла, осуществляется последняя операция: исполняется Выражение_2. Это необходимо ещё раз подчеркнуть особо:

Последним событием, происходящим на каждой итерации при исполнении цикла for, является вычисление Выражения 2.

В результате этого значение переменной i увеличивается на 1 и становится равным 8. Очередная проверка Условия (в начале следующей итерации) подтверждает, что теперь условие ложно, поэтому после проверки управление передаётся за пределы оператора цикла. При этом переменная i выходит из оператора цикла со значением 8, а значение переменной Sum остаётся равным 25, потому что исполнение тела цикла на этом этапе уже не происходит. Это замечание необходимо учитывать в случаях, когда количество итераций заранее неизвестно, и судить об этом программист предполагает, ориентируясь на значение переменной, вычисленной в Выражении_2.

Исключительным случаем можно считать ситуацию, при которой возникает зацикливание. Это становится возможным при различных ошибках. Например, если в качестве Выражения_2 ошибочно использовать оператор:

   i--

то значение счётчика на каждой итерации будет уменьшаться, поэтому Условие никогда не станет ложным.

Другим ошибочным случаем может быть неправильно составленное Условие:

for(i=Nom_1; i>=Nom_1; i++)              // Заголовок оператора цикла

В данном случае значение переменной i всегда будет больше или равным значению переменной Nom_1, поэтому Условие всегда будет оставаться истинным.


Взаимозаменяемость операторов циклов while и for


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

Например, при решении Задачи 13, был использован оператор цикла for:

   for (i=Nom_1; i<=Nom_2; i++)         // Заголовок оператора цикла
{ // Скобка начала тела цикла
Sum = Sum + i; // Сумма накапливается
Alert("i=",i," Sum=",Sum); // Сообщение на экран
} // Скобка конца тела цикла

А так может выглядеть тот же фрагмент программы, но с использованием оператора цикла while:

   i=Nom_1;                             // Оператор присваивания
while (i<=Nom_2) // Заголовок оператора цикла
{ // Скобка начала тела цикла
Sum = Sum + i; // Сумма накапливается
Alert("i=",i," Sum=",Sum); // Сообщение на экран
i++; // Увеличение номера элемента
} // Скобка конца тела цикла

Легко увидеть, что для подобной замены достаточно вынести Выражение_1 в строку, предшествующую оператору цикла, а Выражение_2 указать последним в теле цикла. Вы можете самостоятельно внести изменения в программу и запустить её на выполнение, чтобы убедиться, что результат при исполнении обоих вариантов окажется одинаковым.