English Русский 中文 Español Deutsch Português
preview
初級から中級へ:IF ELSE

初級から中級へ:IF ELSE

MetaTrader 5 | 28 4月 2025, 09:16
40 0
CODE X
CODE X

はじめに

ここで提示されるコンテンツは、教育目的のみを目的としています。いかなる状況においても、提示された概念を学習し習得する以外の目的でアプリケーションを閲覧することは避けてください。

前回の記事「初級から中級まで:値渡しまたは参照渡し」では、異なるプログラム間でデータを受け渡す際に押さえておくべき概念、リスク、注意点について、実用的かつ客観的に説明しました。

この議論と、これまでに取り上げた内容を踏まえ、今回からより高度なトピックに進んでいきます。なぜなら、プログラミングとは単なる数式処理だけではないからです。もし数式処理だけに留まるならば、コンピュータの持つ計算能力や因数分解能力を大きく無駄にすることになり、私たちが本来達成できる可能性を大きく制限してしまうでしょう。

したがって、これから扱う内容を理解するためには、これまでの記事で紹介した概念をしっかりと身につけていることが前提となります。もし、途中で「なぜこうなるのか」が分からなくなった場合は、遠慮せず前の記事に立ち返り、じっくりと復習してください。焦らず、提示された順序に従って、着実に進めていきましょう。

さて、この記事および今後の記事で扱うトピックに入る前に、まず「文」を説明する際に頻繁に登場する、ある重要な用語について整理しておく必要があります。それでは、最初のトピックに進みましょう。


ルーチンとは何かを定義する

すべてのプログラミング言語は、特定の用語の枠組みの中で定義されています。ここでの説明を明確に理解し、正しく解釈するために、まず最初に重要な用語を定義しておきましょう。


図01

図01に示すように、コードブロックは開き中括弧で始まり、閉じ中括弧で終わります。このブロック内のすべてのものは単一のエンティティとして考慮される必要があります。行数や、開始中括弧と終了中括弧の間に何が含まれているかに関係なく、それを1つのまとまりのある単位として考える必要があります。この単位をルーチンと呼びます。

ここで、よく注意してください。ルーチンは、以下に示すものと同様のコードブロックになります。

   {
      ExtAOBuffer[i] = ExtFastBuffer[i] - ExtSlowBuffer[i];

      double sumAO = 0.0;

      for(int j = 0; j < FAST_PERIOD; j++)
         sumAO+=ExtAOBuffer[i - j];

      ExtSMABuffer[i] = sumAO / FAST_PERIOD;
      ExtACBuffer[i] = ExtAOBuffer[i] - ExtSMABuffer[i];

      if ( ExtACBuffer[i] >= ExtACBuffer[i - 1])
         ExtColorBuffer[i] = 0.0; // set color Green
      else
         ExtColorBuffer[i] = 1.0; // set color Red
   }

下記のような任意の表現も可能です。

ExtACBuffer[i] = ExtAOBuffer[i] - ExtSMABuffer[i];

関数やプロシージャを実行する呼び出しも、このカテゴリに含まれます。言い換えれば、これらすべてを総称してルーチンと呼びます。したがって、「ルーチンが実行される」と言うときは、関数やプロシージャの呼び出しから、コードブロック全体に至るまで、さまざまなものを指す可能性があると理解してください。このブロックには、複数の式やプロシージャ・関数呼び出し、さらには元のルーチン内にネストされた別のルーチンが含まれている場合もあります。つまり、心を無限に、そしてさらにその先へと広げましょう。これで用語の定義ができたので、いよいよ本題に入ります。


IF文:究極の制御

本題に入る前に、少しだけ補足をしておきたいと思います。プログラミングの文は英語で記述される必要がありますが、読者の皆さん(将来のプログラマー)は、必ずしも英語ベースの文だけを使わなければならないわけではありません。回避する手段も存在します。しかし、ここではプログラミングを始めたばかりだと仮定して話を進めましょう。今は特定の単語や用語にこだわりすぎず、概念を理解することに集中してください。概念をしっかり習得することは、文法や構文ルールを暗記するよりも、はるかに大きな価値があります。

