第 7 回 状態遷移図の補足

本日の内容


このドキュメントは http://edu.net.c.dendai.ac.jp/ 上で公開されています。

7-1. 計算の状態遷移図の最適化

ここで作ったプログラムは数字を読み込む部分が二箇所あるなど冗長でした。 1+2+3= など連続して演算子と数字を読み込むことを許し、マイナス記号の処 理も可能なように書き直すと次のようになります。

改良された状態遷移図

結果と読み込み中の数をそれぞれ result と num で表すことにします。 そして、演算子を op で表すことにします。 通常、電卓のように次の演算子を読み込んだ時や = を読み込んだ時に、計算 を行ないます。 例えば、 1 + 2 - 3 = であれば、 1 + 2 まで読み込み、次の - を読み込んだ 時に 1 + 2 を計算し、次の = を読み込んだ時に、 3 - 3 を計算します。 つまり、演算子を読み込んだ時の処理は次のようになります。

  1. いままでの計算結果 result と今読み込んだ数 num と記憶しておいた演 算子 op を使って、新しい result を計算します。
  2. 今読み込んだ演算子を op に記憶します。

ここで問題なのは一番最初の数を読み込んで、次の演算子を読み込んだ時です。 この時、新しい result を計算するのに op には何も入ってません。 そこで、この場合は今読んだ数 num をそのまま result に入れることにしま す。


#include <stdio.h>
typedef enum {NUM, OP, END} STATE;
int result=0,num,sign;
char op=' ';
void calc(){
  switch(op){
  case ' ':
    result = num*sign;
    break;
  case '+':
    result += num*sign;
    break;
  case '-':
    result -= num*sign;
    break;
  case '*':
    result *= num*sign;
    break;
  case '/':
    result /= num*sign;
    break;
  }
}
main(){
  char c;
  STATE s=OP;
  while((c=getchar())!=EOF){
    switch(s){
    case OP:
      if((c>='0')&&(c<='9')){
	num=c-'0';
	sign=1;
	s=NUM;
      }else if(c=='-'){
	num=0;
	sign=-1;
	s=NUM;
      }
      break;
    case NUM:
      if((c>='0')&&(c<='9')){
	num*=10;
	num+=c-'0';
	s=NUM;
      }else if((c=='+')||(c=='-')||(c=='*')||(c=='/')){
	calc();
	op=c;
	s=OP;
      }else if(c=='='){
	calc();
	printf("result = %d\n",result);
	return 0;
      }
      break;
    }
  }
}

坂本直志 <sakamoto@c.dendai.ac.jp>
東京電機大学工学部情報通信工学科