解説 4月5日

 今日は「アルゴリズムとデータ構造」の初めての日なので、 講義の内容の紹介と、プログラミングの復習をします。

 次の項目が今日の内容です。

すべての説明を読み、すべての課題を解いて、その解答と 困ったこと、考えたこと、感じたことを 指定のアドレスにメールを送ってください。


アルゴリズムとデータ構造とは

アルゴリズムもデータ構造もプログラムを作るために大事なものです。 もちろん、簡単なプログラムではこのようなものを特に意識しなくてもできかもしれませんが、 「かしこい」プログラムや、複雑なプログラムを作るためには必要な知識であり技術です。

そもそも「アルゴリズムとデータ構造」の講義は、あなたがたがプログラミングの基礎ができている、 という前提の上で行われるよう設計されました。 そこで今までの講義では、プログラムの復習はあまりしてきませんでした。 しかし、今年度はプログラムの復習にも力をいれることにしました。


プログラミングの基本

 プログラミングとは、いろいろな役に立つ プログラムを作り出すことです。

プログラムとは: 命令文の集まりとしての命令書

 プログラムはコンピューターを思い通りに働かせるための手段です。 コンピューターは機械ですが、普通の機械と違うところは、記号(言葉) で書いた「命令文」で動かすことができるところです。 プログラムとはそのような命令文の集まりからなる命令書です。 コンピューターは命令書を解釈し、実行します。ですから、命令書を上手に書いておくことで、 コンピューターにさまざまな仕事をさせることができるのです。

このことを理解するために、もう少し複雑な3行の命令からなるプログラムを見てみましょう。

print "こんにちは。\n"
print "お元気ですか?\n"
print "はい元気にしています。\n"

 実際に実行すると、ディスプレイ上に、次のように表示されるでしょう。

こんにちは。
お元気ですか?
はい元気にしています。

[Rubyのプログラムを実行するには]

いくつかの方法があります。

私の勧めは最後の方法です。 irbを使うと、一つ一つのコマンドの実行結果がどのようなものか、 すぐにわかるからです。ちゃんと一つ一つのコマンドが動くことが確かめられたら、 ファイルにすべて書き出し一番目か二番目の方法で実行する、というのがよいでしょう。

 上のプログラムは、3個の命令文から構成されたプログラムだと見ることができます。 個々の命令文を少し詳しく見ていくと、どれもprintで 始まっている命令文であることが分かります。 そのプリント文を一つ実行すると、 " "、つまり引用符号(ダブルクォート、もしくは二重引用符と言います。)で 囲まれている部分が表示されます。 なお、この"で囲まれた部分のことを「文字列」と言い、「文字の並び」のことを意味します。
この例に現れる文字列の最後にある \n は、これも文字の一種で、「改行」に相当します(これ自体は、 引用符合”で囲まれていることに注意。 そうでないと、大抵の場合はエラーになります)。 これは\とnがくっついたものですが、二つの半角文字が合わさって改行を表わしています。 改行は普通の文字のように個々の形はありませんが、行が変わるので、改行が「表示」されると言ってもよいでしょう。 文字列の中に、\n がある場合には、改行が表示されるということを理解しておいてください。
このような詳細はともかく、上のプログラムは、次のように3つの命令文から構成され ているプログラムだと解釈できます。

命令文1
命令文2
命令文3

それぞれの命令文は、次のような具体的な命令文に対応していることは明らかでしょう。

命令文1 => print "こんにちは。\n"
命令文2 => print "お元気ですか?\n"
命令文3 => print "はい元気にしています。\n"

このように複数の命令文からなるプログラムが実行されるとき、どの命令から実行されるでのでしょう。そこに、基本的な原則があります。

