Top >コンソール・アプリケーション集

逆ポーランド記法電卓 C++

#include    <stdio.h>
#include    <conio.h>
#include    <math.h>


#define     STACK_SIZE  10  // スタックサイズ
#define     NUM_DIGITS  8   // 最大桁数

/**************************************************
* 入力処理の結果
**************************************************/

typedef enum _OPERATION
{
    OPE_PLUS,       // 足し算
    OPE_MINUS,      // 引き算
    OPE_MULTIPLY,   // 掛け算
    OPE_DIVIDE,     // 割り算
    OPE_INVERSION,  // 符号反転
    OPE_CLEAR,      // クリア
    OPE_ENTER,      // 入力
    OPE_EXIT        // 終了
}OPERATION;

/**************************************************
* スタックを実現するクラス
**************************************************/

class CalcStack
{
private:
    double  mValues[STACK_SIZE];    // 数値配列
    int     mCount=0;               // 要素数

public:
    ///////////////////////////////////////////////
    // スタックに関するエラーの内容
    ///////////////////////////////////////////////
    enum STACK_ERROR
    {
        ERR_OVERFLOW,   // オーバーフロー
        ERR_PARAM,      // パラメータが不正
        ERR_EMPTY       // スタックが空
    };

    ///////////////////////////////////////////////
    // スタックに対するPush
    // value:Pushする数値
    ///////////////////////////////////////////////
    void Push(double value)
    {
        if (mCount >= STACK_SIZE)
            throw ERR_OVERFLOW;

        mValues[ mCount++] = value;
    }

    ///////////////////////////////////////////////
    // スタックに対するPop
    // return:Popされた数値
    ///////////////////////////////////////////////
    double Pop()
    {
        if (mCount <= 0)
            throw ERR_EMPTY;

        return mValues[ --mCount];
    }

    ///////////////////////////////////////////////
    // スタックの要素数
    // return:要素数
    ///////////////////////////////////////////////
    int Count() const
    {
        return mCount;
    }

    ///////////////////////////////////////////////
    // 指定した位置の要素を得る
    // n:取得する要素の位置
    ///////////////////////////////////////////////
    double GetValue(int n)  const
    {
        if (n < 0 || n >= mCount)
            throw ERR_PARAM;

        return mValues[n];
    }
};

///////////////////////////////////////////////////
// 入力処理
// pstack:CalcStackクラスへのポインタ
// return:OPERATION
///////////////////////////////////////////////////
OPERATION Input(CalcStack& rstack)
{
    char        number[NUM_DIGITS + 1];
    int         cntnum = 0;
    OPERATION   ope = OPE_ENTER;

    for (;;)
    {
        int ch = _getche(); // 文字を入力

        if ('0' <= ch && ch <= '9' || ch == '.')
        {
            // 数字と小数点の場合

            if (cntnum < NUM_DIGITS)
            {
                number[cntnum++] = (char)ch;
                number[cntnum] = 0;
            }
        }
        else{
            // 演算の場合

            if (ch == '+')
                ope = OPE_PLUS;
            else if (ch == '-')
                ope = OPE_MINUS;
            else if (ch == '*')
                ope = OPE_MULTIPLY;
            else if (ch == '/')
                ope = OPE_DIVIDE;
            else if (ch == '!')
                ope = OPE_INVERSION;
            else if (ch == 'c' || ch == 'C')
                ope = OPE_CLEAR;
            else if (ch == 'q' || ch == 'Q')
                ope = OPE_EXIT;

            break;  // 入力を終了
        }
    }

    // 数字の入力があれば、スタックにプッシュする。
    if (cntnum > 0)
        rstack.Push( atof(number));

    return ope;
}

///////////////////////////////////////////////////
// 電卓画面を表示
// rstack:CalcStackへの参照
///////////////////////////////////////////////////
void ShowCalculator(const CalcStack& rstack)
{
    int     i;

    printf("\n/// RPN Calculator ///////////////////////////////");
    printf("\n///  +:加 -:減 *:乗 /:除 !:符号 c:削除 q:終了  ///\n");

    // スタックの内容を表示する

    for (i = 0; i < rstack.Count(); i++)
        printf("%2d:%f\n", rstack.Count() - i, rstack.GetValue(i));

    printf(">");
}

///////////////////////////////////////////////////
// main
///////////////////////////////////////////////////
void main(void)
{
    CalcStack   stack;

    for (;;)
    {
        OPERATION operation;

        try{
            // 電卓画面を表示
            ShowCalculator(stack);

            // 入力
            operation = Input(stack);

            // 必要な個数の数値をポップして演算を施し、結果をプッシュする

            if (operation == OPE_INVERSION || operation == OPE_CLEAR){
                // 必要とする数値が1つの操作

                double n = stack.Pop();     // ポップする

                if (operation == OPE_INVERSION)     // 符号反転
                    stack.Push(n * (-1.0));
            }
            else if (operation == OPE_PLUS || operation == OPE_MINUS
                || operation == OPE_MULTIPLY || operation == OPE_DIVIDE)
            {
                // 必要とする数値が2つの操作

                double  n1 = stack.Pop();   // ポップする
                double  n2 = stack.Pop();   // ポップする

                if (operation == OPE_PLUS)          // 加算
                    stack.Push( n1 + n2);
                else if (operation == OPE_MINUS)    // 減算
                    stack.Push( n2 - n1);
                else if (operation == OPE_MULTIPLY) // 乗算
                    stack.Push( n1 * n2);
                else if (operation == OPE_DIVIDE)   // 除算
                {
                    if (n1 == 0.0)  // 0での除算
                        printf("\nDivide by Zero!\n");
                    else
                        stack.Push( n2 / n1);
                }
            }
            else if (operation == OPE_EXIT)
            {
                // プログラムの終了
                break;
            }
        }
        catch (CalcStack::STACK_ERROR err)
        {
            if (err == CalcStack::ERR_OVERFLOW)
                printf("\nOverflow!\n");
            else
                printf("\nError!\n");
        }
    }
}
PAPER BOWL
NEZEN