整数値や実数を文字列として出力する際、特定の形式で出力することで、可読性が増します。
可読性とは読みやすさのこと
例えば、出力する小数点以下の桁数を統一して出力することで、出力結果がバラバラになって見づらくなるのを改善することができます。
文字列の出力は、チャート上に情報を表示することのほか、取引結果のロギングやデバッグの際にも多用するので覚えておきましょう。
フォーマットを指定して文字列に変換するための関数
指定の書式に則った文字列に変換する関数は、MQL5ではStringFormat()とPrintFormat()の2つの関数が用意されています。
string StringFormat (
string format, // フォーマット文字列
... // 出力したい値
);
void PrintFormat (
string string_format, // フォーマット文字列
... // 出力したい値
);
戻り値がStringFormat()ではstring、PrintFormat()ではvoid(戻り値なし)からも分かるとおり、用途は異なります。
StringFormat() → 指定した値をフォーマットして文字列として返す。
PrintFormat() → 指定した値をフォーマットしてEAのログに出力。
出力結果を文字列として返すか、ログに出力するかの違いのみで、指定した値をフォーマット文字列に則って変換してくれる関数です。
フォーマット文字列の書式
フォーマット文字列とは
フォーマット文字列は、何桁の文字列にするかなどのルールを示す文字列です。
このフォーマット文字列に則った文字列を生成します。
フォーマット文字列は次のルールに従って指定する必要があります。( []で括られた部分は任意の項目 )
%[フラグ][幅][.精度][指定子]型
型
フォーマット文字列を理解するためには、まず初めに型を理解する必要があります。
型はどんな値を出力するか指定するものです。
型はフォーマット文字列の中で唯一必須の項目です。基本的には、整数値である%d、実数の%f、文字列の%sを覚えておけば必要最低限のことはできます。
型 | 出力するデータ型 | 出力フォーマット |
---|---|---|
c | int | 単一の文字。(short型)(Unicode) |
C | int | 単一の文字。(char型)(ANSI) |
d | int | 10進数整数値。(符号付き) |
i | int | 10進数整数値。(符号付き) |
o | int | 8進数整数値。(符号なし) |
u | int | 10進数整数値。(符号なし) |
x | int | 16進数整数値。(符号なし)(abcdef表記) |
X | int | 16進数整数値。(符号なし)(ABCDEF表記) |
e | double | 実数。(指数(e)表記) |
E | double | 実数。(指数(E)表記) |
f | double | 実数。 |
g | double | 実数。(eまたはfのうち、コンパクトに表示されるフォーマットで出力) |
G | double | 実数。(Eまたはfのうち、コンパクトに表示されるフォーマットで出力) |
a | double | 16進実数。([−]0xh.hhhh p±dd形式)(abcdef表記) |
A | double | 16進実数。([−]0xh.hhhh P±dd形式)(abcdef表記) |
s | string | 文字列出力。 |
- 単一の文字
-
単一の文字を出力するにはcもしくはCを使用します。
cにはUnicodeの文字コードを、CにはANSIの文字コードを指定できます。
int var1=12354; int var2=65; PrintFormat("var1: [%c]", var1); PrintFormat("var2: [%C]", var2);
%cや%Cの部分がパラメータとして指定した文字コードの文字に変換されます。
var1: [あ] var2: [A]
- 整数値
-
整数値は10進数、8進数、16進数いずれで表記するか、符号を付けるか付けないかで、d、i、o、u、x、Xの中から必要なものを選択します。
int var1=123; int var2=-456; PrintFormat("【%%d】 var1: [%d], var2: [%d]", var1, var2); PrintFormat("【%%i】 var1: [%i], var2: [%i]", var1, var2); PrintFormat("【%%o】 var1: [%o], var2: [%o]", var1, var2); // 負の値は表現できない PrintFormat("【%%u】 var1: [%u], var2: [%u]", var1, var2); // 負の値は表現できない PrintFormat("【%%x】 var1: [%x], var2: [%x]", var1, var2); // 負の値は表現できない PrintFormat("【%%X】 var1: [%X], var2: [%X]", var1, var2); // 負の値は表現できない
符号なしの型で負の値を表示しようとすると、想定外の値に変換されてしまうので注意しましょう。
【%d】 var1: [123], var2: [-456] 【%i】 var1: [123], var2: [-456] 【%o】 var1: [173], var2: [37777777070] 【%u】 var1: [123], var2: [4294966840] 【%x】 var1: [7b], var2: [fffffe38] 【%X】 var1: [7B], var2: [FFFFFE38]
- 実数(e or E)
-
実数を指数表記で出力するにはeもしくはEを使用します。
double var1=0.0000123; double var2=-0.0000456; PrintFormat("【%%e】 var1: [%e], var2: [%e]", var1, var2); PrintFormat("【%%E】 var1: [%E], var2: [%E]", var1, var2);
小数部が限りなく小さい値もコンパクトに表示できます。
【%e】 var1: [1.230000e-05], var2: [-4.560000e-05] 【%E】 var1: [1.230000E-05], var2: [-4.560000E-05]
- 実数(f)
-
実数を出力します。
double var1=0.0123; double var2=-0.0456; PrintFormat("【%%f】 var1: [%f], var2: [%f]", var1, var2); double var3=0.0000123; double var4=-0.0000456; PrintFormat("【%%f】 var3: [%f], var4: [%f]", var3, var4); // 小数点以下6桁までしか表示されない
EAやカスタムインジケーターで実数を使用する場合はこの表記がもっともわかりやすいと思います。
【%f】 var1: [0.012300], var2: [-0.045600] 【%f】 var3: [0.000012], var4: [-0.000046]
- 実数(g or G)
-
実数をfのような形で出力するか、必要に応じて指数表記(e or E)するかを自動で判断して、より短い文字列になる方で出力します。
double var1=0.0123; double var2=-0.0456; PrintFormat("【%%g】 var1: [%g], var2: [%g]", var1, var2); PrintFormat("【%%G】 var1: [%G], var2: [%G]", var1, var2); double var3=0.0000123; double var4=-0.0000456; PrintFormat("【%%g】 var3: [%g], var4: [%g]", var3, var4); PrintFormat("【%%G】 var3: [%G], var4: [%G]", var3, var4);
出力する書式はできる限り統一しておいた方が可読性があがるため、使う機会はあまりありません。
【%g】 var1: [0.0123], var2: [-0.0456] 【%G】 var1: [0.0123], var2: [-0.0456] 【%g】 var3: [1.23e-05], var4: [-4.56e-05] 【%G】 var3: [1.23E-05], var4: [-4.56E-05]
- 実数(a or A)
-
実数を16進数で出力します。
double var1=0.0123; double var2=-0.0456; PrintFormat("【%%a】 var1: [%a], var2: [%a]", var1, var2); PrintFormat("【%%A】 var1: [%A], var2: [%A]", var1, var2); double var3=0.0000123; double var4=-0.0000456; PrintFormat("【%%a】 var3: [%a], var4: [%a]", var3, var4); PrintFormat("【%%A】 var3: [%A], var4: [%A]", var3, var4);
為替取引で16進数を使用する機会は限りなくゼロに近いです。
【%a】 var1: [0x1.930be0ded288dp-7], var2: [-0x1.758e219652bd4p-5] 【%A】 var1: [0X1.930BE0DED288DP-7], var2: [-0X1.758E219652BD4P-5] 【%a】 var3: [0x1.9cb8320b15070p-17], var4: [-0x1.7e85411d00c1cp-15] 【%A】 var3: [0X1.9CB8320B15070P-17], var4: [-0X1.7E85411D00C1CP-15]
- 文字列
-
文字列を出力するにはsを使います。
string var1="abcdef"; PrintFormat("【%%s】 var1: [%s]", var1);
sはあくまでも小文字で、%Sなんて指定はできません。
【%s】 var1: [abcdef]
フラグ
数値の表現方法や、幅と組み合わせた桁の表現を指定します。
フラグ | 概要 | フラグを指定しない場合の動作 |
---|---|---|
– (minus) | 指定された幅の中で左寄せして表示する。 | 指定された幅の中で右寄せして表示する。 |
+ (plus) | 表示する値が正の値の場合+、負の値の場合-を表示する。 | 表示する値が負の値の場合-を表示する。(正の値なら何も表示しない) |
0 (zero) | 指定された幅分値の左側に0が表示される。 (精度が指定されている場合、0は無視される) | 0は表示されない。 |
(space) | 表示する値が正の値の場合、値の前にスペースが表示される | 値の前のスペースは表示されない。 |
# | 型にo、x、Xのいずれかが指定された場合、値の前に0、0x、0Xが表示される。 | 値の前には何も表示されない。 |
型にg、Gのいずれかが指定された場合、小数点以下の値が0の場合でも常に小数点で表示される。 | 小数点は0以外の少数部がある場合のみ表示される。 |
- – (minus) フラグ
-
出力結果を幅で指定した中で左詰めして表示します。
int var1=12; PrintFormat("パターン1: [%d]", var1); // 整数値を編集なしで出力 PrintFormat("パターン2: [%10d]", var1); // 整数値を10桁で出力 PrintFormat("パターン3: [%-10d]", var1); // 整数値を10桁で出力(-(minusフラグあり)
– (minus) フラグを指定しない場合のデフォルトの動作は右詰めです。
パターン1: [12] パターン2: [ 12] パターン3: [12 ]
- + (plus) フラグ
-
正の値の場合にも符号を表示する際に指定します。
int var1=12; int var2=-34; PrintFormat("var1 (+なし): [%d]", var1); // +符号を出力しない PrintFormat("var1 (+あり): [%+d]", var1); // +符号を出力する PrintFormat("var2 (+なし): [%d]", var2); // +符号を出力しない PrintFormat("var2 (+あり): [%+d]", var2); // +符号を出力する
負の値は必ず符号が表示されます。
var1 (+なし): [12] var1 (+あり): [+12] var2 (+なし): [-34] var2 (+あり): [-34]
- 0 (zero) フラグ
-
指定した幅になるように値の左側をゼロ埋め(0パディング)します。
int var1=12; int var2=-34; double var3=0.12; PrintFormat("var1: [%010d]", var1); // 正の値の0パディング(ゼロ埋め) PrintFormat("var2: [%010d]", var2); // 負の値の0パディング(ゼロ埋め) PrintFormat("var3: [%010f]", var3); // 小数値の0パディング(ゼロ埋め)
半角スペース埋めだと表示するプロポーショナルフォントなど、フォントによっては値を縦に並べた時、桁がズレて見えてしまうことがあります。(半角スペースの横幅が狭い)
ゼロで埋めれば改善できます。
var1: [0000000012] var2: [-000000034] var3: [000.120000]
- (space) フラグ
-
0 (zero) フラグと意味合いは一緒ですが、こちらはゼロでなく半角スペースて埋めてくれるもの。
int var1=12; int var2=-34; PrintFormat("var1 (spaceなし): [%d]", var1); // 正の値を出力 PrintFormat("var1 (spaceあり): [% d]", var1); // 正の値を出力(spaceフラグあり) PrintFormat("var2 (spaceなし): [%d]", var2); // 負の値を出力 PrintFormat("var2 (spaceあり): [% d]", var2); // 負の値を出力(spaceフラグあり)
ゼロ埋めでも同様ですが、指定した幅以上の場合には当然半角スペースは埋め込まれません。
var1 (spaceなし): [12] var1 (spaceあり): [ 12] var2 (spaceなし): [-34] var2 (spaceあり): [-34]
- # フラグ
-
#フラグは少し特殊。
あまり使う機会はないので覚えなくてもいいかもしれません。
int var1=12; PrintFormat("var1 (型o): [%#o]", var1); // 8進数表記 PrintFormat("var1 (型x): [%#x]", var1); // 16進数表記 PrintFormat("var1 (型X): [%#X]", var1); // 16進数表記 double var2=3; PrintFormat("var2 (型g) (#なし): [%g]", var2); PrintFormat("var2 (型g) (#あり): [%#g]", var2); PrintFormat("var2 (型G) (#なし): [%g]", var2); PrintFormat("var2 (型G) (#あり): [%#g]", var2);
値をログに出力するなどの場合で、少しでもログファイルの容量を節約するには、実数をコンパクトに出力されるgやGの利用も考えられます。
そんな時に利用を検討しても良いでしょう。
var1 (型o): [014] var1 (型x): [0xc] var1 (型X): [0XC] var2 (型g) (#なし): [3] var2 (型g) (#あり): [3.00000] var2 (型G) (#なし): [3] var2 (型G) (#あり): [3.00000]
幅
幅では値を出力する際の桁数を指定します。
桁数なので、1以上の正の値(10進数)を指定しましょう。
int var1=12;
int var2=345678;
PrintFormat("var1 (2桁の値を5桁で出力): [%5d]", var1);
PrintFormat("var2 (6桁の値を5桁で出力): [%5d]", var2);
出力する値が指定した幅よりも大きい場合は、指定した桁数は無視され、値が全桁出力されます。
var1 (2桁の値を5桁で出力): [ 12]
var2 (6桁の値を5桁で出力): [345678]
.精度
幅は最低限出力する桁を維持するものですが、こちらは整数と文字列に対して指定する場合と、実数に対して指定する場合で挙動が異なります。
- 整数値に対する精度指定
-
整数値に対して精度を指定した場合、幅の指定と似た動きをします。(足りない場合は埋めて、桁が超える場合はそのまま出力)
int var1=1; int var2=1234; PrintFormat("var1 (型d) (精度指定あり (.2)): [%.2d]", var1); PrintFormat("var2 (型d) (精度指定あり (.2)): [%.2d]", var2);
精度を指定した場合は、足りない桁はゼロで埋められるという違いがあります。
var1 (型d) (精度指定あり (.2)): [01] var2 (型d) (精度指定あり (.2)): [1234]
- 実数に対する精度指定
-
実数に対する精度の指定は、小数部に対して効いてきます。
実数に対して精度を指定することはよくあるので覚えておきましょう。
double var3=1.234; double var4=1.235; PrintFormat("var3 (型f) (精度指定なし) : [%f]", var3); PrintFormat("var3 (型f) (精度指定あり (.2)): [%.2f]", var3); PrintFormat("var4 (型f) (精度指定あり (.2)): [%.2f]", var4); PrintFormat("var3 (型g) (精度指定あり (.2)): [%.2g]", var3); PrintFormat("var4 (型G) (精度指定あり (.2)): [%.2G]", var4);
指定した精度以上の小数部が続く場合は、四捨五入されて桁が短縮されます。
var3 (型f) (精度指定なし) : [1.234000] var3 (型f) (精度指定あり (.2)): [1.23] var4 (型f) (精度指定あり (.2)): [1.24] var3 (型g) (精度指定あり (.2)): [1.2] var4 (型G) (精度指定あり (.2)): [1.2]
- 文字列に対する精度指定
-
文字列に対しても精度を指定できます。
string var5="abc"; string var6="abcdef"; PrintFormat("var5 (型s) (精度指定なし) : [%s]", var5); PrintFormat("var6 (型s) (精度指定なし) : [%s]", var6); PrintFormat("var5 (型s) (精度指定あり (.4)): [%.4s]", var5); PrintFormat("var6 (型s) (精度指定あり (.4)): [%.4s]", var6);
文字列の場合は精度以上の長さがある場合、後ろが切り捨てられます。
var5 (型s) (精度指定なし) : [abc] var6 (型s) (精度指定なし) : [abcdef] var5 (型s) (精度指定あり (.4)): [abc] var6 (型s) (精度指定あり (.4)): [abcd]
フォーマット指定子
C言語やC++とかだと、scanf()などのユーザーからの入力を伴う関数で、入力された値の取り扱いを示すものとして使用します。
MQLで使用する用途はほぼありません。
データサイズ | 指定子 | 型 |
---|---|---|
int | l | d、i、o、x または X |
uint | l | o、u、x または X |
long | ll | d、i、o、x または X |
short | h | d、i、o、x または X |
ushort | h | o、u、x または X |
int | I32 | d、i、o、x または X |
uint | I32 | o、u、x または X |
long | I64 | d、i、o、x または X |
ulong | I64 | o、u、x または X |
次の例ではすべて%d型として出力しようとしています。
int var1=1234567890;
PrintFormat("【%%ld】 : [%ld]", var1);
PrintFormat("【%%lld】 : [%lld]", var1);
PrintFormat("【%%hd】 : [%hd]", var1); // shortとして扱われる
PrintFormat("【%%I32d】: [%I32d]", var1);
PrintFormat("【%%I64d】: [%I64d]", var1);
しかしフォーマット指定子がh(単精度整数値)の場合は上位1バイト分切り捨てられます。
【%ld】 : [1234567890]
【%lld】 : [1234567890]
【%hd】 : [722]
【%I32d】: [1234567890]
【%I64d】: [1234567890]
フォーマット文字列のサンプル
これまで説明した各種フォーマット文字列を組み合わせて、出力する文字列を組み立てていきます。
最後に組み合わせのかんたんなサンプルを挙げます。
桁数と小数点以下の精度を揃えて表示
幅と精度を指定して、値を縦に並べた時に見やすくします。
double var1=0.123;
double var2=45.678901;
double var3=23;
PrintFormat("var1: [%12.8f]", var1);
PrintFormat("var2: [%12.8f]", var2);
PrintFormat("var3: [%12.8f]", var3);
整数部は半角スペースが、小数部はゼロが足りない分埋め込まれて桁を揃えて表示することができます。
var1: [ 0.12300000]
var2: [ 45.67890100]
var3: [ 23.00000000]
文字列の長さを揃えて表示
– (minus)フラグと幅を指定して、文字列の長さを揃えます。
string var1="hoge";
string var2="hogehoge";
string var3="";
PrintFormat("var1: [%-10s]", var1);
PrintFormat("var2: [%-10s]", var2);
PrintFormat("var3: [%-10s]", var3);
左詰めにして、足りない文字数分スペースを埋め込みます。
var1: [hoge ]
var2: [hogehoge ]
var3: [ ]
まとめ
MQL5で使用できる文字列フォーマットについて説明しました。
通常EAやカスタムインジケーターを作成する際には直接的に使用することはありませんが、覚えておくと動作確認の際に有効です。
必要な書式だけでもしっかり覚えておきましょう。