title=sprintf フォーマット

==== sprintf フォーマット

Ruby の sprintf フォーマットは基本的に C 言語の [[man:sprintf(3)]]
のものと同じです。ただし、short や long などの C 特有の型に対する修飾子が
ないこと、2進数の指示子(%b)が存在すること、sprintf のすべての方言をサ
ポートしていないこと(%': 3桁区切り)などの違いがあります。

Ruby には整数の大きさに上限がないので、%b, %o, %x
に負の数を与えると (左側に無限に1が続くとみなせるので)
..f のような表示をします。絶対値に符号を付けた形式
で出力するためには %+x、% x のように指定します。


以下は sprintf フォーマットの書式です。[] で囲まれた部分は省略可
能であることを示しています。

 %[引数指定$][フラグ][幅][.精度]指示子

`%' 自身を出力するには `%%' とします。

以下それぞれの要素に関して説明します。

==== フラグ

フラグには #, +, ' '(スペース), -, 0 の5種類があります。

: #

 2進、8進、16進の指示子(b, o, x, X) ではそれぞれプレフィック
 スとして "0b", "0", "0x", "0X" を付加します。
 C 言語とは異なり引数が 0 の場合にもプレフィックスが付加されます。

//emlist{
  p sprintf("%#b", 10) #=> "0b1010"
  p sprintf("%#o", 10) #=> "012"
  p sprintf("%#x", 10) #=> "0xa"
  p sprintf("%#X", 10) #=> "0XA"
//}

 浮動小数点数 (f, e, E, g, G) に対しては必ず出力に"."をつけます。

//emlist{
  p sprintf("%.0f", 10) #=> "10"
  p sprintf("%#.0f", 10) #=> "10."
  p sprintf("%.0e", 10) #=> "1e+01"
  p sprintf("%#.0e", 10) #=> "1.e+01"
//}

 また g, G では上記に加えて末尾の余分な0が残ります。

//emlist{
  p sprintf("%.05g", 10) #=> "10"
  p sprintf("%#.05g", 10) #=> "10.000"
//}

: +

 出力文字列を符号付きにします。特に正の数では`+'が付加されます。
 数値の指示子
 (d, i, b, o, x, X, u, f, e, E, g, G)
 に対してだけ意味を持ちます。
 また、特に b, o, x, X, u に対しては、負数に対して "-"
 を付加することを示します。

//emlist{
  p sprintf("%d", 1)   #=> "1"
  p sprintf("%+d", 1)  #=> "+1"

  p sprintf("%x", -1)  #=> "..f"  # ".." は無限に f が続くことを表している
  p sprintf("%+x", -1) #=> "-1"
//}

: ' '(スペース)

 `+' と同じですが正の符号 `+' の代わりに空白を用います。数値の指示子
 (d, i, b, o, x, X, u, f, e, E, g, G)
 に対してだけ意味を持ちます。
//emlist{
  p sprintf("%d", 1)   #=> "1"
  p sprintf("%+d", 1)  #=> "+1"
  p sprintf("% d", 1)  #=> " 1"

  p sprintf("%x", -1)  #=> "..f"
  p sprintf("% x", 1)  #=> " 1"
  p sprintf("% x", -1) #=> "-1"
//}

: -

 出力を左詰めにします幅の指定がなければ
 意味がありません。

: 0

 出力が右詰めの場合に余った部分に空白の代わりに "0" を詰めます。

 数値の指示子の一部(d, i, b, o, x, X, u, f, g, G)に対し
 てだけ意味を持ちます(e, E には意味がない)
//emlist{
  p sprintf("%010d", 10)   #=> "0000000010"
//}
 `#' と一緒に指定した場合の出力は以下のようになります。
//emlist{
  p sprintf("%#010x", 10)  #=> "0x0000000a"
  p sprintf("%#010o", 10)  #=> "0000000012"
  p sprintf("%#010b", 10)  #=> "0b00001010"
//}

 これは、以下と同じです。

//emlist{
  p sprintf("%#10.8x", 10) #=> "0x0000000a"
  p sprintf("%#10.9o", 10) #=> "0000000012"
  p sprintf("%#10.8b", 10) #=> "0b00001010"
//}

 通常は、以下のようになります。

//emlist{
  p sprintf("%#10x", 10)   #=> "       0xa"
  p sprintf("%#10o", 10)   #=> "       012"
  p sprintf("%#10b", 10)   #=> "    0b1010"
//}

==== 幅

0以外の数字で始まる数字列は幅指定になります。幅は生成文字列の長さを示
します。後述の精度の値によらずこの幅分だ
けの文字列が生成されます。

幅の指定はフラグで付与される " ", "+",
"-", "0b", "0", "0x", "0X" の長さも考慮されます。

  p sprintf("%+5d", 11)  #=> "  +11"
  p sprintf("%+-5d", 11) #=> "+11  "
  p sprintf("%+05d", 11) #=> "+0011"

幅は「最低限必要な幅」の指定になります。結果の文字列が指定した幅を超
える場合は幅の指定は無効になります。

幅として `*' を指定すると幅の値を引数から得ることになります。

  p sprintf("%#05x", 10)    #=> "0x00a"
  p sprintf("%#0*x", 5, 10) #=> "0x00a"

==== 精度

"." の後に続く数字列は精度を表します("." のみの場合 ".0" と同じです)。精度は
整数の指示子
(d, i, b, o, x, X, u)
に対しては、数値列部分の長さを意味します。

  p sprintf("%10.5d", 1)  #=> "     00001"
  p sprintf("%#10.5x", 1) #=> "   0x00001"
  p sprintf("%+10.5x", 1) #=> "    +00001"

浮動小数点数の指示子
(f)
に対しては小数部の桁数を意味します。

  p sprintf("%10.5f", 1)   #=> "   1.00000"
  p sprintf("%10.5f", 10)  #=> "  10.00000"

浮動小数点数の指示子
(e, E, g, G)
に対しては有効桁数を意味します。

  p sprintf("%10.5e", 1)   #=> "1.00000e+00"
  p sprintf("%10.5e", 10)  #=> "1.00000e+01"
  p sprintf("%10.5g",  10)  #=> "        10"
  p sprintf("%#10.5G", 10)  #=> "    10.000"

文字列の指示子(s, p)
に対しては引数の文字列のうち指定した数を超える分を切り捨てます。
幅と精度を同じ値にすれば、どのような引数に対してもその
長さだけの出力を行うことになります。

  p sprintf("%10.2s", "foo")  #=> "        fo"

  p sprintf("%5.5s", "foo")     #=> "  foo"
  p sprintf("%5.5s", "foobar")  #=> "fooba"

精度として `*' を指定すると精度の値を引数から得ることになります。

  p sprintf("%.5s", "foobar")    #=> "fooba"
  p sprintf("%.*s", 5, "foobar") #=> "fooba"

==== 指示子

指示子は引数の型の解釈を示します。指示子を省略することはできません。
指示子には大きく分けて

 * 文字列を表す指示子: c, s, p
 * 整数を表す指示子: d, i, u, b, o, x, X,
 * 浮動小数点数を表す指示子: f, g, e, E, G

があります

: c

 引数の数値(0〜255)を文字コードとみなして対応する文字を出力します。
 引数が数値以外のオブジェクトの場合 to_int メソッドによる変換を試みます。
 引数として範囲内の一文字の文字列も受けつけます。文字そのものを出力します。
//emlist{
  p sprintf("%c", 97)  #=> "a"
  p sprintf("%c", 'a') #=> "a"
//}

 フラグ `-' と幅 の指定だけが意味を持ちます。

: s

 文字列を出力します。

 引数が [[c:String]] オブジェクトでなければ to_s メソッドにより文字列化
 したものを引数として扱います。

: p

 [[m:Object#inspect]] の結果を出力します。
//emlist{
  p sprintf("%s", /e+/)  #=> "(?-mix:e+)"
  p sprintf("%p", /e+/)  #=> "/e+/"
//}


: d
: i

 引数の数値を10進表現の整数として出力します。

 引数が整数でなければ関数 [[m:Kernel.#Integer]] と同じ規則で整数に
 変換されます。

//emlist{
  p sprintf("%d", -1) #=> "-1"
  p sprintf("%d", 3.1) #=> "3"
  p sprintf("%d", '0b1010') #=> "10"
//}

: u

 引数の数値を符号なし整数とみなして10進表現の整数として出力します。
//emlist{
  p sprintf("%u", '0b1010') #=> "10"
  p sprintf("%u", -1) #=> "-1"
//}


: b
: o
: x
: X

 整数をそれぞれ2進、8進、16進、16進(大文字)表現の文字列で出力します。

 `#' フラグを指定すれば "0b", "0", "0x", "0X" を先頭に付加します。

 `+', ` ' フラグがない場合、負の数には ".." が先頭(`#' フラグがあれば 
 "0x" などの後)に付加されます。これは最上位桁の文字が無限に続くことを
 意味し、2の補数表現で負の数を表しています。

//emlist{
   p sprintf("%#b", 10)    #=> "0b1010"
   p sprintf("%#o", 10)    #=> "012"
   p sprintf("%#x", 10)    #=> "0xa"

   # 負の数に対して ".." が付加されます
   p sprintf("%#b", -1)    #=> "0b..1"
   p sprintf("%#o", -1)    #=> "0..7"
   p sprintf("%#x", -1)    #=> "0x..f"

   p sprintf("%10x", -1)   #=> "       ..f"
   p sprintf("%-10x", -1)  #=> "..f       "

   # 「精度」を指定した場合、".." は付加されません
   p sprintf("%.10x", -1)  #=> "ffffffffff"
//}

: f
: e
: E
: g
: G

 f は小数点表現(xxx.xxx)で数値を出力します。

 e は指数表現(x.xxxe+xx)で数値を出力します。

 g は 指数が -4 より小さいか精度以上の場合に e と同じ出力を、それ以
 外では f と同じ出力を行います。ただし、小数部の末尾の0は取り除かれ
 ます。

 大文字の指示子(E, G)は出力のアルファベットを大文字にします。
//emlist{
  p sprintf("%f", 1.0) #=> "1.000000"
  p sprintf("%e", 1.0) #=> "1.000000e+00"
  p sprintf("%g", 1.0) #=> "1"
  
  p sprintf("%f", 10.1) #=> "10.100000"
  p sprintf("%e", 10.1) #=> "1.010000e+01"
  p sprintf("%g", 10.1) #=> "10.1"
  
  p sprintf("%g", 10 ** 6)  #=> "1e+06"
  p sprintf("%g", 10 ** -5) #=> "1e-05"
//}
 精度の省略値は 6 です。

 無限大、NaN(Not a Number) に対する出力は以下のとおりです。
//emlist{
  p sprintf("%f",  1.0/0)  #=> "inf"
  p sprintf("%f", -1.0/0)  #=> "-inf"
  p sprintf("%f",  0.0/0)  #=> "nan"

  p sprintf("%E",  1.0/0)  #=> "INF"
  p sprintf("%E", -1.0/0)  #=> "-INF"
  p sprintf("%E",  0.0/0)  #=> "NAN"
//}
 f, e, E, g, G に関しては [[man:sprintf(3)]] の結果を利用しています。従って出力結果は
 実際にはシステムに依存することになります。

==== 引数指定

利用頻度が低いので最後に説明します。

: nth$

 nth 番目の引数のフォーマットを行うことを示します。
//emlist{
  p sprintf("%d, %x, %o", 1, 2, 3) #=> "1, 2, 3"
  p sprintf("%3$d, %2$x, %1$o", 1, 2, 3) #=> "3, 2, 1"
  
  p sprintf("%1$d, %1$x, %1$o", 10) #=> "10, a, 12"
//}
 状況によってフォーマットを変えたいが引数の順序を変えたくない場合に使
 用します。
//emlist{
  case ENV['LC_TIME']
  when /^ja_JP/
    fmt = "%1$d年%2$d月%3$d日"
  else
    fmt = "%2$02d/%03$2d/%1$02d"
  end

  p sprintf(fmt, 1, 4, 22) #=> "04/22/01"
//}
 "*" の後に指定することで幅や
 精度を引数で指定することもできます。
//emlist{
  p sprintf("%5.2f", 1)              #=> " 1.00"
  p sprintf("%*.*f", 5, 2, 1)        #=> " 1.00"
  p sprintf("%1$*2$.*3$f", 1, 5, 2)  #=> " 1.00"
//}
