Exercise 06.06.20

The text for this exercise reads:

(*3) Allow a user to define a function in the calculator. Hint: Define a function as a sequence of operations just as the user would have typed them. Such a sequence can be stored either as a character string or a list of tokens. Then read and execute those operations. If you want user-defined functions to take arguments, you will have to invent a notation for that.

I have changed my func class completely. Before it stored info as a set of symbols. Now I use strings with the character 'x' as the variable. When evaluating the value from an argument I do a replace (arg -> 'x') and use the calculator engine to do the calculations.

class func
{
 public:

 func() {}
 func(string str);
 ~func() {}

 func& operator= (string str) { func tmp(str); *this = tmp; }
 func& operator= (char* p) { this->operator=(string(p)); return *this; }

 double operator() (double) const;

 private:

 static const string rep; //rep = "x"
 static double evaluate(string); // calls the calculator code on the string arg.
 string m_str;
};

The Constructor

There are two ways to use a function: as a macro or as a real function. Macros are defined in the f()="macro" style, functions are defined using f(x)="function". The string passed to the constructors may (but is not required to) contain the function name before the parentheses.

func::func(string str)
{
 string::size_type placer = 0;
 while (str[placer] != '(') ++placer; //eat function name

 if (str[placer + 1] == ')') // we have a simple macro
   {
    placer += 2; // for the ")="
    m_str.assign(str,placer,string::npos);
    return;
   }
 string::size_type func_begin = placer;
 string::size_type var_sz = 0;
 while(str[++placer] != ')') ++var_sz;
 string var_name(str,placer,var_sz);

 while ( (placer = tmp.find(var_name)) != string::npos)
     {
      tmp.replace(placer,var_name.size(),rep);
     }
 m_str.assign(tmp,func_begin,string::npos);
}
 

The Evaluation Function

This is a very simple function:

double func::operator()(double arg) const
{
 string tmp = m_srt;
 istringstream a;
 a << arg;
 string argument = a.str();

 string::size_type where;

 while( (where = tmp.find(rep)) != string::npos)
      {
       tmp.replace(where,1,argument);
      }
 return evaluate(tmp);
}

double func::evaluate(string str)
{
Back to the Exercise Page
Back to my Home Page 1