命令文の逐次実行

 プログラムはいくつかの 命令文の集まりとして成立していることが普通です。 実際、いくつかの命令文を集めうまく並べることで、必要な仕事をさせることができるようになります。 さて、複数の命令文を実行させるとき、 命令文の実行の順番が問題になります。

 さて、それでは、複数の命令文がある時、どれから先に実行されるでしょう。 プログラムでは普通、先に書いてある命令文 (上から書かれた命令文)から順番に一つ一つ実行することになっています。

 これを逐次実行の原則と呼ぶことにします。 上の3個の命令文からなるプログラムでも実際、先に書いてある命令文から実行されました。 このことは当たり前のことなのですが、プログラムを理解する上で非常に重要なことです。

 どのようなプログラムでも、プログラムを構成する命令文がどのような順番で実行されるのかを順に一つづつ追いかけることで、 (実際に動かさなくても)プログラムがどのように動作し、どのような結果をもたらすのか分かります。 (予測が正しいかどうかは実際にプログラムをコンピューターで実行してみて確かめることができます。)

命令文と文

プログラムは命令文を組み合わせて、作ると言いました。 プログラミングでは、いちいち命令とつけずに、単に「」 と表現するのが普通です。つまり、実行の単位になる命令文を単に「文」と表現します。 今後は、命令文の変わりに、文という表現も使います。

エラーメッセージ

プログラムの書き方にはいろいろな約束事があります。約束事を守っていないプログラムを実行すると、 実行の途中でエラーが発生し、プログラムが停止してしまいます。
例えば次のように、文字列をダブルクォートで囲んでいないプログラムを書いたとしましょう。 (2行目の「エラー発生!」という文字列がダブルクォートで囲まれていません。)

print "正しい書き方"
print エラー発生!    #←この部分が間違っています
print "実行完了!"
注意:2行目の # は「コメント」を表す記号です。 Rubyではこの記号からその行の最後までの文字列はコメント、 すなわち「コンピュータに対する命令ではなく、人間のための注釈」として読み飛ばします。

このプログラムを実行すると、ディスプレイには次のように表示されます。

H:\>ruby test.rb
test.rb:2: Invalid char `\203' in expression
test.rb:2: Invalid char `\203' in expression
test.rb:2: Invalid char `\211' in expression
test.rb:2: Invalid char `\201' in expression
test.rb:2: Invalid char `\224' in expression
test.rb:2: Invalid char `\255' in expression
test.rb:2: Invalid char `\220' in expression
test.rb:2: Invalid char `\266' in expression
test.rb:2: Invalid char `\201' in expression
test.rb:3: syntax error, undexpected tIDENTIFIER, expectiong ']'
print "実行完了!"
     ^

上のように、エラーが発生したときにディスプレイに表示される文字のことをエラー メッセージと呼びます。

エラーメッセージには決められた形式があります。たいてい行の最初に書かれるのは、 エラーの発生したプログラムの書かれているファイル名です。上のエラーメッセージを 見てみると、test.rbというファイルの実行中にエラーが発生したことがわかります。

ファイル名の次に書かれている数字は、プログラム中のエラーの原因となっている部分の行数 (行番号といいます)です。 上のエラーメッセージでは、2がいくつか続いた後で、最後に3が表示されています。 これは、コンピューターがプログラムを3行目まで読んだ時点で、プログラムに誤りがあると 判断し、停止したことを表します。このように、エラーメッセージに表示される行数が、 エラーの直接の原因とは違う行を示すこともあるので注意してください。

行番号の次に表示されるのは発生したエラーに対する説明文です。上のエラーの場合、 ダブルクォートで囲まれていない無効な文字が書かれていることや、文字列の開始と終了を 表すダブルクォートのつじつまが合っていないことを示しています。 [このエラーメッセージの説明]

ここでは日本語で書かれた「エラー発生!」が関係してエラーが起こったため、 エラーが本当はどこで起きたのか、エラーメッセージが少しわかりにくくなっています。 そこで、rubyのあとに -Ks を付けて

ruby -Ks test.rb
で実行させてみてください。今度は先とは違う別なメッセージが表示されます。 ここで、-Ks とは、test.rbで使っている日本語はShift-JISというコード体系ですよ、 とrubyに教えていることを表しています。
H:\>ruby test.rb
test.rb:2: undefined local variable or method `エラー発生!' for main:Object (NameError)
このように、プログラムの中に日本語(全角文字)を使った場合には、-Ks をつけておくとよいでしょう。

課題1

課題1-1

