TL;DR
Rustのprintln!のフォーマット指定についての記事です。
長い記事でもありませんが、以下のソースを見れば大体わかります。
https://gist.github.com/YusukeHosonuma/6ee32ade9ac88cbc9fbd6b494154c5a0
はじめに
最近「Rustはいいぞ!」という声を聞いたり、Swiftが影響を受けた言語がRustだったりと、気になったので勉強し始めました。
Rustで標準出力はprintln!マクロで行うのですが、フォーマット指定がC言語などのprintfとは異なります。
以下のあたりのドキュメントに詳しく書かれているのですが、自分でコードを書いていて迷ったりすることもあったのでまとめてみました。(網羅はしていません)
基本
-
println!で標準出力 -
{}がプレースホルダ -
format!でフォーマット後の文字列を取得(指定方法は同じ) - どちらもマクロで実装されている
- なので実行時のオーバーヘッドが(C言語のprintfよりは)少ない(はず)
- ただコンパイルエラーメッセージがわかりづらいことがある
println!("Hello world!");
println!("Hello {}!", "world");
let s = format!("Hello, {} !!", "Rust"); // s = "Hello, Rust !!"
プレースホルダ
-
{}が基本で引数が順に埋められる -
{n}で n番目(0始まり)の引数で置き換える -
{name}でname="value"と指定した引数で置き換えられる
println!("{} | {} | {1} | {three} | {four}",
"One",
"Two",
three="three",
four=4);
// => One | Two | Two | three | 4
揃え(Align)
-
:の後に条件を指定 -
<nが n桁で左寄せ -
>nが n桁で右寄せ -
^nが n桁で中央寄せ -
>0nまたは<0nで「0埋め」
println!("{0: <8} | {1: >8} | {2: ^8} | {3: <08} | {4: >08} | {hundred: >08}",
"Left",
"Right",
"Center",
42,
999,
hundred=100);
// => Left | Right | Center | 42000000 | 00000999 | 00000100
基数 / 小数点
-
bがバイナリ表現 -
oが8進数 -
xが16進数(Xで大文字出力) -
eが指数表現(Eで大文字出力)
println!("{:b}", 1234); // => 10011010010
println!("{:o}", 1234); // => 2322
println!("{:x}", 1234); // => 4d2
println!("{:X}", 1234); // => 4D2
println!("{:e}", 12.34); // => 1.234e1
println!("{:E}", 12.34); // => 1.234E1
fmt::Display / fmt::Debug
-
{}ではfmt::Displayの実装が使われ -
{:?}ではfmt::Debugの実装が使われる
// 構造体の宣言
struct Point {
x: i32,
y: i32,
}
// fmt::Display トレイトの実装
impl fmt::Display for Point {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "({}, {})", self.x, self.y)
}
}
// fmt::Debug トレイトの実装
impl fmt::Debug for Point {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Point(x: {}, y: {})", self.x, self.y)
}
}
let p = Point { x: 1, y: 2 };
println!("{}", p); // => (1, 2)
println!("{:?} ", p); // => Point(x: 1, y: 2)
終わり
Rustはいいぞ!