さて、なぜこのセクションでIF文を「究極の制御」と呼んだのでしょうか。そして、なぜIFから始めるのでしょうか。他の文から始めることもできるはずです。もちろんできます。しかし、IF文の仕組みを本当に理解し、これまでの記事で学んだことを適用できるようになれば、プログラミングでほぼ何でもできるようになります。ここで「ほぼ」と言っているのは、後ほど別の重要な概念を学ぶ必要があるからです。ただし、それも、まずはシンプルなコマンドで基礎を固めておけば、ずっと簡単に理解できるようになります。必要な概念を正しく習得し、正しく適用できるようになれば、IF文といくつかの演算子、そして変数だけで、あらゆるプログラムを作れるようになります。それだけで十分です。それ以上は何もありません。信じられないかもしれませんが、それは事実です。そして、時間が経てば自然とその意味がわかるようになるでしょう。

では、まずIF文の基本を理解することから始めましょう。IFとは文字通り「もし」という意味です。この文に出会ったら、必ずそのまま「もし」と読んでください。これだけで、IF文の意味が格段に掴みやすくなります。

IF文が実行されるとき、条件が評価されます。この条件は常にtrueかfalseかのいずれかとして判断される必要があります常にです。何がテストされるか、何を分析するかは関係ありません。IF文が内部のルーチンを実行するかどうかは、テストされた条件がtrueかfalseかによって決まります。前回の記事でも説明したとおり、条件が0ならfalse、0以外ならtrueとみなされます。多くの人が誤解しているように、IF文で比較演算子(>、<、== など)を使う必要は必ずしもありません。必要なのは、「条件がtrueかfalseか」を判断することだけです。それ以上のことはありません。

この概念をもっと直感的に理解するために、次は簡単な例を見ていきましょう。

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. void OnStart(void)
05. {
06.     char info = 10;
07. 
08.     Print(__FUNCTION__, " : #1 => ", info);
09. 
10.     if (info)
11.         Print("True condition...");
12. 
13.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
14. }
15. //+------------------------------------------------------------------+

コード01

このコードを実行すると、MetaTrader 5で次のようなものが表示されます。


図02

ここでは、先ほど説明した内容をそのまま適用しています。6行目では変数を定義し、続く8行目では、データの現在の状態を確認するためのメッセージを出力しています。そして10行目で、制御フロー文――つまりIF文が登場します。さて、読者の皆さん、ここはしっかり注目してください。infoがtrueであれば、IF文の内部にあるルーチンが実行されます。逆に、infoがfalseであれば、IF文内のルーチンは実行されず、コード上の次のルーチンへと処理が進みます。このようにして、私たちはコードの実行フローを自由に制御・誘導できるわけです。ここでの「次のルーチン」は、13行目に存在しています。

さて、今回はinfoの値がゼロではないため、IF文内のルーチンが実行されます。その結果、画像02に示されているような出力結果が得られるわけです。ここで、IF文を書く際に知っておくべき重要なポイントがいくつかあります。その中には必須のものもあれば、オプションのものもあります。ですが、まず押さえておくべき基本的なIF文の構文は以下のとおりです。


図03

これで、文がどのように実行されるかがはっきりとわかりました。構文もシンプルで、非常に理解しやすいものです。

さて、条件がtrueのときにIF文内のルーチンを実行せず、代わりにfalseのときに実行したい場合はどうすればよいでしょうか。そんなことが可能なのでしょうか。これは素晴らしい質問です。そして実は、こここそが多くの初心者プログラマーがつまずき、時には挫折してしまうポイントでもあるのです。その理由は、IF文の本質的な概念を正しく理解できていないからです。もう一度強調しておきます。IF文は、条件がtrueの場合にのみ、その内部のルーチンを実行します。それ以外の場合、IF文内のルーチンは実行されません。「でも待ってください。値がfalseの場合でもIF文内のルーチンが実行されるコードを見たことがあります。ご自分が何をおっしゃっているのかお分かりですか。」そんなふうに思った方もいるかもしれません。ここでは議論するのではなく、実際に確かめてみることにしましょう。これが本当に可能なのかを検証するため、簡単なプログラムを作成します。そのために、IF文の式が常にtrueと評価されるように、わざと条件を設定します。そのコードは下にリストしてあります。これはどのように可能なのでしょうか。値がfalseの場合でもIF文内のルーチンが実行されるコードを見たことがあるかもしれません。すると、私が何を言っているのか分からないと思われるかもしれません。

