编程语言
首页 > 编程语言> > 表达式求值(c++,符号栈+数字栈)

表达式求值(c++,符号栈+数字栈)

作者:互联网

问题:输入前缀表达式,输出计算结果
分析:
1.输入:对应infixExp的input函数,要保证能接受多位十进制数,我选用cin.peek()函数,对输入流中的下一个字符先peek,分类讨论,如果是符号,用cin输入一个数;如果是数字,再peek下一个字符,直到符号为止。
存储形式:如果要让符号和数字都在一个vector中存储,就需要自己编写一个类型,可以分别容纳符号和数字,对应MyNum类。
2.前缀转后缀:对应infixExp::toPostfixExp()函数,维护一个符号栈,根据符号的优先级,来维护这个符号栈。
存储形式:转换好的后缀表达式保存在PostFixExp类中。
3.后缀求值:对应Calculator类中的run()函数,维护一个数字栈。
代码如下:可以直接运行
(栈是自己实现的,也可以选用stl中的stack容器,稍加修改即可)

#include <iostream>
#include <vector>
#include <string>
using namespace std;

const double e = 1E-7;

template <class T>
class Stack {
private:
    int mSize;
    int top;
    T *st;
public:
    Stack():mSize(0), top(-1), st(NULL) {}
    Stack(int n): mSize(n), top(-1), st(new T[mSize]) {}
    Stack(const Stack & s) {
        if( s != this) {
            delete [] st;
            mSize = s.mSize;
            top = -1;
            st = new T[mSize];
        }
        else cout << "copy constructor false" << endl;
    }
    ~Stack() { delete [] st;}
    bool push(const T item);
    bool pop(T &item);
    bool getTop(T & item);
    void clear() {top = -1;}
    bool isEmpty() const {
        return top == -1 ? true: false;
    }
};


template <class T>
bool Stack<T>::push(const T item) {
    if(top == mSize - 1) {
        T * newSt = new T[mSize * 2];
        for(int i = 0; i <= top; i++)
            newSt[i] = st[i];
        delete [] st;
        st = newSt;
        mSize *= 2;
    }
    st[++top] = item;
    return true;
}

template <class T>
bool Stack<T>::pop(T & item) {
    if(top == -1) {
        cout << "栈为空,不能执行出栈操作" << endl;
        return false;
    }
    item = st[top--];
    return true;
}

template <class T>
bool Stack<T>::getTop(T & item) {
    if(top == -1) {
        cout << "栈为空,不能读取栈顶元素" << endl;
        return false;
    }
    item = st[top];
    return true;
}
// 以上栈实现完成

enum MyNumType {number, charactor, nothing};// 枚举类型,标志MyNum的类型

class MyNum {
private:
    char c;
    double d;
    MyNumType flag ; // flag = 1(true), myNum = char;
                // flag = 0(false), myNum = double;
public:
    MyNum():flag(nothing) {}
    explicit MyNum(char a):c(a), flag(charactor) {}
    explicit MyNum(double a):d(a), flag(number) {}
    friend ostream & operator << ( ostream & o, const MyNum num);
    bool isDouble() const {
        if(flag == MyNumType::number)
            return true;
        else
            return false;
    }
    char getCharValue() const {
        if(flag == MyNumType::charactor)
            return c;
        else {
            cout << "the MyNum is not char!" << endl;
            return '?';
        }
    }
    double getDoubleValue() const {
        if(flag == MyNumType::number)
            return d;
        else {
            cout << "the MyNum is not double!" << endl;
            return 0;
        }
    }
};

ostream & operator << ( ostream & o, const MyNum num) {
    if (num.flag == MyNumType::charactor)
        o << num.c;
    else
        o << num.d;
    return o;
}

//以上MyNum类实现完成

class Calculator { //表达式求值
private:
    Stack<double> s;
    bool getTwoOperands(double& opd1, double& opd2);
    void compute(char op);
public:
    Calculator():s(50) {};
    void run(const vector<MyNum> & v);
    void clearElem() { s.clear();}
};

bool Calculator::getTwoOperands(double& opd1, double& opd2) {
    if(s.isEmpty()) {
        cerr << "Missing operand" << endl;
        return false;
    }
    s.pop(opd2);  // 后操作数
    if(s.isEmpty()) {
        cerr << "Missing operand!" << endl;
        return false;
    }
    s.pop(opd1); // 前操作数
    return true;
}

void Calculator::compute(char op) {
    bool result;
    double opd1, opd2; // opd1 is front of op, opd2 is after op
    result = getTwoOperands(opd1, opd2);
    if(result == true) {
        switch(op) {
            case '+': s.push(opd1 + opd2); break;
            case '-': s.push(opd1 - opd2); break;
            case '*': s.push(opd1 * opd2); break;
            case '/':
                if( -e <= opd2 && opd2 >= e ) {
                    s.push(opd1 / opd2);
                }
                else {
                    cout << "Divided by 0" << endl;
                    clearElem();
                    exit(1);
                }
                break;
        }
    }
    else
        clearElem();
}

