Kinx Tips - UTF8 文字列のフォーマッティング
はじめに
「見た目は JavaScript、頭脳(中身)は Ruby、(安定感は AC/DC)」 でお届けしているスクリプト言語 Kinx。Kinx で実装したちょっとした小技を紹介。
- 参考
- 最初の動機 ... スクリプト言語 KINX(ご紹介)
- 個別記事へのリンクは全てここに集約してあります。
- リポジトリ ... https://github.com/Kray-G/kinx
- Pull Request 等お待ちしております。
- 最初の動機 ... スクリプト言語 KINX(ご紹介)
そう、ちょっとした小技。
UTF8 文字列のフォーマッティングの問題
C 言語の printf
UTF8 はバイト数と文字幅が一致しないので、"%-20s" とかしても微妙に揃いませんよね。半角カナも試しに使ってみましょう。
#include <stdio.h>
int main()
{
struct fruits {
char *name;
int price;
} fruits[] = {
{ .name = "りんご", .price = 230 },
{ .name = "みかん(1袋)", .price = 450 },
{ .name = "グレープフルーツ", .price = 120 },
};
printf("01234567890123456789\n");
for (int i = 0; i < sizeof(fruits)/sizeof(fruits[0]); ++i) {
printf("%-20s ... %3d 円\n", fruits[i].name, fruits[i].price);
}
return 0;
}
結果はこうなります。
01234567890123456789
りんご ... 230 円
みかん(1袋) ... 450 円
グレープフルーツ ... 120 円
基本的にバイト数なので、日本語 3 バイトであれば 3 消費します。したがって幅が縮みます。
Ruby の sprintf
C と同じかと思いきや、違います。
fruits = [
["りんご", 230],
["みかん(1袋)", 450],
["グレープフルーツ", 120],
]
puts "01234567890123456789"
fruits.each {|name, price|
puts sprintf("%-20s ... %3d 円", name, price)
}
結果はこうなりました。
01234567890123456789
りんご ... 230 円
みかん(1袋) ... 450 円
グレープフルーツ ... 120 円
バイト数ではなく文字数です。日本語も(何バイトであろうと) 1 文字で 1 消費します。なので、表示幅が増えます。文字数なので、半角カナだと実は一致します。
Kinx のフォーマッタ
Kinx では UTF8 の文字幅を確認してフォーマット文字列の数値部分を自動調整します。表示幅として機能します。
var fruits = [
["りんご", 230],
["みかん(1袋)", 450],
["グレープフルーツ", 120],
];
System.println("01234567890123456789");
fruits.each(&(e) => {
System.println("%-20s ... %3d 円" % e[0] % e[1]);
});
結果はこうなります。
01234567890123456789
りんご ... 230 円
みかん(1袋) ... 450 円
グレープフルーツ ... 120 円
Qiita のコードブロックでは等幅で表示されていない感じなので微妙ですが、等幅フォントで見れば縦ラインはきちんと揃っています。東アジア文字幅(East Asian Width)に従って調整するので概ねうまく動くはず 1。
多くの人が期待する動作は コレ ではないでしょうか。
おわりに
なかなか忙しくて記事が書けないとき用に、こういった小ネタもストックしておこう。
ではまた、次回。