roy > naoya > 基礎プログラミングI·情報検索 > (2)プログラミングの基礎

(2) 04/23の授業内容:プログラミングの基礎

コンパイル型言語とスクリプト型言語(説明)

人間は「事務局行ってきて。あ、その前にメディアセンターにも」などと言われても理解することができるが、コンピュータは全ての手順を最初から順番かつ正確に伝えなえれば理解できず、正しく実行することもできない。これから学ぶプログラミング言語は、人間がコンピュータに正確に指示を伝えるために作られたものである。

コンピュータは一見するとアルファベットや漢字を理解できているように感じるが、実際には1と0しか取り扱うことができない。アルファベットも漢字も記号も全て1と0の組み合わせに置き換えられている。これを機械語という。このため、コンピュータに命令を行う場合は、機械語を用いなければならない。しかし、人間が機械語を用いるのは労力が大きく、間違いが生じやすい。プログラミング言語は人間が直接扱うことが難しい機械語のかわりにわかりやすい言葉で書いたもので、その後で機械語に翻訳してコンピュータに実行させている。機械語への翻訳方法によりプログラミング言語は以下の2種類に分類できる。

  • コンパイル型言語:わかりやすい言葉で書いたプログラム(これをソースコードとかソースと呼ぶ)を変換プログラムであるコンパイラを用いて事前に一括で機械語に変換する。ソースコードを作成した後で人間がこのコンパイルの作業を行う必要がある。コンパイルを行うと機械語に翻訳された実行形式のファイルが生成されるので、そのファイルを実行する。
  • スクリプト型言語:ソースコードをそのまま実行することができる。人間がコンパイルを行うコンパイル型言語とは異なり、実行するとソースコードの解釈プログラムであるインタプリタが勝手に1行ずつ機械語に翻訳してくれる。

このため、コンパイル型言語ではソースコードに誤りがあると、機械語への変換中(コンパイル中)にエラーとなり、実行することができない。これに対して、スクリプト型言語では1行ずつの変換であるため、エラーが出現する手前までは実行が可能である。この授業で扱うRubyはスクリプト型言語に分類される。

準備

Rubyプログラムの作成はemacsで行い、実行はktermで行う。まずはemacsの使い方を思い出そう(1年生のときと同じ)。主なコマンドを以下に示す。その他のコマンドはemacs操作方法のページを参照すること。

emacs操作方法

  • 新規作成:Ctrl-x Ctrl-f
  • ファイルを開く:Ctrl-x Ctrl-f
  • ファイルの保存:Ctrl-x Ctrl-s
  • 日本語入力のオンオフ:Ctrl-o
  • コピー&ペースト:コピーしたい部分をマウスで反転すると自動的にコピーされる。ペーストしたい場所でマウスの真ん中ボタンを押すとペーストされる
  • コマンドをうち間違えて変なメッセージが出ている:Ctrl-gでなかったことになる(コマンドの中止)

簡単なプログラムの作成

まず簡単なプログラムを作成してみよう。emacsでファイルの新規作成を行うコマンドはCtrl-x Ctrl-fなので、これを入力しよう。するとemacs下部のミニバッファに以下のように表示される。

Find file: ~/

この後に続けて以下のように入力しよう(入力した部分を黄色で示す)。

Find file: ~/ruby/keisan.rb[Return]

Rubyプログラムはファイル名に必ず.rbの拡張子をつける。ruby/keisan.rbとなっているが、これはrubyディレクトリの中にkeisan.rbというファイルを新規作成せよという意味である。正しく入力すると、emacsの上部に(keisan.rb)と表示される。

emacs上部にファイル名が表示される

では、プログラムを書いてみよう。まずは余り考えずに以下の通り入力してみよう。

#!/usr/koeki/bin/ruby
print "計算をします。\n"
x = 10
y = 20
z = x + y
p z
printf ("10足す20は%dです。\n", z)

日本語の入力を行う場合はCtrl-oを押す。Ctrl-oを押すごとに日本語入力と英語入力が切り替わる。

半角英数字と日本語入力の切り替えはCtrl-o

入力したら保存をする。保存はCtrl-x Ctrl-sである。保存をしていない場合は-E:の横に**と表示されている。保存をすると**が消えることを確認しよう。

保存していない場合はミニバッファの上のEの右横に**が表示される

プログラムを作成したら、今度は実行してみよう。実行するのはktermなので、ktermでrubyディレクトリに移動し、下記のように入力する。

irsv{naoya}% cd ruby[Return] #=>ruby/に移動
irsv{naoya}% ruby keisan.rb[Return] #=>keisan.rbの実行

すると次のように表示される(はずである)。

