Rubyで対話的なプログラムを作成する際、ユーザーからの入力を受け取る処理は避けて通れません。
コマンドラインツールや自動化スクリプトにおいて、実行時にパラメータを渡したり、対話形式で設定値を決定したりする場面で入力機能が活用されます。
Rubyには標準で複数の入力取得方法が用意されており、用途に応じて適切に使い分けることが重要です。
本記事では、最も基本的なgetsメソッドから、数値への変換、複数行の取得、さらには実用的で応用的なテクニックまでを詳しく解説します。
getsメソッドの基本的な使い方
Rubyでユーザーからのキーボード入力を受け取る際、最も頻繁に利用されるのがgetsメソッドです。
getsは「get string」の略称であり、標準入力から1行のデータを読み取る役割を持っています。
プログラムがgetsを実行すると、ユーザーがエンターキーを押すまで待機状態になります。
入力された内容は、末尾の改行文字も含めて文字列(String)として返されます。
まずは、単純に入力を受け取って表示するコードを確認してみましょう。
# ユーザーに入力を促すメッセージを表示
print "お名前を教えてください: "
# 入力を変数nameに格納
name = gets
# 入力内容を出力
puts "こんにちは、#{name}さん!"
お名前を教えてください: Ruby太郎
こんにちは、Ruby太郎
さん!
実行結果を見ると、出力の途中で改行されていることがわかります。
これは、getsがユーザーが押したエンターキーによる改行(\n)も一緒に取得してしまうためです。
chompメソッドによる改行の除去
前述の通り、getsで取得した文字列には末尾に改行が含まれます。
多くのプログラムでは、この改行文字は不要であり、文字列の連結や比較の邪魔になることがよくあります。
この問題を解決するために使用されるのが、chompメソッドです。
chompを使用すると、文字列の末尾にある改行コードを簡単に取り除くことができます。
Rubyの入力処理では「gets.chomp」とセットで記述するのが一般的です。
print "都市名を入力してください: "
# getsの後にchompを繋げて呼び出す
city = gets.chomp
puts "あなたは#{city}にお住まいですね。"
都市名を入力してください: 東京
あなたは東京にお住まいですね。
このように、chompを併用することで、期待通りのレイアウトで出力を行うことが可能になります。
なお、chompは元の文字列をコピーして新しい文字列を生成するため、元のオブジェクトを直接変更したい場合は破壊的メソッドであるchomp!を使用しますが、基本的には通常のchompで問題ありません。
数値データの取得と型変換
getsで取得したデータは、たとえ数字を入力しても必ず「文字列」として扱われます。
そのため、入力された値を計算に使用したい場合は、明示的に数値型へ変換する必要があります。
Rubyでは、文字列を整数に変換するto_iメソッドや、浮動小数点数(小数)に変換するto_fメソッドが提供されています。
整数への変換(to_i)
ユーザーから年齢や個数などの整数を受け取る場合は、to_iを使用します。
print "あなたの年齢を入力してください: "
# 文字列を整数に変換
age = gets.to_i
# 数値として計算が可能になる
next_year_age = age + 1
puts "来年は#{next_year_age}歳になりますね。"
あなたの年齢を入力してください: 25
来年は26歳になりますね。
ここで注目すべき点は、数値変換を行う際はchompを省略できるという点です。
to_iメソッドは、文字列の末尾に改行が含まれていても、それを無視して数値部分だけを変換してくれる性質があるからです。
小数への変換(to_f)
体重や気温など、小数を扱う場合はto_fメソッドを利用します。
print "現在の気温を入力してください: "
temp = gets.to_f
puts "現在の気温は #{temp} 度です。"
現在の気温を入力してください: 22.5
現在の気温は 22.5 度です。
もし「abc」のような数値に変換できない文字列が入力された場合、to_iやto_fはエラーを返さず0や0.0を返します。
厳密な数値チェックが必要な場合は、正規表現やKernel.#Integerメソッドなどを用いたバリデーションを検討してください。
複数の入力を一度に処理する方法
競技プログラミングや特定のデータ入力形式では、1行の中にスペース区切りで複数の値が含まれることがあります。
これを個別の変数に分割して格納するには、splitメソッドを使用するのが効率的です。
print "幅と高さをスペース区切りで入力してください: "
# splitは引数なしで呼び出すと空白文字(スペースやタブ)で分割する
width, height = gets.split
# 数値として計算するために変換
area = width.to_i * height.to_i
puts "面積は #{area} です。"
さらに、分割した要素すべてを一括で数値に変換したい場合は、mapメソッドを組み合わせると非常に短く記述できます。
# 入力を分割して、全ての要素にto_iを適用する
nums = gets.split.map(&:to_i)
# numsは整数の配列になる
sum = nums.sum
puts "合計値は #{sum} です。"
この「gets.split.map(&:to_i)」というパターンは、Rubyの入力処理において非常によく使われるテクニックです。
複数行の入力を受け取る方法
1行だけでなく、あらかじめ決められた行数や、特定の終了条件を満たすまで複数行の入力を受け取りたい場合もあります。
これには、ループ処理やreadlinesメソッドが活用されます。
指定した回数だけ繰り返す
例えば、最初に「入力する行数」を受け取り、その回数分だけ入力を繰り返す処理は以下のようになります。
print "何行入力しますか?: "
count = gets.to_i
lines = []
count.times do |i|
print "#{i+1}行目: "
lines << gets.chomp
end
puts "入力された内容は: #{lines.join(', ')}"
終了文字が出現するまで読み込む
「exit」と入力されるまで無限に入力を受け取り続けるような、対話型ツールでよく見られる構成です。
puts "メッセージを入力してください(exitで終了)"
input_list = []
while (input = gets.chomp) != "exit"
input_list << input
end
puts "#{input_list.size}件の入力を受け取りました。"
全ての入力を一括で取得する
標準入力の内容を最後まで(EOF: End Of Fileまで)まとめて読み込みたい場合は、readlinesメソッドやreadメソッドが便利です。
readlinesは各行を要素とした配列を返し、readは全ての入力を一つの巨大な文字列として返します。
# Ctrl+D (WindowsはCtrl+Z) で入力を終了させるまで全て読み込む
all_lines = readlines
puts "--- 入力結果 ---"
all_lines.each_with_with_index do |line, i|
puts "#{i + 1}: #{line}"
end
コマンドライン引数の利用(ARGV)
プログラム実行後に入力を求めるのではなく、プログラムの実行開始時にパラメータを渡す方法もあります。
これを「コマンドライン引数」と呼び、Rubyでは組み込みの定数ARGVに配列として格納されます。
getsが「実行中にユーザーから話しかけてもらう」手法なら、ARGVは「実行前にメモを渡しておく」手法と言えるでしょう。
# 実行例: ruby script.rb output.txt 10
filename = ARGV[0]
count = ARGV[1].to_i
puts "ファイル名: #{filename}"
puts "繰り返し回数: #{count}"
注意点として、ARGVに値が存在する場合、単なるgetsメソッドはARGVの値をファイル名と見なして中身を読み取ろうとしてしまいます。
コマンドライン引数と標準入力を併用したい場合は、明示的にSTDIN.getsと記述することで、標準入力からの取得であることをRubyに伝えます。
# ARGVがある場合でも標準入力から受け取る
print "確認コードを入力してください: "
code = STDIN.gets.chomp
入力処理メソッドの比較まとめ
用途に合わせた入力メソッドの選択基準を以下の表にまとめました。
| メソッド名 | 戻り値の型 | 主な用途 |
|---|---|---|
gets | String | 標準入力から1行取得する。末尾に改行を含む。 |
gets.chomp | String | 改行を除去して1行取得する。最も一般的。 |
gets.to_i | Integer | 入力値を整数として扱う場合に使用する。 |
readlines | Array | 全ての入力行を配列として取得する。 |
ARGV | Array (定数) | プログラム実行時に渡された引数を取得する。 |
まとめ
Rubyにおける入力処理の基本は、getsメソッドとその関連メソッドをいかに組み合わせるかにあります。
文字列を取得するならgets.chomp、数値を扱うならto_iやto_fを使い分けましょう。
また、複数のデータを一度に受け取る際はsplitとmapを活用することで、コードの可読性を大幅に向上させることができます。
基本的な挙動を理解しておけば、ユーザーフレンドリーなコマンドラインツールや、複雑なデータ解析スクリプトの作成もスムーズに行えるようになります。
今回紹介したテクニックを駆使して、Rubyプログラミングにおける柔軟な入力処理を実装してみてください。
