文字列変換 string.format – FlyWithLua

2023年7月31日

数値を扱う時X-Plaenのdatarefではそのまま使えない場合が出てくる。

数値の桁数を揃える

これはどれにも有効だが%の後に0を付けると良い。

a =123
Test = string.format(“%04d”, a) — Test は 0123と表示される

%05dとすれば:5桁表示で左を0で埋める

値を2つ表示

a =123
b =654
string.format(“%d %d”, a, b) –123 654と表示される

8桁表示で「-」で左寄せ、「-」無しで右寄せ

a =123
string.format(“%-08d”, a) –0000123と左寄せで表示される
string.format(“%08d”, a) –0000123と右寄せで表示される

不動小数点で桁数と小数点以下の桁をコントロール

%の後の数値は「.」も入れた全ての数、以下ではc=6桁になるが0を1つ増やしたいので%7としている。「.」は小数点以下の桁数になるのだが総数が7なので下に0が増える。このやりかたでは123の前には0は一切増やすことはできない。この下にその方法を記述している。

c =123.45
string.format(“%7.3f”, c) –123.450と表示される

以上に対して「%8.3f」とすると頭にスペースが入り、その分右に数値が移動する。一見すると違いが分からない。

0を入れて全ての桁数を表示するには

以下のように頭に0を追加してやると解決する。これで全ての桁数で表示されるようになる。この0を外すとスペースが入ることに成る。

c =123.45
string.format(“%08.3f”, c) –0123.450と表示される

「トランスポンダ」の例

例えば:4桁で3桁しか表示されなくて、どうしても4桁にしたいという場合。
234を0234としたい場合、下の数値は3桁だかトランスポンでは0234と表示されているので、実際の表示も0234としたい場合など

以下の方法で0234となる。4桁の数字の場合はそのまま表示されるので便利である。

dataref("SQUAWK", "sim/cockpit/radios/transponder_code", "writable")
function Text_draw()
    SQUAWK_data = string.format("%04d", SQUAWK) --hogeの値が%d(整数)に入る
    draw_string( 100, 100, SQUAWK_data, 0, 1, 0)
end
do_every_draw("Text_draw()")

この関数は文字列の書式を指定して画面に表示する。書式指定子一覧は以下の通り。
この記号とstring.formatを使えば、以下のような書式で変換して出力できるようになる。

  • %d:整数の10進法として出力。整数表現にできない値はエラーになる。
  • %i:整数の10進法として出力。整数表現にできない値はエラーになる。
  • %u:符号なし整数の10進法として出力。
  • %o:整数の8進法として出力。%x:整数の16進法として出力。
  • %f:小数点表示、小数点以下の桁数はデフォルトで6。
  • %c:1文字出力。整数表現が可能なnumber型を渡すとASCIIコードに対応した文字列が1文字だけ出力される。2文字以上は不可。
  • %%:%を出力。
  • %s:文字列出力。値(number、boolean、nilなど)を文字列として出力する。
    nilの変数なら「NIL」と表示されたり、「true and false」なら「FALSE」と表示されたりする。
  • %q:文字列出力。%sとほぼ同じ。描画上でも文字列にダブルクォーテーションが表示されるなどの違いがある。

以下はフォーマット指定子と併せて使うフラグ指定子の一覧。数の表示に関する細かい指定ができる。

  • -:左詰め。デフォルトでは右詰めとなっている。桁数指定の前に-(マイナス)を付けると左詰めにできる。
  • +:符号表示。デフォルトでは右詰めとなっている。桁数指定の前に-(マイナス)を付けると左詰めにできる。
  • 0:ゼロファイル。フィールド幅に合わせてゼロ埋めされる。左詰めとの併用はできず、両方書くとゼロフィルは無視される。

実際の変換方法(整数、文字列、小数点以下の桁数)

X-Planeの中に直接、以下のように表示する。一緒に文字も入れることができる。

function Text_draw()
  	hoge = 10
    polo = string.format("この値は: %d", hoge)	--hogeの値が%d(整数)に入る
    draw_string( 100, 100, polo, 0, 1, 0)
end
do_every_draw("Text_draw()")

結果:この値は:10(整数の10進法として出力されたことになる)

一度に複数の変数を入れることもできる。

function Text_draw()
	hoge1 = 10
	hoge2 = 15
	hoge3 = 30
	polo = string.format("%d %s %3.1f", hoge1, hoge2, hoge3) 
	--%3.1fは小数点の前と後の桁を指示している。前の数字が動作していない。	--hogeの値が%d(整数)に入る
	draw_string( 100, 100, polo, 0, 1, 0)