irsv{naoya}% ruby keisan.rb[Return]
計算をします。
30
10足す20は30です。

keisan.rbは短いが立派なプログラムである。各行についてそれぞれ解説する。

  • 1行目:#!/usr/koeki/bin/rubyはrubyインタプリタのあるディレクトリを指定している。次の次の「プログラムの実行方法」の項で詳しく説明する。プログラムの1行目に必ず書くと覚える。
  • 2行目:「計算をします。」と表示しなさいという命令が書かれている。
  • 3行目:xに10を代入しなさいという命令が書かれている。
  • 4行目:yに20を代入しなさいという命令が書かれている。
  • 5行目:x+yの結果をzに代入しなさいという命令が書かれている。
  • 6行目:zに代入されている値を表示しなさいという命令が書かれている。
  • 7行目:「10足す20は○です。」の○の部分にzに代入された値を入れ込んで表示しなさいという命令が書かれている。

プログラム作成に関わるルール

  • emacsでFind File:~/ruby/プログラム名としてrubyディレクトリの中にプログラムを作成する
  • ファイルの拡張子は.rbとする
  • 1行目には#!/usr/koeki/bin/rubyと書く

メソッドと変数

メソッド

今実行したkeisan.rbをktermで実行すると結果が3行表示された。これらはそれぞれ2行目、6行目、7行目が対応していた。2行目のprint、6行目のp、7行目のprintfはいずれも「表示せよ」という命令であった(若干働きは違うが)。このように、何らかの働きを持つあらかじめ登録された文字列のことをRubyではメソッドと呼ぶ。

では、printメソッド、pメソッド、printfメソッドの働きについて、それぞれの違いを意識しながら確認してみよう。

  • printメソッド:後ろに指定した""内のメッセージを表示する。
  • pメソッド:後ろに指定した変数(後述)に代入された値を表示する。
  • printfメソッド:後ろに指定した""内のメッセージを表示するが、その際に%dの位置に""の後ろで指定した変数(後述)に代入された値を入れ込んで表示する。

printfについてはもう少し複雑な働きをするが、当面は上述の通り理解しておいて問題ない。

変数

keisan.rbで用いられたxyzのように何らかの値を代入して保管しておく役割を果たすものを変数とよぶ。中学や高校の数学でも登場しているので、それなりに馴染み深い(はずである)。

中学や高校ではxyzが主に用いられてきたが、プログラム中に登場する変数名は1文字である必要はない。例えば、keisan.rbで使用したxappleとしてもよいし、hogehogehogeでも構わない。ただしあらかじめメソッドとして登録されている文字列は変数名として利用することはできない。

keisan.rbではx = 10などと書かれていた。この意味は以下のとおりである。

  • × xは10である。
  • ○ xに10を代入する

=は右辺を左辺に代入するという意味を持つ。したがって、z = x + yx+yの結果をzに代入するということになる。ここでは、=や+の前後に半角のスペースをとっているが、スペースはあってもなくてもよい。

  • ○ z = x + y(全てスペースをあけている)
  • ○ z=x+y(全てスペースなし)
  • × z = x +y(一方だけスペースなし)
  • × z = x+ y(一方だけスペースなし)

変数には数字だけでなく文字を代入することもできる。文字を代入する場合には値に""をつける。

  • ○ name = "公益太郎"(文字なので""でくくる)
  • ○ age = 20(数字なので""なし)
  • × name = 公益太郎(文字なのに""がない)

変数名は、代入されている値が想像できるような名称にする。

  • ○ name = "公益太郎"(名前なのでnameという名称にしている)
  • × book = "公益太郎"(名前なのにbookという名称にしている)

メソッドと変数のまとめ

  • 何らかの働きを持つ文字列をメソッドという。
  • printメソッドは""内を表示する。
  • pメソッド指定した変数内の値を表示する。
  • printfメソッドは""内のメッセージに変数内の値を入れ込んで表示する。
  • 値を代入して保管するものを変数と呼ぶ。
  • 変数名は何文字でも良い。
  • 変数に文字を代入する時は""をつける。
  • 変数名は代入されている値がわかるような名称にする。。
  • =は右辺を左辺に代入するという意味。

\nの働き(練習)

\nは「バックスラッシュエヌ」と呼び改行をあらわす。バックスラッシュは環境により円マークとして表示される場合がある。バックスラッシュのないキーボードを使用している場合は円マークで代用する。

\nの有無により、出力結果が変化することを確認しよう。以下の2つのプログラムは\nの有無のみが異なっている(違いがわかりやすくなるよう\nを黄色で表示している)。それぞれのプログラムを指定した名前をつけて保存し、結果がどうなるか確認してみよう。

