C++
 Computer >> コンピューター >  >> プログラミング >> C++

C++におけるゼロ除算例外の処理方法を実例付きで解説

本記事では、C++プログラミングにおいてゼロ除算(0による割り算)の例外を適切に処理する方法を、具体的なコード例とともに解説します。

数学においてゼロによる除算は未定義の演算です。そのため、プログラム内でゼロ除算が発生すると、実行時エラーや予期しない動作につながる可能性があります。ユーザー側でエラーが発生しないよう、事前に適切な例外処理を実装しておくことが重要です。

1. runtime_errorクラスを使用する方法

C++の標準ライブラリには、実行時エラーを表すstd::runtime_errorクラスが用意されています。ゼロ除算を検出した時点でこの例外をスローし、呼び出し元で捕捉するのが最も基本的なアプローチです。

コード例

#include <iostream>
#include <stdexcept>
using namespace std;

// ゼロ除算を処理する関数
float Division(float num, float den) {
    if (den == 0) {
        throw runtime_error("Math error: Attempted to divide by Zero\n");
    }
    return (num / den);
}

int main() {
    float numerator, denominator, result;
    numerator = 12.5;
    denominator = 0;
    try {
        result = Division(numerator, denominator);
        cout << "The quotient is " << result << endl;
    }
    catch (runtime_error& e) {
        cout << "Exception occurred" << endl << e.what();
    }
}

実行結果

Exception occurred
Math error: Attempted to divide by Zero

この例では、分母が0の場合にruntime_errorオブジェクトをスローします。tryブロック内でDivision関数を呼び出し、例外が発生した場合はcatchブロックで捕捉してエラーメッセージを表示しています。例外オブジェクトのwhat()メソッドを呼び出すことで、スロー時に設定したメッセージを取得できます。

2. ユーザー定義の例外クラスを使用する方法

より柔軟な例外処理を実現したい場合は、runtime_errorクラスを継承した独自の例外クラスを定義する方法が有効です。プロジェクト固有のエラー情報を持たせたり、複数種類の例外を区別したりできるようになります。

コード例

#include <iostream>
#include <stdexcept>
using namespace std;

// 例外処理用のユーザー定義クラス
class Exception : public runtime_error {
public:
    Exception()
        : runtime_error("Math error: Attempted to divide by Zero\n") {
    }
};

float Division(float num, float den) {
    if (den == 0)
        throw Exception();
    return (num / den);
}

int main() {
    float numerator, denominator, result;
    numerator = 12.5;
    denominator = 0;
    // tryブロックからDivision関数を呼び出す
    try {
        result = Division(numerator, denominator);
        cout << "The quotient is " << result << endl;
    }
    catch (Exception& e) {
        cout << "Exception occurred" << endl << e.what();
    }
}

実行結果

Exception occurred
Math error: Attempted to divide by Zero

ここではExceptionという独自クラスを定義し、コンストラクタの初期化リストで基底クラスであるruntime_errorにエラーメッセージを渡しています。これにより、標準例外の機能を保ちながら、独自の例外型として扱うことが可能になります。

3. スタック巻き戻し(Stack Unwinding)を利用する方法

C++の例外機構では、例外がスローされると、それを捕捉するcatchブロックが見つかるまで呼び出しスタックを遡っていきます。この仕組みを「スタック巻き戻し」と呼びます。この特性を利用すれば、深い階層の関数で発生した例外を、上位の呼び出し元で一括して処理できます。

コード例

#include <iostream>
#include <stdexcept>
using namespace std;

// 例外を処理するための関数
float CheckDenominator(float den) {
    if (den == 0) {
        throw runtime_error("Math error: Attempted to divide by zero\n");
    }
    else
        return den;
}

float Division(float num, float den) {
    return (num / CheckDenominator(den));
}

int main() {
    float numerator, denominator, result;
    numerator = 12.5;
    denominator = 0;
    try {
        result = Division(numerator, denominator);
        cout << "The quotient is " << result << endl;
    }
    catch (runtime_error& e) {
        cout << "Exception occurred" << endl << e.what();
    }
}

実行結果

Exception occurred
Math error: Attempted to divide by zero

この例では、分母のチェックを専用のCheckDenominator関数に切り出しています。mainDivisionCheckDenominatorという呼び出し階層の中で例外が発生しても、スタック巻き戻しによって自動的にmain関数のcatchブロックまで伝播し、そこで適切に処理されます。

まとめ

ゼロ除算はプログラムのクラッシュや不正な動作を引き起こす典型的なエラーの一つです。C++では以下の3つのアプローチで対処できます。

  • runtime_errorクラス: 標準ライブラリの例外を使ったシンプルで基本的な方法
  • ユーザー定義例外クラス: 独自のエラー情報を持たせたい場合に有効な拡張的な方法
  • スタック巻き戻し: 呼び出し階層の深い場所で発生した例外を上位で一括処理する方法

状況に応じて適切な手法を選択し、堅牢でユーザーフレンドリーなプログラムを目指しましょう。

  1. C++で解く迷路問題:転がるボールが目的地に止まれるかをBFSで判定する方法

    迷路の中にボールがあるとします。迷路には空きスペース(通路)と壁があります。ボールは上下左右のいずれかの方向に転がって空き通路を進むことができますが、壁にぶつかるまで止まりません。ボールが停止したときに、次の方向を選べます。この問題では、ボールの開始位置、目的地、そして迷路そのものが与えられ、「ボールが目的地の位置で停止できるかどうか」を判定する必要があります。迷路は2次元配列で表現され、1は壁、0は空きスペースを意味します。迷路の外周はすべて壁になっています。開始位置と目的地は行・列のインデックス(座標)で与えられます。問題例たとえば、次のような2次元配列で表される迷路を考えてみましょう。0

  2. C++の例外処理入門!try・catch・throwの基本と標準例外クラス一覧

    C++における例外処理(Exception Handling)とは、プログラムの実行時に発生するエラー(ランタイムエラー)を適切に扱うための仕組みです。例外とは、実行時に送出(スロー)されるイベントのことで、C++ではすべての標準例外が std::exception クラスから派生しています。もし例外を捕捉しなかった場合、例外メッセージが出力され、プログラムは強制終了してしまいます。 C++標準では、例外関連のクラスが <exception> ヘッダに定義されており、プログラムの中で自由に利用できます。親子関係によるクラス階層は次のようになっています。 C++の主な標準例外クラス