Операторы

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

Оператор

Описание

Составной оператор {}

Один или более операторов любого типа, заключенные в фигурные скобки { }

Оператор-выражение (;)

Любое выражение, заканчивающееся точкой с запятой (;)

Оператор return

Прекращает выполнение текущей функции и возвращает управление вызвавшей программе

Условный оператор if-else

Используется при необходимости сделать выбор

Условный оператор ?:

Более простой аналог условного оператора if-else

Оператор выбора switch

Передает управление оператору, который соответствует значению выражения

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

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

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

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

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

Выполняет оператор до тех пор, пока проверяемое выражение не станет ложным. Проверка условия окончания производится в конце, после каждого прохода цикла. Тело цикла всегда выполняется по крайней мере один раз.

Оператор break

Прекращает выполнение ближайшего вложенного внешнего оператора switch, while, do-while или for

Оператор continue

Передает управление в начало ближайшего внешнего оператора цикла while, do-while или for

Оператор new

Создает объект соответствующего размера и возвращает описатель созданного объекта.

Оператор delete

Удаляет созданный оператором new объект

Один оператор может занимать одну или более строк. Два или большее количество операторов могут быть расположены на одной строке. Операторы, управляющие порядком выполнения (if, if-else, switch, while и for), могут быть вложены друг в друга.

Пример:

if(Month() == 12) if(Day() == 31) 
   Print("Happy New Year!");

 

Составной оператор

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

Пример:

if(x==0) 
{
   Print("invalid position x = ",x);
   return; 
}

Оператор-выражение

Любое выражение, заканчивающееся точкой с запятой (;), является оператором. Далее следуют примеры операторов-выражений.
Оператор присваивания:

Идентификатор = выражение;

x=3;
y=x=3; 
bool equal=(x==y);

В выражении оператор присваивания может присутствовать много раз. В этом случае обработка выражения ведется справа налево.

Оператор вызова функции:

Имя_функции (аргумент1,…, аргументN);

FileClose(file);
 

Пустой оператор cостоит только из точки с запятой (;) и используется для обозначения пустого тела управляющего оператора.

Оператор возврата return

Оператор return прекращает выполнение текущей функции и возвращает управление вызвавшей программе. Результат вычисления выражения возвращается вызываемой функции. Выражение может содержать оператор присваивания.

Пример:

int CalcSum(int x, int y)
{
   return(x+y);
}

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

void MyFunction()
{
   Print("Hello!");
   return; // этот оператор можно удалить, т.к. тип функции void не возвращает значений
}

Завершающая фигурная скобка функции предполагает неявное исполнение оператора return без выражения.

Можно возвращать простые типы, простые структуры, указатели объектов. При помощи оператора return нельзя возвращать любые массивы, объекты классов, переменные типа сложных структур.

Условный оператор if-else

Оператор IF — ELSE используется при необходимости сделать выбор. Формально синтаксис имеет вид:

if (выражение)
оператор1
else
оператор2

Если выражение истинно, то выполняется оператор1 и управление передается на оператор, следующий за оператором2 (т.е. оператор2 не выполняется). Если выражение ложно, то выполняется оператор2.

Часть else оператора if может опускаться. Поэтому во вложенных операторах if с пропущенной частью else может возникнуть неоднозначность. В этом случае else связывается с ближайшим предыдущим оператором if в том же блоке, не имеющим части else.

Примеры:

//--- Часть else относится ко второму оператору if:
if(x>1)
  if(y==2) z=5;
else z=6;
//--- Часть else относится к первому оператору if
if(x>l)
{
   if(y==2) z=5;
}
else z=6;
//--- Вложенные операторы
if(x=='a')
{
   y=1;
}
else if(x=='b')
{
   y=2;
   z=3;
}
else if(x=='c')
{ 
   y=4;
}
else Print("ERROR");

Условный оператор ?:

Общая форма тернарного оператора выглядит так:

выражение1 ? выражение2 : выражение3

В качестве первого операнда – «выражение1» – может быть использовано любое выражение, результатом которого является значение типа bool. Если результат равен true, то выполняется оператор, заданный вторым операндом, то есть, «выражение2».

Если же первый операнд paвен false, то выполняется третий операнд – «выражениеЗ». Второй и третий операнды, то есть «выражение2» и «выражениеЗ», должны возвращать значения одного типа и не должны иметь тип void. Результатом выполнения условного оператора является результат «выражения2» либо результат «выражение3», в зависимости от результата «выражение1».