今回はいちいち入力するのは面倒なので、コピー&ペーストを使ってみよう。emacsでファイルを新規作成した後で、コピーしたいところをマウスで反転させて選択し、emacs上でマウスの真ん中クリックで貼り付けよう。

greeting1.rb

#!/usr/koeki/bin/ruby
print "はじめまして。\n"
print "私の名前は\n"
print "○○(自分の名前)です。\n" 

greeting2.rb

#!/usr/koeki/bin/ruby
print "はじめまして。"
print "私の名前は"
print "○○(自分の名前)です。\n" 

早くできた人はgreeting2.rbの\nを削除して実行してみよう(greeting3.rb)。何が起こるだろうか?

irsv{naoya}% ruby greeting1.rb[Return]
はじめまして。
私の名前は
公益太郎です。
irsv{naoya}% ruby greeting2.rb[Return]
はじめまして。私の名前は公益太郎です。
irsv{naoya}% ruby greeting3.rb[Return]
irsv{naoya}% 

実行結果を見ると、greeting1.rbでは途中で改行され3行に分かれて表示される。改行が行われているのは\nの位置である。greeting2.rbではプログラムでは3行に分割して記述した内容が1行で表示されている。greeting3.rbは実行しても何も表示されない。

printメソッドやprintfメソッドを使ってメッセージを表示させる場合、\nをつけることで改行させることができる。なお、表示する一連のメッセージの一番最後には必ず\nが必要である。最後の\nがないと何も表示されない。

ただし表示をさせるメソッドのうち、pメソッドについては\nは不要である。pメソッドは変数内の値を表示して自動的に改行する。""内のメッセージを表示する働きを持つprintメソッド、printfメソッドのみ""の末尾に必ず\nが必要となる。

\nの働きと用法についてのまとめ

  • \nは改行するという意味をもつ。
  • ""内のメッセージを表示するprintメソッドやprintfメソッドでは""の末尾に必ず\nをつける。
  • ""内の任意の位置に\nをつけることで自由な位置で改行して表示させることができる。
  • pメソッドは自動的に改行するので\nは不要。

Rubyプログラムの実行方法(説明)

Rubyはスクリプト型の言語であり、実行時にインタプリタという翻訳プログラムが1行ずつ機械語に翻訳する。Rubyインタプリタの起動方法により、2種類の実行方法を選択することができる。どちらを使用してもよい。

  • Rubyインタプリタを起動してからプログラムを実行する方法(ruby プログラム名[Return])
irsv{naoya}% ruby greeting.rb[Return]
  • Rubyインタプリタをソースコードに埋め込む方法(ファイルに実行属性を与えてから、./ファイル名)
irsv{naoya}% chmod +x greeting.rb[Return]
irsv{naoya}% ./hello.rb[Return]

1行目のchmod +x greeting.rbはファイルに実行属性を与えるというもので、最初に1回だけ実施すればよい。その後は2行目の./greeting.rbを入力するだけで実行できる。新しいプログラムファイルをを作成した場合のみ、最初に実行する際に1行目を実施する。

2つの方法の違いについて例をあげながら説明しよう。以下はWindowsのWordで作成したファイルである。左側はgreeting.docという名称で、.docという拡張子がついている。拡張子はどのプログラムで作成されたかを示すもので、.docはWordで作られたファイルであることをあらわしている。左側はダブルクリックするとWordが起動し、ファイルを開くことができる。右側は左側のファイルから拡張子を取り除いたものである。拡張子を取り除くとどのプログラムで作成されたのかがわからなくなるため、アイコンの絵柄も変わる。右側はダブルクリックしてもWordは起動せず、ファイルを開くことはできない。右側のファイルを開く場合には、まずWordを起動し、メニューの「開く」からファイルを指定する必要がある。

Windowsでは拡張子のついたファイルはダブルクリックすると関連付けされたプログラムで開くことができる。拡張子を取り除くと何のプログラムで作られたファイルだかわからなくなるのでダブルクリックしても開けない

ruby ファイル名[Return]という実行方法は、上記の例で言えば右側のファイルを開くことに相当する。ruby ファイル名[Return]のrubyの部分でRubyインタプリタというプログラムを起動し、その後に対象ファイルを開いて実行している。./ファイル名[Return]による実行は左側のファイルを開くことに相当する。ファイル名のみの入力による実行は、アイコンのダブルクリックと同一のイメージである。では、./ファイル名[Return]の場合、プログラムとファイルの関連付けはどのように行われているのであろうか。Windowsの場合、そのファイルがどのプログラムで作成されたのかは拡張子で判断される。Rubyプログラムの場合、関連付けは1行目の#!/usr/koeki/bin/rubyで行われている。これは、このファイルを実行する際には、usrというディレクトリの中のkoekiというディレクトリの中のbinというディレクトリの中にあるrubyインタプリタを利用せよという指示である。

