I decided it was about time I finished the little infix calculator I started a week ago, and ran into a problem in my evaluate function. My switch statement seems to have an issue with the way I'm handling my array over operator structures. I'm not entirely sure what I'm doing wrong. This isn't the only error I'm getting, but I'm sure that if I fix this then the other issues should be easier to clear up. Obviously my code ins incomplete, but considering what I have so far am I on the right track?
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
bool die(const string &msg);
//stack class
class Stack{
public:
Stack();
void push(const double &val);
void push(const string &oper);
double popnum();
string popop();
double getopele();
double getnumele();
unsigned getarity(string token);
unsigned getprec(string token);
string topop();
private:
static const unsigned MAX=30;
string opstack[MAX];
double numstack[MAX];
unsigned opele;
unsigned numele;
};
//operators
bool add(double &r, double &x, double &y);
bool subtract(double &r, double &x, double &y);
bool multiply(double &r, double &x, double &y);
bool divide(double &r, double &x, double &y);
//operator type
struct OP{
string name;
void * func;
unsigned arity;
unsigned prec;
bool lass;
string descrip;
};
//operator table
OP op[]={{"+", add, 2, 4, true, "2+3 is 5"},
{"-", subtract, 2, 4, true, "2-3 is -1"},
{"*", multiply, 2, 6, true, "2*3 is 6"},
{"/", divide, 2, 6, true, "2/3 is 0.666666..., div by 0 illegal"}};
unsigned OPELE =sizeof(op)/sizeof(op[0]);
//Manip
unsigned findindex(string token);
bool parseval(double &t, const string &token);
double parseforeval(double &result, string line);
void evaluate(double &result, Stack &s);
bool weird(double x);
int main(){
for(string line; getline(cin, line);){
if(line=="QUIT") break;
if(line.empty()) continue;
if(line=="DOC")
for(unsigned i=0; i<OPELE; i++)
cout<<op[i].name<<" | "<<op[i].descrip<<'\n';
double result;
if(parseforeval(result, line)){
cout<<result<<'\n';
}else{
cout<<"Could not understand input\n\n";
}
}
}
Stack::Stack(){
opele=0;
numele=0;
}
void Stack::push(const double &val){
if(MAX) die("Stack Overflow");
numstack[numele++]=val;
}
void Stack::push(const string &oper){
if(MAX) die("Stack Overflow");
opstack[opele++]=oper;
}
double Stack::popnum(){
if(!numele) die("Stack Underflow");
return numstack[--numele];
}
string Stack::popop(){
if(!opele) die("Stack Underflow");
return opstack[--opele];
}
double Stack::getopele(){
return opele;
}
double Stack::getnumele(){
return numele;
}
unsigned Stack::getprec(string token){
unsigned i=findindex(token);
return op[i].prec;
}
unsigned Stack::getarity(string token){
unsigned i=findindex(token);
return op[i].arity;
}
string Stack::topop(){
if(!opele) die("Undeflow");
return opstack[opele-1];
}
double parsforeval(double &result, string line){
istringstream sin(line);
Stack s;
for(string token; sin>>token;){
double t;
if(parseval(t, token)){
s.push(t);
}else if(token=="("){
s.push(parsforeval(result, line));
}else if(s.getprec(s.topop()) >s.getprec(token)){
//write eval function
s.push(token);
}else if(token== ")"){
if(!s.getnumele()) die("Bad format");
return s.popnum();
}else{
s.push(token);
}
}
while(s.getopele()){
evaluate(result, s);
}
}
void evaluate(double &result, Stack &s){
unsigned i= findindex(s.popop());
switch(op[i].arity){
case 1:
if(s.getnumele()<1) die("Underflow");
double x = s.popnum();
if( !reinterpret_cast<bool (*)(double &, double &)> !op[i].func (result, x) ) die("No OP");
break;
case 2:
if(s.getnumele()<2) die("Underflow");
double y = s.popnum();
double x = s.popnum();
if( !reinterpret_cast<bool (*)(double &, double &,double &)> op[i].func (result, x, y) ) die("No OP");
break;
case 3:
if(s.getnumele()<3) die("Underflow");
double z = s.popnum();
double y = s.popnum();
double x = s.popnum();
if( !reinterpret_cast<bool (*)(double &, double & , double & , double &)>op[i].func (result, x, y, z) ) die("No OP");
break;
default:
die("uuuuuuhhhh i have no idea");
break;
}
s.push(result);
}
bool add(double &r, double &x, double &y){
double t = x + y;
if( weird(t) ) return false;
r = t;
return true;
}
bool subtract(double &r, double &x, double &y){
double t = x - y;
if( weird(t) ) return false;
r = t;
return true;
}
bool multiply( double & r, double& x, double &y ){
double t = x * y;
if( weird(t) ) return false;
r = t;
return true;
}
bool divide( double & result, double &x, double &y ){
double t = x / y;
if( weird(t) ) return false;
result = t;
return true;
}
unsigned findindex(string token){
for(unsigned i=0; i<OPELE; i++)
if(op[i].name==token)
return i;
return UINT_MAX;
}
bool parseval(double &val, const string &token){
istringstream sin( token );
double t;
if( !(sin >>t) ) return false;
char junk;
if( sin >>junk ) return false;
val = t;
return true;
}
bool weird( double x ){
return x != x || x != 0 && x == 2*x;
}
bool die(const string &msg){
cout<<"Error: "<<msg;
exit(EXIT_FAILURE);
}
The parameter to reinterpret_cast should have parentheses around it. I think it may be parsing it as trying to reinterpret the result of calling the func instead of the func member iself.
E.g.
if( !reinterpret_cast<bool (*)(double &, double &)>(op[i].func) (result, x) ) die("No OP");