表达式求值(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;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
我可以为您提供一个简单的中缀表达式求解程序,以下是使用C语言编写的代码: ``` #include <stdio.h> #include <stdlib.h> #define STACK_SIZE 50 // 符号结构体 struct stack { int items[STACK_SIZE]; int top; }; // 初始化符号 void init_stack(struct stack *s) { s->top = -1; } // 判断符号是否为空 int is_empty(struct stack *s) { return s->top == -1; } // 判断符号是否已满 int is_full(struct stack *s) { return s->top == STACK_SIZE - 1; } // 入操作 void push(struct stack *s, int item) { if (is_full(s)) { printf("\nStack is full!"); exit(1); } s->items[++s->top] = item; } // 出操作 int pop(struct stack *s) { if (is_empty(s)) { printf("\nInvalid expression!"); exit(1); } return s->items[s->top--]; } // 获取顶元素 int peek(struct stack *s) { if (is_empty(s)) { printf("\nInvalid expression!"); exit(1); } return s->items[s->top]; } // 判断是否为操作符 int is_operator(char c) { return (c == '+' || c == '-' || c == '*' || c == '/' || c == '(' || c == ')'); } // 判断操作符的优先级 int precedence(char c) { if (c == '(' || c == ')') { return 0; } if (c == '+' || c == '-') { return 1; } if (c == '*' || c == '/') { return 2; } return 0; } // 运算操作 int operate(int op1, int op2, char operator) { switch (operator) { case '+': return op1 + op2; case '-': return op1 - op2; case '*': return op1 * op2; case '/': return op1 / op2; } return 0; } // 解析中缀表达式 int evaluate(char *expression) { struct stack operand_stack, operator_stack; int i, n, operand1, operand2; char token, operator; init_stack(&operand_stack); init_stack(&operator_stack); n = strlen(expression); for (i = 0; i < n; i++) { token = expression[i]; // 如果是数字,压入操作数 if (isdigit(token)) { push(&operand_stack, token - '0'); } // 如果是左括号,压入操作符 else if (token == '(') { push(&operator_stack, token); } // 如果是右括号,将操作符中左括号之间的操作符依次弹出,并进行运算,最后将左括号弹出 else if (token == ')') { while (peek(&operator_stack) != '(') { operand2 = pop(&operand_stack); operand1 = pop(&operand_stack); operator = pop(&operator_stack); push(&operand_stack, operate(operand1, operand2, operator)); } pop(&operator_stack); } // 如果是操作符,需要进行进一步判断 else if (is_operator(token)) { // 如果当前操作符优先级小于等于操作符顶的操作符,将操作符顶的操作符依次弹出,并进行运算 while (!is_empty(&operator_stack) && precedence(token) <= precedence(peek(&operator_stack))) { operand2 = pop(&operand_stack); operand1 = pop(&operand_stack); operator = pop(&operator_stack); push(&operand_stack, operate(operand1, operand2, operator)); } // 将当前操作符压入操作符 push(&operator_stack, token); } } // 处理剩余的操作符 while (!is_empty(&operator_stack)) { operand2 = pop(&operand_stack); operand1 = pop(&operand_stack); operator = pop(&operator_stack); push(&operand_stack, operate(operand1, operand2, operator)); } // 返回最终结果 return pop(&operand_stack); } int main() { char expression[50]; int result; printf("Please input an infix arithmetic expression:\n"); scanf("%s", expression); result = evaluate(expression); printf("\nResult = %d", result); return 0; } ``` 使用该程序求解中缀表达式的值时,需要注意输入表达式时需用括号括起来,例如:(1+2)*3。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值