int main() { int type; double op2; char s[MAXOP]; while ((type = getop(s)) != EOF) { switch (type) { case NUMBER: push(atof(s)); break; case MATHFUNC: push(mathfunc(s)); break; case '+': push(pop() + pop()); break; case '*': push(pop() * pop()); break; case '-': op2 = pop(); push(pop() - op2); break; case '/': op2 = pop(); if (op2 != 0.0) push(pop() / op2); else printf("error: zero divisor\n"); break; case '%': op2 = pop(); if (op2 != 0.0) push(fmod(pop(), op2)); else printf("error: zero divisor\n"); break; case '\n': printf("\t%.8g\n", pop()); break; default: printf("error: unknow command %s\n", s); break; } } return 0; }
/******************************************************************************* This function evaluates an expression. It is passed a pointer to an expression node to evaluate (results are also put here), and it evaluates the expression tree. Note: the argument stack is used for user function calls. Even though it looks cumbersome, indices have been used instead of stack pointers. This is because this is a recursive function, and it is neccessary to save previous stack information AND the stack is dynamically resizable - that is - it can move at any time. Hence, any pointers saved on previous invocations of this function would be pointing to where the stack USED to be, not where it NOW is. *******************************************************************************/ void evalexpr(Exprnode *exprptr) { extern Field *aggrfldtbl, *fldtbl; extern Opmode opmode; /* report or selrej mode */ extern Statsinfofld *statsinfofldtbl; Exprnode lresult, rresult; Exprptrlistnode *exprptrlistptr; int tmpidx, argctr, intval, savebotargstkidx; float floatval; switch (exprptr->typ) { case INTEGER: case FLOAT: case STRING: break; case FIELD: if (opmode == REPORTMODE) { if (curfldvalptrtbl[exprptr->arg.ival] == NULL) { fprintf(stderr, "field `%s'", aggrfldtbl[exprptr->arg.ival].name); fatalerrlin(" is referenced outside a foreach loop"); } exprptr->typ = aggrfldtbl[exprptr->arg.ival].typ; switch (exprptr->typ) { case STRING: exprptr->arg.sval = curfldvalptrtbl[exprptr->arg.ival]->arg.sval; break; case INTEGER: exprptr->arg.ival = curfldvalptrtbl[exprptr->arg.ival]->arg.ival; break; case FLOAT: exprptr->arg.fval = curfldvalptrtbl[exprptr->arg.ival]->arg.fval; break; default: fatalerror("evalexpr: SNARK!"); break; } } else { /* selrej mode */ evalselrejfld(exprptr); } break; case UFNCCALLEXPR: argctr = exprptr->arg.ufnc.argctr; if (argstkctr + argctr > maxargstkctr) { /* enlarge stk if nec */ maxargstkctr = MAX(maxargstkctr*ARGSTKMULTFACTOR, argstkctr+argctr); argstk = (Exprnode*)realloc((void*)argstk, (size_t)maxargstkctr*sizeof(Exprnode)); } /* eval all args & push them on the stk */ exprptrlistptr = exprptr->arg.ufnc.exprptrlistptr; while (exprptrlistptr != NULL) { /* eval all args */ lresult = *exprptrlistptr->exprptr; evalexpr(&lresult); *(argstk+argstkctr++) = lresult; /* & push on stk */ exprptrlistptr = exprptrlistptr->next; } savebotargstkidx = botargstkidx; botargstkidx = argstkctr-argctr; tmpidx = exprptr->arg.ufnc.begstmtidx; /* call user func */ *exprptr = doblock(tmpidx+1, stmts[tmpidx].s.ufncdef.endstmtidx); argstkctr -= argctr; botargstkidx = savebotargstkidx; break; case UFNCPARAMEXPR: if (botargstkidx+exprptr->arg.ival >= argstkctr) fatalerror(STKERRMSG); *exprptr = *(&argstk[botargstkidx]+exprptr->arg.ival); break; case UNARYOPEXPR: lresult = *(exprptr->leftptr); evalexpr(&lresult); switch (lresult.typ) { case INTEGER: exprptr->arg.ival = iunaryop(exprptr->arg.optyp, lresult.arg.ival); break; case FLOAT: exprptr->arg.fval = funaryop(exprptr->arg.optyp, lresult.arg.fval); break; default: fatalerrlin("evalexpr: unary operation on illegal type"); break; } exprptr->typ = lresult.typ; break; case BINARYOPEXPR: lresult = *(exprptr->leftptr); evalexpr(&lresult); rresult = *(exprptr->rightptr); evalexpr(&rresult); if ((lresult.typ == INTEGER)&&(rresult.typ == INTEGER)) { exprptr->arg.ival = ibinop(lresult.arg.ival, exprptr->arg.optyp, rresult.arg.ival); exprptr->typ = INTEGER; } else if (lresult.typ == INTEGER && rresult.typ == FLOAT) { if ((exprptr->typ=fbinop((float)lresult.arg.ival, exprptr->arg.optyp, rresult.arg.fval, &floatval, &intval)) == FLOAT) exprptr->arg.fval = floatval; else exprptr->arg.ival = intval; } else if (lresult.typ == FLOAT && rresult.typ == INTEGER) { if ((exprptr->typ=fbinop(lresult.arg.fval, exprptr->arg.optyp, (float)rresult.arg.ival, &floatval, &intval)) == FLOAT) exprptr->arg.fval = floatval; else exprptr->arg.ival = intval; } else if (lresult.typ == FLOAT && rresult.typ == FLOAT) { if ((exprptr->typ=fbinop(lresult.arg.fval, exprptr->arg.optyp, rresult.arg.fval, &floatval, &intval)) == FLOAT) exprptr->arg.fval = floatval; else exprptr->arg.ival = intval; } else if (lresult.typ == STRING && rresult.typ == STRING) { sbinop(lresult.arg.sval, rresult.arg.sval, exprptr); } else { fatalerrlin( "evalexpr: illegal binary op argument type(s)"); } break; case COUNT: if (exprptr->arg.tdbfnc.maxdepth != INVALIDFLDIDX) { chk4badflds(exprptr->arg.tdbfnc.fldbits, exprptr->arg.tdbfnc.maxdepth); exprptr->arg.ival = getcount(datarootptr, exprptr->arg.tdbfnc.fldbits, 0, exprptr->arg.tdbfnc.maxdepth); } else { exprptr->arg.ival = getcount(datarootptr, exprptr->arg.tdbfnc.fldbits, 0, 0); } exprptr->typ = INTEGER; break; case NUMBER: chk4badflds(exprptr->arg.tdbfnc.fldbits, exprptr->arg.tdbfnc.maxdepth); exprptr->arg.ival = getnumber(datarootptr, exprptr->arg.tdbfnc.fldbits, exprptr->arg.tdbfnc.depth, exprptr->arg.tdbfnc.maxdepth); exprptr->typ = INTEGER; break; case SUM: intval = statsinfofldtbl[exprptr->arg.tdbfnc.depth].typ; switch (intval) { case INTEGER: if (exprptr->arg.tdbfnc.maxdepth != INVALIDFLDIDX) { chk4badflds(exprptr->arg.tdbfnc.fldbits, exprptr->arg.tdbfnc.maxdepth); exprptr->arg.ival = getintsum(datarootptr, exprptr->arg.tdbfnc.fldbits, 0, exprptr->arg.tdbfnc.maxdepth, exprptr->arg.tdbfnc.depth); } else { exprptr->arg.ival = getintsum(datarootptr, exprptr->arg.tdbfnc.fldbits, 0, 0, exprptr->arg.tdbfnc.depth); } break; case FLOAT: if (exprptr->arg.tdbfnc.maxdepth != INVALIDFLDIDX) { chk4badflds(exprptr->arg.tdbfnc.fldbits, exprptr->arg.tdbfnc.maxdepth); exprptr->arg.fval = getfltsum(datarootptr, exprptr->arg.tdbfnc.fldbits, 0, exprptr->arg.tdbfnc.maxdepth, exprptr->arg.tdbfnc.depth); } else { exprptr->arg.fval = getfltsum(datarootptr, exprptr->arg.tdbfnc.fldbits, 0, 0, exprptr->arg.tdbfnc.depth); } break; default: fatalerrlin("evalexpr: illegal SUM field type"); break; } exprptr->typ = intval; break; case SUMSQRD: intval = statsinfofldtbl[exprptr->arg.tdbfnc.depth].typ; switch (intval) { case INTEGER: if (exprptr->arg.tdbfnc.maxdepth != INVALIDFLDIDX) { chk4badflds(exprptr->arg.tdbfnc.fldbits, exprptr->arg.tdbfnc.maxdepth); exprptr->arg.ival = getintsumsqrd(datarootptr, exprptr->arg.tdbfnc.fldbits, 0, exprptr->arg.tdbfnc.maxdepth, exprptr->arg.tdbfnc.depth); } else { exprptr->arg.ival = getintsumsqrd(datarootptr, exprptr->arg.tdbfnc.fldbits, 0, 0, exprptr->arg.tdbfnc.depth); } break; case FLOAT: if (exprptr->arg.tdbfnc.maxdepth != INVALIDFLDIDX) { chk4badflds(exprptr->arg.tdbfnc.fldbits, exprptr->arg.tdbfnc.maxdepth); exprptr->arg.fval = getfltsumsqrd(datarootptr, exprptr->arg.tdbfnc.fldbits, 0, exprptr->arg.tdbfnc.maxdepth, exprptr->arg.tdbfnc.depth); } else { exprptr->arg.fval = getfltsumsqrd(datarootptr, exprptr->arg.tdbfnc.fldbits, 0, 0, exprptr->arg.tdbfnc.depth); } break; default: fatalerrlin("evalexpr: illegal SUM field type"); break; } exprptr->typ = intval; break; case TYPE: lresult = *(exprptr->leftptr); evalexpr(&lresult); switch (lresult.typ) { case INTEGER: /* we've got an integer, make a ... */ if (exprptr->arg.casttyp == FLOAT) { exprptr->arg.fval = (float)lresult.arg.ival; exprptr->typ = FLOAT; } else { /* an integer */ exprptr->arg.ival = lresult.arg.ival; exprptr->typ = INTEGER; } break; case FLOAT: /* we've got a float, make an ... */ if (exprptr->arg.casttyp == FLOAT) { exprptr->arg.fval = lresult.arg.fval; exprptr->typ = FLOAT; } else { /* an integer */ exprptr->arg.ival = (int)lresult.arg.fval; exprptr->typ = INTEGER; } break; default: fatalerrlin("evalexpr: illegal type cast"); break; } break; case REPORTDT: /* get the report date or time */ exprptr->arg.ival = getreportdt(exprptr->arg.ival); exprptr->typ = INTEGER; break; case FORMATDT: /* format a date or time */ lresult = *(exprptr->leftptr); evalexpr(&lresult); rresult = *(exprptr->rightptr); evalexpr(&rresult); exprptr->arg.sval = formatdt(exprptr->arg.ival, &lresult, &rresult); exprptr->typ = STRING; break; case STRFUNCEXPR: strfunc(exprptr); break; case ATOI: lresult = *(exprptr->leftptr); evalexpr(&lresult); if (lresult.typ != STRING) fatalerrlin("evalexpr: atoi of non-string expression"); exprptr->arg.ival = atoi(lresult.arg.sval); exprptr->typ = INTEGER; break; case ATOF: lresult = *(exprptr->leftptr); evalexpr(&lresult); if (lresult.typ != STRING) fatalerrlin("evalexpr: atof of non-string expression"); exprptr->arg.fval = (float) atof(lresult.arg.sval); exprptr->typ = FLOAT; break; case MATHFUNC: lresult = *(exprptr->leftptr); evalexpr(&lresult); switch (lresult.typ) { case INTEGER: exprptr->arg.fval = mathfunc(exprptr->arg.optyp, (double)lresult.arg.ival); break; case FLOAT: exprptr->arg.fval = mathfunc(exprptr->arg.optyp, (double)lresult.arg.fval); break; default: fatalerrlin("evalexpr: math function on illegal type"); break; } exprptr->typ = FLOAT; break; case ARRAYVAREXPR: evalarrvar(exprptr); break; case NEED: lresult = *(exprptr->leftptr); evalexpr(&lresult); exprptr->typ = INTEGER; exprptr->arg.ival = need(&lresult); break; case UNDEFVAREXPR: fprintf(stderr, "evalexpr: variable `%s'",exprptr->varptr->name); fatalerrlin(" is undefined"); break; case NORETVALEXPR: fatalerrlin("function returns no value (one is required)"); break; default: fatalerrlin("evalexpr: illegal expr type"); break; } }
type function(double t, double *X) { char f[20], *p; type v; p = f; while(p-f < 19 && c >= 'a' && c <= 'z') { *p++ = c; next(); } *p = 0; if(!strcmp(f,"pi")) return M_PI; if(!strcmp(f,"e" )) return M_E; v = term(t,X); #define mathfunc(a,b) if(!strcmp(f,a)) return b; mathfunc("abs" , fabs(v)); mathfunc("fabs" , fabs(v)); mathfunc("floor" , floor(v)); mathfunc("ceil" , ceil(v)); mathfunc("sqrt" , sqrt(v)); mathfunc("exp" , exp(v)); mathfunc("sin" , sin(v)); mathfunc("cos" , cos(v)); mathfunc("tan" , tan(v)); mathfunc("asin" , asin(v)); mathfunc("acos" , acos(v)); mathfunc("atan" , atan(v)); mathfunc("sinh" , sinh(v)); mathfunc("cosh" , cosh(v)); mathfunc("tanh" , tanh(v)); mathfunc("asinh" , asinh(v)); mathfunc("acosh" , acosh(v)); mathfunc("atanh" , atanh(v)); unknown(f); return 0; }
/*注意输入的时候,需要用空格作为间断*/ main() { int type; double temp,temp2; double v; char s[MAXOP]; int i,var=0; double variable[26];/*26个字母,需要一个长为27的数组*/ for(i=0;i<26;i++) variable[i]=0.0;/*初始化数组*/ printf("\n----------RPN calculator-------------\n"); printf("* 察看栈顶元素-? *\n"); printf("* 复制栈顶元素-c(copy) *\n"); printf("* 清空栈中元素-e(erase) *\n"); printf("* 交换栈顶元素-s(swap) *\n"); printf("* 可用函数:sin,cos,exp,pow *\n"); printf("* 请用空格间隔输入 *\n"); printf("---------------------------------------\n"); printf("please input:"); while((type=getop(s))!=EOF) { switch (type) { case NUMBER: push(atof(s)); break; case NAME:/*数学函数*/ mathfunc(s); break; case '+': push(pop()+pop()); break; case '*': push(pop()*pop()); break; case '-': temp=pop(); push(pop()-temp); break; case '/': temp=pop(); if(temp!=0.0) push(pop()/temp); else printf("error:zero divisor\n"); break; case '%':/*求模运算*/ temp=pop(); if(temp!=0.0) push(fmod(pop(),temp)); else printf("error:zero divisor\n"); break; case '\n': v=pop();/*最近打印的结果存在v中*/ printf("result:\t%.8g\n",v);/*注意:此处是v,不是pop(),否则会弹出下一个值*/ break; case '?': temp=pop(); printf("top element :\t%.8g\n",temp); push(temp); break; case 'c': temp=pop(); push(temp); push(temp); break; case 'e': clear(); break; case 's': temp=pop(); temp2=pop(); push(temp); push(temp2); break; case '=':/*赋值操作*/ pop();/*把varibale相应位置弹出*/ if(var>='A'&&var<='Z')/*此时var是刚才的type(A)*/ variable[var-'A']=pop();/*把压入的字母弹出赋值给数组对应位置*/ else printf("error:no variable name\n"); break; default: if(type>='A'||type<='Z')/*A-Z为数组变量的索引*/ push(variable[type-'A']);/*把数组相应位置元素压入,第一次赋值的时候是0,但是=赋值进行后,就变成了 字母前面的数字,并在调用的时候,该数字被压入*/ else if(type=='v')/*如果输入v,则把结果v压入栈中*/ push(v); else printf("error:unknow command %s\n",s); break; } var=type;/*每次switch结束后,都把刚才的type赋值给var*/ } return 0; }