この記事は
バーチャルキャストでのVCIのluaスクリプトで使う文字列の扱いについてまとめます。といっても今回の内容は、ふつうのluaスクリプトでも同じ振る舞いをしてくれると思います。
文字列の連結
文字列を表示する際に、変数を文字列に埋め込んだり、複数個の文字列を連結したりしたくなることがあると思います。luaでの文字列の連結操作には二通りの方法があります。
・ 2連ピリオドによる単純連結
・ stringクラスによるsprintf風連結
今回はこのうち stringクラスによる方法 を紹介したいと思います。
stringクラスによるsprintf風連結
stringクラスの関数format()を使って文字列を制御します。変数の埋め込みの自由度が高く、フォーマットを細かく調整できます。変数と文字列を分けてきれいに書くことができ、事実上テーブルを扱えるため、きちんと書きたい際には基本的にはこちらをお勧めします(一応保険で書いておきますが、どちらか一つに統一する必要は全然ないです)。
基本
string.format()を使います。引数は可変長になっており、第一引数に出力する文字列を、第二引数以降は埋め込む文字列か数値が入ります。第一因数の文中の埋め込みたい場所に、フォーマット指定子と呼ばれる特定の文字パターンを入れることで、第二引数以降の数値をフォーマット指定子に代入して連結した文字列を返してくれます。引数は数に制限はなく好きなだけ入れることができます。順番に対応するフォーマット指定子の位置に埋め込まれます。(C言語をご存じの方はprintf()やsprintf()のような振る舞いをすると思っていただければわかるかと思います。)
例を見てみましょう
local price = 2
local str = string.format("代金は%dドルになります。ありがとうございます。",price)
print(str)
代金は2ドルになります。ありがとうございます。
型の指定
前述の表記では%dという指定子の中に第二引数の"2"が文中に代入されて、出力されます。この指定子はいくつか種類があります。
指定子 | 概略 | 備考 |
---|---|---|
%d ,%i | 整数(10進数) | |
%u | 符号なし整数 | |
%f | 小数(10進数) | |
%e,%E | 指数表記 | 大文字はeがEになるだけ |
%g,%G | fとeの合わせ | 基本はfのような振る舞いをしますが、桁が多くなるとe表記になります |
%s | 文字列 | |
%q | 文字列 | sとの違いはluaに都合よく変換するらしい?です |
%c | 文字 | 文字コードを指定できます |
%o | 整数(8進数) | |
%x,%X | 整数(16進数) | |
%a,%A | 小数(16進数) | |
%p | ポインタ | VCIだと使いにくいかも |
すべては紹介しきれませんが、主だったケース(%d,%f,%e,%s)を参考にその違いを見ていきましょう。
local price = 2
local str = string.format("代金は%fドルになります。ありがとうございます。",price)
print(str)
代金は2.000000ドルになります。ありがとうございます。
local price = 2400000
local str = string.format("代金は%eドルになります。ありがとうございます。",price)
print(str)
代金は2.400000e+006ドルになります。ありがとうございます。
local price = "???"
local str = string.format("代金は%sドルになります。ありがとうございます。",price)
print(str)
代金は???ドルになります。ありがとうございます。
ざっくりとした使い分けですが、 整数は%d、小数は%f、文字列は%sを使うと覚えておけば9割がた間違いないです。そして桁数が暴れるような数値は%eがいいかなと思います(科学技術計算でおなじみの表記です)。
表示フォーマットの指定
ここからはちょっと小ネタなのですが、%fの例をもう一度見てみましょう。桁数がちょっと気になりませんか
代金は2.000000ドルになります。ありがとうございます。
小数を使う場合でも多くの場合小数点以下の桁数は1,2桁あれば十分なことが多いのに、6桁も出力されておりちょっと余分ですよね。そういう時は以下のようにします。
local price = 2
local str = string.format("代金は%.2fドルになります。ありがとうございます。",price)
print(str)
代金は2.00ドルになります。ありがとうございます。
フォーマット指定子の%とfの間に".2"をいれます。この2は2桁という意味です。今回は2を設定しましたが、逆にもっと小さい値を扱う場合6桁じゃ足りなかったりします。こういう時には8とか9とかを指定することもできます。(あんまり小さい場合は%eのほうがおすすめ)
tableの展開
他にもいろいろ小技があるのですが、全部は紹介しきれないので、最後にtableの展開によるまとめて指定する方法をお伝えします。
スクリプトを書いていると、まとめて複数のパラメーターを扱う型を作ることがあります。例えばVector3やQuaternionなどは代表例ですが、luaにはtableというリストみたいな型があり、よく使用されます。こういうパラメーターはいちいち一つずつ展開すると面倒です。
local price = {1,2,3}
local str = string.format("代金はそれぞれ%dドル,%dドル,%dドルになります。ありがとうございます。",price[1],price[2],price[3])
print(str)
代金はそれぞれ1ドル,2ドル,3ドルになります。ありがとうございます。
そこで、string.format()が可変長であることを利用して、table.unpack()関数を使います。これだとまとめて一回だけ代入するだけでよくなり、コードが見やすくなります。
local price = {1,2,3}
local str = string.format("代金はそれぞれ%dドル,%dドル,%dドルになります。ありがとうございます。",table.unpack(price))
print(str)
代金はそれぞれ1ドル,2ドル,3ドルになります。ありがとうございます。
また、%dドルの部分をpriceの要素分繰り返せばいいので、priceに格納される数値の数が変更されても柔軟に対応することができるようになります。
参考
https://inzkyk.xyz/lua_5_4/standard_libraries/string_manipulation/#gsc.tab=0
https://wikiwiki.jp/sbarjp/Lua%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88/Lua%E5%88%9D%E5%BF%83%E8%80%85%E8%AC%9B%E5%BA%A7#n0c7b01f
http://www.nct9.ne.jp/m_hiroi/light/lua02.html