パソコン活用研究シリコンバレー(C、C++、の活用研究)



Cで計算機を作る(乗算、除算)
―準備中―

C言語で計算機を作ってみます。前回はは足し算、引き算だけの基本形からやってみました。
→「Cで計算機を作る(足し算、引き算)

今回は乗算(掛け算)、除算(割り算)、カッコ( )を使えるようにしてみます。

プログラムはVB.netで作ったプログラムをC用に改変したものなので、
プログラムの説明は「VB.netで計算機を作る(乗算、除算)」をご参照下さい。

今回は、前回「Cで計算機を作る(足し算、引き算)」から変更のあった点のみ説明を書きます。
主要な変更・追加点は、以下の2つです。
・乗算・除算を処理するための関数として、termという関数を追加し
演算のための基本的な関数はexpression, term, primary_expression, get_tokenの4つにします。

・括弧( )の処理は、primary_expressionの中で行い、expressionを再帰的に呼び出すことで
実装します。

以下、変更箇所の説明です。

@expression()関数では乗算、除算処理のため
primary_expressionを呼び出していたのをtermをコールするように変更します。
(A) v1=primary_expression(); => v1=term();  
同様に(B) v2 = term(); に変更

double expression() {
        double v1, v2;
        token t;
        
        v1=term();   /* (A)  */
        printf("expession v1:%lf\n",v1);
        
        while (1){
            get_token(&t);
            printf("expression %s: %d : %d\n", t.str, t.type, t.v);
        if (t.type != add_op && t.type != sub_op) { unget_token(); break;}
            v2 = term();   /* (B) */
            printf("expression v2:%lf\n", v2);
        if (t.type == add_op)  v1 = v1 + v2;
        if (t.type == sub_op)  v1 = v1 - v2;
            printf("expression calculated  v1:%lf\n", v1);
        }

        return (v1);
}

A乗算、除算を処理するための関数term()を追加

double term() {
    double v1, v2;
        token t;
        
        v1=primary_expression();
        printf("term v1:%lf\n",v1);
        
        while (1){
            get_token(&t);
            printf("term %s: %d : %d\n", t.str, t.type, t.v);
        if (t.type != mul_op && t.type != div_op) { unget_token(); break;}
            v2 = primary_expression();
            printf("term v2:%lf\n", v2);
        if (t.type == mul_op)  v1 = v1 * v2;
        if (t.type == div_op)  v1 = v1 / v2;
            printf("term calculated  v1:%lf\n", v1);
        }

        return (v1);    
}

Bprimary_exptression()関数では
(c) のif文で括弧( )の処理の追加
左括弧"(" (type.lparen)が来たら、関数expressionを再帰的に呼び出す。
( ) 内の処理が終わるとexpressionからの戻り値をvに保存し、次のtokenで右括弧")" (type.rparen)が来たら
vをreturnする。


double primary_expression() {
         token t;
        double v;
        get_token(&t);
        printf("primary_expression %s: %d : %d \n", t.str, t.type, t.v);
        if (t.type == number)  return (t.v);
 /* (C) */   if (t.type == lparen) 
                        {v=expression(); get_token(&t);
                                        if (t.type==rparen) {return(v);} else printf("raparen is missing");}
        else return (0);
 }


Cunget_token()関数で
unget=1 というフラグを立てる。

これによりget_token()関数内でもungetのフラグが経っているときの処理を追加


void get_token(token *t) {
         static int i = 0;
        if (unget == 1) {i=i-1; unget=0;} 
        printf("get_token %d: %s : %d : %d \n", i, tok[i].str, tok[i].type, tok[i].v);
        /* Assign the structure  *t=toku[i]  */
        *t=tok[i];
        i++;
}

void unget_token() {
        unget=1;
}



TopPage