#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define VER "Calc Program Ver.5d (2013.05.24 11:33am)"
/*
逆ポーランド表現のパーサと
その演算をするプログラム
参考資料:
技術評論社 河西 朝雄 著
C言語による はじめてのアルゴリズム入門
2718円+税
P252〜254より引用
技術評論社 奥村晴彦 著
C言語による最新アルゴリズム事典 2330円+税
P72〜73より引用・改変
*/
int ch,ii,jj,bi;
char p[100],polish[100],bit[100];
void readch();
void expression();
void term();
void factor();
int cmpch0( char *pp);
int cmpch( char *pp);
void writech(char *pp);
void m1(int i);
void t1(int i,char *pp);
double v[50];
int sp1,m2flg;
int m,flg,mflg,dflg,xflg;
double dd,ms;
main(){
int i,j;
char po;
START:
ii=jj=sp1=bi=0;
for(i=0;i<100;i++) p[i]=polish[i]=bit[i]=0;
printf("\n(q) is quit, (h) is help, (k) is 関数一覧;\nCalc: ");
scanf("%s",p);
if(p[0]=='q'||p[0]=='Q') exit(1);
if((p[0]=='h'||p[0]=='H')&&p[1]==0){
printf("\n%s\n",VER);
printf("Example:\n");
printf(" Calc: 3*(1+2+3+4)/2\n");
printf(" Calc: 2*(3*(567+433)/300+15)+17\n");
printf(" Calc: 776&773 また 776|773 また 234#234 また 345<3\n");
printf(" Calc: -0.2*(2+(-1.5/-.2)+2.5)-pi\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 (k)関数一覧\n");
printf("CTRL+C で強制終了します\n");
goto START;
}
if((p[0]=='k'||p[0]=='K')&&p[1]==0){
printf("\n%s\n",VER);
printf("関数一覧:\n");
printf("三角関数: cos sin tan atan=arctan acos=arccos\n");
printf(" asin=arcsin sinh cosh tanh atanh=arctanh\n");
printf(" acosh=arccosh asinh=arcsinh\n");
printf("対数関数等: exp log=ln log10 sqrt cbrt=sqrt3\n");
printf("丸め・反転: ceil floor abs neg\n");
printf("進数: bin oct hex 0xbf58という風に0xをつけると16進\n");
printf("定数: pi=3.1415926 ei=ネイピア数 do=pi/180\n");
printf("三角関数で30度で使いたい時は cos(30*do)\n");
printf("(q)quit (h)help (k)関数一覧\n");
printf("CTRL+C で強制終了します\n");
goto START;
}
do{
readch();
expression();
} while(ch);
p[ii]='\0';
polish[jj]='\0';
puts(polish);
sp1=flg=mflg=dflg=xflg=0;dd=1.0;
m2flg=0;
for(ii=0;ii<jj;ii++){
po=polish[ii];
if(po=='m') mflg=1;
else if(cmpch("pi")){ v[++sp1]=M_PI; m1(2); }
else if(cmpch("do")){ v[++sp1]=M_PI/180.0; m1(2); }
else if(cmpch("ei")){ v[++sp1]=M_E; m1(2); }
else if(cmpch("cos")){ v[sp1]=cos(v[sp1]); m1(3); }
else if(cmpch("sin")){ v[sp1]=sin(v[sp1]); m1(3); }
else if(cmpch("tan")){ v[sp1]=tan(v[sp1]); m1(3); }
else if(cmpch("atan")){ v[sp1]=atan(v[sp1]); m1(4); }
else if(cmpch("asin")){ v[sp1]=asin(v[sp1]); m1(4); }
else if(cmpch("acos")){ v[sp1]=acos(v[sp1]); m1(4); }
else if(cmpch("arctan")){ v[sp1]=atan(v[sp1]); m1(6); }
else if(cmpch("arcsin")){ v[sp1]=asin(v[sp1]); m1(6); }
else if(cmpch("arccos")){ v[sp1]=acos(v[sp1]); m1(6); }
else if(cmpch("tanh")){ v[sp1]=tanh(v[sp1]); m1(4); }
else if(cmpch("sinh")){ v[sp1]=sinh(v[sp1]); m1(4); }
else if(cmpch("cosh")){ v[sp1]=cosh(v[sp1]); m1(4); }
else if(cmpch("acosh")){ v[sp1]=acosh(v[sp1]); m1(5); }
else if(cmpch("asinh")){ v[sp1]=asinh(v[sp1]); m1(5); }
else if(cmpch("atanh")){ v[sp1]=atanh(v[sp1]); m1(5); }
else if(cmpch("arctanh")){ v[sp1]=atanh(v[sp1]); m1(7); }
else if(cmpch("arcsinh")){ v[sp1]=asinh(v[sp1]); m1(7); }
else if(cmpch("arccosh")){ v[sp1]=acosh(v[sp1]); m1(7); }
else if(cmpch("exp")){ v[sp1]=exp(v[sp1]); m1(3); }
else if(cmpch("log")){ v[sp1]=log(v[sp1]); m1(3); }
else if(cmpch("ln")){ v[sp1]=log(v[sp1]); m1(2); }
else if(cmpch("log10")){ v[sp1]=log10(v[sp1]); m1(5); }
else if(cmpch("sqrt")){ v[sp1]=sqrt(v[sp1]); m1(4); }
else if(cmpch("cbrt")){ v[sp1]=cbrt(v[sp1]); m1(4); }
else if(cmpch("sqrt3")){ v[sp1]=cbrt(v[sp1]); m1(5); }
else if(cmpch("ceil")){ v[sp1]=ceil(v[sp1]); m1(4); }
else if(cmpch("floor")){ v[sp1]=floor(v[sp1]); m1(5); }
else if(cmpch("neg")){ v[sp1]=~(int)v[sp1]; m1(3); }
else if(cmpch("abs")){ if(v[sp1]<0){v[sp1]=-v[sp1];} m1(3); }
else if(cmpch("bin")){
m=(int)v[sp1];
printf("\nbin(%d)=",m);
m2flg=0;
if(m<0){ m=-m; m2flg=1; }
bi=0;
while(m){
bit[bi++]=m%2;
m/=2;
if(m2flg==1){ m2flg=2; m^=0x40000000; }
}
for(i=bi-1;i>=0;i--){
printf("%d",bit[i]);
if(i%4==0) printf(" ");
}
printf("\n");
m1(3);
m2flg=3;
}
else if(cmpch("oct")){
m=(int)v[sp1];
printf("\noct(%d)=",m);
m2flg=0;
if(m<0){ m=-m; m2flg=1; }
bi=0;
while(m){
bit[bi++]=m%8;
m/=8;
if(m2flg==1){ m2flg=2; m^=0x10000000; }
}
for(i=bi-1;i>=0;i--){
printf("%d",bit[i]);
if(i%4==0) printf(" ");
}
printf("\n");
m1(3);
m2flg=3;
}
else if(cmpch("hex")){
m=(int)v[sp1];
ms=v[sp1]-m;
printf("\nhex(%f)=",v[sp1]);
m2flg=0;
if(m<0){ m=-m; m2flg=1; }
bi=0;
while(m){
if(isdigit(m%16+'0')) bit[bi++]=m%16+'0';
else bit[bi++]=m%16+'a'-10;
m/=16;
if(m2flg==1){ m2flg=2; m^=0x08000000; }
}
for(i=bi-1;i>=0;i--){
printf("%c",bit[i]);
if(i==4) printf(" ");
}
if(ms!=0.0){
printf(".");
for(i=0;i<8;i++){
ms*=16;
m=(int)ms;
if(isdigit(m+'0')) j=m+'0';
else j=m+'a'-10;
ms-=m;
printf("%c",j);
if(i==3) printf(" ");
}
}
printf("\n");
m1(3);
m2flg=3;
}
else if(isxdigit(po)||po=='x'||po=='.'){
if(po=='.') dflg=1;
if(po=='x'){ xflg=1; v[sp1]=0.0;}
if(dflg==0&&xflg==0){
if(flg==0){
if(isdigit(po)){
flg=1;
v[++sp1]=po-'0';
}
}
else{
if(isdigit(po)) v[sp1]=v[sp1]*10+po-'0';
}
}
else if(dflg==1&&xflg==0){
if(flg==0){
flg=1;
v[++sp1]=0.0;
}
else{
if(isdigit(po)){
dd/=10.0;
v[sp1]=v[sp1]+dd*(po-'0');
}
}
}
else if(dflg==0&&xflg==1){
if(flg==1){
if(isdigit(po)){flg=2;v[sp1]=po-'0';}
else if('a'<=po&&po<='f'){flg=2;v[sp1]=po-'a'+10;}
else if('A'<=po&&po<='F'){flg=2;v[sp1]=po-'A'+10;}
}
else{
if(isdigit(po)) v[sp1]=v[sp1]*16+po-'0';
else if('a'<=po&&po<='f') v[sp1]=v[sp1]*16+po-'a'+10;
else if('A'<=po&&po<='F') v[sp1]=v[sp1]*16+po-'A'+10;
}
}
else if(dflg==1&&xflg==1){
if(flg==0){}
else{
if(isdigit(po)){
dd/=16.0;
v[sp1]=v[sp1]+dd*(po-'0');
}
else if('a'<=po&&po<='f'){
dd/=16.0;
v[sp1]=v[sp1]+dd*(po-'a'+10);
}
else if('A'<=po&&po<='F'){
dd/=16.0;
v[sp1]=v[sp1]+dd*(po-'A'+10);
}
}
}
}
else if(po=='@'){
if(mflg==1) v[sp1]=-v[sp1];
flg=mflg=dflg=xflg=0;dd=1.0;
}
else if(ispunct(po)){
flg=mflg=dflg=xflg=0;dd=1.0;
switch(po){
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--;
}
}
if(m2flg==0) printf("\n%s=%9.9f\n",p,v[1]);
goto START;
}
void readch(){
ch=p[ii++];
}
void expression(){
term();
while(1){
if(ch=='+'){ readch(); term(); writech("+"); }
else if(ch=='-'){ readch(); term(); writech("-"); }
else break;
}
}
void term(){
factor();
while(1){
if(ch=='*'){ readch(); factor(); writech("*"); }
else if(ch=='/'){ readch(); factor(); writech("/"); }
else if(ch=='^'){ readch(); factor(); writech("^"); }
else if(ch=='%'){ readch(); factor(); writech("%"); }
else if(ch=='<'){ readch(); factor(); writech("<"); }
else if(ch=='>'){ readch(); factor(); writech(">"); }
else if(ch=='&'){ readch(); factor(); writech("&"); }
else if(ch=='|'){ readch(); factor(); writech("|"); }
else if(ch=='#'){ readch(); factor(); writech("#"); }
else break;
}
}
void factor(){
int mflg=0,dflg=0,pflg=0,xflg=0,m2;
if(ch=='('){
while(ch!=')'&&ch){
readch();
expression();
}
if(ch==')'){
readch();
}
else printf("error2 %d\n",ii);
}
else if(isalnum(ch)||(ch=='-'&&mflg==0)||(ch=='+'&&pflg==0)||(ch=='.'&&dflg==0)){
while(isalnum(ch)||(ch=='-'&&mflg==0)||(ch=='+'&&pflg==0)||(ch=='.'&&dflg==0) && ch){
mflg=1;pflg=1;
if(ch=='.') dflg=1;
if(ch=='-') writech("m");
else if(ch=='+'){}
else if(cmpch0("cos")){ t1(3,"cos"); }
else if(cmpch0("sin")){ t1(3,"sin"); }
else if(cmpch0("tan")){ t1(3,"tan"); }
else if(cmpch0("atan")){ t1(4,"atan"); }
else if(cmpch0("acos")){ t1(4,"acos"); }
else if(cmpch0("asin")){ t1(4,"asin"); }
else if(cmpch0("arctan")){ t1(6,"arctan"); }
else if(cmpch0("arcsin")){ t1(6,"arcsin"); }
else if(cmpch0("arccos")){ t1(6,"arccos"); }
else if(cmpch0("sinh")){ t1(4,"sinh"); }
else if(cmpch0("cosh")){ t1(4,"cosh"); }
else if(cmpch0("tanh")){ t1(4,"tanh"); }
else if(cmpch0("atanh")){ t1(5,"atanh"); }
else if(cmpch0("acosh")){ t1(5,"acosh"); }
else if(cmpch0("asinh")){ t1(5,"asinh"); }
else if(cmpch0("arctanh")){ t1(7,"arctanh"); }
else if(cmpch0("arccosh")){ t1(7,"arccosh"); }
else if(cmpch0("arcsinh")){ t1(7,"arcsinh"); }
else if(cmpch0("exp")){ t1(3,"exp"); }
else if(cmpch0("log")){ t1(3,"log"); }
else if(cmpch0("ln")){ t1(2,"ln"); }
else if(cmpch0("log10")){ t1(5,"log10"); }
else if(cmpch0("sqrt")){ t1(4,"sqrt"); }
else if(cmpch0("cbrt")){ t1(4,"cbrt"); }
else if(cmpch0("sqrt3")){ t1(5,"sqrt3"); }
else if(cmpch0("ceil")){ t1(4,"ceil"); }
else if(cmpch0("floor")){ t1(5,"floor"); }
else if(cmpch0("bin")){ t1(3,"bin"); }
else if(cmpch0("oct")){ t1(3,"oct"); }
else if(cmpch0("hex")){ t1(3,"hex"); }
else if(cmpch0("abs")){ t1(3,"abs"); }
else if(cmpch0("neg")){ t1(3,"neg"); }
else if(cmpch0("pi")){ ii+=1; writech("pi"); }
else if(cmpch0("do")){ ii+=1; writech("do"); }
else if(cmpch0("ei")){ ii+=1; writech("ei"); }
else polish[jj++]=ch;
readch();
}
writech("@");
}
else printf("error1 %d\n",ii);
}
int cmpch0(char *pp){
int i=0,j=0;
while(*(pp+i)){
if(p[ii+i-1]!=*(pp+i)) return 0;
i++;
}
if(ispunct(p[ii+i-1])) return 1;
else if(!p[ii+i-1]) return 1;
else return 0;
}
int cmpch(char *pp){
int i=0,j=0;
while(*(pp+i)){
if(polish[ii+i]!=*(pp+i)) return 0;
i++;
}
if(ispunct(polish[ii+i])) return 1;
else if(!polish[ii+i]) return 1;
else return 0;
}
void writech(char *pp){
int i=0;
while(*(pp+i)){
polish[jj++]=*(pp+i);
i++;
}
}
void m1(int i){
if(mflg) v[sp1]=-v[sp1];
flg=mflg=dflg=xflg=0;dd=1.0;
ii+=i;
}
void t1(int i,char *pp){
int m2;
ii+=i;
m2=0;
if(polish[jj-1]=='m'){ m2=1; jj--;}
readch();
expression();
if(m2) writech("m");
writech(pp);
}