1.7 Операторы цикла: While, Do While, Оператор-переключатель switch

Обучение программированию на языке MQL4

Доброго времени суток. На прошлом уроке мы познакомились с циклом for — последовательным перебором вводных параметров, без которого программирование на языке MQL просто невозможно представить. Настало время пройтись по другим вариантам операторов цикла.

Оператор цикла while

Основное предназначение цикла while — повторять одинаковые или похожие вычисления чаще, чем один раз. В отличие от цикла for, у которого можно указывать три выражения тут используется только одно. Цикл будет работать, пока заданное выражение не станет ложным.

При объявлении оператора пишется слово while (пока что), в скобках указывается выражение, условие и далее в фигурных скобках происходит действие, которое должно повторяться пока выражение истинно.

Пример выполнения цикла: мы объявили логическую переменную check, который присвоили истинное значение. Далее запускаем цикл, в котором проверяется, чтобы данная переменная была true (как мы помним из этого урока, для того, чтобы указать, что bool переменная является истинной не обязательно приписывать == true, достаточно просто написать ее наименование). В блоке операторов был выведен принт и значение check изменено на false. Это означает, что цикл while имеет всего одну итерацию, потому что при следующей проверки выражение уже будет ложью.

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

Попробуем математический пример:

Это выражение содержит условие, при котором цикл может продолжать пока i меньше пяти. Начальное значение переменной i задается до самого цикла, а шаг при подсчете регулируется внутри тела цикла. Этот алгоритм работает аналогично в представленном цикле for:

Стоит заметить, что в выражении можно использовать сразу несколько условий и он будет продолжаться, пока одно из условий не станет ложью.

Цикл while можно выполнять бесконечно, если указать условие, которое никогда не сможет быть выполнено:

В примере выше a2 всегда будет больше нуля, соответственно у данного цикла нет причин останавливаться. Проблема с зацикливанием частенько случается из-за ошибки написания кода, это может стать серьезной проблемой, цикл будет крутиться бесконечно. Такую ошибку можно найти только вручную. Чтобы избежать в этом случае зависание терминала MetaTrader 4, необходимо в выражение дописать функцию !IsStopped() — проверку на принудительное завершение работы программы.

Примером использования зацикливания можно считать стандартный скрипт терминала «PeriodConverter«, суть которого создавать нестандартные таймфреймы и обновлять котировки каждый тик. Как известно, скрипт совершает свое действие только один раз, после чего удаляется с графика. С помощью зацикливания скрипт будет находиться на графика до момента удаления программы или закрытия терминала. Нам не совсем понравилась такая логика работы и было решено разработать свой алгоритм для работы с пользовательскими графиками, поэтому был создан индикатор Chart Period Converter.

Цикл while полезно использовать, когда вы не знаете, сколько итераций должно совершить тело цикла и можете завершить работу цикла при соблюдении какого либо условия. Я использую его для перебора валютных пар в окне обзора рынка, для работы с открытыми графиками, когда нужно пробежаться по каждому. Также при загрузке данных из интернета невозможно заранее знать, сколько строк информации нужно анализировать. При модификации или открытии ордера можно делать необходимое повторение, пока тело цикла не выдаст истину.

Оператор цикла do while

Цикл do while выполняет абсолютно то же действие, что цикл while с единственной разницей — проверка условия, заданного в выражении осуществляется после итерации тела цикла. То есть вначале свою работу выполняет оператор, потом проверяется условие:

Тут оператор do вначале прибавляет к c число два, потом выводит принт. Далее тело цикла завершает работу и идет проверка, чтобы целая переменная c была меньше семи. В нашем случае будет три итерации, где переменная будет равна 3, 5 и 7. После ложного результата проверки этот цикл остановится.

Цикл do while выполняет минимум одну итерацию, в отличие от цикла while.

Я не так часто использую данную конструкции, редко есть нужда. Как пример, для проверки, что график подгрузился, можно узнать текущую цену Бид, и, если котировки еще не загружены, то терминал вернет значение 0. 