以下のように、実行すると1から10までの数字を出力するプログラムを作成しなさい。 ただし、10個の数字を一度に表示するのではなく、1秒ごとに一つずつ表示するようにしてみましょう。

1 2 3 4 5 6 7 8 9 10    # ← 1秒おきに表示していく

[プログラムの実行を1秒止めておくには]

コンピュータをしばらく停止(「お休み」)させるための命令は sleepです。 コンピュータを1秒お休みさせるには
sleep(1)
とします。これを使うと、プログラムが実行される様子がよく分かることがあります。


変数

プログラミングとはコンピュータに「意味のある働き」をさせるために、「命令」を 適切に組み合わせ、命令書として構成していく作業です。
このような役に立つプログラムを作る上で 変数は不可欠な存在です。

変数とその値

変数とは何か、まず具体例で示しましょう。 次のプログラムを実行すると「こんにちは」をディスプレイに表示することは学びました。

print "こんにちは"
これを実行するとディスプレイに次のように表示されます。
こんにちは

次のプログラムは全く同じように「こんにちは」を出力するプログラムですが、 aisatsu という変数を使って作られています。

aisatsu = "こんにちは"
print aisatsu
実行すると同様に、次のように表示されます。
こんにちは

変数は入れ物、例えば箱のようなものだと説明されることがあります。 これは、変数にその時々でいろいろな「内容」を持たせられるからです。 上のプログラムの一行目を実行すると、 aisatsu という変数の内容は "こんにちは"という文字列になります。このプログラムの一行目の = は 変数に内容を与えるという働きをしているのです。 この内容のことを変数の(あたい)と呼びます。 このように変数に値を与えることを、代入と言いま す。

注意:上のプログラムの一行目に出てくる = は数学の等号ではありません。 左辺と右辺は等しくありません。
プログラミングの世界では内容のことを「値」と言うことが多いので、 変数に値をセットするとも言われます。

次のプログラムが何を出力するか分かりますか?

aisatsu = "こんばんは"
print aisatsu

今度は「こんばんは」が出力されるはずです。実行される2行目の命令が先程と全く同じ print aisatsu という形をしていることに注意してください。同じ aisatsu という変数を print している のに別の結果になるのは、 aisatsu という変数の値(内容)が異なるからです。
print という命令は次にくるものを出力する命令ですが、これまでには二つの形 が出てきたことになります。 次のプログラムの1行目と3行目を比べてみてください。

print "こんにちは","\n"
aisatsu = "こんばんは"
print aisatsu,"\n"
aisatsu = "こんにちは"
print aisatsu,"\n"

これまで出てきたprint文は、printの後には二重引用符 " で括られた文字列がくるものだけでしたが、今度はaisatsuという変数が後に来ています。
このprint文を実行すると、変数の内容、つまり値が表示されることが大事なことです。
(aisatsuというアルファベットが表示されるのではありません。)
このように変数を内部に持つ文が実行されるときは、まず変数が保持している値 が取り出されてから実行されます。
この場合、aisatsuという変数の中身は文字列です。print文は実行すると、その値(特定の文字列)を表示することになります。
ここで aisatsuが二重引用符 "で括られていないことに注意してください。 もし、二重引用符でくくられて"aisatsu"のようになっていたら、変数aisatsuの値ではなく、 いままで出てきたように文字列そのもの、つまり aisatsu が表示されます。
今後はprint文以外にもさまざまな命令文を使っていくことになりますが、プログラム の実行の過程で、変数の値がまず取り出されて実行されるという原則は、どの命令でも同じです。 プログラムを「理解する」ためには、どんな変数を使用しているかを把握し、その値が何になるかを 把握する必要があります。変数の値を把握することは、プログラムを 理解する上で最も基本的で重要なことです。

課題2

課題2-1

