書式の変換
今回は指定値を書式付き文字列に変換することを行います。
書式とはフォーマット、決められた形式のことで、主に数値を指定書式に変換するのです。
例えば数値の桁数を統一したり、数値の前後に「\」や「%」等のある文字を付加したりするのに使います。
まぁ、数値の前後に特定の文字を付加することくらいなら今から説明する命令を使わずとも出来ますが。

 1
 2
 3
	var = "98"
	var += "%"
	mes var
1行目を文字数値にしてますが、意味はお分かりですね? 「数値+文字列」は「数値」になる為、数値で行って場合、後の'%'が付きません。 コレは4章で既に説明していますよね。覚えていますか? 同様にして先頭に'\'を付けてみてください。
 1
 2
 3
	var = "98"
	var = "\" + var
	mes var
もし、上のように書くと「\98」ではなく「\" + var」と表示されます。 意図した通りに表示されませんでしたね。 もっと前の段階で説明すべきことですが、ココで説明しておかなければならないことが一点。 \」は予算演算子としても使われていますが、文字列内に書くとプログラム上で特別な意味を持ちます。 この特殊なコードをエスケープコード、コードに対応する制御文字をエスケープ文字、 そしてコードと文字を合わせた一対のものをエスケープシーケンス(以下、シーケンス)と呼びます。 他言語を知っている方には馴染み深いことですが、文字列内で改行したりタブを入れたりします。 言語によってはビープ音を鳴らしたり、文字列終端文字を意味したりしますが、HSPでは使用できません。 HSPで意味のあるシーケンスは下記に紹介するものになります。 文字列内で改行させる時に使うシーケンスは「\n」です。 画面へのテキスト出力命令を実行する度に自動改行されていましたが、 1つのテキスト内で改行させるにはこのシーケンスを使うのです。
1
	mes "こんな風に\n改行することができるんですね。\n\n1回につき1つの改行となります。"
