2013年5月20日月曜日

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



バージョン2から3への変更点

ヘルプの追加
ビット積、ビット和、ビット排他 演算の追加

実行結果:

akira@akira:~$ cd arm1305b
akira@akira:~/arm1305b$ ./calc3

(q) is quit,(h) is help;  Calc: h

Calc Program  Ver.3 (2013.5.19)
Example:
   Calc: 3*(1+2+3+4)/2
   Calc: 2*(3*(567+433)/300+15)+17
(+)足し算(-)引き算(*)掛け算(/)割り算(%)余り
(<) 1<3と入力すると 1<<3=8左シフト
(>)64>3と入力すると64>>3=8右シフト
(&)ビット積(|)ビット和(#)ビット排他,内部では{^}
(^)2^3で2の3乗 (q)quit (h)help
CTRL+C で強制終了します  入力は整数のみです

(q) is quit,(h) is help;  Calc: 134|345
134@345@|
134|345=479.000000

(q) is quit,(h) is help;  Calc: 456&444
456@444@&
456&444=392.000000

(q) is quit,(h) is help;  Calc: 1123#1156
1123@1156@#
1123#1156=231.000000

(q) is quit,(h) is help;  Calc: q
akira@akira:~/arm1305b$





#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("\n(q) is quit,(h) is help;  Calc: ");
   scanf("%s",p);

   if(p[0]=='q'||p[0]=='Q') exit(1);
   if(p[0]=='h'||p[0]=='H'){
      printf("\nCalc Program  Ver.3 (2013.5.19)\n");
      printf("Example:\n");
      printf("   Calc: 3*(1+2+3+4)/2\n");
      printf("   Calc: 2*(3*(567+433)/300+15)+17\n");
      printf("(+)足し算(-)引き算(*)掛け算(/)割り算(%%)余り\n");
      printf("(<) 1<3と入力すると 1<<3=8左シフト\n");
      printf("(>)64>3と入力すると64>>3=8右シフト\n");
      printf("(&)ビット積(|)ビット和(#)ビット排他,内部では{^}\n");
      printf("(^)2^3で2の3乗 (q)quit (h)help\n");
      printf("CTRL+C で強制終了します  入力は整数のみです\n");
      goto START;
   }

  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;
            case '<': m=(int)v[sp1-1]<<(int)v[sp1];
                       v[sp1-1]=(double)m;
                       break;
            case '>': m=(int)v[sp1-1]>>(int)v[sp1];
                       v[sp1-1]=(double)m;
                       break;
            case '&': m=(int)v[sp1-1]&(int)v[sp1];
                       v[sp1-1]=(double)m;
                       break;
            case '|': m=(int)v[sp1-1]|(int)v[sp1];
                       v[sp1-1]=(double)m;
                       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;*/
   ch=p[ii++];
}

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 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 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 件のコメント:

コメントを投稿