今回は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文を使用する