2013年5月19日日曜日

逆ポーランド表現のパーサとその演算


こんなもんじゃろ

$ gcc -o calc1 calc1.c -lm
$ ./calc1

止めたい時はqを入力するかCTRL+C


#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

/*
逆ポーランド式のパージング

参考資料:

技術評論社 河西 朝雄 著
C言語による はじめてのアルゴリズム入門
2718円+税
P252〜254より引用

技術評論社 奥村晴彦 著
C言語による最新アルゴリズム事典 2330円+税
P72〜73より引用・改変

*/


int ch,ii,jj;
char p[100]="",polish[100];

void readch();
void expression();
void term();
void factor();
double v[50];
int sp1;

main(){
   int i,m,flg;

START:
   ii=0;jj=0;
   printf("(q)Button is quit;     calc: ");
   scanf("%s",p);

   if(p[0]=='q'||p[0]=='Q') exit(1);

  do{
      readch();
      expression();
   } while(ch!='\0');
   p[ii]='\0';
   polish[jj]='\0';

   sp1=0;flg=0;
   for(i=0;i<jj;i++){
      printf("%c",polish[i]);
      if(isdigit(polish[i])){
         if(flg==0){
            flg=1;
            v[++sp1]=polish[i]-'0';
         }
         else v[sp1]=v[sp1]*10+polish[i]-'0';
       
      }
      else if(polish[i]=='@') flg=0;
      else{
         flg=0;
         switch(polish[i]){
            case '+': v[sp1-1]+=v[sp1]; break;
            case '-': v[sp1-1]-=v[sp1]; break;
            case '*': v[sp1-1]*=v[sp1]; break;
            case '/': v[sp1-1]/=v[sp1]; break;
            case '^': v[sp1-1]=pow(v[sp1-1],v[sp1]); break;
            case '%': m=(int)v[sp1-1]%(int)v[sp1];
                       v[sp1-1]=(double)m;
                       break;
         }
         sp1--;
      }
   }
   printf("\n%s=%f\n",p,v[1]);
   goto START;
}

void readch(){
      if((ch=p[ii++])=='\0') return;
}

void expression(){
   term();
   while(1){
      if(ch=='+'){      readch(); term(); polish[jj++]='+'; }
      else if(ch=='-'){ readch(); term(); polish[jj++]='-'; }
      else break;
   }
}

void term(){
   factor();
   while(1){
      if(ch=='*'){       readch(); factor(); polish[jj++]='*'; }
      else if(ch=='/'){ readch(); factor(); polish[jj++]='/'; }
      else if(ch=='^'){ readch(); factor(); polish[jj++]='^'; }
      else if(ch=='%'){ readch(); factor(); polish[jj++]='%'; }
      else break;
   }
}

void factor(){
   if(ch=='('){
      while(ch!=')'&&ch!='\0'){
         readch();
         expression();
      }
      if(ch==')') readch();
      else puts("error2");
   }
   else if(isdigit(ch)){
      while(isdigit(ch) && ch!='\0'){
         polish[jj++]=ch;
         readch();
      }
      polish[jj++]='@';
   }
   else puts("error1");
}

0 件のコメント:

コメントを投稿