網絡学習管理 C言語演習 Reverse Polish Notation Calculator

Reverse Polish Notation Calculator

逆ポーランド記法

逆ポーランド記法

逆ポーランド記法を使えば、式の計算をする(評価)には、先頭からひとつずつ順番に記号を読み込み、その記号が演算子以外であればスタックに値を積み、演算子であればスタックから値を取り出して演算し結果をスタックに積む、という簡単な操作の繰り返しだけでよい。そのため、プログラミング初心者の練習課題として、逆ポーランド記法の電卓を作ることがよく行われる。

逆ポーランド記法による計算の例

2+3を計算するとき,逆ポーランド記法では,次のように表す.数値や演算子(+, -, *, /)の間にはスペースを設ける.

2 3 +

これはいくつかのメモリー(記憶場所)が準備されているとき,

  • 2を1番目のメモリーに記憶
  • 3を2番目のメモリーに記憶
  • 1番目のメモリーの内容と2番目のメモリーの内容を加算
  • 加算結果を1番目のメモリーに記憶

という手順で計算することを表している.

特徴:

  1. 日本語の並びと同じ計算順序
  2. 逆ポーランドには括弧がない
  3. キータッチ数は最少

o0125007411785329651

【中置記法】
3 * ( 1 + 2 ) / ( ( 4 – 5 ) / ( 6 + 7 ) ) =  キータッチ数は22回

【逆ポーランド記法】
3 1 2 + * 4 5 – 6 7 + / /           キータッチ数は13回

問題

次のような機能を持つ電卓プログラムを実現せよ。

    1. 基本機能
      1. 演算子は+,-,*,/を許す。
      2. 被演算子にはdouble型を許す。
      3. 式の記法には逆ポーランド記法を用いよ。
      4. 演算子=により結果を表示する。
    2. 数学関数
      1. sin,cos,tan,exp,sqrなど

文字列解析、配列によるスタック実装など、総合的な演習問題としてよく使われます。K&Rにも同様の演習があります。

回答例

#define STACK_DEPTH 100
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<ctype.h>
#include<math.h>

double stack[STACK_DEPTH];
int sp=STACK_DEPTH;

double pop(void){ return (sp<STACK_DEPTH)?stack[sp++]:0.0; }
void push(double f){ if(sp>0)stack[--sp]=f; }
int getword(char* dst, const char* str, int limit) {
    int i, j, len = strlen(str);
    for(i=0; i<len && isspace(str[i]); i++);
    for(j=0; j<limit && (j+i)<len && !isspace(str[i+j]); j++) dst[j]=str[i+j];
    dst[j]='\0';
    return i+j;
}

int main(void)
{
    char line[100], tmp[100];
    int i, c;
    while(1){
        i = 0;
        fgets(line, 100, stdin);
        while((c=getword(tmp, &line[i], 100)) && strlen(tmp)){
            if(strcmp(tmp, "sin")==0) push(sin(pop())); else
            if(strcmp(tmp, "cos")==0) push(cos(pop())); else
            if(strcmp(tmp, "sqr")==0) push(pow(pop(),2)); else
            if(strcmp(tmp, "+")==0) push(pop()+pop()); else
            if(strcmp(tmp, "-")==0) push(pop()-pop()); else
            if(strcmp(tmp, "*")==0) push(pop()*pop()); else
            if(strcmp(tmp, "/")==0) push(pop()/pop()); else
            if(strcmp(tmp, "=")==0) printf("%f\n", pop()); else
            push(atof(tmp));
            i+=c;
        }
        if (line[0] == '\n') break;
    }
    return 0;
}

 

1 thought on “Reverse Polish Notation Calculator”

Leave a Reply

Your email address will not be published. Required fields are marked *

CAPTCHA


Related Post

a C HTTP Clienta C HTTP Client

C#やJavaでは簡単にhttp Clientプログラムができる。C言語ではソケットを作成するところから必要です。またWindowsとLinux両方対応するように書いたのでプログラムが長くなる。 (bcc32で動作確認済み) プログラムは、最初にsocketを生成してWebサーバに接続し、テキスト形式でHTTPリクエストメッセージを作成してWebサーバに送信する。 HTTPリクエストメッセージは、複数行から成り立つ一連のデータ列。ここでいう1行とは、終端にCR(キャリッジリターン、16進の0x0d)とLF(ラインフィード、16進の0x0a)を持つデータの単位を示す。ほぼ、通常のテキスト・データの1行と等しくなる。メッセージ・ヘッダとメッセージボディ部に分かれ、両者は空行(単独のCR+LF)で分割される。 httpを理解するには、telnetで手入力でHTTPをしゃべってみるがいい方法。 https://www.softel.co.jp/blogs/tech/archives/263 まずプログラムをリストする: #include <stdio.h> /* printf, sprintf */ #include <stdlib.h> /* exit, atoi, malloc, […]

Dump fileDump file

DUMP で出力された内容を ダンプリスト と呼ぶ ダンプリスト左端はアドレス(ファイル先頭からの位置) ダンプリスト中央にある16進数(バイト)が列挙されてる部分がマシン語プログラム(バイトコード)を表している。 ダンプリスト右端は、バイトコードをキャラクタコードで表現したときの内容。ただしバイトで表現可能な数値はキャラクタコードの範疇を超えることがあるため、そのような場合はピリオドで表現される。 dump.c #include <stdio.h> int main(int argc, char* argv[]) { FILE *fp; unsigned char buf[16]; /* 読み込みバッファ […]

CalculatorCalculator

電卓プログラムの考え方、書き方例 2つの数値の加減乗除をする電卓のようなプログラムを作ります。 簡単なようですが、多くの話題(データ型の選択、入力、判断や繰り返しなど)を含んでおり、学習に役立つ例題です。 今回は、プログラムをつくる流れも分かるように、どんなプログラムにするか検討するところから始めます。 それを処理手順に書き、C言語のコードに直します。 プログラムの機能を考える まずは、どんなプログラムにするかを考え、前提とすることや制約についても検討します。 数や演算の指定はどうする? たとえば「2 + 5」のように、「数値1 演算記号 数値2」の順に入力すると計算結果が表示されるようにする。 演算記号は、+, -, *, / のみとする。 繰り返して計算できるようにする 繰り返しの終了は、指定が上記の書式でなかったときとしよう。 […]