MQL言語の処理の種類と内容【使用例あり】

処理の種類一覧

プロフラムの処理は、これらの演算処理が連続して行われています。1つ1つの演算は、セミコロン( ; )で区切られます。

処理文の種類内容
{}1つ以上の様々な演算を囲うのに使用します。
;式の終了を意味します。
return関数を終了し、呼び出し元のプログラムへ戻ります。
if else条件判定が必要な時に使用します。
?:if else 文を簡易的にしたもの。
switch式の値と一致する場合に処理を行います。
while式が false になるまで、ループ処理を継続します。
式はループ処理の前に判定されます。
for式が false になるまで、ループ処理を継続します。
式はループ処理の前に判定されます。
do while式が false になるまで、ループ処理を継続します。
式はループ処理の後に判定されます。
ループ処理は最低1回は行われます。
break最も近くにある外側のループ処理( switch、while、do-while、for)から抜けます。
continue最も近くにある外側のループ処理(while、do-while、for)の次のループ処理を呼び出します。
newクラスオブジェクトを作成します。
deletenew演算子によって作成されたオブジェクトを削除します。

1つの処理を、複数行に渡って記述することが出来ます。
2つ以上の処理を、同じ行に記述することも出来ます。

各処理文の使用例

重文処理 {}(中括弧、ブレース)

重文処理は、中括弧 {}で囲まれた1つ、または複数のさまざまな型で構成されます。括弧の後のセミコロン(;)は不要です。

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

式の終わり ;(セミコロン)

式の最後は、セミコロン(;)を記述して終わります。

代入処理

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

代入演算子は式の中で複数回使用出来ます。このケースでは、処理は右から左へ行われます。

関数の呼び出し方

関数名 (引数1,…, 引数N);

関数の呼び出しは、関数名の後に小括弧()をつけます。
引数がある場合(void型以外)は、小括弧内に対応する型の値を書きます。
戻り値がある場合は、代入演算子の右側に関数の呼び出しを書きます。

空の演算子

セミコロン( ; )のみで構成され、制御演算子の本体が、空であることを示すために使用されます。

参照:変数の初期化

関数の終了(return)

return 演算子は、実行中の関数を終了し、呼び出し元のプログラムに戻ります。
返り値がある場合は、呼び出し元の関数に値を返します。式は代入演算子を含むことが出来ます。

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

void 型の関数では、return 演算子を省略することができます。

void SomeFunction()
  {
   Print("Hello!");
   return;   // この演算子は省略できる
  }

関数の右中括弧{}は、式の部分を含まない、return 演算子の実行を暗黙的に示します。

return 処理で返り値として返すことが出来るのは、基本データ型、基本構造体、オブジェクトポインタがあります。

配列、クラスオブジェクト、複合構造体の変数を返すことは出来ません。

参照:変数の初期化

条件判定 if else

if (条件式)
    処理x //条件式を満たしたときに行われる処理
else
    処理y //条件式を満たさなかったときに行われる処理

条件式が true の場合、処理x が実行され、処理y は実行されません
条件式が false の場合、処理y のみが実行されます。

if 文の else 部分は、省略することができます。

//--- else 部分は2つ目の if 演算子と関係する
if(x > 1)
   if(y == 2)
      z = 5;
   else
      z = 6;
//--- else 部分は1つ目の if 演算子と関係する
if(x > l)
  {
   if(y == 2)
      z = 5;
  }
else
   z = 6;
//--- else 文の中で、更に if else 文に分岐
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型であればどんな式でも使えます。
式1の結果がtrueの場合、式2の処理が実行されます。
式2の結果がfalseの場合、式3の処理が実行されます。
式2と式3は、void型以外の値を返す必要があります。

//--- 一日の始値と終値の差を正規化
double true_range = (High == Low) ? 0 : (Close - Open) / (High - Low);

//上記の式と、下記の式は、同じ意味合いです。

double true_range;
if(High == Low)
   true_range = 0;             // 高/安値が等しい場合
else
   true_range = (Close - Open) / (High - Low); // 範囲が null でない場合

演算子の使用制限

三項演算については、いくつかの制限があります。

  • ユーザ定義型と基本データ型や列挙型を混同してはいけません。ポインタには、NULLを使用出来ます。
  • 値が基本型であれば、一番大きい型のオペレータが使用されます(型キャストをご参照ください)。
  • 値のいずれかが列挙型で、2つ目が数値型の場合、列挙型は int 型に置き換えられ、2番目のルールが適用されます。
  • 両方の値が列挙型の場合は、その型が同一である必要があり、演算子は列挙型となります。

ユーザ定義型(クラスまたは構造体)の制限について

  • 型は同一であるか、2つ目が、1つ目からの派生型である必要があります。
  • 型が同一(または継承)でない場合、子の型は暗黙的に親にキャストされ、演算子は親の型になります。
  • オブジェクトとポインタを混同してはいけません。式は両方ともオブジェクトまたはポインタでなければいけません。ポインタには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); // 文字列への暗黙的キャストに警告
   func(!Expression1 ? Expression2 : Expression3); // 文字列への暗黙的キャストに警告
  }