次のプログラムがどんな結果を出力するか予測してから実際に実行してみましょう ここでは、プリント文の後に、複数のものを置く形を理解し、特に「,」の役割を理解することが目的です。
name = "中京太郎"
aisatsu = "今日は。"
print name, "さん、", aisatsu, "\n"
上記のことを行ってから、以下のプログラムを実行するとディスプレイに何が出力されるのか、コンピュータで実行せずに、自分の頭でプログラムを一歩一歩おいかけて、予測した結果を報告しなさい。 次に、実際にプログラムを実行し、予測と適合したかどうか確かめ、予測と適合したかどうかを報告しなさい。 適合しなかった場合はその理由も報告すること。
aisatsu1 = "今日は"
aisatsu2 = "今晩は"
aisatsu3 = "お久しぶりですね"
aisatsu4 = "また会いましたね"
name1 = "中京太郎"
name2= "中京花子"
san = "さん"
maru = "。"
ten = "、"
kaigyo = "\n"

print name1, san, ten, aisatsu1, maru, kaigyo
print name2, san, ten, aisatsu4, maru, kaigyo

課題2-2

次のプログラムを実行すると、
name1 = "中京太郎"
name2= "中京花子"
san = "さん"
maru = "。"
ten = "、"
kaigyo = "\n"
print aisatsuBan, maru, name1, san, ten, aisatsuOhisa, maru, kaigyo
print name2, san, ten, aisatsuBan, maru, aisatsuAgain, maru, kaigyo
次のような出力が得られたとします。
今晩は。中京太郎さん、お久しぶりですね。
中京花子さん、今晩は。また会いましたね。
このためにはaisatsuBan, aisatsuOhisa, aisatsuAgainは、それぞれどのような値 が与えられていたかを答えなさい。

[変数に値がセットされていないときは?]

変数に値をセットしないで、実行しようとすると、エラーになります。 ですから、変数を使うときにはまず何らかの値が入るようにプログラムを書きましょう。 ただ、あとで学ぶforやeachのような構文では必要ないことがあるのですが... これについては徐々に学んでいくことにしましょう。

変数の働き

変数は意味のあるプログラムを作る上でとても重要です。 その理由は、変数に自由に値を設定でき、変数名を書きさえ すればその値を取り出して使うことができるという基本的な 性質があるからです。 変数がこのような性質を持つので、同じプログラムの中で変数にいろいろ違った値を設定することで、 変数を使い回すことができるようになります。
次の二つの変数を使ったプログラムを見てください。

aisatsu = "こんにちは"
name = "中京太郎"
print aisatsu, "、", name, "さん。\n", "お元気ですか。", "\n"

このプログラムは、次のように aisatsu と name という変数の値を変えるだけで、 後のprintの部分を変えずに繰り返し使うことができます。

aisatsu = "こんにちは"
name = "中京太郎"
print aisatsu, "、", name, "さん。\n", "お元気ですか。", "\n"

aisatsu  =  "こんばんは"
name = "花子"
print aisatsu, "、", name, "さん。\n", "お元気ですか。", "\n"

プログラムは繰り返し使う部分をうまく作ることで強力なものとなります。 繰り返し使うパターンを実現するためには、変数は不可欠なものなのです。 だんだんに複雑なプログラムを扱っていくと、実際に変数の力を納得することができるようになるでしょう。

変数名

変数は値を持つものであることが分かりましたが、一方で変数は、その変数自体を表す名前を 持っています。変数自体を表す名前のことを変数名と言います。 上の例では「aisatsu」という名前が変数名です。変数には値と変数名という、 二つの側面があることになります。
変数名は一定の制限はありますが プログラムの作成者が自由に決めることができます。 次の二つのプログラムは、変数名が違うだけでディスプレーに同じ表示が現れるので、 実質的に同じプログラムだと言えます。

プログラム 1

aisatsu = "こんばんは"
print aisatsu

プログラム 2

aaa = "こんばんは"
print aaa

ここで二つ目のプログラムは変数名が aaa となっていますが、一番目のプログラムと振る舞いは同じです。 これは変数が「入れ物」としての側面を持つからです。 print文自体は入れ物の中身を扱うのですから、入れ物自体の名前(変数名)がどんなものでも、 入っている値を問題にしている限り、変数という入れ物が違っても中身が同じならば同じ結果になるのは当然ですね。

変数名をつける時の制限と規則

