Adding the ! operator and sqrt(), pow(), etc. to a calculator example application
There are a few solutions posted on Stroustrup - Programming and more will be coming over time.
Try solving exercises only with the language features and the library facilities presented so far in the book -- real novice users can't do anything else. Then return later to see how a solution can be improved.
I thought a map of strings to function pointers might be a concise way to represent things like sqrt, sin, cos, etc. that take a single double and return a double:
map<std::string, double (*)(double)> funcs;
funcs["sqrt"] = &sqrt;
funcs["sin"] = &sin;
funcs["cos"] = &cos;
Then when the parser detects a correct string (str) it can call the function with an argument (arg
) like so:
double result = funcs[str](arg);
With this method, a single call can handle all cases of functions (of that type).
Actually I'm not sure if that's the correct syntax, can anyone confirm?
Does this seem like a usable method?
It is easier to work with derived classes and virtual functions: each specialized class reading its own input...
class base {
public:
virtual double calc() = 0;
};
class get_sqrt : public base {
int useless;
public:
virtual double calc() {
cin >> number;
return sqrt(number);
}
}
get_sqrt;
Now we organize these in a map, and we will only use their pointers:
map<string,base*> func;
func["sqrt"] = &get_sqrt;
There is also a specialized method which only looks at the next character: peek();
char c = cin.peek();
You can get rid of the switch by using 1 if putting !
, +
, -
, etc. in func
; (they should operate on left_param for simplicity):
if (c>='0' && c<='9')
cin >> right_param; // Get a number, you don't have to put the
// character back as it hasn't been removed
else {
string s;
cin >> s;
right_param = func[s]->calc();
}
So basically some kind of function pointers, but without the messy syntax and in which you could store data between calculations.
I thought about the whitespace problem; it can be added before it starts to compute, I also think there could be a way to set different separators, like numbers, but I don't know how.