void Calculator::run(const vector<MyNum> &v) {
    char c;
    double newOperand, res;
    for(auto i: v) {
        if(i.isDouble()) {
            s.push(i.getDoubleValue() );
        }
        else {
            c = i.getCharValue();
            if(c == '=')
                break;
            else {
                compute(c);
            }
        }
        /*switch(i) {
            case '+':
            case '-':
            case '*':
            case '/':
                compute(c);
                break;
            default:
                cin.putback(c);
                cin >> newOperand;
                s.push(newOperand);
                break;*/
        
    }
    if(s.pop(res))
        cout << endl << "Result is " << res <<endl;
}

//以上Calculator类完成

class InfixExp {
private:
    vector<MyNum> v;
    Stack<char> opstack;
    vector<MyNum> postfixExp;
    bool opCompare(MyNum i);
public:
    InfixExp();
    ~InfixExp() {} ;
    vector<MyNum> input();
    friend ostream & operator << ( ostream & o, const InfixExp & i );
    vector<MyNum> toPostfixExp();
};

InfixExp::InfixExp():opstack(50){
    v = input();
    //opstack(50);
}

ostream & operator << ( ostream & o, const InfixExp & in) {
    for(auto &i: in.v)
        o << i;
    return o;
}


vector<MyNum> InfixExp::input() {
    double num;
    char c;
    vector<MyNum> v;
    while(1) {
        c = cin.peek();
        if( c == ' ') {
            cin.get();
            continue;
        }
        if( c == '=') {
            cin >> c;
            v.push_back(MyNum(c) );
            break;
        }
        else if( '0' <= c && c <= '9' ) {
            cin >> num;
            v.push_back(MyNum(num) );
        }
        else{
            cin >> c;
            v.push_back(MyNum(c) );
        }
    }
    cout << "input done!" << endl;
    return v;
}

ostream & operator << ( ostream & o, const vector<MyNum> v) {
    for (auto i: v)
        o << i << " ";
    return o;
}

bool InfixExp::opCompare(MyNum i) {
    //cout << "op: " << i ;
    const char c = i.getCharValue();
    if(c == '=') {
        char ch;
        while(!opstack.isEmpty()) {
            opstack.pop(ch);
            //cout << "before = is: " << ch << endl;
            postfixExp.push_back(MyNum(ch) );
        }
        postfixExp.push_back(MyNum(c) );
        //cout << "The final postfixexp is: " << postfixExp << endl;
        return true;
    }// end if
    else if(c == ')') {
        //cout << 1 << endl;
        char ch = ')' ;
        while(ch != '(') {
            if(opstack.isEmpty()) {
                cout << "the expression is illicit! "
                     << "miss '(' " << endl;
                exit(0);
            }
            opstack.pop(ch);
            if(ch != '(' )
                postfixExp.push_back(MyNum(ch) );
        }
        return true;
    } // end else if
    else if( opstack.isEmpty() || c == '(') {
        //cout << 2 << endl;
        opstack.push(c);
        return true;
    }// end else if
    else {
        //cout << 3 ;
        char ch;
        opstack.getTop(ch);
        if(ch == '(') {
            //cout << ".1" << endl;
            opstack.push(c);
            return true;
        }
        else {
            //cout << ".2" ;
            while(!opstack.isEmpty() ) {
                if(ch == '(' ) {
                    //cout << 1 << endl;
                    opstack.push(c);
                    return true;
                }
                else if (ch == '*' || ch == '/') {
                    //cout << 2 << endl;
                    opstack.pop(ch);
                    postfixExp.push_back(MyNum(ch) );
                
                }
                else if (ch == '+' || ch == '-') {
                    //cout << 3 << endl;
                    if(c == '*' || c == '/') {
                        opstack.push(c );
                        return true;
                    }
                    else {
                        opstack.pop(ch);
                        postfixExp.push_back(MyNum(ch) );
                    }
                }
                if(opstack.isEmpty()) {
                    opstack.push(c);
                    return true;
                }  
                opstack.getTop(ch);
            }
            opstack.push(c);
            return true;
        }// end inner else
    }//else
}// end function



vector<MyNum> InfixExp::toPostfixExp() {
    for(auto i: v) {
        //cout << "the current postfixExp is: " << postfixExp << endl;
        //cout << i << endl; // 这里我加了一个调试信息,从这里下手开始调试,可能时Stack的错误,必要时全部换成标准库中的stack
        if(i.isDouble() == true) {
            //cout << "number:" << i << endl;
            postfixExp.push_back(i);
        }
        else
            opCompare(i);
    }
    return postfixExp;
}

//以上infixExp类完成


class PostfixExp {
private:
    vector<MyNum> postfixExp;
public:
    PostfixExp(vector<MyNum> v):postfixExp(v) {}
    const vector<MyNum> getPostfixExp() const {
        return postfixExp;
    }
};


int main() {
    InfixExp infixExp;
    cout << "infixexp is: " << infixExp << endl;
    cout << "postfixexp is: " << infixExp.toPostfixExp() << endl;
    PostfixExp postfixExp( infixExp.toPostfixExp() );
    Calculator c;
    c.run(postfixExp.getPostfixExp() );
    return 0;
}

标签:opstack,cout,double,c++,else,push,MyNum,求值,表达式
来源: https://blog.csdn.net/GshWooho/article/details/115323455