2012-12-24 83 views
0

我认为是时候我完成了我一周前开始的小中缀计算器,并在我的评估函数中遇到了一个问题。我的switch语句似乎与我在操作符结构上处理数组的方式有关。我不完全确定我做错了什么。这不是我得到的唯一的错误,但我相信,如果我解决了这个问题,那么其他问题应该更容易清理。很显然,我的代码不完整,但考虑到目前为止,我在正确的轨道上?表达式必须有(指针)函数类型错误

#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); 
} 
+0

tl; dr哪条线出错? – Barmar

+0

在评估函数中,switch语句中的每个op实例都有该问题。 – Painguy

+1

'reinterpret_cast'的参数应该在其周围有括号。我认为它可能会解析它,试图重新解释调用func而不是func成员iself的结果。 – Barmar

回答

1

reinterpret_cast的参数应该在其周围有括号。我认为它可能会解析它,试图重新解释调用func而不是func成员iself的结果。

E.g.

if( !reinterpret_cast<bool (*)(double &, double &)>(op[i].func) (result, x) ) die("No OP"); 
相关问题