0

1週間前に始めた小さな中置計算機が完成する頃だと判断し、評価関数で問題が発生しました。私の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);
}
4

1 に答える 1

1

reinterpret_castのパラメーターは、括弧で囲む必要があります。funcメンバーiselfの代わりにfuncを呼び出した結果を再解釈しようとしているように解析しているのではないかと思います。

例えば

if(  !reinterpret_cast<bool (*)(double &, double &)>(op[i].func) (result, x)  ) die("No OP");
于 2012-12-25T01:52:22.490 に答える