вторник, 8 мая 2012 г.

Циклы и Условия, Функции, Переменные в MQL4


Циклы и Условия

Программа, которую Вы пишите на MQL4 (или на любых других языках) выполняется сверху вниз (я имею ввиду откомплированный файл). Оператор за оператором.
Оператор — это строчка кода, которая говорит компьютеру что-либо сделать.
Например:

Код:
Print("Hello World");
return 0;
Точка с запятой является очень важной частью оператора, но обычно очень легко забывается, потому является причиной 90% всех ошибок.
Принцип выполнение кода сверху вниз имеет исключения — это циклы и условия.
Программа, которую Вы пишите, может, как человек, принимать решения в ответ на изменение обстоятельств. В таких случаях управление перепрыгивает из одной части программы в другую её часть.
Операторы, которые вызывают такие прыжки называются Операторами Контроля (контроллерами).
Контроллеры состоят из циклов и условий.

Циклы

Циклы заставляют раздел программы выполнятся определённое число раз.
Такое повторение продолжается пока какое-то условие явлется истинным (true) и прекращается как только условие становится ложным (false).
Когда цикл завершается контроль переходит следующему за циклом оператору.

В MQL4 существует два вида циклов:

1 — цикл for

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

Код:
int j;

for(j=0; j<15; j++)

 Print(j);
Как это работает?
Оператор состоит из ключевого слова for, за этим следуют круглые скобки, в которых указаны 3 выражения, разделённые точками с запятыми:

for(j=0; j<15; j++)

Эти три выражения — это: выражение инициализации, выражение проверки и выражение инкремента.

j = 0 — выражение инициализации
j < 15 — выражение проверки
j++ — выражение инкремента

Тело цикла — это код, который будет выполняться:

Print(j); — тело цикла.

В нашем примере тело цикла выполняется 15 раз.

Замечание: сразу после выражения for(…;…;…) точка с запятой НЕ ставится, т.к. это выражение + идущее после него тело цикла считаются единым оператором.
Кстати, в этом заключается очень распространённая ошибка — оператор ; (просто точка с запятой) называется пустым оператором (он не говорит компьютеру что-либо делать), поэтому цикл for(…;…;…); имеет пустое тело. В основном это не то, чего мы хотим.

Выражение инициализации

Выражение инициализации выполняется только один раз — когда цикл запускается. И его задача — снабдить переменную цикла начальным значением (в нашем случае — нулём).
Вы можете объявить переменную цикла вне самого цикла, как в нашем примере:

Код:
int j;

for(j=0; j<15; j++)
Или Вы можете объявить её прямо внутри скобок цикла:

Код:
for(int j=0; j<15; j++)
Две предыдущие строчки кода эквиваленты за тем исключением, что области видимости (об этом в уроке про переменные) переменной цикла в обоих случаях разные. Во втором случае переменная считается объявленной только внутри самого цикла.

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

Код:
int i;

int j;

for(i=0 ,j=0;i<15;i++)

 Print(i);

Выражение проверки

Выражение проверки — это выражение, которое построено на операциях сравнения и логических операциях (см. пред. урок).
Проверка истинности выражения происходит после каждого прохождения цикла. Цикл продолжается, если выражение истинно, цикл завершается, если выражение ложно.
В нашем примере тело цикла будет продолжать печатать i ( Print(i); ), пока условие j<15 верно. j пробежит значения 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14, затем j станет = 15 и цикл остановится. Контроль перейдёт оператору, следующему за циклом.

Выражение инкремента

Выражение инкремента только так называется. Его задача — изменять переменную цикла. В нашем случае оно увеличивает j на 1.
Например, в следующем примере распечатаются числа 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1:

Код:
int i;

for(i=15;i>0,i<;i--)

 Print(i);
Выражение инкремента выполняется самым последним в списке шагов цикла.
Схема 1. Цикл for.
Как и в выражении инициализации, в выражении инкремента можно использовать более одного выражения, разделив их запятой:

Код:
int i;

int j;

for(i=0 ,j=0;i<15,i<;i++,j++)

 Print(i);
Но выражение проверки может быть только одно.

Тело цикла

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

Код:
for(int i=1;i<=15;i++)

{

 Print(i);

 PlaySound("alert.wav");

}
В этом коде в теле цикла содержится два оператора. Программа будет выполнять 1й оператор, а за ним 2й при каждом прохождении цикла.
Не забывайте ставить точку с запятой в конце каждого оператора.