このようにだけ書いておくと、
1つのテキスト内で改行させるにはこの方法しかないように誤解されてしまいますので
このようにすることでも出来るというのを紹介しておきます。
 1
 2
 3
 4
 5
 6
	mes {"
		エスケープシーケンスを使わずとも、
		このような書き方にすることで、
		スクリプト上で実際に改行した通り、
		出力でも改行させられます。
	"}
また、誤解を招く内容がもう一点ありますので、併せて紹介しておきます。 「\n」は厳密に言うと「改行」ではなく、「復帰改行」になるのです。「改行」は「\r」になります。 HSP上では「\r」と「\n」のどちらで書いても同じ様に改行されます。 文字コードを調べる際に違いが出てきますが、現段階ではほぼ同じものとして、 改行する時は「\r」ではなく、「\n」を使うと覚えておきましょう。 HSP3から使えるようになったタブを入れる場合には「\t」を使います。 タブと言ってどんなものか想像はできていますか? ココではテキストの表示位置を揃える為の一定間隔の空白を指し、 HSPではタブの間隔が8文字分となっています。
1
	mes "12345678901234567890\n1\t23\t45"
\」はWindowsのフォルダ区切り文字として使われるので使用頻度は高いのですが、 「\」だけを書くと「これから特殊な意味に使われる」とHSPに認識されますので、 今回のように「\」を実際に表示させたい場合でも出力文字ではなく、制御文字として出力されません。 当講座でも今後にフォルダ区切りを書く機会があるかと思いますが、 「\」自体を表示する場合は「\\」と書きますので、この機会に覚えておいてください。
1
	mes "c:\\program files\\hspbc\\" // 「c:\program files\hspbc\」を表す
スクリプトに直接文字列を記述する時は「mes "test"」のように文字列の両端を「"」で囲みますから、 文字列内に「"」自体も書けない事になります。 「"」をスクリプト上で書く場合は、「\"」と書きましょう。 また「'」にもシーケンスがあり「\'」で1つの「'」となります。 HSPではあまり影響を受けませんが、「'」を表示させたい時は 下記のサンプルスクリプトのように「'」か「\'」のどちらでも好きなほうを使ってください。
 1
 2
	mes "文字列内で「\"」を書く時はスクリプトに「\\\"」と書く。"
	mes "文字列内で「'」を書く時はスクリプトに「'」または「\\'」と書く。"
これらは基本ですので、しっかり身に付けておきましょう。 さて、書式付文字列に話を戻しまして使い方の説明に移りますが、 HSP3.2で若干の変更があったので、HSP3.2以降を使用している場合の書式はコチラをご覧ください。
書式付文字列 = strf(フォーマット, 対象値)
書式付文字列書式化された文字列。
フォーマットC言語のsprintf構文準拠の書式指定を行う。
対象値変換対象の変数または定数。
使用する命令はstrf関数となります。 対象値で指定した値をフォーマットの形式に整形し、書式付文字列として返します。 「フォーマットはC言語のsprintf構文です」と言われてもわかりにくいので補足しておきますと、 C言語にもHSPで言うstrf関数があり、書式付文字列に変換する場合は、このsprintf構文を使用します。 ヘルプに必要最低分だけが記述されていますが、分かりにくい方がいるかと思います。 これから説明を書きますのでご参考にどうぞ。 今回のstrf関数のフォーマット部は文字列で指定すると書きましたが、 文字列内のこの部分が対象値を表しているんだよ、と言った書き方で指定します。 フォーマットの指定は、1023バイトまでの文字列を指定することができ、 フォーマット文字列自体を変数で別途指定して、入れ子や複数書式を合わせたりもできます。 書き方は与える対象値によって指定の仕方が変わりますので整数値の場合から紹介します。 整数は10進法を意味するDecimalから取って「d」が対象値を表すワードとなり、 エスケープシーケンスと同じ様に、「%」を頭につけて、「%d」と指定することで、 この文字列部分に対象値が入り、その前後の文字列が書式を意味するようになります。
 1
 2
 3
	mes strf("書式付「%d」", 12345)
	mes strf("\\%d", 98)
	mes strf("\\%d%%", 98)
上記を実行すると「書式付「12345」」や「\98」や「98%」('%'の表示は%%と書く)と表示されますが、 この程度の為にわさわざstrf関数を使うことを覚えておくのは無駄な気がします。 「%d」部分をちょっと整形するパラメータを以下のように組み合わせて使用すると利用価値が上がります。
記述例表示結果
mes strf("[%4d]", 123)[ 123]
mes strf("[%4d]", 12)[  12]
mes strf("[%4d]", 12345)[12345]
mes strf("[%4d]", -12)[ -12]
mes strf("[%5d]", "7")[7]
'%'と'd'の間に整数値を指定すると、指定桁数になるよう空白が自動補完されます。 つまり、例えば「%3d」と記述すると、 対象値が3桁未満の場合に、数値の左側にスペースが補完され桁数を3桁に合わせることができます。 もし、逆に指定桁数よりも対象値の桁数が大きい場合は、そのまま増えることも減ることもありません。 数値でも文字数値の場合は、桁数指定を行っても、数値ではないとみなされて書式の変換は行われません。 これは通常の文字でも当てはまり、エラーにはならず何の処理も行われないという結果になります。 スペースではなく、前ゼロを補完するには下記の様に桁数の前部に'0'を付け「%05d」のように指定します。
記述例表示結果
mes strf("[%04d]", 123)[0123]
mes strf("[%04d]", 12)[0012]
mes strf("[%04d]", 12345)[12345]
mes strf("[%04d]", -12)[-012]
上記のようにマイナス符号も一文字分とみなされます。 整数値は以上で終了し、実数値(小数点以下付)の書式について紹介します。 実数値のパラメータ表記は浮動小数を意味するFloatingPointから取って「%f」を指定します。 整数値と違い、実数値は整数値桁数・小数点以下桁数(精度)の二種類を指定します。 デフォルトでは小数点以下が6桁表示されてしまう為、大半の場合が不要になるかと思います。 具体的には右記「%2.2f」のような指定を行います。 値が「3.5」である場合、上記の指定を行うと、「 3.50」となります。 スペースではなく前ゼロを付ける場合は、整数値同様に桁数値の前に0を付けます。 尚、小数点以下は指定なしでもゼロ表記となります。というか、逆にスペースにすることはできません。 それと、ゼロが付くのは、前ではなく必ず後ろです。 小数点以下(小数点を含む)を全く表示しないようにするには、「%X.0f」と指定しましょう。
記述例表示結果
mes strf("[%3.8f]", 50.75)[50.75000000]
mes strf("[%02.1f]", 9.99)[10.0]
mes strf("[%9.0f]", 12345.6789)[  12346]
mes strf("[%08.02f",-12.3)[-0012.30]
上記結果から分かるように、整数側に各桁数は整数値の桁数ではなく、 小数点や小数点以下、その他マイナス符号までも含んだ全体の文字数であることが分かります。 また、実際の対象値の小数点以下桁数が指定書式桁数よりも大きかった場合、 指定桁数以上の部分が四捨五入されていることが分かります。 続いて16進値の説明を行います。 16進数とは何ってレベルの方は、別ページのトリビアや、その他16進数の説明サイトをご覧ください。 簡単に申しますと、0〜9の他にA〜Fの計16種を使って1桁を表す表現方法のこと。 10進数の10がAを、15がF、16なら桁上がりして10となる。 コンピュータ内部で扱われる「0」「1」のみの2進数4桁で16進数となって親和性が高い、というもの。 16進数のパラメータ表記は16進数HexaDecimalから取って「x」を用います。
記述例表示結果
mes strf("[%2x]", 14)[ e]
mes strf("[%03X]", 90)[05A]
mes strf("[%4x]", -111)[ffffff91]
mes strf("[%05x]","6C")[6C]
上記のように「」だと小文字で、「」だと大文字でアルファベットが表示されます。 また、10進数と異なるのがマイナス値の場合に、マイナス記号付きの表現ではなく、 −1FFFFFFFF(又はffffff)とした負数(補数)となります。 16進数等の数値以外のアルファベットを書こうとしてもダブルクォテーションがあると処理されないのです。 というかstrf関数で基数変換できるのは10進数のみです。 X進数からY進数はおろか、X進数から10進数への変換は行えません。 先にヘルプに書いてある他のものを紹介します。 ヘルプに書かれてあり、残りの使用出来るものは文字を表すCharの「%c」です。 文字という名の通り、指定数値を文字(ASCII)コードとみなして変換します。 少々古い記事になりますが、半角文字の主要コードについてはコチラをご覧ください。 例えば64を指定するとに、97を指定するとになるといった具合です。
記述例表示結果
mes strf("[%c]", 100)[ e]
mes strf("[%2c]", 300)[,]
mes strf("[%3c]", 0)[
ASCIIコードというのは1バイトですので、0〜255までが指定可能範囲となります。 もし範囲外のものを指定してもエラーにはならず、256を1周期とした値になった後にコード化され、 256ならを、上記の300なら44を指定したことと同意義となります。 尚、(もしくは256の倍数)を指定すると、対象値以下の書式もろとも表示されなくなってしまいます。 ASCIIコードの0はNULL文字(HSPで文字列終端を意味する)となる為に、 HSPは文字列終端まで表示したと認識して、その文字が表示されないだけでなく後の文字も表示しません。 NULLについては10章でチラッと触れましたが、今章でも詳しくは紹介しません。 今はただ終了文字コードとだけ書いておきます。 詳細な説明については今しばらくお待ちください。 さて、ヘルプには今まで説明した内容(%Xは書いてなかった…)をごく簡単にしか書いていません。 sprintf構文には、10進数、16進数の他にHSP(sprintf構文)で使えるものとして8進数があります。 対象ワードは8進数を意味するOctalから取って「%o」になります。
記述例表示結果
mes strf("[%o]", 4)[4]
mes strf("[%o]", 8)[10]
mes strf("[%4o]", 12)[  14]
mes strf("[%03o]", 16)[020]
言語によっては2進数(Binaryから取って「%b」)というのもありますが、 C言語sprintf構文にはない為、HSPでも同様に使用することができないようです。 尚、strf関数で変換はできませんが、スクリプト上に2進数表記を行うことは可能です。 記述できるだけで表示されるのは全て10進数になりますけどね。
 1
 2
 3
 4
 5
	mes  %1100 // 2進数表記1
	mes 0b1101 // 2進数表記2
	mes  $2D   // 16進数表記1
	mes 0x2E   // 16進数表記2
	mes strf("%x", $9ABCD) // 記述も表示も16進数にしてみる
パッと見た目が8進数は10進数と変わらない為、違いが分かりにくいですね。 こういう時に使える#というフラグがあります。 コレは表示する数値が何進数であるかをプレフィックスとして付加するものです。
記述例表示結果
mes strf("[%#o]", 20)[024]
mes strf("[%#d]", 20)[20]
mes strf("[%#x]", 20)[0x14]
mes strf("[%#X]", 20)[0X14]
上記結果の通り、8進数には(オーではなくゼロ)、10進数にはプレフィックスなし。 16進数小文字には0x、大文字には0Xがそれぞれ付けられます。 また、この他にも%eもしくは%Eという浮動小数を指数表現で表すものがあります。 指数Exponentialを意味するもので、Excel等で数値を表示しきれない時に見かけるかと思います。
記述例表示結果
mes strf("[%e]", 0.0000000003)[3.000000e-010]
mes strf("[%E]", 10000.0)[1.000000E+004]
mes strf("[%2e]", 999999.9)[9.999999e+005]
mes strf("[%03E]", 0.00000005)[5.000000E-008]
上記結果を見ていただければお分かりいただけるかもしれませんが、 指数表現は[整数1桁].[小数(仮数)6桁][指数表記(E)]±(符号)[べき乗(指数)]の形式で表します。 0.0000000003だと、指定した3が先頭(整数値)に置かれて、他の数値は全て小数6桁内に丸められます。 ココでは3以外が全て0である為、小数6桁共が0となります。 次の符号は、表現後の形はもとの数値に比べて大きいのか小さいのかを表してます。 今回は極小値を整数に来るまで大きくした為、元の形は小さかったことを意味するマイナス符号が付きます。 そして、最後の指数部に何乗したものかを表します。 今回10乗したものなので10となり、3.000000e-010と表現されるわけですね。 フラグには、マイナス符号のようにプラス値の場合にも常に符号が付く表記があります。
記述例表示結果
mes strf("[%+o]", 30)[36]
mes strf("[%+d]", 30)[+30]
mes strf("[%+#d]", 30)[+30]
mes strf("[%#+d]", 30)[+30]
mes strf("[%+d]", -30)[-30]
結果から分かる通り、プラス符号が付くのは10進数だけである事が分かります。 また、フラグを同時使用した場合、どちらが先に来ても処理されることが分かります。 マイナスの場合はプラス符号が付かず、マイナスに換わっていることも見られますね。 通常の整数値は、32ビット(4バイト)値やInteger型(32bitWindows上に限る)と呼ばれ、 −2,147,983,648〜2,147,983,647(計4,294,967,296種)を表現できます。 何故、扱える数値の範囲が表現できる種類の半分かというと、 負数(マイナス値)を使用できるようにする為、マイナス符号用に1ビット犠牲にしているんですね。 つまり、2の32乗扱えるものを1ビットだけ値として使えなくしてマイナスを表現しています。 このコンピュータの基礎的な考えについては、これ以上説明しません。 他サイト等でお勉強してきてください。 …で、マイナス符号用の1ビットを値として使えるようにすることで、 最大4,294,967,295(0を含む為)まで使えるようになるわけです。但し最低値は0ですけどね。 このプラス値だけのことをUnsignedInteger(符号なし数値)と呼び、 strf関数の対象ワードには「%u」と記述します。
記述例表示結果
mes strf("[%d]", 3000000000)[-1294967296]
mes strf("[%u]", 3000000000)[3000000000]
mes strf("[%u]", -1)[4294967295]
mes strf("[%+u]", 1)[1]
mes strf("[%u]", 4294967296)[0]
通常の符号あり10進数では、範囲外の数値を記述しても先頭1ビット目がマイナスである為、 符号なしでは表示できる値でもマイナスで表示されてしまっています。 逆に符号なしでマイナス値やプラス値でも範囲外の値を使おうとしても、 値が一回りして範囲内の値が表示されています。 10進数なら+フラグが使えると書きましたが、厳密には符号あり10進数「%d」だけです。 ヘルプに補足されていますが、sprintf構文で使えるがHSPでは使えないものがあります。 文字列指定を行える「%s」です。 また、C言語のsprintf構文と同じ様に、と言えども、使い方は違います。 変換された値を入れる変数を用意しなくてよいものの、 1回strf関数に複数の対象値を記述することはできません。 注意することはコレ位で、後は同じ様に使えますよってことです。 64ビット(8バイト)幅を扱えるdouble型の小数点以下の無駄桁消去用には使えるものと思います。 strf関数がなくてもさほど影響はないかもしれませんが、 使えないよりかは使えた方がいいに決まってます。(その分ランタイムサイズが大きくなるわけですが) 使える以上は、どんどん活用してください。 HSP3.2でも上記の使い方が出来ますが、 HSP3.2でフォーマットパラメータ内に対象値を複数同時に指定することが出来るようになりましたので、 この変更に伴い、strf関数の書式が次のように変更されました。
書式付文字列 = strf(フォーマット, 対象値…)
書式付文字列書式化された文字列。
フォーマットC言語のsprintf構文準拠の書式指定を行う。
対象値…変換対象の変数または定数。書式ワードの数だけ対象値を指定する。
以上の様に書いても変更箇所が「対象値」から「対象値…」に変更されただけなのでわかりにくいですね。 HSP3.1までは、
 1
 2
 3
 4
	mes strf("%5d", 123)
	mes strf("%5d",  45)
	mes strf("%5d", 678)
	mes strf("%5d",  90)
と、書式付にしたいものが複数個ある場合は、strf関数を複数使用する必要ありましたが、 HSP3.2からは、
 1
	mes strf("%5d\n%5d\n%5d\n%5d",123, 45, 678, 90)
と、同時に記述することが出来るようになったというわけです。 小さな変更ですが、大量に書式付文字列が必要であった場合には嬉しい改善点ですよね。 この「対象値…」パラメータは、フォーマットパラメータの書式ワードの個数と一緒にしてください。 フォーマット内に2個の書式ワードがあるなら、指定する対象値も2つ。 対象値が4つあるなら、フォーマット内に指定する書式ワードも4つ…という具合です。