値の型変換・入出力処理


メソッドとは

日本語や英語には、ものや概念を表す名詞と動作を表す動詞がある。それと同じように、プログラミング言語にはデータ(値)の他に、データを使って何かの処理を行う仕組みとして、前回習った演算子やメソッドがある(ところで、Rubyの演算子の殆どは文法上ではメソッドである)。Rubyのオブジェクトにはその種類(クラス)に応じた機能があらかじめ備わっており、メソッドを通じてその機能を利用できる。今までのプログラムによく出てきた printputs もメソッドの例である。メソッドを呼び出すときは下記のような形にするのが一般的である。

オブジェクト.メソッド名(引数)

printやputsなど、一部のメソッドはオブジェクトとピリオド(.)を省略することが可能である。例えば print は Kernel というオブジェクトのメソッドであるので下記のような書き方もできる。

Kernel.print "Hello world\n"  # 「print "Hello world\n"」と同じ結果になる

引数とは、メソッドが行う処理に必要な情報である。例えば、printを使う時は表示してほしい文字列や数字を引数として与える。また、(「/」演算子と同じ役割を持つ)divメソッドによって一つの数値を他の数値で除算したいときは、除数を引数として与える必要がある。

10.div(5)  # 「10 / 2」と同じ意味である

2つ以上の引数をとるメソッドの場合、カンマ(,)で区切って表記する。引数をとらないメソッドや、print・putsのようによく使うメソッドの場合は、括弧を省略するプログラマーが多い。それ以外のメソッド、特に2つ以上の引数をとるメソッドについては、括弧なしで表記するとソースコードが分かりにくくなるので、必ず引数を括弧で括るようにしてください。

10.to_s()  # OK (引数をとらないメソッド)
10.to_s  # OK (括弧を省略しても問題ない)

print("Hello ") # OK
puts("World!") # OK
# printとputsの場合は括弧を省略することが一般的である
# (そうする場合はメソッド名の後ろに空白を入れること)
print "Hello " # OK
puts "World!" # OK

printf("年齢: %d", 20)  # OK
printf "年齢: %d", 20  # NG (文法上は大丈夫だが、読みにくい)

今回の授業ではデータを入力して処理の結果を出力するプログラムを作るために必要なメソッドについて勉強する。


ユーザー入力(getsメソッド)

キーボードからの入力(文字列)を読み込むときはgetsメソッドを使用する。

 練習問題  greetings.rb
#!/usr/koeki/bin/ruby
# -*- coding: utf-8 -*-

puts "名前を入力し、Enterキーを押してください"
name = gets

print "Hello, "
print name
print "Nice to meet you!\n"

結果の例(黄色い部分はキーボードから入力された名前である):

名前を入力し、Enterキーを押してください
Momotaro
Hello, Momotaro
Nice to meet you!

解説:

chompメソッド

キーボードから文字列を入力すると、文字列の末尾は必ず改行文字(\n)が入る。改行文字を削除したい場合はchompメソッドを使う。

 練習問題  greetings2.rb
#!/usr/koeki/bin/ruby
# -*- coding: utf-8 -*-

puts "名前を入力し、Enterキーを押してください"
name = gets.chomp

print "Hello, "
print name
print ", nice to meet you!\n"

結果の例:

名前を入力し、Enterキーを押してください
Momotaro
Hello, Momotaro, nice to meet you!

name = gets.chomp(getsでキーボードから入力された文字列にchompを使う)のように、複数のメソッドをピリオド(.)で繋ぐ記法をメソッドチェインと呼ぶ。メソッドチェインを用いることで、処理の流れを簡潔に記述することができる。メソッドチェインを使わない場合は、下記のような書き方になる。

name = gets
name = name.chomp

値の型変換

getsなどでデータを読み込む場合、たとえ数字が入力されてもそれは必ず文字列(String)として読み込まれる。数値として計算に利用したい場合は文字列を数値に変換する必要がある。逆に、数値を文字列に戻すことが必要になることもある。

数値と文字列の足し算をしようとすれば結果がどうなるか、確認しよう。

 練習問題  int_plus_str.rb
#!/usr/koeki/bin/ruby
# -*- coding: utf-8 -*-
  
puts 1 + '1'

結果:

Traceback (most recent call last):
        1: from type.rb:4:in `<main>'
type.rb:4:in `+': String can't be coerced into Integer (TypeError)

解説:整数同士だったらその合計が計算されるし2つの文字列だったら結合されるが、整数と文字列で演算することはできないため、データ型のミスマッチを意味する「TypeError」が出る。

下記に値の型変換を行うメソッドを紹介する。


フォーマット出力(printfメソッド)

printf ("print with format"[書式付きで出力]の省略)とは、与えられた引数を指定されたフォーマットで出力するメソッドである。以下のような形式で使用される。

printf(フォーマット文字列, 表示して欲しい値[複数可])

