LoginSignup
0

More than 3 years have passed since last update.

RubyのString#%について

Posted at

はじめに

以下のようなRubyのコードを見かけました。

sample.rb
names = ['Jon', 'Bob', 'Alice']
puts "Their names are %s, %s and %s" % names

#=> Their names are Jon, Bob and Alice

文字列中に含まれている%sやその後の%namesが何を意味しているのか分からなかったため、調べてみました。

String#%

リファレンスを確認したところ、Stringクラスのインスタンスメソッドで%がありました。
https://docs.ruby-lang.org/ja/2.5.0/method/String/i/=25.html

self % args -> String
printf と同じ規則に従って args をフォーマットします。
args が配列であれば Kernel.#sprintf(self, *args) と同じです。 それ以外の場合は Kernel.#sprintf(self, args) と同じです。

引数argsを変換してくれるようです。
文字列 % argsというのが最初に見たコードの

"Their names are %s, %s and %s" % names

の部分と一致してそうですが、イマイチよく分かりません。
printfと同じ規則に従ってとは?
printfって何だっけ?
ということで調べてみました。

printfとは

こちらもリファレンスを確認すると、Karnelモジュールのモジュール関数に定義されていました。
https://docs.ruby-lang.org/ja/2.5.0/method/Kernel/m/printf.html

C 言語の printf と同じように、format に従い引数を文字列に変換してportに出力します。

どうやらprintfは元々C言語の関数で、ある規則に従って引数を変換し、文字列として出力してくれるようです。C言語は全く分からないのでスルーします。

つまり、String#%はprintfで使われている規則に従って引数のargsを変換してくれるメソッドのようです。

では、printfで使われている規則とは何か?

sprintf フォーマットとは

String#%のリファレンスに規則について記載されていました。
Rubyの場合はC言語のものと少し違うが、ほとんど一緒のようです。
このsprintfフォーマットの中で指示子という項目があり、その中に文字列を表す指示子としてsがありました。

指示子は引数の型の解釈を示します。指示子を省略することはできません。 指示子には大きく分けて
・文字列を表す指示子: c, s, p
・整数を表す指示子: d, i, u, b, B, o, x, X,
・浮動小数点数を表す指示子: f, g, e, E, G
があります

こちらのサイトが分かりやすかったです。
http://www9.plala.or.jp/sgwr-t/c/sec05.html

まとめ

以上の知識を得てレベルアップしたため、最初に書いたコードを再度見てみると、以下の事が分かりました。

names = ['Jon', 'Bob', 'Alice']
"Their names are %s, %s and %s" % names
  • 二行目でString#%メソッドが使用されて、 self % args の形になっている。
  • 一行目で定義された配列 names が%メソッドの引数(args)になっている。
  • self(文字列)の中で文字列を表す指示子sが使用されている。

したがって、%メソッドの引数に指定された配列namesの各要素が、文字列中の%s(指示子)により、文字列として表示されているようです。(間違っていたらすいません)

おまけ

今回の例のように配列を引数にする場合、配列の要素数に対して文字列中の指示子の数が多いと、引数が不足しているというエラーになりました。

names = ['Jon', 'Bob', 'Alice']
puts "Their names are %s, %s, %s and %s" % names
# 配列の要素数は3に対して、%sを4つ使用しています。

#=> too few arguments (ArgumentError)

逆に、配列の要素数が多い場合は余剰分が無視されます。

names = ['Jon', 'Bob', 'Alice']
puts "Their names are %s and %s" % names
# 配列の要素数は3に対して、%sを2つ使用しています。

#=> Their names are Jon and Bob
#余計な存在の'Alice'は無視されます。

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
0