end
do_every_draw("Text_draw()")

結果:この値は:10 15 30.0とそれぞれの値を取り出して入れている。

但し%3.1fの場合、小数点以下の1という設定はうまく動作するが前の3とう数値は動作しない。

この原因は「%3.1f」に入る数値が不動小数点でないからである。hode3 = 30となっているのを、30.1というように不動小数点にすると解決する。「%3.1f」の3は小数点まで入れた全ての桁数で30.1なら4桁になるので「%4.1f」とすれば30.1と表示される。030.1と表示したいなら「%5.1f」となる。

小数点以下の桁数を指定する方法(2)

同じく小数点以下をプログラムから制御。後ろにある「f」も忘れずに。

function Text_draw()
	hoge1 = 100
	width = 3
	polo = string.format("%." .. width .. "f になります。", hoge1)
	draw_string(100, 100, polo, 0, 1, 0)

	width = 2
	polo = string.format("%." .. width .. "f です。", hoge1)
	draw_string(100, 80, polo, 0, 1, 0)
end
do_every_draw("Text_draw()")

正負の符号が入る場合

符号の付いた数値の場合、不安定になる場合がある。こういう時にには修飾で強制的に符号をつけるようにすれば正負で符号の有無が変化しなくなりレイアウトが維持されます。

function Text_draw()
	hoge1 = -10
	hoge2 = 15
	hoge3 = -30
	polo = string.format("%-d:%+d:%-d", hoge1, hoge2, hoge3) 
	--%3.1fは小数点の前と後の桁を指示している。前の数字が動作していない。	--hogeの値が%d(整数)に入る
	draw_string( 100, 100, polo, 0, 1, 0)
end
do_every_draw("Text_draw()")

+はそのままでも+と表示されるが、-は初期設定で-と入れる必要がある。つまり上のような初期設定で-がある場合、%dでそのまま変換すると不安定になるということらしい、そのために符号を強制的につけてやる。

パティングを入れる

0でなくスペースによるパディングをすることもできます。0の代わりに半角スペースを入れる?。
残念ながら、これは機能しない。少しは移動するが桁がピッタリ合うことが無い。

function Text_draw()
	hoge1 = 10
	hoge2 = 15
	hoge3 = 30
 	hoge4 = 1
	hoge5 = 5
	hoge6 = 3
	polo = string.format("% 2d:% 2d:% 2d", hoge1, hoge2, hoge3) 
  	malon = string.format("% 2d:% 2d:% 2d", hoge1, hoge2, hoge3)
	--%3.1fは小数点の前と後の桁を指示している。前の数字が動作していない。	--hogeの値が%d(整数)に入る
	draw_string( 100, 100, polo, 0, 1, 0)
  	draw_string( 100, 100, malon, 0, 1, 0)
end
do_every_draw("Text_draw()")

テーブルのリストを表示する

表示するテーブルが多い場合は指定文が長くなって煩雑になりがちです。

function Text_draw()
	list = {1,2,4,8,16,32,64}
	polo = string.format("%d,%d,%d,%d,%d,%d,%d", list[1], list[2], list[3], list[4], list[5], list[6], list[7])
	draw_string(100, 100, polo, 0, 1, 0)
end

do_every_draw("Text_draw()")

上と同じ結果になる、簡略できる「table.unpack()」関数を使う方法がLuaではあったがエラーになる。

■Step1.取り出す個数を考える。

取り出す要素は三つとします。そのそれぞれが()に相当するので、string.matchに対して与えるパターンは「()()()」でできることがわかります。

■Step2.区切りを表現をする。

今回の文字列は「,」で二箇所区切ってあります。区切り文字「,」は特別な文字なので、「%,」とかけます。実際には「()%,()%,()」と書くことができます。

■Step3.取り出す要素を表現する。

最後に取り出したい要素がまだ()のままになっているので、()の中身をきちんとパターンで表現して、string.match()に与えるパターンを完成させます。
住所や名前に特に文字に縛りはないため、任意の文字が繰り返されると考えます。任意の文字は「.」で、それが繰り返されるので「-」か「+」が続きます。
「+」にすると出来るだけ最長でマッチさせようとし、「-」は最短にしようとします。
名前や住所の要素を取り出すために(.+)としてしまうと行全体の範囲をマッチさせようとしてしまいます。名前と住所は次の「,」までで止めたいので(.-)とします。
逆に電話番号は最短マッチをさせてしまうと1文字目だけで終了してしまうため、(.+)とし、最長マッチさせます。

(.-)%,(.-)%,(.+)