これについては議論しないようにしましょう。代わりに、次のことを実行してみましょう。これが実際に発生するかどうかを確認するための簡単なプログラムを作成します。これを実行するには、IF文内の式が常にtrueとなる条件を意図的に強制します。そのコードはこちらです。

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. void OnStart(void)
05. {
06.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
07. 
08.     if (true)
09.         Print("True condition...");
10. 
11.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
12. }
13. //+------------------------------------------------------------------+

コード02

これで、8行目のテストが常にtrueになることがわかります。したがって、コードが何回実行されても、9行目は常に実行されます。結果は以下の通りです。


図04

先ほど、式がfalseの場合にルーチンを実行するIF文について説明しました。さて、式をfalseにして何が起こるか見てみましょう。これは次のコードに示されています。 

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. void OnStart(void)
05. {
06.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
07. 
08.     if (false)
09.         Print("True condition...");
10. 
11.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
12. }
13. //+------------------------------------------------------------------+

コード03

変更したのは、8行目のIF文内の式だけであることに注意してください。ただし、コードを実行すると、出力は以下の画像のようになります。


図05

待ってください。図04に表示されたもう1行はどこですか。どこに行ってしまったのですか。読者の皆様、図05にそれが表示されていないのは、実行されなかったためです。これは、8行目でテストされた式がfalseであるからです。そしてそれは常にfalseです。条件がfalseであるため、IF文内のルーチンは実行されません。しかし、ここには小さいながらも重要な詳細があり、多くの人がそれを見落としています。おそらくこれが、falseの条件でもIF文内のルーチンがトリガーされる可能性があると考えた理由です。この誤解は通常、式の結果が何らかの理由で反転したときに発生します。つまり、以前はfalseだったものがtrueになるか、その逆の場合です。

これには、ぜひ細心の注意を払ってください。コードの書き方ひとつで、最終的な値がtrueになるか、falseになるかが決まるのです。一見すると式は正しいように見えるため、この種の問題はプログラマーを悩ませることが多いです。しかし、内部的な要因、特に演算子の優先順位に関係する問題によって、思いがけない結果が出ることがあります。この問題は、数学的なエラーではありません。IF文の文脈における論理的なエラーなのです。このテーマは非常に重要なので、本来であればそれだけで一つの記事を書いてもよいほどです。ただし、これを完全に理解するには、さらに別の文や演算子の知識も必要になります。そのため、今回は詳細な解説はいったん保留にしておきましょう。

なお、この話題に興味がある方は、ドキュメント「優先順位ルール」 を参照して、ぜひ自主的に学習してみてください。

とはいえ、優先順位ルールを知らなくても、簡単なコード修正だけで次のことを試すことができます。それは、式がfalseに見えても、8行目のIF文内のルーチンを実行させる方法です。そのためのコード修正版を、以下に示します。

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. void OnStart(void)
05. {
06.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
07. 
08.     if (~false)
09.         Print("True condition...");
10. 
11.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
12. }
13. //+------------------------------------------------------------------+

コード04

このほとんど気づかれないほどの変更を加えることで、以下に示す結果が得られます。


図06

