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); }
②乗算、除算を処理するための関数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); }
③primary_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); }
④unget_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; }