【Ruby】Lesson3-6|例外処理の基本を理解しよう

一つ前のページではエラーメッセージについて学習しました。
今回は 例外処理 について見ていきましょう。
Lesson1:基礎文法編
Lesson2:制御構造編
Lesson3:メソッド編
 ・Lesson3-1:メソッドの基本を理解しよう
 ・Lesson3-2:デフォルト引数とキーワード引数を理解しよう
 ・Lesson3-3:メソッドの戻り値を理解しよう
 ・Lesson3-4:真偽値を返すメソッドを理解しよう
 ・Lesson3-5:エラーメッセージを読めるようになろう
 ・Lesson3-6:例外処理を理解しよう ◁今回はココ
 ・確認問題3-☆1:石取りゲームを作ろう
 ・確認問題3-☆2:丁半賭博ゲームを作ろう
Lesson4:コレクション編
Lesson5:オブジェクト指向編
例外処理とは?|基本構文と活用例を学ぼう

プログラムは実行中に予期しないエラーが発生することがあります。
たとえばファイルが存在しない場合にファイルを読み込もうとしたり、ゼロで割ろうとしたときなどです。
このようなエラーに対して、事前に対処する方法を「例外処理」と呼びます。
Rubyでは例外処理を使うことで、エラーが発生してもプログラムが強制終了せず、適切な対応をとることができます。
例外処理の基本構文|begin〜rescueの使い方
Rubyで例外処理を行うには begin〜rescue構文 を使います。
以下が基本的な例外処理の構文です。
begin # エラーが発生する可能性のある処理 rescue # エラーが発生した場合に実行する処理 end
この構文ではbeginブロック内にエラーが発生しうる処理を記述し、その下にrescueブロックを置きます。
rescueブロック内のコードは、エラーが発生した際に実行されます。
これによりプログラムが異常終了せず、指定した方法でエラーに対処することが可能です。
例外処理を実装したコードの例
次に具体的な例を見てみましょう。
以下はゼロで割り算を試みる場合の例です。
puts "割り算を行います。"
begin
  result = 10 / 0  # ゼロで割ることでエラーが発生します
  puts "結果: #{result}"
rescue
  puts "エラーが発生しました:ゼロで割ることはできません。"
endこのコードでは10 / 0によってゼロ除算のエラーが発生しますが、rescueブロックが実行され、「エラーが発生しました:ゼロで割ることはできません。」というメッセージが表示されます。
通常であればゼロ除算のエラーでプログラムが異常停止しますが、例外処理を使うことでエラーに対して適切なメッセージを出し、プログラムを続行させることができます。
まとめ|エラー処理の注意点と使い所の見極め方

例外処理は必ずしもすべてのエラーに対して使うべきではありません。
たとえばエラーが発生した場合の挙動をプログラムの設計上重要なポイントとして扱うべき場合や、あえてエラーを発生させることで早期に問題を発見したい場合などもあります。
例外処理を使う場面を見極め、必要な箇所でのみ使うことが重要です。
Rubyの例外処理は非常にシンプルでわかりやすいため、エラー処理が必要な箇所にうまく取り入れて、プログラムの信頼性と安定性を向上させましょう。
練習問題|例外処理を使って割り算エラーを回避しよう

例外処理をしっかりと身に着けるため、練習問題に挑戦しましょう。
「例外処理」の練習問題
例外処理を使って、ゼロで割った場合にエラーメッセージを表示する割り算プログラムを作成してください。
ユーザーから2つの数値を入力させ、2つ目の数値がゼロでない場合は割り算を行い、ゼロの場合はエラーメッセージを表示します。
以下の要件に従ってコードを完成させてください。
- ユーザーに2つの数値を入力させ、それぞれ変数
num1とnum2に格納すること。 begin-rescue-end構文を使用して、ゼロ除算エラーを処理すること。- ゼロで割った場合、
rescueブロック内で「ゼロで割ることはできません」というエラーメッセージを表示すること。 - 割り算が成功した場合、計算結果を「
num1/num2= 結果」という形式で表示すること。 
ただし、以下のような実行結果となること。
最初の数値を入力してください: 10 二番目の数値を入力してください: 2 結果:10 / 2 = 5
最初の数値を入力してください: 10 二番目の数値を入力してください: 0 エラー:ゼロで割ることはできません。
【ヒント】自力で解くのが難しい人へ
1からコードを組み立てることが難しい場合は、以下のヒントを開いて参考にしましょう。
- ヒント1【コードの構成を見る】
 - 
