1-1 Rubyの概要
Ruby(ルビー) は、まつもとゆきひろ(通称Matz)氏により開発された、プログラミング言語です。
世の中には200種類以上のプログラミング言語があると言われていますが、インターネットが広く普及して以降、Rubyの人気は徐々に上がってきており、プログラミング言語のシェア率で見てもランキング上位に入っています。 Webに向いているプログラミング言語の中ではTOP3に入る人気の言語で、世界中で多くの人が使用しているプログラミング言語になります。
Rubyの使用例
Rubyは様々な企業で利用されており、有名なところではcookpad、GitHub、SlideShareなどの企業がサービス開発にRubyを採用しています。 弊社CodeCampでも、Rubyを利用してサービスを提供しています。
例えばCodeCampのサービスの場合は、以下のような場面でRubyを利用してサービスを構築しています。
- ユーザー認証(ログイン)
- 名前やメールアドレスなど個人ごとに異なる情報の読み込みから表示
- レッスンの履歴の表示 など
プログラミング言語はなぜ必要か
Rubyに限らず、webページを作成する上でなぜプログラミング言語が必要かというと、ブラウザに表示する内容をプログラミング言語を使って「動的」に変えることで、よりリッチなwebページを作ることができるからです。
例えば、ブラウザで「ページを表示した瞬間の時刻」を表示したい場合、時刻というのは常に変動している動的な値であり、HTMLで現在時刻を表現することはできません。
しかし、Rubyを代表としたプログラミング言語を利用することで、簡単に現在時刻を表示することができます。
Rubyの普及
Rubyの利用、なかでもRubyのフレームワーク「Ruby on Rails」を利用したweb開発は、その開発効率の高さから、アメリカのシリコンバレーや日本のベンチャー企業を中心に急速に普及しています。
更にエンジニアの年収が高いアメリカでは、Ruby on Railsプログラマーの平均年収が約1,300万円という高額な金額になっている事からもわかるように、Ruby on Railsができるプログラマーに対する評価も高いフレームワークといえます。
3-1 プログラムを作成
まずはRubyで文字を表示するプログラムを書いてみましょう。
「hello.rb」というファイルを新規作成し、以下のとおりプログラムを書いて保存しましょう。 hello.rbの「rb」という拡張子は、rubyのプログラムファイルであることを表します。
ファイルが保存できたら、このRubyのプログラムを実行してみましょう。
AWS Cloud9上でプログラムを実行する場合、 AWS Cloud9のRun機能を使う方法 と、ターミナルからRubyコマンドを使う方法 の2種類があります。
hello.rb1print("Hello, Ruby")
Run機能の使い方については、AWS Cloud9の使い方のページを参照してください。
Rubyコマンドを使う場合は、以下の手順で実行します。
(実行するhello.rbファイルのパスが、「basic/01/hello.rb」の場合)
1.AWS Cloud9のターミナルエリアで「bash」タブを開く
2.以下のコマンドをターミナルに入力してEnterを押す
ruby basic/01/hello.rb
3.ターミナルに「Hello, Ruby」が表示されることを確認する
AWS Cloud9のRun機能を使った場合でも、コマンドを使った場合でも、同じくターミナルに「Hello, Ruby」と表示されれば成功です。
- コマンドで実行した場合
- AWS Cloud9のRun機能で実行した場合
3-2 プログラムの解説
今回書いたプログラムはたった1行だけですが、これも立派なプログラムです。
実行することで今回のプログラムの「 文字を表示する 」という目的を果たします。
この1行のプログラムの中にも、Rubyを理解するための重要な要素が含まれていますので、順番に見ていきましょう。
“Hello, Ruby”
print(”Hello, Ruby”)
まず ”Hello, Ruby” という部分に注目します。
今回プログラムを実行して表示された「Hello, Ruby」というテキストが、プログラム上では ダブルクォーテーション で囲われています。
これはほとんどのプログラミング言語で共通なのですが、シングル・ダブルクォーテーションで囲われたものは、文字の羅列である「 文字列 」としてプログラムに解釈され、Rubyでは「文字列オブジェクト」と呼ばれます。
同様に、後述する 数値 や 配列 といったもの等、Rubyではほとんどのすべてのものが「オブジェクト」として解釈されます。
この”Hello, Ruby”も「文字列オブジェクト」という単位でRubyで扱われます。
print(”Hello, Ruby”)
今度は行頭のprintという部分を見てみましょう。
このprintは、Rubyでは「 メソッド 」と呼ばれるものになります。 Excelを触ったことがある人は「SUM」や「AVERAGE」などの関数をイメージするとわかりやすいかもしれません。
メソッドは、オブジェクトを扱うための手続きのことです。
例えば「数値」を使って足し算や掛け算をしたり、「文字列」同士をつなげたり、「ある時刻」を基準にして1時間後や1日後を求めたり…といったような事は、その処理機能を持つメソッドを使うことで処理することができます。
このprintメソッドは、カッコの中の内容をコンソールに出力する機能をもつ、Rubyで最初から用意されているメソッドになります。
また、カッコの中に書かれている値は「 引数(ひきすう) 」と呼ばれ、メソッドに渡す情報のことになります。
メソッドやオブジェクトの詳細については、また別の章で説明します。
ここでは、「オブジェクト=文字や数値などのデータとメソッドをセットで持っている”もの”」と理解しておいてください。
また、Rubyではメソッドの引数の括弧は省略することができますが、本テキストではメソッドであることを明確にするために、括弧を全て書いた形で進めていきます。
改行文字
さきほどのプログラムを実行すると、コマンドで実行した場合は画面上で改行されずに表示されました。
(Run機能で実行した場合はわかりにくいですが、こちらも同様に出力した文字列の後に改行はされていません)
これは、printメソッドが表示した文字列の中に改行がないためです。
Rubyのプログラムで改行を入れるには、以下3つの方法があります。
- その1
print("hello,ruby")
改行を入れたい箇所で、適宜プログラムを改行することで実現します。
ただし、この書き方はプログラムが複雑になると読みにくくなってしまいます。
- その2
print("hello \n ruby \n")
そこで、改行を表す特殊な文字「\n」を文章中に入れるのが好ましいとされています。
こちらの方法では、1行でプログラムを書き切ることができます。
Windowsの場合、「\」はフォントの仕様上「¥」で表示されます。MacのJISキーボード場合は「Option + ¥」でバックスラッシュが入力できます。
- その3
puts("Hello")puts("Ruby")
3つ目の方法ですが、 puts というメソッドを利用します。
こちらはprintメソッドと似ていますが、printメソッドと異なり、表示する文字の最後で必ず改行をしてくれます。
printメソッドとは改行がつく・つかないで勝手が異なるので、場面に応じて使い分けていきます。
4-1 変数とは
プログラミングに欠かせない要素として、 変数 があります。
変数とは、データを入れる箱のようなものです。
この箱は様々な値の出し入れに使用します。
「variable.rb」というファイルを新規作成し、以下のとおりプログラムを書いて実行してみましょう。
variable.rbhp = 200
mp = 80
puts("現在のhpは")
puts(hp)
puts("現在のmpは")
puts(mp)
puts("です")
ここでは「hp」と「mp」が変数となります。まずは変数の書き方から見ていきましょう。
4-2 変数の書き方
Rubyにおける変数の書き方は以下のとおりです。
- 名前に利用できるのは英数字か_(アンダースコア)で、数字が使えるのは2文字目以降
- 「hp」→ OK
- 「hp1」→ OK
- 「11」 → NG
- 「_11」 → OK
- 「_hp」 → OK
- 必ずしも変数宣言($など)やデータ型宣言(Stringなど)は必要ない
4-3 変数の命名
変数名は 英単語 を利用し、意味が分かる範囲で可能な限り短くしましょう。
また、英単語が複数となる場合、その区切りとして「_(アンダースコア)」か「単語の始めのみ大文字」を利用するのが一般的です。
# 「_」でつなぐスネークケース
user_nameuser_name_other
# 単語の始めのみ大文字、キャメルケース
userNameuserNameOther
一定の法則に従って分かりやすい変数名をつけることは、プログラムを書く上で非常に重要な要素になります。
4-4 変数の値を取り出す
変数に入れた値を利用する場合、変数をそのまま書くことで利用できます。
puts("現在のhpは")
puts(hp)
# 変数hpの値を取り出している
puts("です")
もし変数をダブルクォーテーションで囲んでしまうと、変数の値ではなく「hp」という文字が表示されてしまうので注意しましょう。
puts("hp")
4-6 コメントとは
プログラムの中にはコメントを書くことができます。
コメントはプログラム中に書かれていても、直接プログラムとしては扱われません。
なぜコメントが必要かと思われるかもしれませんが、例えば自分で一度書いたプログラムを誰か他のプログラマーが見ることもあります。 その時、
- プログラムの名前や作者、配布条件などの情報
- プログラムの説明
- プログラムの目印(あとで修正する箇所など)
- 複雑な処理の補足説明
というような、プログラムの情報を言葉で説明するためにコメントを使用します。
逆に、複雑なロジックで組まれたプログラムにコメントがない場合、そのプログラムを初めて見た人からすれば、変数名やロジックなどから処理の内容を把握するしかなくなります。
そのため、仮に自分しか見ないプログラムであっても、何ヶ月後の自分がそのプログラムを見て把握できるか怪しいような箇所は、積極的にコメントを残しておくようにしましょう。
4-7 コメントの書き方
コメントを表す記号は「#」です。行頭に「#」があれば、行全体がコメントになります。行の途中に「#」があれば、「#」の部分から後ろの部分がコメントになります。
# 変数にhp、mpの初期の値を代入
hp = 200
mp = 80
# 変数に格納された情報を出力する
puts("現在のhpは")
puts(hp)
puts("現在のmpは")
puts(mp)
puts("です")
上記のプログラムでは、変数に値を入れる前に、コメントをつけています。
プログラムの中のどこまで細かい情報をコメントで入れるようにするかは、プロジェクトや所属している会社のプログラミングのルールによって異なります。
(全くコメントのないプログラムも存在します)
5-1 文字列オブジェクト
復習になりますが、”Hello, Ruby”のようにシングルまたはダブルクォーテーションで囲まれた文字は「文字列オブジェクト」としてRubyに認識されます。
# 変数str1、str2に文字列を代入
str1 = "これは"
str2 = "文字列オブジェクトです"
# 変数に格納された情報を出力する
puts(str1)puts(str2)
また、オブジェクトは「メソッド」と「データ」というものを持っています。
メソッド は、データを操作する処理がまとまったものです。
上図の自動車の例でたとえると、「自動車」というオブジェクトは、「走行する」「停車する」「曲がる」といった操作ができるメソッドを持っています。
文字列オブジェクトは、文字列に対する操作ができるメソッドを持っていることになります。
データ は、文字列オブジェクトであれば”Hello ,Ruby”、”こんにちは”などの「文字列」のことになります。
つまり、”Hello, Ruby”は文字列オブジェクトであり、”Hello, Ruby”という文字列のデータと、このデータを操作するメソッドを持っていることになります。
この後、文字列オブジェクトで利用できるメソッドをいくつか見ていきますが、そのメソッドを使うことで
- 文字列の字数を数える
- 文字列の一部を削除する
- 複数の文字列を連結する
といった、文字列に対する操作をすることができます。この文字列の操作は、プログラミングで(特にwebの世界で)よく使う処理ですので、ぜひ覚えておきましょう!
5-2 便利な文字列メソッド
文字列を操作するメソッドでよく使うものを見ていきます。
文字列オブジェクトのメソッドを利用する際は、以下のような形でオブジェクトのあとに「.」で繋ぎ、メソッド名を続けることで利用することができます。
"Hello, Ruby".メソッド名
「string.rb」というファイルを新規作成し、その中に以下のプログラムを記述して実行結果を見ていきましょう。
- 文字列の長さを得る (length)
puts("こんにちは".length)
puts("Hello world".length)
- 文字列の連結 (+)
puts("Hello"
+ "Ruby")
文字列の連結は、複数個を同時に連結することもできます。
puts("Hello"
+ "World"
+ "!")
- 文字の削除 (delete)
str = "a/b/c/d/e/f/g"
puts(str.delete("/"))
- 先頭と末尾にある空白文字をとる (strip)
puts(" Hello World ")
puts(" Hello World ".strip)
- 大文字にする (upcase)
puts("hello world".upcase)
- 小文字にする (downcase)
puts("HELLO WORLD".downcase)
実際にプログラムを書く際には、変数に格納されている文字の体裁やフォーマットを整えて、自分の好きな形にして表示をするというのが基本の流れになります。
この章で出てきたメソッドや、その他この章では扱っていないメソッドもありますので、プログラムを書いている最中に文字列を「連結したい」「検索したい」「分割したい」「大文字にしたい」「切り取りたい」など操作を加えたい時には、Rubyのリファレンスやweb上で使い方を調べながら進めていきましょう。
参考:リファレンス
6-1 数値オブジェクト
前章で、文字は文字列オブジェクトとして表されると説明しましたが、数値も「 数値オブジェクト」として扱われます。
「num.rb」というファイルを新規作成し、以下のプログラムを記述して実行してみましょう。
num.rbputs(1)
puts(100)
puts(1+1)
puts(4-1)
結果は数値の「1」「100」「2」「3」が表示されたと思います。
このように、文字列と同じく数値もputsで値を表示したり、簡単な足し算や引き算を行うことができます。
次に、掛け算と割り算もやってみましょう。
プログラミング言語の世界では、掛け算を表す記号に「*(アスタリスク)」を、割り算を表す記号に「/(スラッシュ)」を利用します。
num.rbに以下のプログラムを追記し、実行してみましょう。
num.rbputs(2*2)
puts(2/2)
puts((1+1)*2)
通常の四則演算と同じく、括弧の中の計算から優先的に行われます。
最後に、同じくnum.rbに以下のプログラムを追記し、実行してみましょう。
num.rbputs(1+1)
puts("1"+"1")
最初の行は数値オブジェクト同士の足し算のため、「2」が表示されますが、最後の行は文字列オブジェクト同士の連結のため、「11」が表示されますのでご注意ください。
6-2 便利な数値メソッド
文字列メソッドほど多くはありませんが、数値オブジェクトにも便利なメソッドがあります。順番に試してみましょう。
- 四捨五入 (round)
puts(20.3.round)
- 切り上げ (ceil)
puts(20.4.ceil)
- 切り捨て (floor)
puts(20.5.floor)
上記3つのメソッドは、Rubyだけでなく他のプログラミング言語でも同じ機能・同じ名称でメソッドが用意されていることが多いので、ぜひ覚えておきましょう。
7-1 制御構造とは
プログラミング言語には、制御構造という重要な概念があります。
制御構造はプログラミングの醍醐味で、プログラムの実行順序を変えたり、プログラムを繰り返し実行するような仕掛けとなります。
この章では、プログラミングの制御構造について順番に紹介していきます。
7-2 条件判断 if
「if」は英語の「もしも〜」を表しますが、プログラミングの世界では、ある条件によって挙動が変わるプログラムを作る際に利用します。
例えば、web開発の現場では
- スマホからのアクセスだけ◯◯の処理を行う
- 有料会員登録者のみクーポンを配る
といった、特定の条件下のみで実行したい(または実行したくない)処理がある場合に、ifが利用されます。
if文の書式は以下のようになります。
if
もしも会員が有料会員の場合
クーポンを配る処理
end
このように「if」の直後に、 条件式 と呼ばれる「もしも○○の時」という○○の条件を書き、「if」〜「end」の間に、特定条件下で実際に実行したい処理を記述します。
前章で学んだ「数値」を使って、簡単なif文を組み立ててみます。
「if.rb」というファイルを新規作成し、以下のプログラムを記述して実行してみましょう。
if.rbif
2
> 1
puts("2は1より大きい")
end
このプログラムを実行すると「2は1より大きい」と表示されます。これは「2 > 1」が正しいので、その中身の処理が実行された結果です。
では以下のように書き換えるとどうでしょうか?
if.rbif
2
< 1
puts("2は1より大きい")
end
今度は何も表示されていないかと思います。
これは「2 < 1」が正しくないため、その中身の処理が実行されませんでした。
このように、「if」はifに続く 条件式 とセットで記述し、「正しい」ときには中身が実行され、「間違っているとき」には何も実行されません。
7-3 条件式
プログラミングの世界では、ifの条件式の「正しい」「間違っている」は true/false という英語で表されます。
trueは「正しい」、falseは「間違っている」という意味になります。
if文はこのtrue/falseという結果を見て判定し、プログラムの条件判断を行っています。
if
2
> 1
puts("これはtrue")
endif
2
< 1
puts("これはfalse")
end
「bool.rb」というファイルを新規作成し、以下のプログラムを記述して実行してみましょう。
bool.rbputs(2
== 2)
puts(1
== 2)
puts(3
> 1)
puts(3
> 3)
puts(3
>= 3)
puts(3
<= 3)
実行結果は以下のようになります。
数値の場合、大小関係の比較には等号や不等号を使います。
Rubyでは「=」は変数へ代入するための記号として使われるため、一致するかどうか調べるためにはイコール2つの「==」を利用します。 「≦」「≧」は、「<=」「>=」を使います。
このような比較の結果は、trueまたはfalseとなります。
例えば1行目の「2 == 2」という条件式は正しいため、trueが表示されています。2行目の「1 == 2」という条件式は正しくないため、falseが表示されています。
この条件の比較は、数値だけでなく文字列も判定することができます。
puts("Ruby"
== "Ruby")
puts("Ruby"
== "PHP")
また、これまで値が一致している場合の比較を見てきましたが、反対に値が一致していないことを判断するには「!=」を使います。
puts("Ruby"
!= "Ruby")
puts("Ruby"
!= "PHP")
それではこれまで学んだ事を応用して、変数numの値が10以上の場合は”bigger”、9以下の場合は”smaller”と表示するプログラムを作っていきます。
「else.rb」というファイルを新規作成し、以下のコードを記述して実行してみましょう。
else.rbnum = 20
if
num >= 10
puts("bigger")
endif
num <= 9
puts("smaller")end
結果はbiggerと表示され、smallerとは表示されません。
変数numの値を20から様々な数値に変更して、結果がどうなるか試してみましょう。
7-4 else
特定条件下の処理は「if」を使いますが、「else」を使うことで条件に一致しない時の動作を記述できます。
else.rbを以下のように修正して実行してみましょう。
else.rbnum = 20
if
num >= 10
puts("bigger")
else
puts("smaller")
end
変数numの値を色々変えて結果を確認してみましょう。
numが20のときは、if文の中身が実行され「bigger」と表示されますが、numが10より小さい数値のときは「smaller」が表示されます。
このように、「ifの条件を満たさない場合の処理」はelseを使って記述することができます。
7-5 elsif
elseを使って、条件に一致しない場合の処理もできるようになりました。
次は、条件が複数ある場合に使う「elsif」を使ってみます。
num1とnum2という2つの変数を比較して、num1の方が大きい場合は”num1の方が大きい”、num2の方が大きい場合は”num2の方が大きい”、両方の値が同じ場合は”num1とnum2は同じ”と出力するプログラムを作成していきます。
「elsif.rb」というファイルを新規作成し、以下のコードを記述して実行してみましょう。
elsif.rbnum1 = 10
num2 = 15
if
num1 > num2
puts("num1の方が大きい")
elsif
num1 < num2
puts("num2の方が大きい")
else
puts("num1とnum2は同じ")
end
このように、条件によって処理が3つ以上にわかれる時は「elsif」を使います。elsifは何個でも追加することができますが、複数の条件に合致した場合、実行されるのは最初に合致した条件の処理のみになるので注意してください。
elsifの書式は以下のようになります。
if
条件式1
条件式1に当てはまった時に実行する処理
elsif
条件式2
条件式2に当てはまった時に実行する処理
elsif
条件式3
条件式3に当てはまった時に実行する処理
else
条件式1/条件式2/条件式3のいずれにも当てはまらなかった時に実行する処理
end
7-6 条件の組み合わせ
ifの条件式では、複数の条件式を組み合わせることもできます。
例えば、変数num1が10で、 かつ 変数num2が15の場合は”num1が10かつnum2が15です”と出力するプログラムを作成していきます。
「and.rb」というファイルを新規作成し、以下のコードを記述して実行してみましょう。
コピーand.rb12345num1 =
10
num2 =
15
if
num1 ==
10
&& num2 ==
15
puts(
"num1が10 かつ num2が15です"
)
end
2つの条件式の間に「&&」という記号が入っています。
「条件1 && 条件2」は、「条件1 かつ 条件2」という意味で、どちらの条件も満たしていればtrueになります。どちらかの条件を満たさない場合はfalseになります。
次に、「or.rb」というファイルを新規作成し、以下のコードを記述して実行してみましょう。
コピーor.rb12345num1 =
10
num2 =
15
if
num1 ==
10
|| num2 ==
20
puts(
"num1が10 または num2が20です"
)
end
今度は2つの条件式の間に「||」という記号が入っています。
「条件1 || 条件2」は、「条件1 または 条件2」という意味で、どちらかの条件を満たしていればtrueになります。
条件判断は、プログラムの制御を行う重要な部分です。
条件の記述がわかりにくいと、そこで何をやろうとしているのかが読み取りにくくなってしまうため、できるだけ読みやすい条件を書くように心がけましょう。
8-1 繰り返し
if文と並び、「繰り返し」(ループ)もプログラムに欠かせない仕組みです。
プログラムを書いていると、「同じ処理を繰り返したい」ということが多々あります。
決まった回数や条件を満たしている間は同じ処理を実行したいという時に、繰り返しを使います。
この章では「while」文と「for」文の構文について説明します。
8-2 while文
while文は、どんなタイプの繰り返しにも使える単純な構文です。
while文は指定した条件式がtrueの間、繰り返しを実行します。
while文の書式は以下のようになります。
コピー123while
条件式
do
繰り返したい処理
end
※doは省略可能です。
条件式には、if文と同じように「num == 15」や「num1 > num2」といった条件式を記述します。
この条件式がtrueになっている間は、doからendの間に記述された処理が繰り返し実行されます。
「while.rb」というファイルを新規作成し、以下のコードを記述して実行してみましょう。
コピーwhile.rb12345i =
1
while
i <
10
puts(i)
i = i +
1
end
書いたコードの処理を順番に見ていきましょう。
- まず、1行目に「i = 1」と、変数iに対して「1」という数値を入れています。
- 2行目のwhie文の条件式には、「i < 10」とあるので、iという変数が10よりも小さい間は、繰り返し処理を実行することになります。
- 3行目と4行目が繰り返される処理の部分になります。3行目では、変数iの中身を出力しています。
- 4行目では、 変数iに対し、1を足しています 。
こうすることで、変数iの値を出力した後、変数iの値は1つずつ大きくなっていきます。
while文の条件式には「i < 10」とあるので、変数iの値が10になった時点で、繰り返し処理は実行されず、 while文から抜ける ことになります。
実行した結果、コンソールには以下のように表示されます。
このように、「while」文は条件式を評価し、条件式を満たしているtrueの場合は「end」までの処理を繰り返し実行します。
もし条件式が「1 == 1」のように変化しない場合、繰り返し処理は無限に実行されてしまいます。( 無限ループ )
無限ループを実行してしまうと、サーバーに負荷がかかりシステムがダウンしてしまうので絶対にやらないよう注意してください。
8-3 for文
while文は、指定した条件式によって繰り返しを継続するかどうかを判断していましたが、「for」文ではあらかじめ指定したオブジェクトから順番に値を取り出しながら繰り返しを行います。
for文の書式は以下のようになります。
コピー123for
変数
in
オブジェクト
do
繰り返したい処理
end
「for.rb」というファイルを新規作成し、以下のコードを記述して実行してみましょう。
コピーfor.rb123for
i
in
1
..
9
puts(i)
end
書いたコードの処理を順番に見ていきましょう。
- まず、1行目に変数「i」が宣言されており、ここで宣言される変数は繰り返し処理の中でのみ使うことができます。
「1..9」というのは「1から9まで」という意味で、 範囲オブジェクト と呼ばれるものです。 for文の中で指定されると、最初の値から最後の値までを順番に取り出します。 - 2行目が繰り返される処理の部分になります。2行目では、変数iの中身を出力しています。
実行した結果、コンソールには以下のように表示されます。
このように、for文では予め指定したオブジェクトから要素を全て取り出すと繰り返しは終了します。
そのため、while文のように条件式を変化させるような処理は必要ありません。
9-1 配列オブジェクト
これまでの章で、変数は値を入れる箱と例えましたが、配列オブジェクト(以下「配列」と呼びます)はその箱を複数集めた、大きな箱のようなものです。
「array.rb」というファイルを新規作成し、以下のコードを記述して実行してみましょう。
コピーarray.rb12classmates = [
"鈴木"
,
"佐藤"
,
"斎藤"
,
"伊藤"
,
"杉内"
]
puts(classmates[
2
])
実行すると、1行目に書いた5つの苗字のうち、「斎藤」が表示されます。
図で例えると、classmatesという大きい箱(配列)の中にはさらに箱が5つあり、それぞれの箱の名前と中身は、
- 「箱0の中身が鈴木」
- 「箱1の中身が佐藤」
- 「箱2の中身が斎藤」
- 「箱3の中身が伊藤」
- 「箱4の中身が杉内」
となっています。
このように、配列とは複数の箱と値を1つにまとめて扱うことができ、 配列という大きな箱の中にある1つ1つの箱の名前のことを「 インデックス 」と呼びます。
ここでは、インデックスは0、1、2、3、4のそれぞれの値につけられた名前の事を指します。また、箱の中身である値とインデックスをセットで 要素 と呼びます。
ほとんどのプログラミング言語では、配列のインデックスは0から数え始めます。
1から数え始めない事に違和感を覚える方もいるかもしれませんが、ここでは人間の年齢も生まれたときは0歳で、その後1年経つと1歳になるように、0から数え始める物だと理解しましょう。
9-2 配列の書き方
Rubyにおける配列の書き方は、実は1つではなく複数存在しますが、今回はその中でもよく使われる3つをご紹介します。
1. [ ]を利用する
「array.rb」のような書き方です。記号の[ ]を利用し、[値1, 値2, 値3・・・・・]と書くことで配列を定義できます。
コピー12classmates = [
"鈴木"
,
"佐藤"
,
"斎藤"
,
"伊藤"
,
"杉内"
]
puts(classmates[
2
])
2. インデックス名を指定して配列を定義
「array2.rb」というファイルを新規作成し、以下のコードを記述して実行してみましょう。
コピーarray2.rb1234567classmates = []
# 空の配列を作成
classmates[
0
] =
"鈴木"
classmates[
1
] =
"佐藤"
classmates[
2
] =
"斎藤"
classmates[
3
] =
"伊藤"
classmates[
4
] =
"杉内"
puts(classmates[
1
])
最初に空の配列を生成し、インデックスを指定してデータを1つずつ入れていくことで配列を定義することもできます。
3. 文字列オブジェクトでsplitメソッドを使う
文字列オブジェクトの splitメソッド は、文字列を特定の文字で分解し、結果を配列で返してくれるメソッドです。
「array3.rb」というファイルを新規作成し、以下のコードを記述して実行してみましょう。
コピーarray3.rb123str =
"鈴木,佐藤,斎藤,伊藤,杉内"
classmates = str.split(
","
)
# カンマで文字列を分解し、配列にする
puts(classmates[
1
])
このように、文字列オブジェクトのsplitメソッドを使って、カンマや空白など一定の法則で区切られた文字列から配列をつくることもできます。
9-3 配列の操作
配列の操作でよく使われるメソッドをとりあげていきます。
全てを覚える必要はありませんが、ここで利用される方法はRubyのプログラミングでも多用されますので、メソッド名の意味からどういう操作が行われるのかを予想できるようにしておくと、今後の開発が楽になります。
「array_method.rb」というファイルを新規作成し、以下のコードをそれぞれ記述して実行してみましょう。
要素を加えるメソッド (unshift)
配列の先頭 に新しい要素をつけくわえます。
コピーarray_method.rb123a = [
1
,
2
,
3
,
4
,
5
]
a.unshift(
0
)
puts(a)
要素を加えるメソッド (push)
配列の末尾 に要素をつけくわえます。
コピーarray_method.rb123a = [
1
,
2
,
3
,
4
,
5
]
a.push(
0
)
puts(a)
配列を連結する (concat)
配列に別の配列を連結します。
コピーarray_method.rb123a = [
1
,
2
,
3
,
4
,
5
]
a.concat([
6
,
7
])
puts(a)
配列から要素を削除 (delete)
配列から指定した要素を取り除きます。
コピーarray_method.rb123a = [
1
,
2
,
3
,
4
,
5
]
a.delete(
2
)
puts(a)
この他にも、配列を操作するメソッドはたくさんあります。
Rubyはあらかじめ便利なメソッドが用意されているので、自分が実現したい処理に対して一番適したメソッドを選択することが重要になってきます。
Rubyのメソッドをすべてを覚えることは難しいかもしれませんが、自分で1から作成した処理が、実はすでにRubyでメソッドが用意されており、それを利用すれば事足りていた・・・というようなことは結構ありますので、適宜インターネットやリファレンスを調べるなど、状況に適したメソッドがないか調べる癖をつけましょう。
9-4 配列の繰り返し処理
6章ではwhile文, for文を使っての繰り返し(ループ)を学びました。
一方で、配列の繰り返し処理では eachメソッド を使った繰り返しが可能で、こちらの方が繰り返し処理を書きやすいという特徴があります。
このeachメソッドを使って、配列内の要素の合計値を計算するプログラムを見てみます。
「each.rb」というファイルを新規作成し、以下のコードを記述して実行してみましょう。
コピーeach.rb12345678910list = [
1
,
2
,
3
,
4
,
5
]
sum =
0
list.
each
do
|elem|
sum += elem
# sum = sum + elem と同じ処理です
print(elem)
puts(
"を足します"
)
end
puts(
"合計は"
)
puts(sum)
puts(
"です"
)
eachの書式は以下のようになります。
コピー123オブジェクト.
each
do
|変数|
繰り返したい処理
end
eachのあとの「do ~ end」で囲まれた部分を ブロック と呼びます。 ブロック内部の処理はひとかたまりの処理として扱われ、ブロックではいくつかの処理をまとめて書くことができます。
今回は、以下の部分の3つの処理がブロックの中で行われています。
コピー123sum += elem
puts(elem)
puts(
"を足します"
)
- 1行目:合計の値を格納する変数sumにelemを足す
- 2行目:elemの値を出力
- 3行目:「を足します」を出力
また、ブロックの冒頭には |変数| という部分があります。今回変数はelemという名前にしています。この部分の変数名は任意で変更できます。
eachは 配列から要素を一つずつ取り出し、 |変数| で指定された変数に代入して、ブロックの中の処理を繰り返し実行 していきます。 |変数| は、ブロックの中でのみ使うことができます。(※ |変数| のように||で変数を囲むのは、Rubyのお作法です。)
今回のプログラムでは、変数elemの値は以下のとおり、繰り返しとともに変化していきます。
- 1回目 → 1 (list配列の最初の要素の値)
- 2回目 → 2
- 3回目 → 3
- 4回目 → 4
- 5回目 → 5 (list配列の最後の要素の値)
- 終了 (list配列の最後の配列まで繰り返したため)
9-5 nilについて
配列のデータを取り出す際に、まだ存在していないインデックスを指定すると nil(ニル) というものが返されます。
nilは オブジェクトが存在していないことを表す特別な値 として覚えましょう。
「nil.rb」というファイルを新規作成し、以下のコードを記述して実行してみましょう。
コピーnil.rb123classmates = [
"鈴木"
,
"佐藤"
,
"斎藤"
,
"伊藤"
,
"杉内"
]
puts(classmates[
0
])
puts(classmates[
5
])
上記のプログラムを実行すると、「0」というインデックスに紐付く値は存在しますが、「5」というインデックスに紐づく値がないため、この状態でnilというオブジェクトが返ってきていますが、nil自体は何も出力しないため結果的に何も表示されません。
10-1 ハッシュオブジェクト
9章で学習した配列は、インデックスを利用して、そのインデックスに対応する値を取り出したり、逆に与えたりすることができました。
ハッシュオブジェクト (以下「ハッシュ」と呼びます)は、配列と同様にオブジェクトの集まりをまとめて表現するオブジェクトです。
配列では、インデックスを用いて各要素にアクセスしましたが、ハッシュでは「キー」というものを利用します。 インデックスには数値しか利用できませんでしたが、キーにはどんなオブジェクトでも利用できます。
このキーを利用して、配列同様、値を取り出したり、逆に与えたりします。
10-2 ハッシュの書き方
復習になりますが、配列の場合は以下のように [ ] を利用しました。
コピー12classmates = [
"鈴木"
,
"佐藤"
,
"斎藤"
,
"伊藤"
,
"杉内"
]
puts(classmates[
2
])
Rubyでは、ハッシュの場合は { } を利用するルールとなっています。
「hash.rb」というファイルを新規作成し、以下のコードを記述して実行してみましょう。
コピーhash.rb12345678classmates = {
"suzuki"
=>
"鈴木"
,
"satou"
=>
"佐藤"
,
"saitou"
=>
"斎藤"
,
"itou"
=>
"伊藤"
,
"sugiuchi"
=>
"杉内"
}
puts(classmates[
"suzuki"
])
ハッシュの書式は以下のようになります。複数ある場合は「,」で区切ります。
コピー1{キー
1
=> 値
1
, キー
2
=> 値
2
, キー
3
=> 値
3
, ...}
配列の場合、書き方によってはキーを省略して0から順に割り当てる(先頭や末尾を操作etc)ということが可能でした。 しかしハッシュの場合は、どのような書き方でも キーと値をセットで書く必要があります 。 「=>」を挟み、左側が「キー」で右側が「値」になります。
また、値の取り出し方も配列と変わらず、キーの指定により取り出すことができます。
10-3 ハッシュの性質
キーには、文字列や数値など自由に設定することができます。 例えば、アダ名(文字列)をハッシュのキーに設定するプログラムを見てみましょう。
「hash_nickname.rb」というファイルを新規作成し、以下のコードを記述して実行してみましょう。
コピーhash_nickname.rb12345678classmates = {
"ガリ勉"
=>
"鈴木"
,
"委員長"
=>
"佐藤"
,
"セレブ"
=>
"斎藤"
,
"メガネ"
=>
"伊藤"
,
"女神"
=>
"杉内"
}
puts(classmates[
"ガリ勉"
])
このように、文字列をキーとして値を設定することができます。
配列とハッシュは似ているところもありますが、 キーとなるものが数値のものは配列 、 キーとなるものが文字やそれ以外のものはハッシュ と覚えるようにしましょう。
また、配列でもいくつかメソッドを見てきましたが、ハッシュにも専用のメソッドが用意されており、その種類や使い勝手の部分で配列とは異なります。
ただのデータの羅列(例えば名前だけのリストなど)ではなく、複数のデータの性質(名前、趣味など)が登場する場合はハッシュが向いています。
逆に、データに特に意味を持たせることなく羅列する場合は配列が向いています。
10-4 ハッシュの操作
ハッシュの操作方法について見ていきます。
「hash_sample.rb」というファイルを新規作成し、以下のコードをそれぞれ記述して実行してみましょう。
ハッシュの要素を更新する
「ハッシュ[キー] = 値」と設定すると、キーに対応している値を更新することができます。
コピーhash_sample.rb123456789classmates = {
"ガリ勉"
=>
"鈴木"
,
"委員長"
=>
"佐藤"
,
"セレブ"
=>
"斎藤"
,
"メガネ"
=>
"伊藤"
,
"女神"
=>
"杉内"
}
classmates[
"委員長"
] =
"加藤"
# キーが「委員長」の要素を更新
puts(classmates)
ハッシュに要素を追加する
「ハッシュ[新しいキー] = 値」と設定すると、ハッシュに新しい要素を追加することができます。
※すでに存在しているキーを指定してしまうと更新されてしまうので注意してください。
コピーhash_sample.rb123456789classmates = {
"ガリ勉"
=>
"鈴木"
,
"委員長"
=>
"佐藤"
,
"セレブ"
=>
"斎藤"
,
"メガネ"
=>
"伊藤"
,
"女神"
=>
"杉内"
}
classmates[
"スポーツマン"
] =
"加藤"
# キーが「スポーツマン」の要素を追加
puts(classmates)
10-5 シンボル
ハッシュは、キーの部分を文字列ではなく、先頭にコロン「:」を付けた書き方をすることもできます。
この「:key」という書き方のことを シンボル といいます。
シンボルとは、文字を「”」や「’」で囲むかわりに、先頭に「:」をつけた書き方のことです。
そのため、以下の実行結果は同じになります。
コピー12puts(
"suzuki"
)
puts(
:suzuki
)
このシンボルは、よくハッシュのキーとして使われます。
ハッシュのキー部分を「:suzuki」というようにシンボルで記述した場合は、その値を使う時も「classmates[:suzuki]」とシンボルで指定する必要があります。
この場合はキーに文字列を指定してもうまくいかないので注意しましょう。
コピー123456789# ハッシュキーをシンボルで書いた場合
classmates = {
:suzuki
=>
"鈴木"
,
:satou
=>
"佐藤"
,
:saitou
=>
"斎藤"
,
:itou
=>
"伊藤"
,
:sugiuchi
=>
"杉内"
}
puts(classmates[
:suzuki
])
また、ハッシュのキーにシンボルを使うときには、以下のように省略した書き方をすることもできます。
コピー12345678classmates = {
suzuki:
"鈴木"
,
satou:
"佐藤"
,
saitou:
"斎藤"
,
itou:
"伊藤"
,
sugiuchi:
"杉内"
}
puts(classmates[
:suzuki
])
省略した書き方であっても、あくまでキーはシンボルのため、要素を取り出す時はシンボルを使う必要があります。
11-1 オブジェクトとは何か
これまで数値オブジェクトや、文字列オブジェクトなど「 オブジェクト 」というものを扱ってきました。
今回はオブジェクトについて改めて考えていきますが、まずはオブジェクト指向の特徴である、 クラス という概念について説明します。
このページに「たい焼き」の画像がありますが、たい焼きは焼くときには「型」が存在し、材料を入れて焼くと型どおりの形に出来上がります。
同じようにオブジェクト指向では クラス という型があり、そのクラス(型)を元にオブジェクト(たい焼き)が生成されます。
更に、オブジェクトは姿形が似ているだけではなく、クラスで定義されているメソッドを利用することができます。
これまで文字列オブジェクトとして「Hello」「こんにちは」などの文字列を利用してきましたが、実はあれもStringという文字列クラスがあり、そのクラス(型)を元に生成したオブジェクトになります。
そのため、文字列クラスで定義されているメソッドを「hello」「こんにちは」といった文字列でも利用することができます。
また、これまで配列やハッシュについて学びましたが、これらの配列やハッシュは、オブジェクト指向では「Arrayクラスのオブジェクト」と表されます。
11-2 オブジェクトの生成
基本的に、オブジェクトを生成する際は new メソッドを利用します。
例えば、配列は以下のようにArray.newを使用してオブジェクトを生成します。
コピー12array =
Array
.
new
puts(array)
これまで、文字列オブジェクトであれば “Hello, Ruby” のようにシングルクォーテーションやダブルクォーテーション、配列であれば [1, 2, 3] のように括弧をつかってオブジェクトを作ってきました。
これらは リテラル と呼ばれるもので、例えば配列を作る際にArray.newのように書くよりも [ ] と書くほうが、文字数としては少なく同じ配列オブジェクト生成できます。
このように、基本となるStringやArrayなどのクラスであれば、簡単に記述できる記法があらかじめ用意されていますので、そちらを使えば事足りますが、次章で学ぶような「DateTimeクラス」などリテラルが用意されていないクラスからオブジェクトを作る際には、上記のnewによる記法を利用することになります。
コピー12345678910# 以下は実質同じ意味。②のほうが文字数は少なく生成することができる
# ① newで生成
array1 =
Array
.
new
# ② リテラルで生成
array2 = []
# DateTimeはリテラルがないので、newを使う
datetime = DateTime.
new
12-1 ライブラリとは
ここまで、文字列や数値・配列などのオブジェクトや、ifやwhile文・for文などの制御構造など、多くのプログラムを作成してきました。
そのプログラムファイルにはそれぞれ「文字列を表示する」「足し算を行う」など何かしらの機能を持っています。
ライブラリ とは、同じように何らかの機能(特に汎用性の高いもの)を再利用可能な形でまとめたもので、後から呼び出して利用する用途で作られたプログラムになります。
例えば、
- 時刻を簡単に扱うプログラム
- 行列やベクトルなど数学的な計算を行うプログラム
- ファイルの読み込み/書き込みを扱うプログラム
など特定の機能を持ち、他のファイルから呼び出されて利用される事を前提にしたプログラムの事を ライブラリ と呼びます。
実際のプログラムを作成する際は、Rubyで用意されているライブラリや自作のライブラリなどを機械のパーツのように組み合わせて、一つのプロダクトを開発していきます。
実際のライブラリを利用する例を見ていきましょう。
12-2 日付を扱うためのライブラリ
今回は日付をプログラム中で扱う Date のライブラリを見ていきます。
プログラムの中でライブラリを読み込むには、requireメソッドを使用します。
requireメソッドの書式は以下のようになります。
コピー1require(使いたいライブラリ名)
requireメソッドが呼ばれると、Rubyは引数で指定されたライブラリファイルを探して、そのファイルに書かれた内容を読み込みます。
「date.rb」というファイルを新規作成し、以下のコードを記述して実行してみましょう。
コピーdate.rb123require(
"date"
)
days = Date.today
puts(days.to_s)
コードを順番に見ていきましょう。
- 1行目:「require」を使い、Ruby付属のライブラリであるDateを読み込んでいます。
こうすることで、Dateオブジェクトを利用することが可能になります。 - 2行目:Dateオブジェクトのtodayメソッドを使って「本日の日付情報」をもったDateオブジェクトを生成し、変数daysに格納しています。
- 3行目:「to_s」メソッドを使い、「本日の日付情報」をもったDataオブジェクトを文字列オブジェクトに変換しています。
このDateオブジェクトにはいくつかメソッドがあります。「to_s」メソッドを使うことで、決まったフォーマットで日付情報を文字列で返してくれます。
また、Dateオブジェクトからは以下のように、本日の「年」、「月」、「日付」などの情報を取得することもできます。
12345require("date")d = Date.todayputs(d.year)puts(d.month)puts(d.day)
12-3 日付の計算
基本的にはDateオブジェクトは日数単位での計算を行います。
「calc_date.rb」というファイルを新規作成し、以下のコードを記述して実行してみましょう。
コピーcalc_date.rb1234require(
"date"
)
day = Date.today
puts(day +
1
)
# 明日の日付
puts(day +
100
)
# 100日後の日付
12-4 日付のフォーマットを変更する
日付情報を文字として出力したい場合に、フォーマットを調整したいときがあります。
例えば、「2015年1月10日」という日付でも
- 2015/1/10
- 2015年1月10日
- 1/10
- 1月10日
というような場合です。
これを実現するには、Dateオブジェクトの strftime を利用します。
このメソッドは、フォーマット文字列という特殊な文字を引数にとります。
そのフォーマット文字列に対応する出力形式が返ってきますので、このフォーマット文字列を組み合わせて自身が欲しい形式を指定する形になります。
フォーマット | 説明 |
---|---|
%A | 曜日の名称 (Sunday, Monday, …) |
%a | 曜日の省略名 (Sun, Mon, …) |
%B | 月の名称 (January, February, …) |
%b | 月の省略名 (Jan, Feb, …) |
%d | 日 (01-31) |
%H | 24時間制の時 (00-23) |
%I | 12時間制の時 (01-12) |
%M | 分 (00-59) |
%m | 月を表す数字 (01-12) |
%S | 秒 (00-60) (60はうるう秒) |
%Y | 西暦を表す数 |
%y | 西暦の下2桁 (00-99) |
「format_date.rb」というファイルを新規作成し、以下のコードを記述して実行してみましょう。
コピーformat_date.rb123require(
"date"
)
t = Date.today
puts(t.strftime(
"%Y/%m/%d"
))
12-5 その他のライブラリ
日付を扱うライブラリであるDateを見てきましたが、Date以外にもRubyで用意されているライブラリは存在します。 ここにあるライブラリについてはrequireで呼び出し、利用することができます。
何かの機能を作成する際には、すでに同じような機能がRubyのライブラリで用意されていないか調べるようにしましょう。 すでに用意されていれば、requireの1行で利用することができ、効率的に開発することができます。
13-1 ファイルの操作
Rubyプログラムでファイルを操作することもできます。
この章では、「read_file.txt」ファイルを読み込み、読み込んだファイルの内容に行番号を追加して「write_file.txt」ファイルに書き込む、という処理を作成します。
以下の「read_file.txt」ファイル(読み込み用)を作成してください。
コピーread_file.txt1234567891011121314151617Ruby(ルビー)はまつもとゆきひろ(通称Matz)氏により開発された、プログラミング言語です。
世の中には200種類以上のプログラミング言語があると言われていますが、
インターネットが広く普及して以降、Rubyの人気は徐々に上がってきており、
プログラミング言語のシェア率で見てもベスト10に入っています。
webに向いているプログラミング言語の中ではTOP3に入る人気の言語で、
世界中で多くの人が使用しているプログラミング言語になります。
Rubyに限らず、webページ作成の上でなぜプログラミング言語が必要かというと、
プログラミング言語で表示する内容を「動的」に変えることにより、
よりリッチなWebページ作成が可能となるためです。
例えばブラウザで「ページを表示した瞬間の時刻」をwebページに表示したいといった場合、
時刻というのは常に変動している動的な値であり、HTMLで現在時刻を表現することはできません。
しかし、Rubyを代表としたプログラミング言語を利用すると、簡単に現在時刻を表示することができます。
プログラミング言語Rubyの利用、とりわけフレームワーク「Ruby on Rails」を利用したweb開発は
その開発効率の高さから、アメリカのシリコンバレーや日本のベンチャー企業を中心に急速に普及しています。
更にエンジニアの年収が高いアメリカではRuby on Railsエンジニアの平均年収が約1,300万円という
高額な金額になっている事からもわかるように、企業からのRuby on Railsを利用している
エンジニアへの評価も高いフレームワークといえます。
13-2 ファイルを開く
Rubyプログラムからファイルの内容を利用するためには、最初にファイルを開く処理をする必要があります。
read_file.txtと同じ階層にfile.rbというファイルを作成し、以下のコードを書いてみましょう。
ファイルを開くだけの処理なので、実行はしなくて大丈夫です。
コピーfile.rb1file =
File
.open(
"read_file.txt"
,
"r"
)
ファイルを開くためのプログラムは、以下のような書式になります。
コピー1変数 =
File
.open(
"ファイル名"
, モード)
まず任意の名前の変数(今回はfile)を用意し、その変数を使ってファイルを操作していきます。
モードは、ファイルをどのような状態で開くかを指定します。 モードを省略した場合は、読み込み専用(r)になります。
モード | 処理区分 | 処理内容 |
---|---|---|
r | 読込 | ファイルポインタはファイルの先頭を指します。 |
w | 書込 | ファイルポインタはファイルの先頭を指します。ファイル内容を削除してから書き込みます。ファイルが存在しない場合は作成します。 |
a | 書込 | ファイルポインタはファイルの終端を指します。ファイルが存在しない場合は作成します。 |
ファイルポインタとは、 ファイルの中で今どこが対象になっているか「ファイル内の位置」を示すもの です。
例えばテキストエディタでキーボードから文字を入力した際、文字が表示される箇所がファイルポインタの位置で、大抵は点滅してファイルポインタの位置を表示しています。
また「w」「a」はファイルが存在しない場合はファイルを新規作成してくれます。
13-3 ファイルを閉じる
ファイルを開いて作業をした後は、ファイルを閉じる必要があります。
file.rbのコードを以下のようにしましょう。
コピーfile.rb12file =
File
.open(
"read_file.txt"
,
"r"
)
file.close
「file.close」という処理を追記しました。
上記のコードでは、read_file.rbというファイルを読み取り専用モードで開いて、そのままファイルを閉じる処理をしています。
このプログラムを実行してみると、ファイルを開いて閉じているだけなので、目に見える変化は起きません。
ファイルを閉じるためのプログラムは、以下のような書式になります。
コピー1変数.close
13-4 ファイルを読み込む
ファイルを開くことと閉じることができるようになったので、次はファイルの内容を出力するプログラムを作っていきます。
file.rbのコードを以下のようにして実行してみましょう。
コピーfile.rb1234file =
File
.open(
"read_file.txt"
,
"r"
)
f = file.read
puts(f)
file.close
新しく追加したのは2行目と3行目です。
2行目では「read」メソッドを使ってファイルの内容を読み出し、変数fに代入しています。 これで、変数fを使って開いたファイルの内容を参照できるようになります。
変数名はfileの先頭文字を取ってfとしていますが、fでなくてもかまいません。
3行目でファイルの内容をputsメソッドで出力しています。
そして4行目でファイルを閉じています。
readメソッドはファイルの内容を一気に読み込むことができますが、
- ファイルのデータをまとめて読み込むのに時間がかかる
- 一時的に全てのデータをメモリに貯めることになるので、大きなファイルの場合に困ることがある
といった問題があります。
100万行あるようなファイルでも、本当に必要なのは最初の数行だけ、ということもあります。 そのような場合、全てのファイルを読み込むまで何もしない、というのは、時間とメモリを無駄に使ってしまうことになります。
このような問題を解決するには、データを全て読み込んでから処理を開始するのではなく、一行ずつ読み込みながら処理をするというアプローチがあります。
file.rbのコードを以下のようにして実行してみましょう。
コピーfile.rb12345file =
File
.open(
"read_file.txt"
,
"r"
)
file.each_line
do
|line|
puts(line)
end
file.close
readメソッドではなく、each_lineメソッドを使うと、ファイルの内容を1行ずつ読み込むことができます。
また、2行目から4行目で繰り返し処理が行われています。
each_lineメソッドで読み込んだ1行分のデータを変数lineに格納し、3行目のputsメソッドでその内容を出力しています。
ファイルの末尾に達するまでその処理を繰り返します。
1行のデータを格納するので、変数名はlineにしましたが、変数名はなんでもかまいません。
以下のように書くと、ファイルを閉じる処理(file.close)を書かなくても、ファイルを全部読み込んだら自動的に閉じる処理を実行してくれるようになります。
コピー12345File
.open(
"read_file.txt"
,
"r"
)
do
|file|
file.each_line
do
|line|
puts(line)
end
end
どちらの書き方でもかまいませんが、ファイル操作の流れを理解するためにも、この章では最初の書き方で進めていきます。
13-5 行数をカウントする
ファイルを開いて読み込むところまでできるようになりました。
以下は、読み込んだファイルの内容に対し、行番号を追加する処理を実装していきます。
まずは、ファイルが何行あるのか調べてみましょう。 file.rbのコードを以下のようにして実行してみましょう。
コピーfile.rb123456file =
File
.open(
"read_file.txt"
,
"r"
)
file.each_line
do
|line|
puts(line)
end
puts(file.lineno)
file.close
5行目が追加された行です。
each_lineメソッドが実行される度に1つずつカウントされる「lineno」というメソッドを使っているため、ファイルの内容が出力された後に行数が出力されています。
もし出力するのが行数だけでよいのなら、以下のようなプログラムになるでしょう。
コピー12345file =
File
.open(
"read_file.txt"
,
"r"
)
file.each_line
do
|line|
end
print(
"line: "
, file.lineno)
file.close
しかし今回出力したいのは行番号なので、このlinenoメソッドを上手く活用して書き方を変えていきます。
13-6 行番号を追加する
さらにプログラムを少し変更して、行番号を左側に追加して出力するプログラムを作ってみましょう。
file.rbのコードを以下のようにして実行してみましょう。
コピーfile.rb123456file =
File
.open(
"read_file.txt"
,
"r"
)
file.each_line
do
|line|
print(file.lineno,
" : "
)
puts(line)
end
file.close
printメソッドとputsメソッドの違いですが、printメソッドは自動的に改行されず、putsメソッドは出力後に改行されます。
3行目のprintメソッドでは行番号と「:」を、4行目のputsメソッドではファイルの該当行(変数line)を出力します。
このプログラムだと、要件は満たしていますが、行番号の桁が増えると(10以降)本文も右側に1スペース分ずれてしまいます。
これを防ぐためには、最初から行番号の桁数を固定しておくと良いでしょう。
file.rbのコードを以下のようにして実行してみましょう。
コピーfile.rb123456file =
File
.open(
"read_file.txt"
,
"r"
)
file.each_line
do
|line|
printf(
"%4d : "
, file.lineno)
puts(line)
end
file.close
3行目のprintメソッドが、 printfメソッド に置き換わっています。
printfメソッドは2つの引数を取り、1つ目は文字列、2つ目は式になります。
文字列の中に「%d」のように書いておくと、その部分に式を評価した値(%dは整数)が入ります。
式の部分は変数も使用できます。
printfメソッドの書式は、以下のようになります。
コピー1printf(
"文字列"
, 式)
%dを「%4d」とすると、数値が4桁で出力されます。桁数を固定したい時に使います。
13-7 ファイルに書き込む
読み込んだファイルに行番号を追加して出力するところまでできるようになりました。
あとは行番号を追加した内容を、コンソールに出力するのではなくwrite_file.txtファイルに書き込む処理を実装すれば完成です。
file.rbが以下のようなコードになるよう修正して実行してみましょう。
コピーfile.rb123456789101112# ファイル読み込み
file =
File
.open(
"read_file.txt"
,
"r"
)
file.each_line
do
|line|
printf(
"%4d : "
, file.lineno)
puts(line)
end
file.close
# ファイル書き込み
file_w =
File
.open(
"write_file.txt"
,
"w"
)
file_w.puts(
"test"
)
file.close
write_file.txtに書き込む処理を追加しました。
openメソッドのモードは「w」にして、write_file.txtファイルに「test」という文字列を出力するようにしています。
上記のコードだと、ファイルの読み込み時にprintfとputsを使ってコンソールに出力していますが、まずこの部分を変更していきましょう。
write_file.txtに書き込むため、読み込んだ内容を配列に格納します。
コピーfile.rb1234567891011121314arrays =
Array
.
new
# 一行ずつ格納するための配列を準備
# ファイル読み込み
file =
File
.open(
"read_file.txt"
,
"r"
)
file.each_line
do
|line|
str = sprintf(
"%4d : "
+ line, file.lineno)
# 行番号をつけた文字列を作成
arrays.push(str)
# 行番号のついた文字列を配列に格納
end
file.close
# ファイル書き込み
file_w =
File
.open(
"write_file.txt"
,
"w"
)
file_w.puts(
"test"
)
file.close
sprintfは、printfと同じく文字列をフォーマットしてくれますが、出力はせずにフォーマットした文字列を返す役割を持ちます。
コンソールに出力したい場合はprintf、変数として取り扱いたい場合はsprintfを使います。
読み込んだファイルの内容を配列に格納することができたので、いよいよ配列の中身をwrite_file.txtに書き込んでいきます。
file.rbが以下のようなコードになるよう修正して実行してみましょう。
コピーfile.rb12345678910111213141516arrays =
Array
.
new
# 一行ずつ格納するための配列を準備
# ファイル読み込み
file =
File
.open(
"read_file.txt"
,
"r"
)
file.each_line
do
|line|
str = sprintf(
"%4d : "
+ line, file.lineno)
# 行番号をつけた文字列を作成
arrays.push(str)
# 行番号のついた文字列を配列に格納
end
file.close
# ファイル書き込み
file_w =
File
.open(
"write_file.txt"
,
"w"
)
arrays.
each
do
|arr|
file_w.puts(arr)
end
file.close
実行し、read_file.txtの内容に行番号を追加したものが、write_file.txtに書き込まれていれば成功です。
13-8 まとめ
ファイル操作は、基本的に以下のような流れになります。
- ファイルを開く
- ファイルを読み込み/書き込み
- ファイルを閉じる
処理する内容が複数行ある場合は、配列を使うと便利です。