Оператор Break

Если при выполнении цикла for (или цикла while, или оператора switch) встречается оператор break;, то цикл терминируется, а контроль переходит оператору, следующему за циклом. PS: break — это ключевое слово.

Например:

Код:
for(int i=0;i<15;i++)

{

 if((i==10)

 break;

 Print(i);

}
В этом примере цикл будет нормально выполняться пока i не достигнет значения 10. Как только это произойдёт, операторbreak; остановит цикл. В результате, на экран распечатаются: 0,1,2,3,4,5,6,7,8,9.

Оператор Continue

Оператор break; останавливает цикл, а оператор continue; переводит цикл на следующий шаг, игнорируя оставшиеся операторы тела цикла.
Например:

Код:
for(int i=0;i<15; i++)

{

 if(i==10) continue;

 Print(i)

}
В этом примере цикл будет нормально выполняться пока i не достигнет значения 10. Как только это произойдёт, операторcontinue; переведёт цикл на следующий шаг, и i=10 НЕ распечатается. В результате, на экран распечатаются: 0,1,2,3,4,5,6,7,8,9,11,12,13,14.

Важно!

Часть или даже все управляющие выражения цикла for можно опускать.
Например:

Код:
for(;;)
Этот цикл равносилен циклу while, в котором выражение проверки всегда истинно.

Мы Вам представим цикл while прямо сейчас:

2 — цикл while

Цикл for обычно используется, когда Вы знаете, сколько раз цикл должен быть пройден. А что делать, если это не так?
Для этого есть цикл while.
В цикле while, как и в цыкле for есть выражение проверки, но в нём нет выражений инициализации и инкремента.
Пример:

Код:
int i=0;

while(i<15)

{

 Print(i);

 i++;

}

  • Переменная цикла была объявлена и про инициализирована ДО цикла. В отличии от цикла for, внутри скобок этого делать нельзя.
  • Формально i++ НЕ является выражением инкремента, но нам нужно чтобы что-то в цикле менялось, чтобы мы когда-нибудь из него выбрались.

Как же приведённый пример работает?
Оператор while содержит только выражение проверки, и он его проверяет после каждого прохождения цикла. Если оно истинно, цикл продолжится. Если оно ложно, цикл завершится и контроль перейдёт оператору, следующему за циклом.

В приведённом примере цикл будет выполняться пока i не станет равным 16. Как только это произойдёт, проверка условия i<15 вернёт false, и цикл завершится.
Схема 2. Цикл while.
Я уже говорил, что цикл while похож на цикл for. Вот их сходства:

1. В обоих можно использовать операторы break; и continue; .
2. В обоих тело цикла может быть одиночным или составным. Во вотром случае операторы тела цикла нужно брать в фигурные скобки.
3. Аналогом for(;;) является while(true).

Изучаем основной материал:
Циклы и Условия (часть 2)

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

1 — Оператор if

Оператор if является самым простым среди операторов условия.
Пример:

Код:
if( x < 100 )
 Print("hi");
После if идут круглые скобки, в которых записывается выражение проверки (в данном случае x < 100). Если результат выражение проверки является истиной (true), то тело оператора if будет выполнено. В данном случае тело состоит из одного оператора — Print(«hi»); . А если результат выажения проверки является ложью (false), то тело оператора if НЕ выполняется, а контроль переходит оператору, следующему за телом if.
Схема 1. Оператор if.
Несколько операторов в теле if

Точно, как и в циклах, тело оператора if может состоять из нескольких операторов, взятых в фигурные скобки.
Пример:
Код:
if(current_price==stop_loss)

{

 Print("you have to close the order");

 PlaySound("warning.wav");

}
Обратите внимание на сумбол == и выражении проверки. Это одна из операций сравнения, которые Вы изучали в уроке 4 «Операции и Выражения».
Отсюда происходит очень много ошибок — когда Вы забываете символ ==, и вместо него используете символ операции присваивания =.

Вложенные циклы и условия

Циклы и условия можно вкладывать друг в друга.
Пример:
Код:
for(int i=2; i<10; i++)

 if(i%2==0)

 {

 Print("It's definetly not a prime number");

 PlaySound("warning.wav");

 }
Заметьте, что тело цикла в данном примере НЕ нужно заключать в фигурные скобки, потому что оператор if и все операторы внутри его тела считаются как один оператор.

2 — Оператор if … else

Оператор if позволяет что-то сделать, если определённое условие выполняется. Допустим, мы хотим сделать что-то другое, если это условие не выполнено. Для этого есть оператор if … else. Он состоит из оператора if и его тела, после чего идёт ключевое слово else и его тело.
Пример:
Код:
if(current_price>stop_loss)

 Print("It’s not too late to stop, please stop!");

else

 Print("you're playing well today!");
 
Схема 2. Оператор if … else.
Вложенные операторы if…else

Операторы if … else и оператор if можно как угодно вкладывать друг в друга.
Пример:
Код:
if(current_price>stop_loss)

 Print("It’s not too late to stop, please stop!");

if(current_price==stop_loss)

 Print("It’s time to stop!");

else

 Print("you're playing well today!");
Есть опастность, связанная с вложенными операторами if … else. По невнимательности Вы можете случайно связать какой-то else не с тем if.
Чтобы избежать подобных ошибок, можно сделать одно из двух:

1 — всегда брать пары if … else в фигурные скобки.
Вот так:
Код:
if(current_price>stop_loss)

{

 Print("It’s not too late to stop, please stop!");

if(current_price==stop_loss)

 Print("It’s time to stop!");

else

 Print("you're playing well today!");

}
2 — Если Вам не подходит 1й вариант (слишком много этих if … else, или Вам просто лень), то просто следуйте правилусвязывать else с ближайшим if.

3 — Оператор switch

Если у Вас есть большое дерево условий, и все условия зависят от одного параметра, то можно применить оператор switch.
Пример:
Код:
switch(x)
 {

 case 'A':
 Print("CASE A");
 break;

 case 'B':

 case 'C':
 Print("CASE B or C");
 break;

 default:
 Print("NOT A, B or C");
 break;

 }
После ключевого слова switch идут круглые скобки. Внутри этих скобок находится switch-константа. Внктри фигурных собок находятся case-константы — это проверямые условия switch-константы. Они записываются в виде case <значение>: <что делать>. <Значение> может быть integer, character или неизменным выражением. Неизменность выражения означает, что оно не зависит от переменных. Например, выражение X+Y не является неизменным.

Как же работает указанный пример?
Оператор switch сравнивает switch-константу поочерёдно со всеми case-константами.
В случае x==’A’ программа напечает «CASE A» и оператор break; прервёт оператор switch. Контроль передастся за пределы блока switch.
В случае x==’B’ или x==’C’, программа напечатает «CASE B or C». Это потому что нет оператора break; в case ‘B’: .
В случае x!= ни одной из case-констант, оператор switch выполнит блок default: и напечатает «NOT A, B jr C».
Схема 3. Оператор switch.

Изучаем основной материал:
Функции

Добро пожаловать в мир функций языка MQL4.
Работа с функциями в любом языке состоит из двух этапов:
- изучение функций, что, порой, очень скучное занятие
- использование функций, что всегда является спасательной шлюпкой.

В чём смысл функций ?

Функция очень похожа на мясорубку — вы кладёте в неё мясо, лук, специи и получаете фарш.
Мясо, лук и специи называются параметрами функции (входными параметрами функции), фарш — возвращаемое значение. А механизм мясорубки — тело функции.
Есть только одно различие между функциями и Вашей мясорубкой: некоторые функции возвращают НИЧЕГО (в MQL4 ничего называется словом void).
Пример:
Код:
double // тип фарша - возвращаемое значение
my_func (double a, double b, double c) // название функции и список параметров (мясо, лук и специи)

 {

 return (a*b + c); // фарш на выход - функция возвращает некоторое значение

 }
Как Вы видите выше, функция начинается с типа возвращаемого значения «double», за ним следует имя функции, после которого идут круглые скобки.
Внутрь скобок Вы кладёте мясо, лук и специи, точнее параметры функции.
В данном случае — три параметра: double a, double b, double c.
Затем идёт тело функции, которое заключено в фигурные скобки.
В данном примере, тело функции выполнит операцию (a*b + c).
Ключевое слово return ответственно за возвращение итого результата.

Ключевое слово return

Оператор return (); завершает работу функции (как break; завершает работу цикла), и передаёт контоль в точку вызова функции (об этом скоро).
Оператор return (); может содержать выражение в своих скобках, как в нашем примере. Это означает, что надо завершить работу функции и вернуть результат вычисление этого выражения.
Или оператор return (); может не содержать выражения в своих скобках. Тогда его единственная задача — завершить работу функции.
Внимание: не все функции используют оператор return (); Особенно, если возвращаемого значения нет, как в следующем примере:
Код:
void // void означает, что фарша не будет – возвращаемое значение
my_func (string s) // function name and parameters list (meat & spices)

 {

 Print(s);

 }
Эта функция не вернёт никакого значения, но она напечатает параметр s, который Вы ей предоставите. Чтобы показать, что функция ничего не возвращает, используется «void» в качестве её возвращаемого значения.
В некоторых языках программирования такие функции называются «методам», но в MQL4 они всё равно функции.

Вызов функции

Теперь, я надеюсь, мы понимаем, что такое функция. Как же использовать функции в Вашей программе?
Есть ещё один шаг, который нужно для этого сделать.
Этот шаг называется вызовом функции (её использованием).

Допустим, у Вас есть функция, котороая возвращает сумму двух integer.
Вот она:
Код:
int collect (int first_number, int second_number)

 {

 return(first_number+ second_number);

 }
Вы хотите ей воспользоваться в своей программе.
Делается это так:
Код:
int a = 10;

int b = 15;

int sum = collect(a,b);

Print (sum);
В этом примере на экран распечатается 25. Магия! Но как компьютер узнал, что печатать?
Магической является строчка int sum = collect(a,B); Здесь Вы объявили переменную sum, чтобы в неё положить возвращаемое значение, а затем дали функции на вход два параметра (a,b).

Вы просто-напросто вызвали функцию.

Когда MQL4 видит имя функции в Вашей программе, он берёт Ваши параметры и идёт к функции, после чего он возвращается с результатом и кладёт его на то же место.
На самом деле, происходит следующее: в процессе компиляции MQL4 заменяет строчку с вызовом функции в вашей программе целиком телом самой функции (с учётом Ваших параметров). Причём вместо оператора return(); MQL4 производит присваивание возвращаемого им значения в родготовленную Вами переменную.

Вложение функций друг в друга

В тело одной функции можно вкладывать другие функции. Это потому что строчка вызова обрабатывается, как оператор (это и есть оператор).
Пример:
Код:
void print_collection (int first_number, int second_number)

 {

 int sum = collect(first_number, second_number);

 Print(sum);

 }
В этом примере мы вызвали функцию collect внутри функции print_collection и распечатали результат. void означает, что возвращаемого значения нет (ещё помните?).

Спец. функции MQL4: init(), deinit(), start().

В MQL4 любая программа начинает своё выполнение с функции «init()» (initialize) и она срабатывает, когда Вы перетаскиваете программу (советника или индикатор) на график MetaTrader или если Вы поменяете валюту или период графика. Задача этой функции заключается в инициализации основных переменных, необходимых для работы Вашей программы. (Больще об инициализации переменных Вы узнаете далее).

Когда Ваша программа заканчивает свою работу, или Вы закрываете окно графика, или меняете валюту или период графика, или закрываете терминал, срабатывает функция «deinit()» (de-initialize).

Третья функция (самая важная) «start()» срабатывает каждый раз, когда приходят новые котировки. 90% своей программистской жизни Вы проводите внутри этой функции.

Мы больше узнаем об этих функциях, когда будем писать советник или индикатор

Изучаем основной материал:
Переменные в MQL4

Зачем нужны переменные?

Как я уже говорил ранее, переменные — это всего лишь имена, которые привязаны к кускам памяти, где храняться соответствующие данные.
Чтобы было легче понимать, что происходит, представьте себе, что память — это набор коробок различных размеров. Размер коробки — это эквивалент количества бит, требуемого для хранения данного типа.

  • Чтобы использовать коробку для хранения данных, необходимо присвоить ей имя. Этот процесс называется объявлением.
  • В процессе объявления Вы используете слово, чтобы объяснить компьютеру какого размера коробка Вам нужна. Это слово называется ключевым.
  • Лучше дать имя коробке такое, чтобы потом было легко понять, что в ней лежит.
  • Данные кладутся в коробку путём присвоения данных коробке.
  • Если объявление и присвоение данных происходит в одной строчке, то такой процесс называется инициализацией.

Когда мы создаём переменную, мы говорим компьютеру, что мы хотим, чтобы он присвоил часть памяти определённого размера (в битах) нашей переменной. Поскольку хранение числа, буквы или большого числа занимает разный объём памяти, компьютер спросит, что Вы хотите хранить в этой памяти, и каков размер данных. Для этого и нужны типы данных.

Например, если мы дадим компьютеру следующую строчку кода:
Код:
int MyVaraible=0;
то мы говорим компьютеру, что хотим, чтобы он выделил блок памяти длиной 4 байта под нащу переменную «MyVariable».

В этом примере:

int — это ключевоу слово

int — тип данных integer

int — объявление

MyVariable — имя переменной

=0 — инициализация

О переменных мы узнаем больше далее.

В MQL4 присутствубт следующие типы данных:


  • Integer (int)
  • Boolean (bool)
  • Character (Char)
  • String (String)
  • Floating-point number (double)
  • Color (color)
  • Datetime (datetime)

Я скопировал для Вас предыдущие строки из поста про типы данных. Теперь Вы вспомнили, что такое переменные в MQL4  — давайте посмотрим, как их надо объявлять:

Объявление:

Объявить переменную означает представить её миру и указать её тип. Для этого используются ключевые слова, которые мы упоминали в посте про типы данных (int, double, char, bool, string, color и datetime) и имя, которое Вы выбрали для своей переменной.
Например:
Код:
int MyVaraible;
Здесь Вы объявили переменную под именем MyVariable, которая имеет тип integer. До строчки объявления ‘слово’MyVariable в коде использовать нельзя. Если Вы попробуете это сделать, то компилятор MQL4 будет жаловаться и выдаст такую ощибку: ‘MyVaraible’ — variable not defined. 1 error(s), 0 warning(s).

Инициализация (присвоение)

Итак, инициализация означает присвоение значения переменной, например: MyVaraible=0; Инициализацию можно производить в той же строчке, что и объявление: int MyVariable=0;
А можно объявить переменную в одном месте, а инициализацию производить совершенно в другом:
Код:
int MyVaraible;



MyVaraible=5;
Но помните, что объявление всегда идёт ДО инициализации.

Зоны видимости переменных

Есть два типа зон видимости переменной — локальная и глобальная.

1 — Локальная зона видимости

Локальные переменные не видны вне того мира, где они были объявлены. Границы ‘мира’ определяются ближайшей парой фигурных скобок {}. Сверху мир ограничен скобкой {, а снизу — скобкой }. Например, переменные, объявленные внутри функции, локальны для тела этой функции. Переменные, объявленные внутри цикла или услови локальны для этого цикла или условия, и они НЕ видны и НЕ могут быть использованы вне этого цикла или условия.
Например:
Код:
double my_func (double a, double b, double c)

 {

 int d;

 return (a*b + c);

 }
В приведённом примере переменные a,b,c и d являются локальными и могут быть использованы только внутри тела этой функции.

2 — Глобальная зона видимости

Глобальные переменные — это переменные, объявленные вне всех фигурных скобок. Они видны и могут быть использованы в любой части Вашей программы.
Например:
Код:
int Global_Variable;

double my_func (double a, double b, double c)

 {

 return (a*b + c + Global_Variable);

 }
Здесь глобальная переменная Global_Variable объявлена вне функции (на уровне обявления функций), поэтому она видна всем функциям Вашей программы.
Глобальные переменные автоматически выставляются на нуль, если Вы их не проинициализировали при объявлении.

Внешние переменные

Ключевое слово «extern» используется для объявления переменных специального вида (не типа, а вида). Переменные такого вида используются для хранения входных данных программы, которые Вы можете ввести в окошке настроек Вашего советника или индикатора.
Например:
Код:
extern color Indicator_color = C'0x00,0x00,0xFF'; // blue

int init()

 {

 ...

 }
В этом примере переменная Indicator_color была объявлена, как extern, которую Вы увидите, когда прикрепите индикатор к графику в терминале, и которую можно менять в окошке настроек.
Рис. 1. Окошко настроек индикатора MA.
Здесь переменные Period, Shift, MA_method, Apply_to и Style — переменные, объявленные с использованием ключевого слова «extern«. Поэтому они появляются в окошке настроек.
Если Вы хотите, чтобы пользователь мог изменять какую-либо переменную, сделайте её extern-переменной

0 Responses to “Циклы и Условия, Функции, Переменные в MQL4”

Отправить комментарий