C言語アルゴリズム-計算式 |
計算式を演算子の優先順位にしたがって計算し、結果を表示する。演算子には、四則演算(+,-,*,/)が使用でき、括弧による演算順位の変更もできる。扱える数値は、実数(double型)で1E2のような指数表現も可能である。このようなプログラム(関数)を作成する。
例1) 11 + 20 * 30 答え=611
例2) (1.12 + 2.24 - 3) * 1e3 答え=360
計算式を評価するには、読み込んだ計算式を数値と演算子に分解しなければならない。分解して単語(数値と演算子)を取り出す関数get_tokenについては別ファイル(gettoken.c)として作成してあるものとする。
例1)の場合、関数get_token()で計算式を 11, +, 20, *, 30 に分解しながら1つずつ取り出して、下のチャートにしたがって処理をしていく(図の下に処理の説明)。
下のチャートは、流れ線に沿って処理を進めていく。○は末端記号といい実際の文字・記号であり、□は別のところで定義されているもので非末端記号という。
項A、項BなどのA,Bは、説明のために便宜的に付けたもので、両者に違いはない。
この手法を再帰的下向き構文解析という。この他に計算式を処理する方法として、逆ポーランド記法(これも再帰的下向き構文解析の手法を使用している)等がある。
入力された計算式(数式)を評価(evaluation)する。
コンパイルは、次のようにする。
MS-DOS> cc eval.c gettoken.c または MS-DOS> cc -c gettoken.c MS-DOS> cc eval.c gettoken(.obj) |
UNIX% gcc -o eval eval.c gettoken.c UNIX% gcc -c -o gettoken.o gettoken.c UNIX% gcc -o eval eval.c gettoken.o |
[eval.c]
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: |
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include "gettoken.h" /* 関数プロトタイプ宣言 */ double expression(void); /* 式 */ double term(void); /* 項 */ double factor(void); /* 因子 */ double number(void); /* 数値データ */ void main(void) { double ans; while(1){ printf("計算式 : "); gets(gt_line); get_token(); if(*token == '\0') break; ans = expression(); printf("答え=%g\n", ans); } } double expression(void) /* 式 */ { double ans; ans = term(); while(1){ if(*token == '+'){ get_token(); ans = ans + term(); }else if(*token == '-'){ get_token(); ans = ans - term(); }else break; } return(ans); } double term(void) /* 項 */ { double ans, x; ans = factor(); while(1){ if(*token == '*'){ get_token(); ans = ans * factor(); }else if(*token == '/'){ get_token(); x = factor(); if(x == 0){ printf("0では割れない\n"); exit(1); } ans = ans / x; }else break; } return(ans); } double factor(void) /* 因子 */ { double ans; if(*token == '('){ get_token(); ans = expression(); if(*token != ')'){ printf(")がない\n"); exit(1); } get_token(); return(ans); }else return(number()); } double number(void) /* 数値データ */ { double ans; char sign; if(*token == '+' || *token == '-'){ sign = *token; get_token(); } ans = atof(token); get_token(); if(sign == '-') return(-ans); return(ans); } |
計算式 : 11+20*30
答え=611
計算式 :
|
繰り返し実行できるようになっている。「計算式 : 」でリターンキーだけを押せばプログラムは終了する。
Copyright © 2001 Hiroshi Masuda |