ぱっと見た限りでは、コード04ではテストされている式がfalseだと思ってしまうかもしれません。しかし、ここで注目すべきなのは、予約語falseの前にある記号です。多くの場合、この場所には感嘆符「!」が使われています。ただし、これを実現する方法は、他にもたくさん存在します。たとえば、テストでは「値がゼロかどうか」を常にチェックしていることがわかっていれば、次のようなコードを書くこともできます。

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. void OnStart(void)
05. {
06.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
07. 
08.     if (false | true)
09.         Print("A very crazy condition always true ...");
10. 
11.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
12. }
13. //+------------------------------------------------------------------+

コード05

このコードを実行すると、以下のような出力が表示されます。


図07

さまざまなバリエーションを紹介し続けることもできますが、何が起こっているかを完全に理解したうえで、自分自身で実験してみることに勝るものはありません。これでIF文については一通りカバーできたので、次の制御構造に進みましょう。次は、IFがなければ存在しないELSE文についてです。これについては次のセクションで詳しく見ていきましょう。


ELSE文は単独では成り立たない

初心者がよく陥るミスの一つは、おそらく使用している教材の影響で、ELSE文を単独で使おうとしてしまうことです。「そうでない場合」とも説明できるELSE文は、必ず別の文とセットで使わなければなりません。このとき、ELSEの前に来る文はプログラミング言語によって異なります。多くの人は、ELSEは常にIF文に続くものだと考えがちですが、例えばSQLでは、ELSEはCASE文に付随する形で使われます。これは少し奇妙に思えるかもしれませんが、単純にその言語がそう設計されているからです。つまり、ひとつのプログラミング言語を知っているからといって、他の言語もすぐに使いこなせるとは限らないということです。基本的な考え方は共通していても、各言語には独自のルールやニュアンスが存在します。

IF文の仕組みが理解できていれば、ELSE文の理解はさらに簡単です。IFと組み合わせて使う場合、IF条件がfalseだったときだけELSEブロックが実行されます。基本的にはそれだけの話です。深く考えすぎる必要はありません。

ただ、よりイメージを明確にするため、ここで実行フローを確認してみましょう。以下にフローチャートを示します。


図08

図08を見てみると、ELSE文が存在する場合、それは必ずIF文とセットで使われていることがわかります。この概念は一見すると単純に思えるかもしれませんが、実際にコードを書くとなると、必ずしもそう簡単ではありません。読者の皆さん、ELSEブロックを含むIF文を使う際には、いくつか注意すべきポイントがあります。これについては、この記事の後半で詳しく説明します。その前に、ちょっとした練習をしてみましょう。前に出てきたコード例を少しアレンジして、ELSE文を追加してみるのはどうでしょうか。これまで説明してきた内容はシンプルなので、すべての例を修正する必要はありません。ここでは、コード例のひとつを取り上げ、そこにELSEブロックを加えてみることにします。

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. void OnStart(void)
05. {
06.     int info = 10;
07. 
08.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway... #1 => ", info);
09. 
10.     if (info)
11.         Procedure(info);
12.     else
13.         Print("Variable info is equal to zero...");
14. 
15.     if (info)
16.         Print("True condition...");
17.     else
18.         Print("False condition...");
19.     
20.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway... #2 => ", info);
21. }
22. //+------------------------------------------------------------------+
23. void Procedure(int & arg1)
24. {
25.     Print(__FUNCTION__, " ", __LINE__, " #1 => ", arg1);
26.     arg1 = 0;
27.     Print(__FUNCTION__, " ", __LINE__, " #1 => ", arg1);
28. }
29. //+------------------------------------------------------------------+

コード06

一見複雑に見えるコード06は、実際には、最初に思ったよりもはるかに単純で明確です。コード06を実行すると、以下のような結果が得られます。


図09

画像09を見て、情報量が多すぎて処理しきれないと思うかもしれません。しかし、だからこそ、ここでさらに集中して、しっかりと理解を深めていくことが大切です。それでは、IF-ELSEの組み合わせを効果的に使う方法を、段階的に整理していきましょう。