プログラムを作成する際には、変数名はプログラムの作成者が決めなければなりません。 つまり、プログラムの作成者が好きな変数名を使うことができるのですが、 だからと言って全く勝手な変数名を使ってよいというわけではありません。
Rubyでは、変数名を構成する文字は半角文字のアルファベットか数字か _ (アンダーバー)という記号でなければなりません。 さらに、最初の1文字目(頭の文字)は大文字や数字は不可ですが、 2文字目以降は数字も大文字も使えます。 また、print や sleep のような、 Rubyであらかじめ役割を持っている文字列は、 そのまま変数名として使用することはできません(これは予約語と呼ばれています)。

分かりやすい変数名を使うことが大事

分かりやすいプログラムを作るためには、分かりやすい変数名を 選ぶことが大事です。 下手な変数名を使うと後になって自分でも分らなくなってしまいます。 分かりやすい変数名を考えることは結構頭を悩ます問題なのですが、 工夫して分かりやすい変数名を使うように習慣づけてください。
先程の aaa という変数を使ったプログラムは、上のものと変数名が違うだけでその働きは 全く同じですが、変数の使い方については分かりやすいとはとても言えませんから、 プログラムとしてよいものだとは言えません。

一言: プログラムには英語が頻繁に使われます。ですからこの際、 英語を勉強することを兼ねて、変数名にも英語を使うことはよい考えです。 多くのプログラマが使っている方法は「らくだ記法(キャメルネーム)」というものです。 これについては自分で調べてみてください。


上の変数の説明を理解した上で以下の演習問題を行い、変数名についての理解を確かなものに しましょう。

課題3

課題3-1

次のリストの中で、変数として、使えないものを選び、またなぜ使えないのか,その理由ものべなさい。
nen   y   i   Year   day   "year"   year   0year0   ねん   yyy   print   y-e-a-r   x_v_x

課題3-2

課題3-1の変数のリストの中から、「年」を表す変数を選びたい。 しかし、このリストの中には使えないことはないけれど、不適切なものがある。 不適切だと考えるものを選びなさい。理由も述べなさい。

課題3-3

次のプログラムを実行すると、ディスプレイに何が表示されるか、正確に予測し、それを報告しなさい。 次に、実際に計算機で実行し、自分の予測結果と合うかどうか確かめ、その結果も報告しなさい。 予測と違った場合は、その理由も報告すること。
namae = "Chukyo Tarou"
print "+++\n"
print "namae"
print "+++\n"
print namae
print "+++\n"

代入文の理解を深める

いろいろな形の代入文

みなさんは既に代入文を使ったプログラムを書いているわけですが、ここでは 代入に対する理解をさらに深めていくことにします。
先程も少し説明しましたが、代入とは変数に特定の値を 持たせることです。Rubyでは下のように = を用いて表します。

変数 = 値
namae = "中京太郎"

