next up previous
Next: 今回のテキストと演習問題 Up: 逆ポーランド記法電卓のプログラム Previous: 逆ポーランド記法電卓のプログラム

実際のプログラム

プログラムの作成のためには, プログラムの動作や, 全体の設計を もう少し詰めなければ書けません. ここでは, 次のような仕様にしました.

  1. 計算する型は int 型とし, 演算は 4則のみを許す.
  2. スタックは配列 stack[STACKSIZE]として外部変数で確保.
  3. スタックの深さを示す変数も外部変数で確保.
  4. stack[0] には何も入れず, スタックの深さの値が 0 のときには stack は空であると判断する.
  5. ENTER キーが押された時点で, その行を評価する. 行の計算式に意味があれば, 答を出し, スタックを初期化する. そうでなければエラーメッセージを出して スタックを初期化する
  6. 計算として無効な入力がされた場合は, スタックを初期化する.
  7. 長過ぎる入力がされた場合は, スタックを初期化する.

入力文字列を逐次数であるか演算子であるかを見る必要がありますが, 次の処理をしています.

  1. 1文字を読み込む.
  2. 入力が数から始まれば数だと判断してその文字を戻し scanf で数として 値を取得してスタックに積む.
  3. 空白なら語の区切りと判断する.
  4. 演算子の文字 + - * / なら, 演算を実行してスタックに積む.
  5. 改行文字(ENTER)なら, その時点での計算を表示してスタックを初期化.
  6. それ以外の文字なら, 入力エラーしてスタックを初期化.

上の方針で書いたのが次のプログラムです。 方針の 2以降は, case文を用いて分岐しています.

#include <stdio.h>

#define STACKSIZE 1024

int stack[STACKSIZE];

int n=0;

void push(int x)
{
        if ( n >= STACKSIZE){
                fprintf(stderr, "stack overflow\n");
                n=0;
        }
        n++;
        stack[n]=x;
}

int pop()
{
/**************************************************

       レポート問題

***************************************************/
}

main()
{
        int c;
        long x, a, b;

        while ((c=getchar())!=EOF){
                if (isdigit(c)){
                        ungetc(c, stdin);
                        scanf("%d", &x);
                        push(x);
                }
                else {
                        switch(c) {
                        case '+':
                                b=pop();
                                a=pop();
                                push(a+b);
                                break;
                        case '-':
                                b=pop();
                                a=pop();
                                push(a-b);
                                break;
                        case '*':
                                b=pop();
                                a=pop();
                                push(a*b);
                                break;
                        case '/':
                                b=pop();
                                a=pop();
                                push(a/b);
                                break;
                        case '\n':
                                if (n==1){
                                        printf("The answer is %d.\n", pop());
                                }
                                else {
                                        printf("Invalid expression.\n");
                                        n=0;
                                }
                        case ' ':
                                break;
                        case '\t':
                                break;
                        default:
                                printf("Invalid input.\n");
                                n=0;
                                break;
                        }
                }
        }
}

コンパイルが終れば, ./a.out でプログラムが起動するはずです. 逆ポーランド記法で計算式を入力してみて下さい. 演算子や被演算子の等の区切りは, 空白で入れます. 終了は CTRL+d です.



Next: 今回のテキストと演習問題 Up: 逆ポーランド記法電卓のプログラム Previous: 逆ポーランド記法電卓のプログラム