//   結果:
//   double argument: 3.141592653589793
//   string argument: 3.1415926
//   string argument: 3.141592653589793
//   string argument: 3.1415926

選択処理 switch

式の値と、全てのcaseの定数と比較し、一致する処理を行います
caseの定数は、整数定数、リテラル定数が使用出来ます。
caseの定数に、変数又は関数の呼び出しは使用出来ません
switch文は、整数型(int、uint)である必要があります。

switch(式)
  {
case constant:
   operators
case constant:
   operators
   ...
default:
   operators
  }

caseの定数に一致する値が無い場合、defaultラベルの処理が実行されます。
defaultは省略する事が可能で、式の最後に記載しないことも可能です。

caseの定数に一致せず、defaultラベルも存在しない場合は、何も処理が行われません。

caseと定数はただのラベルです。複数のラベルが存在する場合、breakに到達するまで処理が実行されます。

定数式は、コンパイル時に計算されます。
1つのswitch 内で、複数の定数が同じ値を持つことは出来ません。

//--- 例1
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;
  }

//---  例 2
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(式)
 処理;

条件式が true であれば、条件式が false になるまで処理が継続して実行されます。
処理が実行される前に、条件式の値を判定します。
そのため、条件式が初めから false であれば、処理は一度も行われません。

ループ処理の回数が多いと予想される場合は、IsStopped()関数を使用して、ループから抜ける処理を施すことが推奨されています。

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

ループ処理 for

for文は、3つの式と、それに伴う処理によって構成されています。

for(式 1 ; 式 2 ; 式 3 )
  処理;

式1は、ループの初期値を記述します。
式2は、ループの終了条件を記述します。
式2の結果が true であれば処理が実行され、false になるまでループ処理が実行されます。false になるとループ処理が終了します。
式2が、最初から false の場合は一度も処理されません。
式3は、繰り返し処理の後で計算されます。

for文は、while文で下記のように記述することもできます。

式1;
while(式2)
  {
処理;
式 3 ;
  };

for文においては、式1~式3のいずれも、省略する事が出来ますが、式1~式3を区切っている、セミコロン(;)は省略出来ません。

式2を省略した場合は、式2が常に true であると判定されます。
式1~式3の全てを省略した場合は、while文と同じ動作になります。

式1と式3は、それぞれカンマ(,)によって結合された、複数の式を使う事が出来ます。

while文と同様に、ループ処理の回数が多いと予想される場合は、IsStopped()関数を使用して、ループから抜ける処理を施すことが推奨されています。

for(x = 1; x <= 7000; x++)
  {
   if(IsStopped())
      break;
   Print(MathPower(x, 2));
  }
//--- 例 2
for(; !IsStopped();)
  {
   Print(MathPower(x, 2));
   x++;
   if(x > 10)
      break;
  }
//--- 例 3
for(i = 0, j = n - l; i < n && !IsStopped(); i++, j--)
   a[i] = a[j];

ループ処理 do while

for文とwhile文では、ループ処理のに終了条件を判定しますが、
do while文は、ループ処理ので終了条件を判定します。
そのため、ループ処理は、最低でも1回は行われます。

do
  処理;
while(式);

最初に do 以降の処理が実行され、その後に while の条件式が判定されます。
その結果が true であれば、再び処理が実行され、この流れがループします。
条件式が false であれば、ループ処理が終了します。

こちらも、ループ処理の回数が多いと予想される場合は、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ループの処理から抜けます
break処理の目的のひとつは、変数が特定の値になった場合に、ループ処理を終了させることです。

for(i = 0; i < array_size; i++)
   if(array[i] == 0)
      break; //配列の i が 0 の時、forループを抜ける

次のループへ continue

continue処理は、最も近くにある外側の while、do while、forループの処理の始まりに戻ります
continue処理の目的は、変数が特定の値になった場合に、次のループ処理へ移行することです。

int func(int array[])
  {
   int array_size = ArraySize(array);
   int sum = 0;
   for(int i = 0; i < array_size; i++)
     {
      if(a[i] == 0)
         continue; //配列の i が 0 の時、forループの始まりに戻る(下の行の sum += a[i];は処理されない)
      sum += a[i]; //配列の i が 0 以外の時に処理される
     }
   return(sum);
  }

クラスオブジェクト生成 new

new演算子は、対応する大きさのオブジェクトを自動的に作成し、オブジェクトのコンストラクタを呼び出し、 作成されたオブジェクトの記述子を返します
エラーが発生した場合、NULLを返します。

new演算子は、クラスのオブジェクトのみ適用でき、構造体には適用できません

new演算子は、オブジェクト配列の作成には使用できません
オブジェクト配列の作成には、ArrayResize()関数を使用します。

//+------------------------------------------------------------------+
//| 図の作成                                                          |
//+------------------------------------------------------------------+
void CTetrisField::NewShape()
  {
   m_ypos = HORZ_BORDER;
//--- 7 つの可能な図形から 1 つをランダムに選んで作成する
   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 m_shape;
m_shape = NULL;

//--- 新しい図を作成する
NewShape();

タイトルとURLをコピーしました