2009年4月7日 星期二

知識+ 直譯運算

//===================================================================
// 20090402 知識 +
// http://tw.knowledge.yahoo.com/question/question?qid=1609040211054
// 發問者 : http://tw.knowledge.yahoo.com/my/my?show=AF04167627
//===================================================================

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

double var[26] = {0};
char cd[256];
int cp;

char Op[]={ 0, '*', '/', '+', '-' };
int On[]={ 0, 0x60, 0x61, 0x50, 0x51 };
int lev=0;

int getN(double *n)
{
*n = 0;
int x=1;
int e = -5;
double d = 1.;
if (cd[cp]=='-') { cp++; x=-1; };
for( ;cd[cp]>='0' && cd[cp]<='9' || cd[cp]=='.'; cp++)
{
if (cd[cp]!='.')
{
e=0;
if (d==1.)
{
*n = *n*10+(cd[cp]&0x0F);
continue;
}
*n += d*(cd[cp]&0x0F);
}
else if (d<1) return -4;
d /= 10.;
}
if (x<0) *n *= -1.;
return e;
}

int get( double *n, int *op )
{
int i;
while ( cd[cp]=='(' || cd[cp]==' ')
if (cd[cp++]=='(') lev++;
int p=cp;
if ( (cd[cp]|0x20)>='a' && (cd[cp]|0x20)<='z')
{ i=(cd[cp++]|0x20)-'a'; *n=var[i]; }
else if ((i=getN(n))<0) return i;
while (cd[cp]==')' || cd[cp]==' ')
if (cd[cp++]==')')
if (--lev<0) return -8;
for(i=4; i>=0; i--) if (cd[cp]==Op[i]) break;
if (i<0) return -6;
if (i==0 && lev>0) return -7;
*op=(lev<<8) + On[i];
cp++;
return 0;
}

int oper( double *n1, int *o1 )
{
double n2;
int o2;
int e=get( &n2, &o2);
while( !e && (o2>>4) > ((*o1)>>4) ) e=oper( &n2, &o2 );
if (e) return e;
switch ( (*o1)&0xFF )
{
case 0: *n1=n2; return 0;
case 0x60: *n1*=n2; break;
case 0x61: if (n2) *n1/=n2; else printf("/0錯誤!!\n"); break;
case 0x50: *n1+=n2; break;
case 0x51: *n1-=n2; break;
default: return -3;
}
*o1=o2;
return 0;
}

int parse()
{
char ic[2][8] = { "quit", "print" };
int c=3;
int v=-1;
int p=0;
while(cd[p]==' ')p++;
cp=p;
while((cd[cp]|0x20)>='a'&& (cd[cp]|0x20)<='z')
cd[cp++] |= 0x20;
if (cp-p>1) // 命令
{
cd[cp++] = '\0';
for(c=1; c>=0 && strcmp( &cd[p], ic[c])!=0; c--);
if (c!=1) return c; // 0: 離開 -1: 命令錯誤
}
else if(cp-p==1) // 變數
{
v = cd[p]-'a';
while(cd[cp]==' ')cp++;
if (cd[cp++]!='=') return -2;
c=2;
}
else return (strlen(cd)==0)?3:-1;
int op=0;
double n=0.;
lev = 0;
p = oper(&n, &op);
if (p<0) return p;
if(c==1) printf("%f\n", n);
if(v>=0) var[v] = n;
return c; // 2:指定敘述 1:顯示敘述
}

int main()
{
int c=1;
printf("\n# Welcome!!\n");
while(c!=0)
{
printf("]");
gets(cd);
c = parse();
if (c<0) printf("*** (%d)Error!!\n", c);
}
printf("# Bye.\n");
return 0;
}

沒有留言:

張貼留言