5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

VCIAdvent Calendar 2022

Day 5

VCI luaスクリプトでの文字列の連結 deepdive

Posted at

フォーマット指定子詳解

この記事では、バーチャルキャストのvciluaスクリプトにおける文字列を扱うテクニックのうち、
VCI luaスクリプトでの文字列の連結 その1
VCI luaスクリプトでの文字列の連結 その2
で紹介しきれなかった細かいテクニックをご紹介いたします。

エスケープ文字

luaの文字列では、C言語などの文字列と同様にエスケープ文字を使うことができます。これは、TextMeshProでの文字列表示にもきちんと反映されますので、brタグなしでもエスケープ文字で改行することが可能です。エスケープ文字は""から始まる主に2文字の文字列です。使うものを以下に紹介します

エスケープ文字 役割
\n 改行
\t タブ
\ " \ "の文字そのもの
\" 二重引用符そのもの(文字列中で"をつかうために使う)
\' 引用符そのもの(文字列中で'をつかうために使う)
\r キャリッジリターン(行頭に戻る)
\0 null文字

\nはリッチテキストのオプションをオンにしていなくても使えます。あとはほとんど特殊文字をそのまま表示するために使います。

フォーマット指定子の修飾

%dや%sなどのフォーマット指定子(%何々で変数の表示場所を指定する書き方)は前述のようにいくつか種類がありますが、さらに表示の仕方を細かく指定することができます。これをフォーマット指定子の修飾とここでは読んでいますが、よく使うものをいくつかここでご紹介いたします。

桁数指定

特に数字などで顕著ですが、必要な桁数を指定したくなることがあります。何と成しに小数を表示すると、

デフォルトの桁数
print(string.format("視力は%fです",1.0))
出力
視力は1.000000です。

これはちょっとくどいですね。合計2桁で十分ですよね。こういう時は桁数を指定します。
桁数の指定の際には"%"と"f"との間に指定する桁数を数字で入れます。

全体の桁数の指定
print(string.format("視力は%2fです",1.0))
出力
視力は1.0です。

いい感じになりましたね。この数字は全体の桁数を指定してくれます。

ふつうの日本人だとこれでよさそうですが、このままだと視力10とかのこの目のいいマオリ族の人が来てしまうとちょっと事情が変わってきます。

桁数の大きい数字が入ってしまう際
print(string.format("視力は%2fです",10.0))
出力
視力は10です。

小数点以下の桁がなくなってしまいます。全体の桁数が変わっても小数点以下の桁数を担保したいことがありますよね。こういう時は以下のようにします。小数点以下の桁数の指定の際には"%"と"f"との間に"."を入れてそのあとに指定する桁数を数字で入れます。先ほどの全体の桁数の指定と複合可能です。

小数点以下の桁数の指定
print(string.format("視力は%2.1fです",10.0))
出力
視力は10.0です。

0パディング

等幅フォントと同じように、レイアウトを崩したくないがために数字の位置を固定したいことがあると思います。例えばx:y:zとx2:y2:z2の比較を表示する表を作っている際に、愚直に表示すると下記のようになります

パディングしないコード
print(string.format("%d:%d:%d",x,y,z))
print(string.format("%d:%d:%d",x2,y2,z2))
パディングしないパターン
10:20:20
5:3:40

これだと10未満の数字が混ざってしまうと桁数がバラバラになるため、せっかく表にしても比較するべき数が一見わかりにくい状態になってしまいます。
こういう時にもフォーマット指定子の修飾を使います。

0パディングするコード
print(string.format("%02d:%02d:%02d",x,y,z))
print(string.format("%02d:%02d:%02d",x2,y2,z2))
0パディングするパターン
10:20:20
05:03:40

符号

先ほどは値が全部正でしたが、符号が変わることもあります。こういう正負が混ざる時にもレイアウトが崩れる恐れがあります。

符号を指定しないコード
print(string.format("%d:%d:%d",x,y,z))
print(string.format("%d:%d:%d",x2,y2,z2))
符号を指定しないパターン
-10:20:-20
50:30:40

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

符号を指定するコード
print(string.format("%+d:%+d:%+d",x,y,z))
print(string.format("%+d:%+d:%+d",x2,y2,z2))
符号を指定するパターン
-10:+20:-20
+50:+30:+40

パディング

ちなみに、0でなくスペースによるパディングをすることもできます。0の代わりに半角スペースを入れるだけです。

スペースパディングするコード
print(string.format("% 2d:% 2d:% 2d",x,y,z))
print(string.format("% 2d:% 2d:% 2d",x2,y2,z2))
スペースパディングするパターン
10:20:20
 5: 3:40

修飾をパラメトリックに行う

上記説明では、桁数などは決め打ちでハードコードしていましたが、プログラムから制御したりすることもできます。やり方は簡単で、以下のようになります。

桁数を可変にする
local width = 3
local str = string.format("%."..width.."fドルいただきます。",100)
print(str)

width = 2
str = string.format("%."..width.."fドルいただきます。",100)
print(str)
出力
100.000ドルいただきます。
100.00ドルいただきます。

ここではwidthに3が入っていますが、2を代入してから呼び出してやれば小数点以下2桁までの表示になります。

table.unpack()を使った可変長文

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

unpack()を使わないパターン
local list = {1,2,4,8,16,32,64}
local str = string.format("%d,%d,%d,%d,%d,%d,%d",list[1],list[2],list[3],list[4],list[5],list[6],list[7])
print(str)

そこで活躍するのがtable.unpack()関数です。テーブルに入っている要素をすべて吐き出します。

unpack()を使うパターン
local list = {1,2,4,8,16,32,64}
local str = string.format("%d,%d,%d,%d,%d,%d,%d",table.unpack(list))
print(str)

かなりすっきりします。

この時、string.format()は可変長引数なので、指定されている量よりも多く要素が入っていても動きます。

参考

https://staff.aist.go.jp/yutaka.ueno/lua/manual4jp.html
https://ocraviutl.fandom.com/ja/wiki/Lua%E3%81%AE%E6%96%87%E5%AD%97%E5%88%97

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?