正解のコードは上から順に以下のような構成となっています。
1:
puts "最初の数値を入力してください:"によりメッセージを出力
2:ユーザーの入力を取得し、整数型に変換して変数num1に代入
3:puts "二番目の数値を入力してください:"によりメッセージを出力
4:ユーザーの入力を取得し、整数型に変換して変数num2に代入
5:beginにより例外処理の開始を宣言
□ 変数resultにnum1をnum2で割った結果を代入
□putsにより計算結果を出力
6:rescue ZeroDivisionErrorでゼロ除算エラーの発生を検出
□putsによりエラーメッセージ「ゼロで割ることはできません。」を出力
7:endにより例外処理の終了 
- ヒント2【穴埋め問題にする】
 - 
以下のコードをコピーし、コメントに従ってコードを完成させて下さい。
# ユーザーに最初の数値を入力させる puts "最初の数値を入力してください:" num1 = gets.chomp.to_i # ユーザーに二番目の数値を入力させる puts "二番目の数値を入力してください:" num2 = gets.chomp.to_i =begin 【穴埋め問題1】 ここで例外処理の開始を宣言してください。例外が発生する可能性のある処理を囲むコードを書いてください。 =end # 割り算を行う result = num1 / num2 puts "結果:#{num1} / #{num2} = #{result}" =begin 【穴埋め問題2】 ここでゼロで割った場合の例外を捕捉し、エラーメッセージを表示するコードを書いてください。 =end =end 
このヒントを見てもまだ回答を導き出すのが難しいと感じる場合は、先に正解のコードと解説を見て内容を理解するようにしましょう。
この問題の解答例と解説
この問題の正解コードとその解説は以下の通りです。
クリックして開いて確認してください。
- 正解コード
 - 
# ユーザーに最初の数値を入力させる puts "最初の数値を入力してください:" num1 = gets.chomp.to_i # ユーザーに二番目の数値を入力させる puts "二番目の数値を入力してください:" num2 = gets.chomp.to_i begin # 割り算を行う result = num1 / num2 puts "結果:#{num1} / #{num2} = #{result}" rescue ZeroDivisionError # ゼロで割った場合の例外処理 puts "エラー:ゼロで割ることはできません。" end 
- 正解コードの解説
 - 
コードをブロックごとに分割して解説します。
ユーザーからの入力部分
puts "最初の数値を入力してください:" num1 = gets.chomp.to_i puts "二番目の数値を入力してください:" num2 = gets.chomp.to_i
まず
putsを使ってユーザーに数値を入力してもらいます。getsで入力を受け取り、chompメソッドで改行を取り除きます。その後
to_iを使って文字列を整数に変換します。このようにして2つの数値をnum1とnum2という変数に格納します。割り算と例外処理部分
begin result = num1 / num2 puts "結果:#{num1} / #{num2} = #{result}" rescue ZeroDivisionError puts "エラー:ゼロで割ることはできません。" endここで重要なのがRubyの「例外処理」です。
begin-rescue-endという構文を使って、割り算中にエラーが発生してもプログラムがクラッシュしないようにします。rescueブロック: もしnum2が0の場合、ZeroDivisionErrorというエラーが発生します。このエラーはrescueブロックで捕捉され、「ゼロで割ることはできません」というエラーメッセージを表示します。このようにして、エラーを適切に処理することでプログラムが異常終了することを防ぎます。beginブロック: この中には、エラーが発生する可能性のあるコードを書きます。この場合、num1 / num2という割り算が行われます。num2が0でない場合は割り算が正常に実行され、その結果がresultに代入されます。putsで結果を表示します。 
まとめ
例外処理はプログラムの動作中に予期せぬエラーが発生した場合でも、プログラム全体がクラッシュするのを防ぐために使われます。
Rubyではbegin-rescue-endを使って、特定のエラーが発生したときにどのように対処するかを定義できます。
FAQ|Rubyの例外処理とエラーハンドリング
- Q1. Rubyで複数のエラータイプをrescueで個別に処理するにはどうすればよいですか?
 - 
Rubyでは
rescue節にエラーの種類を指定することで、特定の例外にだけ反応させることができます。複数のエラータイプに対処したい場合は、rescue ZeroDivisionError,rescue StandardError => eのように複数書くことで、詳細なエラーハンドリングが可能です。 
- Q2. begin-rescue構文の中でensureやelseを使うべき場面とは?
 - 
ensureは、例外の有無にかかわらず必ず実行したい処理(たとえばファイルのクローズなど)に使用します。一方、elseは例外が発生しなかった場合だけに実行したい処理に用いるため、処理の流れをより明確に制御したいときに有効です。 
- Q3. rescue節で捕捉できない例外にはどのようなものがありますか?
 - 
SystemExitやNoMemoryErrorなど、一部の例外はrescueで捕捉できないか、あるいは捕捉すべきでないとされます。こうした例外はプログラム全体の終了や異常なリソース不足を示すため、通常のエラーハンドリングではなく、システム的な対応が求められます。 



