/* Funktionsplotter in Storm C Function-Modul */ #include #include #include #include #include #include "fclass.h" // Destruktoren: Func::~Func() { } // Default: garnix UnOpN::~UnOpN() { delete arg; } BinOpN::~BinOpN() { delete l; delete r; } // Konstruktoren: double Func::Dummy; KonstN::KonstN (double c) { Konst = c; } UnOpN::UnOpN(UnOps op, Func *n): oper(op), arg(n) { } BinOpN::BinOpN(BinOps op, Func *ln, Func *rn): oper(op), l(ln), r(rn) { } // "Konstant"-Funktionen: int Func::isconst (double &retval) { return 0; } int KonstN::isconst (double &retval) { retval = Konst; return 1; } // Ausgabe #define EPANIC 26731 void KonstN::print(char*) { printf("%g", Konst); } void VarN::print(char*) { printf("x"); } void ErrorN::print(char*) { printf("?"); } void UnOpN::print(char* str) { switch(oper) { case Op_neg: printf("-"); break; case Op_sqr: printf("sqr "); break; case Op_sqrt: printf("sqrt "); break; case Op_sin: printf("sin "); break; case Op_cos: printf("cos "); break; case Op_exp: printf("exp "); break; case Op_ln: printf("ln "); break; } arg->print(str); } void BinOpN::print(char* str) { printf("("); l->print(str); switch (oper) { case Op_add: printf("+"); break; case Op_sub: printf("-"); break; case Op_mult:printf("*"); break; case Op_div: printf("/"); break; case Op_pot: printf("^"); break; default: exit(EPANIC); } r->print(str); printf(")"); } // Auswertung inline double sqr(double x) { return x*x; } double intpotz(double base, int exp) { if (exp) { if (exp<0) return 1.0/intpotz(base,-exp) else if (exp==1) return base; else if (exp&1) return base*sqr(intpotz(base, exp/2)); else return sqr(intpotz(base, exp/2)); } else return 1; } double UnOpN::eval (double x) { double y = arg->eval(x); switch(oper) { case Op_neg: return -y; case Op_sqr: return y*y; case Op_sqrt: return sqrt(y); case Op_sin: return sin(y); case Op_cos: return cos(y); case Op_exp: return exp(y); case Op_ln: return log(y); default: exit(EPANIC); } } double BinOpN::eval (double x) { double lv = l->eval(x), rv = r->eval(x); switch(oper) { case Op_add: return lv+rv; case Op_sub: return lv-rv; case Op_mult: return lv*rv; case Op_div: return lv/rv; case Op_pot: if (r->isconst() && floor(rv)==rv) return intpotz(lv, int(rv)) else if (lv > 0) return exp(rv*log(lv)); return 0; default: exit(EPANIC); } } // ******** Parsing ******** #define EULER 2.7182818284 #define PI 3.141592653589 char *cp; // Zeiger auf String char c; // gescanntes Zeichen short ErrFlag; // Fehler aufgetreten? char Get() { while ((c = *cp) == ' ') cp++; if(c) cp++; return c; } Func *Fehler() { if (!ErrFlag) { cout << "\nError.\n"; ErrFlag = 1; } return new ErrorN; } Func *Expression(); Func *Term(); Func *Potenz(); Func *Factor() { while (c=='+') Get(); if (c=='x' || c=='X') { Get(); return new VarN; } else if (c >= '0' && c <= '9') { int i = 0; enum {max = 80}; char numstr[max+1]; while (isdigit(c) && i