В теле цикла do мы переводим код в сон на 0.5 секунд, далее обновляем данные в предопределенных переменных и массивах-таймсериях, а также обновляем график и задаем переменной цену Бид. Уже после проходит проверка, и если цена все еще равна нулю, то цикл запускается по новой и так до момента, когда цена не определится.

Давайте попробуем выполнить задачу посложнее. К примеру нам нужно узнать на текущем графике номер свечи и ее цену закрытия, по условию, чтобы расстояние между [1] свечей и искомой было больше 30 старых пунктов. После этого выдать в принт номер свечи, следующей за найденной свечей.

В цикле тела свечи мы последовательно узнаем цену закрытия свечи и к номеру k прибавляем единицу после каждой итерации. В выражении while идет проверка по модулю на разницу расстояния между [1] и проверяемой свечей. Чтобы задать 30 старых пунктов на торговом счете с 3 или 5 знаками, нужно добавить ноль к числу, а также перевести числовое значение в размер пункта символа в валюте котировки Point

Надеюсь пример не оказался слишком сумбурным. Он приведен только для практики работы с оператором, смысловой нагрузки особо не несет.

Оператор-переключатель switch

Данный оператор является альтернативной заменой условному оператору if, но представлен немного в другом виде. В круглых скобках оператора switch задается выражение, в фигурных же скобках ищется константа case, которая бы соответствовала ему. Константа выражения при этом не может быть текстом, либо вызывать функцию, она должна быть целым числом.

В примере выше мы объявили переменную целого типа x, равную трем. Предположим, мы не знаем ее точного значения, как в примере. Для определения записываем переменную в круглые скобки оператора switch. В фигурных скобках мы перечисляем три возможных варианта значения этой переменной: 1, 2 или 3. Перечисление это указывается с помощью слова case (в случае), после константы должно обязательно стоять двоеточие, а уже после идти необходимое действие. Проверка по телу оператора идет сверху вниз, слева направо. Соответственно первым проверялся случай, если бы переменная была равна единице. Так как программный код знает, что это не так, то проверка переходит на второй случай. Наша переменная равна константе 2, соответственно в журнал выдается принт. Чтобы остановить дальнейшую проверку, которая нам больше не нужна, в каждом случае case рекомендуется указывать оператор break после выполнения нужного действия. Если же его не задать, то после нахождения нужного значения в работу будут включены все нижеследующие случаи case, что в большинстве случаев лучше избегать.

Попробуем другой пример. Тут все ясно без комментариев:

Если же пользователь не уверен, что какой-либо из случаев совпадет, то вводится дополнительный вариант default (по умолчанию). Он может располагаться в любом месте тела оператора, но большинство программистов используют его в самом конце. Ниже представлен вариант, где оба варианта case не подходят под определение.

Вариантов case может быть сколько угодно, это зависит только от вашего алгоритма. Очень часто оператор switch примеряется, когда текстом нужно указать период текущего графика, потому что внутренней структурой программы это не заложено:

В качестве выражения была применена функция определения периода текущего графика. Период имеет тип данных int, поэтому его можно использовать в операторе switch. Далее проходим по всем возможным периодам, сохраняем нужное значение и прерываем работу оператора. Уже после него выводим Алерт о значении таймфрейма.

Следующий пример у нас не будет корректно работать, потому что мы еще не начали изучать работу с ордерами, но логика должна быть понятна. Задается выражение в виде торговой функции, цель которой определить тип заданного ордера. Как мы знаем, существует 6 типов ордеров: Buy в числовом формате равняется 0, Sell Stop равняется пяти и т.д. В этом примере мы пробегаем по разным типам, пока не найдем нужный и после этого сохраняем его текстовое наименование в переменную:

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

Ошибку можно опознать, вызвав функцию проверки состояния GetLastError(). В ней нет параметров, имеет тип int, так как все ошибки хранятся именно в целых значениях. После вызова функции она обнуляет свое значение, поэтому ее нужно записывать в заранее созданную переменную.

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

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

На этом все. Надеюсь эта статья была для вас полезной. 

0. Начало работы

Скачать примеры

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Заполните поле
Заполните поле
Пожалуйста, введите корректный адрес email.
Вы должны согласиться с условиями для продолжения

Меню