まず6行目で、コード全体を通して使用する変数を作成します。次に8行目で、図09にある最初の出力メッセージが表示されます。IF文の動作を理解していれば、10行目で何が起こるかはすでに予想できるでしょう。この時点では、Procedureルーチンを実行するかどうかが決まります。ここで何が起こっているのかを正しく理解するためには、以前の記事で解説した「変数」についての知識が必要になります。その後、実行は15行目に進み、2つのルーチンのうちどちらか一方が実行されることになります。いずれにしても、新しいメッセージが端末に出力されます。最後に、20行目で端末に表示される最後のメッセージが出力されます。

この「コード06」は添付してあるので、ぜひ小さな変更を加えて実験してみてください。例えば、6行目の変数の値を変えてみると、10行目のテスト結果が変わり、実行されるルーチンも変わることがわかります。この変更後にコードを実行して、動作を確認してみてください。また、IFの条件を変えて、どのようにメッセージが出力されるかを観察してみるのもいいでしょう。さらに、ルーチン内の条件を調整して、15行目のIF文の挙動を変えることもできます。変更を加えるたびに、結果をしっかりと観察し、なぜそのような動作になるのかを自分なりに分析してみましょう。この練習を積み重ねることで、IF文の理解を確実なものにできます。これは、今後学んでいく他の制御構造を理解するためにも、とても重要なステップになります。

ただし、IF-ELSEの組み合わせを使う場合、少し注意すべき問題点も存在します。これについては、次のトピックで詳しく見ていきましょう。


ネスト問題

IF-ELSEの組み合わせを頻繁に使うと、ネスト問題が発生することがあります。これは、複数のIF-ELSEブロックが互いに埋め込まれ、条件が連鎖(カスケード)することで起こる現象です。ただし、この問題はIF文だけをネストしている場合にはほとんど発生せず、特にELSEが導入されたときに問題となります。とはいえ、熟練したプログラマーも、読みづらいコードになるのを避けるため、IF文の過度なネスト自体を控える傾向にあります。ネストが深くなったコードは、設計としてもあまり良いものとは言えません。

ネストやカスケードがどのようなものかをイメージできるように、次の例を見てみましょう。

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. void OnStart(void)
05. {
06.     char c1 = 10,
07.          c2 = 0,
08.          c3 = -6,
09.          c4 = 3;
10. 
11.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
12. 
13.     if (c1)
14.         if (c2)
15.             if (c3)
16.                 if (c4)
17.                     Print("True condition...");
18.     
19.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
20. }
21. //+------------------------------------------------------------------+

コード07

以下はネストされたIF文の典型的な例です。この書き方の何が問題なのかと疑問に思うかもしれません。技術的には、特に問題はありません。しかし、経験豊富なプログラマーがこのようにコードを書くことはほとんどありません。彼らは通常、論理演算子を使って書き換え、機能は同じでもより読みやすいコードにします。コード07の代替案を以下に示します。

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. void OnStart(void)
05. {
06.     char c1 = 10,
07.          c2 = 0,
08.          c3 = -6,
09.          c4 = 3;
10. 
11.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
12. 
13.     if ((c1) && (c2) && (c3) && (c4))
14.         Print("True condition...");
15.     
16.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
17. }
18. //+------------------------------------------------------------------+

コード08

コード07とコード08の出力が同一であることに注目してください。ただし、コード08では、コード07にあったネストされたIF文が、論理演算のチェーンに置き換えられています。この場合、AND演算子を使用しています。別の種類の演算子を使うと、コード08の動作が変わり、コード07と同じ結果にはならなくなります。もし、自分のコードが期待どおりに動作しているか確信が持てない場合は、異なる形式で書き直してみると、より明確になります。

ただし、ネストの問題は、IF文のカスケードだけに限った話ではありません。特に、IFとELSEの組み合わせで頻繁に発生します。でも、なぜこのような問題が起きるのでしょうか。まだ完全にはイメージできていないかもしれません。これを理解するために、コード07に似たものをベースに、ELSE文を追加したコードを見てみましょう。その結果が、以下に示すコードです。

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. void OnStart(void)
05. {
06.     char c1 = 10,
07.          c2 = 0,
08.          c3 = -6,
09.          c4 = 3;
10. 
11.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
12. 
13.     if (c1)
14.         if (c2)
15.             if (c3)
16.                 if (c4)
17.                     Print("True condition...");
18.         else
19.             Print("False condition...");
20.     
21.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
22. }
23. //+------------------------------------------------------------------+