また、ある変数の持っている値を、別の変数に代入することもできます。 その場合 = の右辺には、代入する値を持つ変数の名前を書きます。 (右辺の変数の値が取り出され、左辺の変数にその値が代入されます。

変数2 = 変数1
その例です。
aisatsu1 = "こんにちは"
aisatsu2 = aisatsu1
print aisatsu2, "\n"
これを実行した結果です:
こんにちは

文字列と数値

これまでは、プログラムの中で、文字列という種類の対象だけを扱ってきましたが、 ここでは、プログラムで数も扱うことにしましょう。 数に対しても、文字列について今まで学んできたことが全く同じように適用できます。 つまり、変数への数の代入や変数からの数の取り出しなども全く同じような操作でできます。 ただし、数は文字列と違って、次のようにプログラムの中ではそのまま書けば意味を持ちます。 (注意: 引用符で囲むと、数ではなく文字列として扱われます。)

num = 1000
print  num
print  "\n"

式と値

これまで、変数を単独で扱ってきましたが、変数や文字列、数を要素にして、 式を作ることができます。
例えば、次のプログラムの中の num1 + num2 は式の例です。

num1 = 1000
num2 = 2000
wa = num1 + num2
print  wa
print  "\n"

このように、プログラムの構成要素には式があります。より複雑な式が 簡単な式を組み合わせて構成できるのは、一般の数式の場合と同じです。
次のような場合です。

num1 = 1000
num2 = 2000
kekka = (num1 + num2) * num2    # * は掛算を表す記号です。
print  kekka
print  "\n"

式は変数と同様に式全体で値を持ちます。 値を持つプログラムの構成要素を式だと言ってもよいでしょう。
文字列を対象にした式も成立します。
以下のように、文字列を + で結合したものも式です。この式を実行すると、それらが結合 された文字列が式の値になります。

kotoba = "おはよう、" + "太郎さん" 
print  kotoba
print  "\n"

もう少し詳しく、プログラムの実行過程を見ていきましょう。 上のプログラムを実行すると、まず1行目の命令が実行されるのは当然ですね。 これまで実行されるプログラムの構成単位を命令と呼んできましたが と呼ぶのがプログラミングでは普通です。 命令が言葉の集まりとして構成されているからです。 一行目は、変数への代入を行う命令ですから、「代入文」と呼ぶこともあります。 代入文は、右辺の式を実行し、その結果の値を左辺の変数に代入するものです。 さて、この代入文は今までに出てきた単純な代入文とは違って、右辺が式になっています。

kotoba = "おはよう、" + "太郎さん"
右辺は
"おはよう、" + "太郎さん" 

となっていて、文字列が「 + 」の記号で繋がっている式です。 このように文字列を演算の対象とする「 + 」は二つの文字列をつなげるという働きをします。 この式を実行すると、二つの文字列が繋がって一つの文字列、

"おはよう、太郎さん" 

が出来上がり、これが式の値になります。 そして「 = 」を使う代入文は右辺の式の値を左辺の変数に代入するということになりますから、 "おはよう、太郎さん" がkotobaという変数に代入され、この変数の値になります。

下のプログラムを追いかけることができますか?

aisatsu = "おはよう、"
namae = "太郎" 
kotoba = aisatsu + namae + "さん"
print  kotoba
print  "\n"

特に3行目で何が起こるのか、十分理解することが大事です。 3行目は右辺から実行されます。右辺は式ですから実行されれば値を持ちます。 この場合、変数が入っていますから、まず変数の値が取り出されます。 変数から取り出されたものは文字列であり、それを結びつけることが 「 + 」の意味ですから、式が実行されると結合された文字列を式の値になります。 「 = 」は右辺の値を左辺の変数に代入するという働きをしますから、kotobaという変数の値が結合された文字列になります。


次のプログラムはいろいろな式から成り立っています。 式の値は数値です。
文字列を対象にした時と同様、一歩一歩プログラムがどのような順序で実行され 式がどのような値を持ち、結果としてプログラムがどのように動いくのか 追いかけてみましょう。これまでになかったものとして( )がありますが この意味は数学の数式の場合と同様、実行の順序を( )で制御することができ ます。もう一つの新しい要素として、print文で表示する対象を「,」で繋げてい るというところに注意してください。

kazu1 = 50
kazu2 = 40
kazu3 = kazu1 - kazu2
print "Kazu3=", kazu3, "\n"
kazu3 = (kazu1 + kazu2) * kazu3
print "Kazu3=", kazu3, "\n"

この上のプログラムを見ても、一つの式は、もっと単純な要素の式から構成されてい ることがわかります。変数も値を持つという意味 で一つの式です。 実は、"おはよう"のような文字列や50のような 数値も、プログラムの一部として 書かれているときは、それ自身が値を持ちますから式です。 式はその構成要素から実行されます。数値や文字列、変数などの 「式」はまず実行されて、値を持つということになります。 複雑な式が最終的に値を持つ過程を追いかけるのは 数学の数式がどのような値を持つのかを追いかけるのと一緒です。

プログラムを理解するためには、プログラムが実行される過程で、その構成要素であ る式がどのような値を取るのかをまずきちんと追いかけていくことが必要です。 その式がさらに(より小さな)構成要素となる式から構成されていれば、その 構成要素の式の値を追いかけていくことが必要です。その構成要素の 式がさらに小さな構成要素の式から成り立っていれば、同じことを 繰り返えすことで、式の値を明らかにすることができます。

キーボード入力

次のプログラムでは、キーボードからの入力を受け取るための命令文が使われています。 gets.chomp がその命令文です。 この命令文が実行されるとキーボードからの入力を待つ状態になります。 文字が入力されるとプログラムの実行を再開し、受け取った文字列をプログラムの 中で扱うことができるようになります。 次のプログラムでは、入力された文字列を aisatsu という変数に代入しています。
まずはこのプログラムをコピーして実行し、キーボードからの入力を受け取れている ことを確認してみましょう。プログラムを実行し、「あいさつ:」と表示された後に 「こんにちは」などの文字列を入力して、Enterキー を押してください。 (コマンドプロンプトで日本語を使うときは Altキー を押しながら 半角/全角キー を押します。)

print "あいさつ:"
aisatsu = gets.chomp

print "\n"
print aisatsu, "。お元気ですか?\n"

課題4

課題4-1

「キーボード入力」で示したプログラムを参考として、 以下のような実行結果になるプログラムを作成しなさい。 ただしここで、オレンジ色の文字はキーボードからの入力を表しています。

名前:中京太郎
あいさつ:こんにちは

中京太郎さん、こんにちは。
お元気ですか?

課題4-2

次のように、キーボードから会計金額と人数を入力すると、一人当たりの割り勘金額を 計算してくれるプログラムを作成しなさい。(オレンジ色の文字はキーボードからの入力を 表しています。キーボードから数の入力を受け取る方法は、下の解説を参照してください。)

お会計:10000
人数:3

お一人様3333円です。
不足金額は1円です。

[gets.to_iでキーボードから数の入力を受け取る]

キーボードから数の入力を受け取るときは次のような命令文を使用します。 キーボードから入力された数字(注意:これは「文字」の並び)を、 プログラムの中で数(注意:これは「数値」)として扱うことができるようになります。

kaikei = gets.to_i

注意: 実行時には半角数字で整数を入力してください。

[割算]

割算を計算するときは / を使用します。

print 10000 / 3
3333

数が変数に代入されている場合も、同じように計算することができます。

kaikei = 10000

print kaikei / 3
3333

ここで、なぜ 3333.3333333 にならないのか、と思った人がいるかもしれません。 これについては後で述べますが、Rubyでは「整数」と「小数点数をふくむ数(これを 浮動小数点数と呼びます)」とは違う扱いがされているからです。 小数点以下の数も表示したければ、

print kaikei / 3.0
というように、整数の3ではなく、浮動小数点数の3.0で割り算してみてください。

[余りを求める計算]

割算の余りを求める計算をするときには % を使用します。

print 10000 % 3
1

課題4-3

次のプログラムを実行すると何がどのように表示されるのか予測して、答えなさい。 その後、実際に実行して、予測と合ったかどうかも報告しなさい。


num = 10

num = num + 10
print num, "\n"

num = num + 10
print num, "\n"

num = num * 10
print num, "\n"

num = num / 3
print num, "\n"
[掛算]

掛算を計算するときは * を使用します。

print 1000 * 3
3000

数が変数に代入されている場合も、同じように計算することができます。

num = 1000

print num * 3
3000

課題4-4

次のプログラムを実行すると何がどのように表示されるのか予測して、答えなさい。 その後、実際に実行して、予測と合ったかどうかも報告しなさい。 STDOUT.flushという命令文については、下の解説を参照してください。


str = "☆☆☆☆☆"

str = str + "☆"
print str, "\n"
STDOUT.flush
sleep(1)

str = str + "☆"
print str, "\n"
STDOUT.flush
sleep(1)

str = str + "☆"
print str, "\n"
STDOUT.flush
sleep(1)

str = str + "☆"
print str, "\n"
STDOUT.flush
sleep(1)

[STDOUT.flushについて]

上のプログラムでは、STDOUT.flushという命令文を使用しています。 STDOUT.flushは、sleep文を正しく機能させるために必要な命令文です。 この命令文がないとsleep文が正しく機能しないことがあるため、仕方なく使用しています。 深く考える必要はありません。 「sleep文とセットで使う」くらいに考えてもらって構いません。

一応説明しておきます。
sleep文を含むプログラムを実行すると、停止前にprint文で出力されるはずの文字列が 表示されないことがあります。 このような場合、次のようにsleep文の直前でSTDOUT.flushを使用することで、溜まって いるそれまでのprint文の出力をまとめて吐き出すことができます。
STDOUT.flushは次のように使用します。

str = "aaa"

print str

STDOUT.flush    #ここまでのprint文の出力を表示する
sleep(3)        #3秒停止

print str

STDOUT.flushを書かなくても、期待通りにsleep文が機能することもあります。 期待通りにsleep文が機能しないときは直前にSTDOUT.flushを書いてください。

課題4-5

次の実行結果のように、長方形の面積を計算するプログラムを作成しなさい。 (オレンジ色の文字はキーボードからの入力を表しています。)

長方形の面積を計算します。
縦と横の辺の長さを入力してください。
縦:10
横:20
長方形の面積は200です。

縦と横の辺の長さは、キーボードからの入力を受け取るようにします。 キーボードから数の入力を受け取る方法については、 [キーボードから数の入力を受け取るには] を参照してください。

キーボードから数の入力を受け取るときは、次のような命令文を書きます。

変数 = gets.to_i    #キーボードからの数の入力を受け取り、変数に代入する。

実は上の命令文では、キーボードから受け取った文字列を数に変換しています。 .to_iのiは「整数」を意味するIntegerのiです。 .to_iには、文字列を整数に変換する働きがあります。

今回は数を2つ受け取る必要がありますので、キーボードから数の入力を受け取るための命令文を、2つ書く必要があります。 2つの数を受け取ったら、それらを使って長方形の面積を計算し、結果を表示しなさい。 掛算の計算には * を使用します。

課題4-6

次のプログラムを実行すると、ディスプレイに何が表示されるか、予測しなさい。 次に、実際にプログラムを実行してみて、自分の予測と適合したかどうかを報告しなさい。 自分の予測と合わなかった場合は、どうして合わなかったのか理由を考え、それを報告しなさい。
ただし、まず、次のgets.to_iの解説を読んで、理解してから、取り掛かること。

print "年齢を数字でキーボードから入力してください。"
nenrei = gets.to_i #ここで、20を入力することにする。
print "あなたの年齢は", nenrei, "才です。\n"

[解説:to_iの役割]

mojiretsu = "20"
kazu = 20
print (mojiretsu == kazu)
上のプログラムを実行すると、falseが表示されます。
ちょっと紛らわしいことのように思うかもしれませんが、"20"と20は違うものです。 "20"は文字"2"と文字"0"が結合したものに過ぎませんが、("ab"のようなものです。)
20は数そのものです。この違いは大事です。 ですから、次のような足算はできません。 文字列と、数を足し合わせることはできません。
mojiretsu = "20"
kazu = 20
goukei = mojiretsu + kazu
print goukei,"\n" 
つぎのように、文字列をまず数に直してからならできるのです。
mojiretsu = "20"
kazu = 20
goukei = mojiretsu.to_i + kazu
print goukei,"\n" 
つまり、to_iは、文字列という値を数という値に変換する役割を持っていると言えます。

[解説:gets.to_iとgets.chomp]

これまで、
gets.chomp
というのはやりました。この命令を実行すると、 コンピュータはキーボードから、入力を「待つ」状態に入ります。
実際、そこで、止まっていると言ってよいでしょう。
次に、キーボードから文字を打ち込んで、最後にEnterを入れると、それをきっかけにして、 コンピュータは動き出します。Enterを押すと実は改行コードつまり"\n"が送られ、実際には この改行コードをきっかけにして、動き出します。(何かのきっかけが必要です。) そして、gets.chompという式が値を持つことになり、その値がキーボードから打ち込んだ文字列+"\n"です。 "\n"は余計なので、これを取るためにchompがついているのです。
ただ、to_i は文字列の最後に改行コードがあっても無視します。そのため、 gets.chomp.to_i と書かずに gets.to_i ですませることが出来るのです。


「アルゴリズムとデータ構造」のホームに戻る