フォーマット文字列内にフォーマット指定子と呼ばれる特殊な記号を使って、出力する値の表示方法を指定することができる。フォーマット文字列の後ろには、それぞれの指定子に対応した引数を記述する(2つ以上与える場合は「,」で区切って書く)。主なフォーマット指定子は以下の通りである。

下記のプログラムformat.rbでprintfを試してみよう。

 練習問題  format.rb
#!/usr/koeki/bin/ruby
# -*- coding: utf-8 -*-
    
num = 100 # Integer(整数)型の10進数

printf("10進整数のままだと%d\n", num)
printf("2進整数として出力すると%b\n", num)
printf("16進整数として出力すると%x\n", num)
printf("10進浮動小数点数として出力すると%f\n", num)
printf("文字列として出力すると%s\n", num)

(赤色で示されているのはフォーマット指定子とそれに対応する値)

結果:

10進整数のままだと100
2進整数として出力すると1100100
16進整数として出力すると64
10進浮動小数点数として出力すると100.000000
文字列として出力すると100

printfによる桁揃え出力

# 整数を入れると右づめになる
printf ("答えは%6dです\n", 100)    # => ___100
  
# 整数にマイナスをつけると左づめになる
printf ("答えは%-6dです\n", 100)   # => 100___
  
# %fでは全体の桁、小数部の桁の順に指定する
# ここでは小数を含めて全体が6桁、小数点以下は2桁になっている
printf ("答えは%6.2fです\n", 12.5)  # => _12.50
# 全体の桁数を指定せず小数点以下の桁数だけを指定することもできる
printf ("答えは%.1fです\n", 3.1415)  # => 3.1

以下は、format.rbを実行した際に得られる結果表示を整えることを意識して書き直したプログラムformat2.rbである。

 練習問題  format2.rb
#!/usr/koeki/bin/ruby
# -*- coding: utf-8 -*-

num = 100

printf("10進整数のままだと%22d\n", num)
printf("2進整数として出力すると%17b\n", num)
printf("16進整数として出力すると%16x\n", num)
printf("10進浮動小数点数として出力すると%8.1f\n", num)
printf("文字列として出力すると%18s\n", num)

これを実行すると、綺麗に整えられた出力が得られる。format.rbの実行結果と比べ、見やすくなっていることがわかる。

10進整数のままだと                 100
2進整数として出力すると           1100100
16進整数として出力すると               64
10進浮動小数点数として出力すると    100.0
文字列として出力すると                100

各指定子の出力幅の計算方法:全角文字を2として数えると最も長い文字列("10進浮動小数点数として出力すると")の長さは32である。また、出力される数値で最も長いのが7桁である(1100100)。したがって、全体の幅を40にすれば良いだろう。それから、各行の文字列の長さを40から引けば指定子に入れるべき幅が分かる。


入出力を行うプログラムの例

これまで習ったことを用いて簡単な電卓プログラムを実装してみよう。

 練習問題  calc.rb
#!/usr/koeki/bin/ruby
# -*- coding: utf-8 -*-

puts "整数を入力してください"
num1 = gets.to_i
puts "もう一つの整数を入力してください"
num2 = gets.to_i

printf("%d足す%dは%dです。\n", num1, num2, num1+num2)
printf("%d引く%dは%dです。\n", num1, num2, num1-num2)
printf("%d掛ける%dは%dです。\n", num1, num2, num1*num2)
printf("%.1f割る%.1fは%.3fです。\n", num1, num2, num1/num2)
(実はこのプログラムには一つの問題点が潜んでいる。今回の授業では発展課題の一つとしてその問題を直す課題がある)

実行結果の例:

整数を入力してください
100
もう一つの整数を入力してください
50
100足す50は150です。
100引く50は50です。
100掛ける5000は150です。
100.0割る50.0は2.000です。

解説:


本日の演習課題

 基本課題 

身長と体重をユーザーに入力してもらって、BMIを計算しprintfによって表示するプログラムbmi_calc.rbを作成せよ

計算方法: BMI = 体重[kg] ÷ 身長[m]の2乗

実行結果の例:

sime{c11xxxx}% chmod +x bmi_calc.rb
sime{c11xxxx}% ./bmi_calc.rb
身長をm単位で入力してください
1.75
体重をkg単位で入力してください
70

HEIGHT (m): 1.75 WEIGHT (kg): 70.00 BMI: 22.86

本文は下記の通り記入してください.

氏名: 苗字名前
学籍番号: C11xxxxx

ソースコード:
...

実行結果:
...

 発展課題 

  1. 上記の電卓プログラムcalc.rbには一つのバグが潜んでいる(エラーは出ないが正しい結果が得られない場合がある)。問題はどこにあるか考えてプログラムを修正すること。
  2. printfを用いて上記の電卓プログラムcalc.rbを、計算の結果を奇麗に整えた形式で出力するように改良すること。

目次