コード09

一見すると、コード09はコード07と非常によく似ています。しかし、コード09には大きな問題が潜んでいます。もし今の時点でその問題の深刻さに気づいていないなら、プログラムの構築方法をより深く理解するために、この記事をしっかり読み進めることをおすすめします。

ここで問題となるのは、18行目にあるELSEです。ここで質問です。このELSEは、どのIF文に対応しているのでしょうか。

インデントを見ていると、18行目のELSEは14行目のIFに対応しているように見えるかもしれません。実際、一部のプログラミング言語ではそのように解釈されます。しかし、多くの言語ではそうではありません。そもそも、ほとんどのプログラミング言語ではインデントはプログラムの機能には直接関係せず、単にコードを整理して読みやすくするためのものにすぎません。

MQL5も例外ではなく、インデントによってコードの動作が変わることはありません。したがって、現在の形では、18行目のELSEは16行目のIFにリンクされています。

この問題を、複雑にせずシンプルに解決する方法を紹介します。しかも今回は、2つの解決策をお見せします。そのうちのひとつは、ほとんどのプログラマーに支持されている方法です。もうひとつは、少数派の方法ですが、特定の場面では役立つこともあります。まずは、多くのプログラマーに好まれている方法から説明しましょう。それは、コードを明確なブロックに分けることで、コンパイラに対して意図をはっきり示す方法です。ここでは、この方法を使用します。このやり方によって、コードの読みやすさと理解しやすさも大きく向上します。この方法で書き直したコードを、以下に示します。

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. void OnStart(void)
05. {
06.     char c1 = 10,
07.          c2 = 0,
08.          c3 = -6,
09.          c4 = 3;
10. 
11.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
12. 
13.     if (c1)
14.         if (c2)
15.         {
16.             if (c3)
17.                 if (c4)
18.                     Print("True condition...");
19.         }
20.         else
21.             Print("False condition...");
22.     
23.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
24. }
25. //+------------------------------------------------------------------+

コード10

実際、これは素晴らしい解決策です。14行目に、ELSEと連携させたいIF文があることに注目してください。14行目のIFの条件式がtrueだった場合に実行されるサブルーチンを正しく定義するため、その処理をブロック内にまとめて配置します。ここでは、IFシーケンス全体をネストしているため、15行目から19行目までのブロックは、14行目のIFに対応するサブルーチンということになります。このブロックは、場合によってはOnStartブロックの外にある別の関数やプロシージャにまとめることもできます。

読者の皆さん、これを理解することは非常に重要です。14行目のIF文の評価結果がfalseだった場合、プログラムは直接ELSE文にジャンプして、そこに記述されているサブルーチンを実行します。なお、ここで実行されるサブルーチンの中身は何でもよいため、単なる構文やスタイルを丸暗記するのではなく、文の意味と動きそのものをしっかり理解することが重要です。

ここで、ぜひ覚えておいてください。もしあなたが本当にIF文を理解し、それをELSE文と正しく組み合わせられるようになれば、コード09に対してもう一つ別の解決策を取ることもできるようになります。とはいえ、この別の解決策はあまり広く使われていません。なぜなら、多くの場合、コードの理解をかえって難しくしてしまうからです。しかし、ここでは学習用の教材として、さまざまなやり方を説明しているので、18行目のELSEを14行目のIFにリンクする方法も紹介しておきましょう。その方法はとてもシンプルで、別のIF文をELSEと一緒に連結するだけです。具体例は以下に示します。

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. void OnStart(void)
05. {
06.     char c1 = 10,
07.          c2 = 0,
08.          c3 = -6,
09.          c4 = 3;
10. 
11.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
12. 
13.     if (c1)
14.         if (c2)
15.             if (c3)
16.                 if (c4)
17.                     Print("True condition...");
18.                 else;
19.             else;
20.         else
21.             Print("False condition...");
22.     
23.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
24. }
25. //+------------------------------------------------------------------+