//--- пронормируем разность между ценами открытия и закрытия на дневной размах
double true_range = (High==Low)?0:(Close-Open)/(High-Low);

Эта запись эквивалентна следующей

double true_range;
if(High==Low)true_range=0; // если High и Low равны
else true_range=(Close-Open)/(High-Low); // если размах ненулевой

Ограничения по использованию оператора

Оператор на основании значения «выражение1» должен вернуть одно из двух значений — либо «выражение2», либо «выражение3». Существует ряд ограничений на эти выражения:

  • Нельзя смешивать пользовательский тип с простым типом или перечислением. Для указателя допустимо использовать NULL.
  • Если типы значений простые, то типом оператора будет максимальный тип (смотри Приведение типов).
  • Если одно из значений имеет тип перечисление, а второе является числовым типом, то перечисление заменяется на int и действует второе правило.
  • Если оба значения являются значениями перечислений, то их типы должны быть одинаковыми, и типом оператора будет перечисление.

Ограничения для пользовательских типов (классов или структур):

  • типы должны быть одинаковыми или один должен наследоваться от другого.
  • если типы не одинаковы (наследование), то потомок неявно приводится к родителю, то есть типом оператора будет тип родителя.
  • нельзя смешивать объект и указатель – либо оба выражения являются объектами, либо указателями. Для указателя допустимо использовать NULL.

Примечание

Будьте внимательны при использовании условного оператора в качестве аргумента перегруженной функции, так как тип результата условного оператора определяется на момент компиляции программы. И этот тип определяется как больший тип из типов «выражение2» и «выражение3».

Пример:

void func(double d) { Print("double argument: ",d); }
void func(string s) { Print("string argument: ",s); }
 
bool Expression1=true;
double Expression2=M_PI;
string Expression3="3.1415926";
 
void OnStart()
{
   func(Expression2);
   func(Expression3);
 
   func(Expression1?Expression2:Expression3); // получим предупреждение компилятора о явном приведении к типу string
   func(!Expression1?Expression2:Expression3); // получим предупреждение компилятора о явном приведении к типу string
}
 
// Результат:
// double argument: 3.141592653589793
// string argument: 3.1415926
// string argument: 3.141592653589793
// string argument: 3.1415926

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

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

switch(выражение)
{
case константа: операторы
case константа: операторы

default: операторы
}

Операторы, связанные с меткой default, выполняются, если ни одна из констант в операторах case не равна значению выражения. Вариант default не обязательно должен быть объявлен и не обязательно должен быть последним. Если ни одна константа не соответствует значению выражения и вариант default отсутствует, то не выполняется никаких действий.

Ключевое слово case вместе с константой служат просто метками, и если будут выполняться операторы для некоторого варианта case, то далее будут выполняться операторы всех последующих вариантов до тех пор, пока не встретится оператор break, что позволяет связывать одну последовательность операторов с несколькими вариантами.

Константное выражение вычисляется в период компиляции. Никакие две константы в одном операторе-переключателе не могут иметь одинаковые значения.

Примеры:

//--- первый пример
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;
 }
//--- второй пример
string res="";
int i=0;
switch(i)
{
   case 1:
   res=i;break;

   default:
   res="default";break;

   case 2:
   res=i;break;

   case 3:
   res=i;break;
}

Print(res);

/*
 Результат
 default
*/

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

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

while(выражение)
оператор;

Если выражение истинно, то оператор выполняется до тех пор, пока выражение не станет ложным. Если выражение ложно, то управление передается следующему оператору. Значение выражения определяется до выполнения оператора. Следовательно, если выражение ложно с самого начала, то оператор вообще не выполняется.

Примечание

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

Пример:

while(k<n && !IsStopped())
{
   y=y*x;
   k++;
}

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

Оператор for состоит из трех выражений и выполняемого оператора:

for(выражение1; выражение2; выражение3)
оператор;

Выражение1 описывает инициализацию цикла. Выражение2 — проверка условия завершения цикла. Если оно истинно, то выполняется оператор тела цикла for. Все повторяется, пока выражение2 не станет ложным. Если оно ложно, цикл заканчивается и управление передается следующему оператору. ВыражениеЗ вычисляется после каждой итерации.