したがって、ruby ファイル名[Return]の形式で実行する場合には#!/usr/koeki/bin/rubyを1行目に記述する必要はない(記述しても良い)。ただしこの授業の中では、どちらの実行方法にも対応できるように、原則として1行目には#!/usr/koeki/bin/rubyを記述するものとする。

Rubyプログラムの実行方法(2種類ある)

  1. ruby プログラム名[Return]
  2. ./プログラム名[Return](先頭の.(ドット)を忘れずに)

2の方法で実行する場合、1回目のみ事前にchmod +x プログラム名[Return]が必要。

入力を受け取るgetsメソッド

もういちど最初の方で取り上げたkeisan.rbを見てみよう。

#!/usr/koeki/bin/ruby
print "計算をします。\n"
x = 10
y = 20
z = x + y
p z
printf ("10足す20は%dです。\n", z)

このプログラムでは3行目と4行目でxyにそれぞれ10と20を代入しており、5行目でzを計算している。3行目と4行目を書き換え、例えばx = 40などとすれば、あらゆる足し算を行うことができる。

ただし、いちいちプログラムを書きなおして保存しなおしてから実行するのは非常に面倒くさい。最初からプログラムの中に数字を書いておくかわりに、プログラムを実行したときに好きな数字を入力し、その値に基づいて計算を行ってくれたほうが便利である。

キーボードからの入力を読み込むメソッドとしてgetsメソッドがある。getsメソッドを使ったプログラムの例を見てみよう。

money.rb

#!/usr/koeki/bin/ruby
print "お会計198円です。いくら支払いますか?\n"
money = gets.chomp!.to_i
change = money - 198
printf ("%d円のお返しになります。ありがとうございました。\n", change)
irsv{naoya}% ruby money.rb[Return]
お会計198円です。いくら支払いますか?
200[Return] #=>入力待ちになる
2円のお返しになります。ありがとうございました。

実行すると、「お会計198円です。いくら支払いますか?」が表示された後でユーザからの入力待ちになる。ここでは200を入力している。すると入力した値に基づいて計算が行われ、その後のメッセージが表示される。

money.rbの1行目と2行目には特に新しいものはない。3行目では

money = gets.chomp!.to_i

が出現している。getsはキーボードからの入力を読み込むメソッドであるが、キーボードから入力した値が数字の場合はchomp!.to_iを後ろにつけて、gets.chomp!.to_iとする必要がある。したがって、この行はキーボードから入力された数字を読み込んでmoneyに代入している。chomp!やto_iもメソッドであるが、ここでは説明しない(第5回で詳しく取り上げる)。

4行目ではmoneyに代入された値から198を引き算した値をchangeに代入している。5行目はkeisan.rbと同じで、""内の%dの位置に""の後ろで指定したchangeに代入された値を入れ込んで表示している。

getメソッドについてのまとめ

  • getsメソッドはキーボードからの入力を読み込むメソッドである。
  • キーボードから入力した数字を読み込むためには変数=gets.chomp!.to_iと書く。これで入力された数字が変数に代入される。

出席課題

表示する役割を持つprintやprintfメソッドに加え、キーボードからの入力を受け取るgetsメソッドを学んだことで、かなりプログラムらしいものが作れるようになってきた。今日のまとめとして、これらのメソッドを駆使したプログラムを何か1つ作ってみよう。プログラムを作成するための要件は以下のとおりである。

キーボードから何か数字を入力してもらい、その数字を使って何か計算をして結果を出力するプログラム

money.rbのように支払額を入力してお釣を計算するプログラム以外にも例えば以下のようなものが該当する。以下を参考にしても良いし自分で考えても良い。

  • 既得単位数を入力してもらい卒業までに必要な残り単位数を計算して出力する
  • 現在時刻を入力し1限の授業に出るためにあと何時間しか寝れないか計算して出力する

  • 提出先:naoya@e.koeki-u.ac.jp
  • Subject:ruby02
  • 提出期限:授業終了時まで

メール本文の構成は以下のとおり。

  1. 1行目に学籍番号と氏名を記載
  2. どんなプログラムを作ったのか(例:既得単位数を入力してもらい卒業までに必要な残り単位数を計算して出力するプログラム)
  3. 作成したプログラムを貼りつける
  4. 実行結果を貼りつける
  5. 感想やプログラムを作って気づいたこと、要望等

採点:本日は出席点のみです

Tips:emacsでの日本語入力のオンオフはCtrl-oです

Tips:Mewによるメールの送り方はMewコマンドを参照