コード11

コード11では、14行目のIF文と、20行目のELSE文との関連を把握するのが、決して簡単ではないことに注意してください。この関係を理解するには、コードを注意深く分析する必要があります。とはいえ、コード10とコード11はいずれも、実行結果は同じになります。つまり、14行目のIFの条件がfalseだった場合、対応するELSEに記述されたサブルーチンが実行されるということです。


最終的な考察

この記事では、制御フロー文について紹介しました。最初はこれらの概念で混乱するように思えるかもしれません。ですが、忍耐強く継続的に練習を重ね、出会う問題に対して新しい解決策を見つけていく努力を続ければ、徐々に高度な習熟度へ到達できるでしょう。これは、ほんの一握りの人しか達成できない領域です。

しかし、そのためには、同じ問題に対しても常に最適な解決策を探し続ける姿勢が欠かせません。一度解決できたからそれで十分というわけではありません。常により良い方法が存在することを忘れないでください。明らかなものだけを鵜呑みにせず、その先を見抜く力を育てていきましょう。

最後にお伝えしておきますが、添付ファイルには、この記事に登場したすべてのコードは含まれていません。提供されるのは、そのうちの一部(サブセット)のみです。ですが、この記事をしっかり読み込み、必要に応じてコードを自分で修正・追加することで、最終的にはすべてのコード例を自力で完成させることが可能です。この練習は、単なる学習以上の意味を持ちます。それは、自分自身のプログラミングスタイルを見つけるための道のりでもあるからです。たとえコードの中身が同じでも、書き方や表現方法はプログラマーによって大きく異なります。いよいよ、あなた自身のスタイルを確立する時です。他のプログラマーにも理解しやすいコードを目指しつつ、自分自身も迅速にソリューションを作成・修正できる力を身につけていきましょう。


MetaQuotes Ltdによりポルトガル語から翻訳されました。
元の記事: https://www.mql5.com/pt/articles/15365

添付されたファイル |
Anexo.zip (2.64 KB)
ニューラルネットワークの実践:最初のニューロン ニューラルネットワークの実践:最初のニューロン
この記事では、シンプルで控えめなもの、つまりニューロンの構築を始めます。ごく少量のMQL5コードでプログラムしますが、それでも私のテストではこのニューロンは見事に機能しました。とはいえ、私がここで何を言おうとしているのかを理解するには、これまでのニューラルネットワークに関する連載を少し振り返ってみる必要があります。
リプレイシステムの開発(第62回):サービスの再生(III) リプレイシステムの開発(第62回):サービスの再生(III)
この記事では、実際のデータを使用する際にアプリケーションのパフォーマンスに影響を及ぼす可能性のある「ティック過剰」の問題について取り上げます。このティック過剰は、1分足を適切なタイミングで構築するうえで支障となることがよくあります。
取引におけるニューラルネットワーク:統合軌道生成モデル(UniTraj) 取引におけるニューラルネットワーク:統合軌道生成モデル(UniTraj)
エージェントの行動を理解することはさまざまな分野で重要ですが、ほとんどの手法は特定のタスク(理解、ノイズ除去、予測)に焦点を当てており、そのため実際のシナリオでは効果的に活用できないことが多いです。この記事では、さまざまな問題を解決するために適応可能なモデルについて説明します。
リプレイシステムの開発(第61回):サービスの再生(II) リプレイシステムの開発(第61回):サービスの再生(II)
この記事では、リプレイ/シミュレーションシステムをより効率的かつ安全に動作させるための変更点について解説します。また、クラスを最大限に活用したいと考えている方にも役立つ情報を取り上げます。さらに、クラスを使用する際にコードのパフォーマンスを低下させるMQL5特有の問題点を取り上げ、それに対する具体的な解決策についても説明します。