初めてお越しの方へ

一部のコンテンツはMTPlaceメールマガジンに登録していただくことで閲覧/ダウンロード可能となります。もちろん登録は無料、解除も簡単にできますのでMTPlaceメールマガジン登録よりお気軽にご登録下さい。記事の一覧はサイトマップを御覧ください。

Categories: MQL4の基本

MQL4での制御構造(switch-case文による条件分岐処理)

今回はswitch-case文による条件分岐処理について解説していきたいと思います。
今回作成するインジケーターは次のようなものです。

10行文字列を出力していますが、1,2,5行目は”Number “に続けて行番号を出力し、それ以外の行は”Hello Indicator”を出力しています。
今回は、前回作成したソースの改造を通して学習して行きたいと思います。
・前回作成したチャートに出力する文字を行ごとに変更するソース TestIndicator

以下は、前々回作成したfor文による繰り返し処理のstart関数です。

int start()
  {
   string moziretu = "";
   for(int i = 0; i = 6 && i 

まずこれを10行とも同じ"Hello MQL4"を出力するように修正してみましょう。
以下が修正後のソースです。

int start()
  {
   string moziretu = "";
   for(int i = 0; i 

これで、10行"Hello MQL4"が表示されると思います。
それではswitch-case文の形式を示します。

switch(式)
  {
   case 定数1:
      // 式の値が定数1と一致する場合の処理
      break;
   case 定数2:
      // 式の値が定数2と一致する場合の処理
      break;
   default:
      // 式の値が上のいずれとも一致しない場合の処理
      break;
  }

式とか定数とか言われても分かりにくいと思います。
具体的にコードを示したほうが分かりやすいと思いますので、以下に今回のお題である「1,2,5行目は"Number "に続けて行番号を出力し、それ以外の行は"Hello Indicator"を出力する」コードを示します。

int start()
  {
   string moziretu = "";
   for(int i = 0; i < 10; i++)
   {
      switch(i)
      {
         case 0:
            moziretu = moziretu + "Number 1\n";
            break;
         case 1:
            moziretu = moziretu + "Number 2\n";
            break;
         case 4:
            moziretu = moziretu + "Number 5\n";
            break;
         default:
            moziretu = moziretu + "Hello Indicator\n";
            break;
      }
   }
   Comment(moziretu);
   return(0);
  }

for文の中でswitch-case文を使用しています。カウンタ変数iが0の場合は1行目の出力ですから"Number 1"を出力し、変数iが1の場合は2行目の出力ですから"Number 2"を出力します。そして同様に変数iが4の場合は5行目の出力ですから"Number 5"を出力し、それ以外の行は"default:"以下が実行されますから、"Hello Indicator"が出力されます。

ここで、もう少しコードをシンプルにできないかを考えてみましょう。
「1,2,5行目は"Number "に続けて行番号を出力」しますよね。そして、カウンタ変数iの状態をみてみると次のような事が言えます。

変数iが0の時は1行目が出力されている。
変数iが1の時は2行目が出力されている。
変数iが4の時は5行目が出力されている。

つまり、カウンタ変数i+1が、出力されている行数になっているわけです。
このことより、「1,2,5行目は"Number "に続けて行番号を出力」するコードは以下のように書き換えることができます。(ただし以下のコードは間違いを含んでいます)

int start()
  {
   string moziretu = "";
   for(int i = 0; i < 10; i++)
   {
      switch(i)
      {
         case 0:
            moziretu = moziretu + "Number " + i + 1 + "\n";
            break;
         case 1:
            moziretu = moziretu + "Number " + i + 1 + "\n";
            break;
         case 4:
            moziretu = moziretu + "Number " + i + 1 + "\n";
            break;
         default:
            moziretu = moziretu + "Hello Indicator\n";
            break;
      }
   }
   Comment(moziretu);
   return(0);
  }

これは、「"Number " + i + 1」によって1行目なら"Number 1"と表示されることを期待したコードです。1行目を出力する際、iは0ですからi+1が行数になるはずだからです。
しかし1行目の結果は"Number 01"となってしまいます。これは、自動変換されることが原因です。
"Number "は文字列。
i はint型、すなわち整数。
1 は整数。
このように、"+"を使った場合に1つでも文字列が含まれていると、内部で全て文字列に変換され、それが結合されてしまうのです。
しかし、やりたいことは 「i + 1」は普通に計算して、その結果を"Number "と結合してほしいわけです。
以下のようにするとそれを実現出来ます。

int start()
  {
   string moziretu = "";
   for(int i = 0; i < 10; i++)
   {
      switch(i)
      {
         case 0:
            moziretu = moziretu + "Number " + (i + 1) + "\n";
            break;
         case 1:
            moziretu = moziretu + "Number " + (i + 1) + "\n";
            break;
         case 4:
            moziretu = moziretu + "Number " + (i + 1) + "\n";
            break;
         default:
            moziretu = moziretu + "Hello Indicator\n";
            break;
      }
   }
   Comment(moziretu);
   return(0);
  }

そうです、"i + 1"をただカッコでくくっただけです。こうすることによりまずカッコ内が計算の対象になり、iも1も整数ですから勝手に文字に変換されることはなく、期待通り足し算をしてくれます。これで「1,2,5行目は"Number "に続けて行番号を出力」するようになりました。
さて、あえてこのような分かりにくいコードに変更したのには理由があります。
お気付きかと思いますが、"case 0"の時の処理と"case 1"および"case 4"の時の処理の内容が全く同じですよね。このような場合、以下のように単純に書き換えることが出来るのです。

int start()
  {
   string moziretu = "";
   for(int i = 0; i < 10; i++)
   {
      switch(i)
      {
         case 0:
         case 1:
         case 4:
           moziretu = moziretu + "Number " + (i + 1) + "\n";
           break;
         default:
           moziretu = moziretu + "Hello Indicator\n";
           break;
      }
   }
   Comment(moziretu);
   return(0);
  }

最初に示したcaseとcaseの間には、必ず"break;"という記述があったと思います。この"break;"がない場合、処理がそこで止まらず、そのまま下のcaseへと流れ、実行されてしまうのです(これをフォールスルーと言います)
それを利用したのが上のコードで変数iが0の場合、1の場合、4の場合の処理が同じ場合に使えるテクニックです。

今回はswitch-case文による条件分岐処理を解説しました。switch-case文は、if-else文ほど柔軟な条件分岐はできません。そのかわり、シンプルな条件分岐の場合には、非常に読みやすいコードになることが多いです。
ですから、シンプルな条件分岐の場合にはswitch-case文を使用し、それが無理な場合はif-else文を使用するというスタンスで良いと思います。
・今回作成したチャートに出力する文字を行ごとに変更するソース TestIndicator

switch-case文とif-else文の使い分け
シンプルな条件分岐の場合にはswitch-case文を使用し、それが無理な場合はif-else文を使用する
だいご