
初級から中級へ:配列と文字列(II)
はじめに
ここで提示されるコンテンツは、教育目的のみに使用されることを意図しています。いかなる状況においても、提示された概念を学習し習得する以外の目的でアプリケーションを利用することは避けてください。
前回「初級から中級まで:配列と文字列(I)」では、文字列と配列について簡単に紹介しましたが、実際のところ内容の大部分は文字列に焦点を当てたものでした。そこで扱った内容は、あくまでこのトピックの簡潔な導入として位置づけられるものです。しかし、他のトピックに進むためには、これまでの説明をもう少し深く掘り下げる必要があります。したがって、この記事の内容を理解するための前提として、前回の記事をしっかりと理解していることが求められます。
この最初の前提に加えて、IF文やループ構造の理解、演算子や変数に関する基本的な知識も同様に重要です。これらについては、これまでの記事で扱ってきた内容なので、すでに理解しているものとします。もしまだ理解が不十分であれば、今回の内容をより深く理解するためにも、過去の記事に一度立ち返ることをお勧めします。
それでは、この記事の本題に入っていきましょう。今回の新しいトピックはこちらです。
カスタム書式設定
MQL5でのプログラミングにおいて最も楽しい側面の一つは、多くの場合、特定の機能を一から作る必要がないという点です。実際、MQL5の標準ライブラリが私たちのニーズに対応できないという場面は稀です。しかし、標準ライブラリが完全には目的や要件に合致しない場合もあります。たとえば、特定の情報を端末上や、後に使用する予定のグラフィカルオブジェクト内に表示するためのカスタムフォーマットを作成したいというケースがその一つです。
現時点ではグラフィカルオブジェクトの操作にはまだ進んでいないため、本記事ではMetaTrader 5の標準出力(すなわち端末)に限定して話を進めます。ただし、まもなくより面白くなる方法をご紹介します。その瞬間が訪れるためにも、まずはプログラミング言語のいくつかの重要な機能について、しっかりとした基礎理解を築く必要があります。
したがって、今回の内容はMQL5に限らず、他のプログラミング言語にも適用可能です。特に、プログラミングの概念やルールに関する部分は汎用的です。冒頭でも述べたように、MQL5の標準ライブラリでは不十分な場合もあります。しかし、たとえ基本的な話題しか扱っていないように見えても、これまでの記事で得た知識と少しの論理的思考を組み合わせることで、非常に興味深い実装が可能になります。
ある特定の知識に目的を与えるという行為は、プログラミングの本質ではありません。本当に面白くなるのは、物事がどう動作しているのかが分かりはじめ、それをどう応用すれば特定の問題を解決できるかと考え始める瞬間です。まさにそのとき、学びは本当の意味を持ち始めます。
さて、ここで一つ問題を考えてみましょう。MetaTrader 5の端末にバイナリ値を表示または出力したいとします。目的は問いません。重要なのはその問題自体です。この課題に直面してすぐに、文字列フォーマットを使えば端末にバイナリ値を表示できるのではないかと考えるかもしれません。それは非常に筋の通った、優れた初期の発想です。しかし、より経験豊富なプログラマーであれば、その時点ですでに問題点に気づいているでしょう。一方、初心者の方は、数値のバイナリ表現を文字列として表示するためのフォーマット指定子を探してドキュメントを読み漁るかもしれません。そしてその結果、そういった機能が存在しないことに気づくのです。ここで必要になるのが、知識と創造力の融合です。
バイナリ値を表示するための組み込みのフォーマットが存在しない以上、自作するしかありません。もしあなたがプログラミング初心者で、これまでの記事で紹介された内容しか知らない場合、それは無理だと感じるかもしれません。でも、本当にそうでしょうか。ここで一度立ち止まって、これまでの情報だけで、それが実現できるかどうかを考えてみましょう。
MQL5の標準ライブラリには、さまざまなデータ型をフォーマットする関数があります。必要なのは、バイナリ値を扱うための独自フォーマットを作ることだけです。これは比較的簡単な部分です。しかし、少し厄介なのが次の問題です。CやC++のように、関数に無制限の数の引数を渡せる言語とは違い、MQL5にはそのような柔軟性がありません。私の知る限り、CとC++はこの機能を提供する数少ない言語であり、アセンブリ言語でも似たようなことが可能です。ただし、正直なところ、アセンブリで何かを書くような人は正気の沙汰ではないでしょう。率直に言えば、それは「狂気の沙汰」です。
さて、関数に無制限の引数を渡せないという制約はありますが、問題は分割すればシンプルになります。私たちの目的は、MQL5ライブラリの既存のフォーマット機能を使いつつ、バイナリ用の新しい書式を作成することです。どうすればいいのでしょうか。答えはシンプルです、親愛なる読者の皆さん。値をバイナリ表現で返す関数を自作し、それを文字列として出力します。MQL5の標準ライブラリは出力時に文字列を扱えるため、それをそのままカスタムフォーマットとして扱えるのです。
こう聞くと、難しそうに思えるかもしれません。でも、以下のコードを見ていただければ、それがいかに簡単なことか、おわかりいただけるでしょう。
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. void OnStart(void) 05. { 06. uchar value = 138; 07. 08. PrintFormat("The value %d in binary is written as: %s", value, BinaryToString(value)); 09. } 10. //+------------------------------------------------------------------+ 11. string BinaryToString(const uchar arg) 12. { 13. return "--BINARY--"; 14. } 15. //+------------------------------------------------------------------+
コード01
コード01を実行すると、結果は次のようになります。
図01
この時点で、もしかするとこれは自分たちが実装したかったものとは違うと思われるかもしれません。確かに、当初の目的とは異なっています。しかし、ここでお伝えしたいのは、既存のものを基にしながら、新しいものを創り出すことが可能であるという点です。13行目にある文字列が画像01と同じ内容になっていることに注目してください。つまり、ちゃんと動作しているのです。
次にやるべきことは、関数が受け取った値をバイナリ表現に変換することです。そして、そのバイナリ表現を文字列として作成し、返すだけです。この処理も、13行目で実装されています。
では、その値を0と1のみで構成された文字列に変換するには、どうすればよいのでしょうか。読者の皆さん。それはとてもシンプルな処理です。この変換にはループを使用しますが、ひとつだけ注意すべき点があります。それについては、以下のコードの中で直接説明していきます。
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. void OnStart(void) 05. { 06. uchar value = 138; 07. 08. PrintFormat("The value %d in binary is written as: %s", value, BinaryToString(value)); 09. } 10. //+------------------------------------------------------------------+ 11. string BinaryToString(const uchar arg) 12. { 13. string sz0 = ""; 14. uchar mask = 0x80; 15. 16. while (mask) 17. { 18. sz0 = sz0 + ((arg & mask) == mask ? "1" : "0"); 19. mask = mask >> 1; 20. } 21. 22. return sz0; 23. } 24. //+------------------------------------------------------------------+
コード02
このコードを実行すると、MetaTrader 5端末に次の出力が表示されます。
図02
本当に完璧です。言い換えれば、最小限の基本的な知識だけでも、このタスクを達成できたということになります。ただし、このコードには1つ小さな注意点があります。ここまでにご紹介してきた知識の範囲では、あらゆるデータ型をそのままバイナリ表現に変換することはできません。それには、より高度なプログラミングの概念が必要になります。つまり、今回のように単一のデータ型(この場合はuchar)を扱うシンプルなケースにおいてのみ、すでに有効に機能する関数が使えるということです。そしてご覧のとおり、その処理は非常に簡単です。ここでおこなわれている内容は、すべてこれまでの記事で扱ってきたものなので、この関数がどのように動作するのかについて改めて説明する必要はありません。ただし、まだ解説していない演算子が1つだけ使われています。それが「シフト演算子」です。この演算子は関数内に登場しており、その仕組みを理解することは非常に重要です。ですので、次のセクションではこの点に焦点を当てて説明します。ただ、その前にもう1つだけ重要なポイントに触れておきましょう。maskという変数は、arg変数と同じビット幅を持っている必要があります。これによって、値の正確かつ正確な変換が保証されるのです。今後、より高度な内容を扱う記事の中で、このビット幅の問題をコンパイラ側で自動的に処理させる方法についても学んでいく予定です。そうすることで、ここで紹介したコード02の関数を大きく変更することなく、最も複雑なデータ型から最も単純なものまで、あらゆる型に対応できるようになります。ただし、それは将来的な話です。今はまず、シフト演算子がどのように動作するのかを学びましょう。それでは、新しいトピックに移りましょう。
シフト演算子
一般的に、演算子というものは直感的に理解できるものです。しかし、シフト演算子に関しては、主にコンピュータサイエンスやデジタルエレクトロニクスの分野で使われるため、少しわかりにくく感じる方もいるかもしれません。私の知る限り、この演算子がそれらの分野以外で登場することはほとんどありません。コード02の19行目に登場するこのシフト演算子は、非常に実用的で、さまざまな場面で活躍します。ただし、これは特別な演算子というわけではなく、他の処理を簡潔に記述するための省略形に過ぎません。実際には、より冗長な2つの処理を置き換える役割を果たしているだけなのです。「2つの処理」と言ったのは、シフト演算子には、右にシフトするためのもの(>>)と左にシフトするためのもの(<<)の2種類あるからです。初心者がよくやってしまうのが、これらのシフト演算子と、値の大小を比較する「関係演算子」(< や >)を混同してしまうことです。これは、注意不足によって起きやすい誤解です。なぜなら、シフト演算子は二重の矢印(<< や >>)を使いますが、関係演算子は一重の矢印(< や >)を使うからです。
では、このシフト演算子は具体的に何をするものなのでしょうか。簡単に言えば、ある値を、指定したビット数分だけ、左または右に押し出す処理をおこないます。初めて聞くと少し難しそうに思えるかもしれませんが、実際には置き換えられる処理よりもシンプルです。
しかし、それなら他の書き方でも同じことができるのではないか。わざわざこんな書き方を使う必要があるのだろうか、と疑問に思う方もいるかもしれません。実際、それは非常にもっともな疑問であり、まさにその問いに答えるためにこのセクションが用意されています。ここでお伝えしたいのは、同じ結果を得るための実装方法は一つではないということです。現実には、2人のプログラマーがまったく同じ解決策を思いつくことは極めてまれです。もちろん、不可能ではありませんが、あまり起こりません。なぜなら、問題の解き方というのは、各プログラマーの知識の深さや経験の違いに大きく左右されるからです。
さて、本題に戻りましょう。シフト演算子の動作をできるだけ明確かつ簡単に理解してもらうために、以下のコードを使って実際に動作を確認してみましょう。
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. void OnStart(void) 05. { 06. const uchar shift = 1; 07. uchar i0 = 153, 08. i1, 09. i2, 10. i3, 11. i4; 12. 13. i1 = i0 << shift; 14. i2 = i0 * (uchar)MathPow(2, shift); 15. i3 = i0 >> shift; 16. i4 = i0 / (uchar)MathPow(2, shift); 17. 18. PrintFormat("Shift value : %d\n" + 19. "Original : %s\t%d\n" + 20. "Shifted to the left : %s\t%d\n" + 21. "Multiplication result: %s\t%d\n" + 22. "Shifted to the right : %s\t%d\n" + 23. "Division result : %s\t%d" 24. , shift, BinaryToString(i0), i0, 25. BinaryToString(i1), i1, 26. BinaryToString(i2), i2, 27. BinaryToString(i3), i3, 28. BinaryToString(i4), i4 29. ); 30. } 31. //+------------------------------------------------------------------+ 32. string BinaryToString(const uchar arg) 33. { 34. string sz0 = ""; 35. uchar mask = 0x80; 36. 37. while (mask) 38. { 39. sz0 = sz0 + ((arg & mask) == mask ? "1" : "0"); 40. mask = mask >> 1; 41. } 42. 43. return sz0; 44. } 45. //+------------------------------------------------------------------+
コード03
このコードを実行すると、下の画像のような出力が表示されます。
図03
さて、親愛なる読者の皆さん、ここでぜひ注目していただきたいのがコード03です。一見すると少しややこしく感じられるかもしれませんが、実際にはとても明快で、その目的をしっかり果たしています。ただし、これを正しく理解するためにはMathPow関数が何をするのかを知っておく必要があります。これはMQL5の標準ライブラリに含まれている関数なので、詳細は公式ドキュメントを参照するのがおすすめです。簡単に言えば、この関数は累乗計算をおこないます。ただし、戻り値の型はdoubleです。今回扱っているデータはuchar型なので、明示的に型変換をおこなっています。これにより、型の不一致によるコンパイルエラーを防ぐことができます。
次に、画像03をご覧ください。各行には、数値とそのバイナリ表現の両方が表示されています。このバイナリ表現は、元の値にどのような変化が起きているのかをより明確に示してくれるため、非常に重要です。左にビットシフトすると値が2倍になり、右にシフトすると2で割られると考える方もいるかもしれません。ある意味では正しいです。少なくとも、図03の範囲で考えればそう見えます。ただし、シフト量をたとえば1から3に変えたらどうなるでしょうか。
図04
図04は、3ビット分シフトした場合に何が起こるかを示しています。このとき、少し不思議に感じるかもしれませんが、3ビットシフトするということは、単に2を掛けたり2で割ったりするだけではなく、2の累乗を扱っているということです。つまり、与えられた数を2の累乗で掛けたり割ったりしているのです。シフト演算子を使うことで、正確な結果が得られます。このような累乗演算を伴う乗算や除算は計算コストが高いため、代わりにシフト演算子を使うほうが効率的です。
ただし、図04の値を見ると、一部の情報が失われていることに気づくかもしれません。これはプログラムのバグではありません。親愛なる読者の皆さん、これはデータ型の制限によるものです。MQL5は厳格な型付け言語であり、型の範囲を超えると情報が失われてしまいます。これを回避する方法はいくつかありますが、現時点では詳細に触れません。これらのケースへの対処法は、より適切なタイミングで説明します。プログラミングの世界では、学ぶべきことが常にありますので、ご安心ください。
これでシフト演算子の動作が理解できたと思います。この理解があれば、コード02も簡単に理解できるはずです。ではここで、文字列や配列といったテーマにまだ関連する別のトピックに移りましょう。
パングラムとアナグラム
これまで扱ってきた内容は限られていますが、この時点で興味深く、時には楽しい応用例を探ることができます。それが「パングラム」です。パングラムとはアルファベットのすべての文字を含む文章のことで、テストなどによく使われます。かなり古い概念ですが、とても教育的で楽しめる演習です。おそらく最も有名なパングラムは以下の文でしょう。
A QUICK BROWN FOX JUMPS OVER THE LAZY DOG 0123456789
この文はもともと古い電信システムのテストに使われていました。メッセージに現れる可能性のあるすべての文字が含まれているからです。さらに有名になったのは、MicrosoftがWordで印刷プレビューでの表示を確認するために、この文を使ったからです。当時はMicrosoft製品に隠しメッセージがあると噂され、多くのユーザーがコンピューターの使用をためらったこともありました。
しかし、現在の話の文脈でも、このようなフレーズで遊ぶことは十分可能です。これにより文字列や配列の理解を深めることができ、シンプルで楽しい学びの機会になります。
強力なパスワードや完全なフレーズをパスワードとして使用すべきだという意見を聞くことは珍しくありませんが、強いパスワードを作ることや覚えることは案外難しいものです。専用のパスワード管理ソフトを使う方法もありますが、それらの多くは全パスワードにアクセスするためのマスターパスワードを必要とします。私個人としては、それがかえって不便だと感じます。
とはいえ、基本的な関数やコマンドの仕組みがわかっている初心者プログラマーでも、比較的強力なパスワードを生成する簡単なツールを作ることは可能です。パスワードの強度はシステム設計に依存しますが、創意工夫すれば、特に目的が教育的なものなので、面白いものを作れるでしょう。
では、そもそも、パスワードとは何か考えてみましょう。パスワードは本質的に文字列として表現される印刷可能な文字の集合です。文字列を操作すれば、文字の並びをシャッフルしたり暗号化したりできるプログラムが作れます。強力なパスワードを作るには、こうしたシャッフル(暗号化の一形態や単なるアナグラムかもしれません)が、元のパスワードを少なくとも部分的に隠すのに有効です。ただし、アナグラムは他で使うような重要なパスワードを隠すには最適とは言えません。そういう場合は、アナグラムやパングラムのフレーズを元にして、シャッフルや暗号化をおこなうのが良いでしょう。キーは覚えやすい文章にし、結果として得られた文字列をパスワードとして使います。
ここで説明していることを理解しやすくするために、シンプルでわかりやすいコード例を見てみましょう。以下に示します。
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. void OnStart(void) 05. { 06. const string sz_Secret_Phrase = "Um pequeno jabuti xereta viu dez cegonhas felizes"; 07. 08. Print("Result:\n", PassWord(sz_Secret_Phrase)); 09. } 10. //+------------------------------------------------------------------+ 11. string PassWord(const string szArg) 12. { 13. const string szCodePhrase = "The quick brown fox jumps over the lazy dog"; 14. 15. string szPsw = ""; 16. uchar pos; 17. 18. for (int c = 0; c < StringLen(szArg); c++) 19. { 20. pos = (uchar)(StringGetCharacter(szArg, c) % StringLen(szCodePhrase)); 21. szPsw = StringFormat("%s%c", szPsw, StringGetCharacter(szCodePhrase, pos)); 22. } 23. 24. return szPsw; 25. } 26. //+------------------------------------------------------------------+
コード04
このコードを見て、一体何をしようとしているのかとと思ったかもしれません。まあまあ、落ち着いてください、親愛なる読者の皆さん。ここでやっていることは、一見すると少し突拍子もなくて意味が分からないかもしれません。でもすぐに、私が何を示そうとしているのかがはっきり分かるはずです。考えてみてください。このコードでは、これまでに扱ってきた内容だけを使っています。新しい概念は何も出てきません。これまでの記事をしっかり読んで、例で使われているライブラリ関数を自分で調べてきたなら、すべてを理解できるはずです。ここで使っているのは、すべてMQL5のドキュメントで簡単に見つけられる機能ばかりです。ですので、使用している関数について細かく説明することはしません。ただし、コードを何も変更せずにそのまま実行すると、次のような出力が得られるはずです。
図05
図05で強調表示されている部分が、使用すべきパスワードを表しています。ただし、スペース文字が含まれているため、少し不完全であることに注意してください。通常、パスワードにはスペースが含まれません。したがって、これを修正する必要があります。この問題を解決する非常に簡単な方法のひとつは、スペースを取り除き、先頭の文字を大文字にすることです。これは非常に簡単に実現できます。コード04の13行目をこのように変更すれば、次のようなコードになります。
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. void OnStart(void) 05. { 06. const string sz_Secret_Phrase = "Um pequeno jabuti xereta viu dez cegonhas felizes"; 07. 08. Print("Result:\n", PassWord(sz_Secret_Phrase)); 09. } 10. //+------------------------------------------------------------------+ 11. string PassWord(const string szArg) 12. { 13. const string szCodePhrase = "TheQuickBrownFoxJumpsOverTheLazyDog"; 14. 15. string szPsw = ""; 16. uchar pos; 17. 18. for (int c = 0; c < StringLen(szArg); c++) 19. { 20. pos = (uchar)(StringGetCharacter(szArg, c) % StringLen(szCodePhrase)); 21. szPsw = StringFormat("%s%c", szPsw, StringGetCharacter(szCodePhrase, pos)); 22. } 23. 24. return szPsw; 25. } 26. //+------------------------------------------------------------------+
コード05
この時点で、コード05とコード04を比較すると、何も変わっていない。これではうまくいかない。結果は前とほとんど同じになるだろう、と感じるかもしれません。しかし、それは本当でしょうか。調べてみましょう。実際にコード05を実行してみると、出力結果は次のようになります。
図06
本当に、結果が大きく変わりました。まったく別物になっています。図05に示されたものとはまるで違って見えるでしょう。多くの人は、こうしたプログラムを書くには数学の天才であるか、何年もの経験を積んだ熟練の開発者でなければならないと思いがちです。しかし、ここで見てきた通り、基本的なプログラミングの知識に少しの創造力を加えるだけで、非常に印象的で、ときには驚くような結果を生み出すことができます。それでもこのパスワードがまだ単純すぎると感じるかもしれません。たしかに長さはありますが、より複雑さがほしいという場合もあります。ですが、それを改善するのはとても簡単です。覚えておいてください。コード04とコード05の違いは13行目だけであり、それ以外の部分は変更していません。そうなると、自然と、「13行目に記号などを追加してみたら、パスワードはもっと強くなるだろうか」という考えが浮かぶはずです。では、実際にそれも試してみましょう、親愛なる読者の皆さん。次に、13行目を更新したバージョンをご紹介します。
const string szCodePhrase = ")0The!1quick@2brown#3fox$4jumps%5over^6the&7lazy*8dog(9";
出力は次のようになります。
図07
このちょっとしたプロジェクト、楽しいと思いませんか。ここで使っているのはとても基本的なプログラミング技術にすぎませんが、それでも十分に面白いものが作れています。とはいえ、もう少し洗練させることもできます。ただし、そのためには少し異なるアプローチを取る必要があります。
今回は、前回の記事で触れたあるポイントをより深く理解していただくために、少し趣向を変えてみます。前回、CやC++にはstring型というものが存在しないという話をしました。その代わり、MQL5ではこの型が用意されていて、CやC++でのややこしい扱い方を避けられるようになっています。CやC++における文字列とは、実際には、終端を示す特殊な値を含む配列にすぎません。そして、MQL5でも同じようにその特殊な値が使われているため、実はライブラリの関数に頼らなくても、パスワード生成コードを少し工夫すれば、同様の処理を実現することが可能です。
ここから少し注意して見てほしいのですが、これから使う方法は、まさにCやC++の考え方に直結しています。だからこそ、MQL5は「中間的な言語」としての立ち位置にあると前回説明したわけです。今回はその導入として簡単に紹介するにとどめますが、このトピックについては次回の記事でもっと深く掘り下げていく予定です。
文字列は配列である
このセクションのタイトルが示しているとおり、実はプログラム内部では文字列は配列として扱われています。最初は少し混乱するかもしれませんが、このことについては次回の記事でさらに詳しく掘り下げていく予定です。今回は、その考え方だけを先にお伝えしておきます。というのも、このテーマに本格的に踏み込むと、話が一気に複雑になるからです。
このタイミングを利用して、前のセクションで示したコードを少し書き換え、文字列を配列として扱う形にしてみましょう。少し奇妙に思えるかもしれませんが、プログラミングの観点から見ると、このようなアプローチにはいくつかの明確な利点があります。
というわけで、先ほどのコード04は、以下のように書き換えることができます。
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. void OnStart(void) 05. { 06. const string sz_Secret_Phrase = "Um pequeno jabuti xereta viu dez cegonhas felizes"; 07. 08. Print("Result:\n", PassWord(sz_Secret_Phrase)); 09. } 10. //+------------------------------------------------------------------+ 11. string PassWord(const string szArg) 12. { 13. const string szCodePhrase = "The quick brown fox jumps over the lazy dog"; 14. 15. uchar psw[], 16. pos; 17. 18. ArrayResize(psw, StringLen(szArg)); 19. for (int c = 0; szArg[c]; c++) 20. { 21. pos = (uchar)(szArg[c] % StringLen(szCodePhrase)); 22. psw[c] = (uchar)szCodePhrase[pos]; 23. } 24. return CharArrayToString(psw); 25. } 26. //+------------------------------------------------------------------+
コード06
コード06を実行すると、その出力は図05に示したものとまったく同じになります。ただし、先ほど説明したように13行目を変更すると、結果が以前と同様であることに気づくはずです。とはいえ、コード06には明確な利点があります。というのも、ここでは文字列を直接扱うのではなく、配列として処理しているからです。このアプローチのメリットについては、次回の記事で詳しく説明する予定です。そこで、このようなモデリング手法をどう活用できるのかを掘り下げていきます。親愛なる読者の皆さん、信じられないかもしれませんが、このコードはまだ非常にシンプルです。きちんと学んでいる初心者であれば、特別な解説がなくても理解できるはずです。
いずれにせよ、このコードについては次の記事でしっかりと解説していきます。今ここでお見せしているのは、内容が一気に積み重なってしまわないようにするためです。見た目が単純で簡単だからといって、後回しにできると考えないでください。
最終的な考察
今回の記事は、個人的にもとても楽しい内容でした。ただの理論の応用ではなく、実際に使える目的を持った実用的なものを作り上げるという、より現実的な体験ができたと思います。確かに、途中で出てきた内容のいくつかは、最初は難しそうに感じたかもしれません。でも、それは決して諦める理由にはなりません。むしろ逆です。ここでお伝えしたかったのは、創造力と少しの工夫さえあれば、初心者のプログラマーでも、テキストデータを操作して、一般的には「上級者向け」と思われているようなことも十分に実現できるということです。
そして、これまでの記事で取り上げてきた基本的な知識だけを使って、このような内容が実現できたという点もポイントです。そうした知識が実際に使えることがわかれば、きっとより積極的に学習に取り組めるようになるはずです。今まで学んだことが、決して無駄ではなく、実践的で価値のあるものだということが伝わったなら、それだけでも十分です。添付ファイルをぜひご覧ください。次の記事では配列について説明します。
MetaQuotes Ltdによりポルトガル語から翻訳されました。
元の記事: https://www.mql5.com/pt/articles/15442





- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索