Оператор for эквивалентен следующей последовательности операторов:

выражение1;
while(выражение2)
{
оператор;
выражение3;
};

Любое из трех или все три выражения в операторе for могут отсутствовать, однако разделяющие их точки с запятыми (;) опускать нельзя. Если опущено выражение2, то считается, что оно постоянно истинно. Оператор for(;;) представляет собой бесконечный цикл, эквивалентный оператору while(1). Каждое из выражение1 и выражение3 может состоять из нескольких выражений, объединенных оператором запятая ‘,’.

Примечание

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

Примеры:

for(x=1;x<=7000; x++)
{
   if(IsStopped())
      break;

   Print(MathPower(x,2));
}


//--- другой пример
for(;!IsStopped();)
{
   Print(MathPower(x,2));
   x++;

   if(x>10) 
      break;
}
//--- третий пример
for(i=0,j=n-l;i<n && !IsStopped();i++,j--) 
   a[i]=a[j];

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

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

do
оператор;
while(выражение);

Сначала выполняется оператор, затем вычисляется выражение. Если оно истинно, то оператор выполняется снова и т.д. Если выражение становится ложным, цикл заканчивается.

Примечание

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

Пример:

//--- вычисление последовательности чисел Фибоначчи
int counterFibonacci=15;
int i=0,first=0,second=1;
int currentFibonacciNumber;

do
{
   currentFibonacciNumber=first+second;
   Print("i = ",i," currentFibonacciNumber = ",currentFibonacciNumber);
   first=second;
   second=currentFibonacciNumber;
   i++; // без этого оператора получится бесконечный цикл!!
}
while(i<counterFibonacci && !IsStopped());

Оператор завершения break

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

Пример:

//--- поиск первого нулевого элемента
for(i=0;i<array_size;i++)
 if(array[i]==0)
 break;

Оператор продолжения continue

Оператор continue передает управление в начало ближайшего внешнего оператора цикла while, do-while или for, вызывая начало следующей итерации. Этот оператор по действию противоположен оператору break.

Пример:

//--- сумма всех ненулевых элементов
int sum_func(int array[])
{
   int array_size=ArraySize(array);
   int sum=0;
   for(int i=0;i<array_size; i++)
   {
      if(a[i]==0) 
         continue;
      sum+=a[i];
   }
   return(sum);
}

Оператор создания объекта new

Оператор new автоматически создает объект соответствующего размера, вызывает конструктор объекта и возвращает описатель созданного объекта. В случае неудачи оператор возвращает нулевой описатель, который можно сравнивать с константой NULL.

Оператор new может быть применен только к объектам класса, к структурам он не применим.

Оператор не применяется для создания массивов объектов. Для этого следует использовать функцию ArrayResize().

Пример:

//+------------------------------------------------------------------+
//| Создание фигуры |
//+------------------------------------------------------------------+
void CTetrisField::NewShape()
{
   m_ypos=HORZ_BORDER;

   //--- случайным образом создаём одну из 7 возможных фигур
   int nshape=rand()%7;
   switch(nshape)
   {
       case 0: m_shape=new CTetrisShape1; break;
       case 1: m_shape=new CTetrisShape2; break;
       case 2: m_shape=new CTetrisShape3; break;
       case 3: m_shape=new CTetrisShape4; break;
       case 4: m_shape=new CTetrisShape5; break;
       case 5: m_shape=new CTetrisShape6; break;
       case 6: m_shape=new CTetrisShape7; break;
   }

   //--- отрисовываем
   if(m_shape!=NULL)
   {
       //--- начальные установки
       m_shape.SetRightBorder(WIDTH_IN_PIXELS+VERT_BORDER);
       m_shape.SetYPos(m_ypos);
       m_shape.SetXPos(VERT_BORDER+SHAPE_SIZE*8);

       //--- отрисуем
       m_shape.Draw();
   }
   //---
}

Следует отметить, что описатель объекта не является указателем на память.

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

Оператор уничтожения объекта delete

Оператор delete удаляет созданный оператором new объект, вызывает деструктор соответствующего класса и освобождает память, занимаемую объектом. В качестве операнда используется действительный описатель существующего объекта. После выполнения операции delete описатель объекта становится недействительным.

Пример:

//--- удаляем уложенную фигуру
delete m_shape;
m_shape=NULL;

//--- создаём новую фигуру
NewShape();