栈实现表达式求值(c/c++/python)

算法逻辑:

OperandType EvaluateExpression(){
    //算术表达式求值的算符优先算法, 设OPTR和OPND分别为运算符栈和运算数栈
    //OP为运算符集合
    InitStack(OPTR); Push(OPTR, '#');
    InitStack(OPND); c = getchar();
    while(c != '#' || GetTop(OPTR) != '#'){
        if(!In(c, OP)){Push((OPND, c)); c = getchar();}//不是运算符进栈
        else 
            switch(Precede(GetTop(OPTR), c)){
                case '<'://栈顶元素优先权低
                    Push(OPTR, c); c = getchar(); break;
                case '='://脱括号并接收下一字符
                    Pop(OPTR, x); c = getchar();
                case '>'://栈顶元素优先权高, 退栈并将结果运算入栈
                    Pop(OPTR, theta); Pop(OPND, b); Pop(OPND, a);
                    Push(OPND, Operate(a, theta, b)); break;
            }
    }
    return GetTop(OPND);
}


算法实现:

1. c

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>

#define MAXSIZE 100
const char* OPERATOR_SET = "+-*/()#";

typedef struct {
    int data[MAXSIZE];
    int top;
} OperandStack;

void initOperandStack(OperandStack *s) {
    s->top = -1;
}

int pushOperand(OperandStack *s, int elem) {
    if (s->top == MAXSIZE - 1) {
        fprintf(stderr, "Stack Overflow\n");
        return -1;
    }
    s->data[++s->top] = elem;
    return 0;
}

int popOperand(OperandStack *s) {
    if (s->top == -1) {
        fprintf(stderr, "Stack Underflow\n");
        return -1;
    }
    return s->data[s->top--];
}

typedef struct {
    char data[MAXSIZE];
    int top;
} OperatorStack;

void initOperatorStack(OperatorStack *s) {
    s->top = -1;
}

int pushOperator(OperatorStack *s, char elem) {
    if (s->top == MAXSIZE - 1) {
        fprintf(stderr, "Stack Overflow\n");
        return -1;
    }
    s->data[++s->top] = elem;
    return 0;
}

int popOperator(OperatorStack *s) {
    if (s->top == -1) {
        fprintf(stderr, "Stack Underflow\n");
        return -1;
    }
    return s->data[s->top--];
}

char peekOperator(OperatorStack *s) {
    if (s->top == -1) {
        fprintf(stderr, "Stack Underflow\n");
        return -1;  // Use an invalid character to indicate error
    }
    return s->data[s->top];
}

int isInOperatorSet(char c) {
    return strchr(OPERATOR_SET, c) != NULL;
}

int precedence(char op1, char op2) {
    static const char precedence_table[7][7] = {
        {'>', '>', '<', '<', '<', '>', '>'},
        {'>', '>', '<', '<', '<', '>', '>'},
        {'>', '>', '>', '>', '<', '>', '>'},
        {'>', '>', '>', '>', '<', '>', '>'},
        {'<', '<', '<', '<', '<', '=', ' '},
        {'>', '>', '>', '>', ' ', '>', '>'},
        {'<', '<', '<', '<', '<', ' ', '='}
    };

    const char* ptr1 = strchr(OPERATOR_SET, op1);
    const char* ptr2 = strchr(OPERATOR_SET, op2);
    if (!ptr1 || !ptr2) {
        fprintf(stderr, "Operator not found in OPERATOR_SET\n");
        return -1;
    }

    int i = ptr1 - OPERATOR_SET;
    int j = ptr2 - OPERATOR_SET;

    return precedence_table[i][j];
}

int operate(int a, char op, int b) {
    switch (op) {
    case '+': return a + b;
    case '-': return a - b;
    case '*': return a * b;
    case '/':
        if (b == 0) {
            fprintf(stderr, "Division by zero error\n");
            return -1;  // Using -1 to indicate an error
        }
        return a / b;
    default:
        fprintf(stderr, "Invalid operator\n");
        return -1;  // Again, using -1 to indicate an error
    }
}

int evaluateExpression(const char* expression) {
    OperatorStack operators;
    OperandStack operands;
    initOperatorStack(&operators);
    initOperandStack(&operands);
    if (pushOperator(&operators, '#') == -1) return -1;

    const char *ptr = expression;
    char c;
    while ((c = *ptr++) != '#') {
        if (!isInOperatorSet(c) && !isdigit(c) && c != ' ') {
            fprintf(stderr, "Invalid character in expression\n");
            return -1;
        }
        if (isdigit(c)) {
            int num = c - '0';  // Convert char to integer
            while (isdigit(*ptr)) {
                num = num * 10 + (*ptr - '0');
                ptr++;
            }
            if (pushOperand(&operands, num) == -1) return -1;
        } else if (isInOperatorSet(c)) {
            while (!operators.top == -1 && precedence(peekOperator(&operators), c) != '<') {
                if (precedence(peekOperator(&operators), c) == '>') {
                    char op = popOperator(&operators);
                    int b = popOperand(&operands);
                    int a = popOperand(&operands);
                    int result = operate(a, op, b);
                    if (result == -1 || pushOperand(&operands, result) == -1) return -1;
                } else if (precedence(peekOperator(&operators), c) == '=') {
                    popOperator(&operators);
                    break;
                }
            }
            if (precedence(peekOperator(&operators), c) == '<') {
                if (pushOperator(&operators, c) == -1) return -1;
            }
        }
    }

    return popOperand(&operands);
}

int main() {
    char expression[1024];
    printf("Enter an expression terminated by #:\n");
    fgets(expression, sizeof(expression), stdin);

    int result = evaluateExpression(expression);
    if (result != -1) {
        printf("Result: %d\n", result);
    } else {
        fprintf(stderr, "Failed to evaluate expression.\n");
    }

    return 0;
}

2. c++

#include <iostream>
#include <string>
#include <cctype>
#include <sstream>
#include <stdexcept>
#include <cstring>

#define MAXSIZE 100
const char* OPERATOR_SET = "+-*/()#";

class OperandStack {
private:
    int data[MAXSIZE];
    int top;

public:
    OperandStack() : top(-1) {}

    void push(int elem) {
        if (top == MAXSIZE - 1)
            throw std::overflow_error("Stack Overflow");
        data[++top] = elem;
    }

    int pop() {
        if (top == -1)
            throw std::underflow_error("Stack Underflow");
        return data[top--];
    }

    int peek() const {
        if (top == -1)
            throw std::underflow_error("Stack Underflow");
        return data[top];
    }

    bool isEmpty() const {
        return top == -1;
    }
};

class OperatorStack {
private:
    char data[MAXSIZE];
    int top;

public:
    OperatorStack() : top(-1) {}

    void push(char elem) {
        if (top == MAXSIZE - 1)
            throw std::overflow_error("Stack Overflow");
        data[++top] = elem;
    }

    char pop() {
        if (top == -1)
            throw std::underflow_error("Stack Underflow");
        return data[top--];
    }

    char peek() const {
        if (top == -1)
            throw std::underflow_error("Stack Underflow");
        return data[top];
    }

    bool isEmpty() const {
        return top == -1;
    }
};

bool isInOperatorSet(char c) {
    return strchr(OPERATOR_SET, c) != nullptr;
}

int precedence(char op1, char op2) {
    static const char precedence[7][7] = {
        {'>', '>', '<', '<', '<', '>', '>'},
        {'>', '>', '<', '<', '<', '>', '>'},
        {'>', '>', '>', '>', '<', '>', '>'},
        {'>', '>', '>', '>', '<', '>', '>'},
        {'<', '<', '<', '<', '<', '=', ' '},
        {'>', '>', '>', '>', ' ', '>', '>'},
        {'<', '<', '<', '<', '<', ' ', '='}
    };

    const char* ptr1 = strchr(OPERATOR_SET, op1);
    const char* ptr2 = strchr(OPERATOR_SET, op2);
    if (!ptr1 || !ptr2)
        throw std::invalid_argument("Operator not found in OPERATOR_SET");

    int i = ptr1 - OPERATOR_SET;
    int j = ptr2 - OPERATOR_SET;

    return precedence[i][j];
}

int operate(int a, char op, int b) {
    switch (op) {
    case '+': return a + b;
    case '-': return a - b;
    case '*': return a * b;
    case '/':
        if (b == 0)
            throw std::runtime_error("Division by zero error");
        return a / b;
    default:
        throw std::invalid_argument("Invalid operator");
    }
}

int evaluateExpression(const std::string& expression) {
    std::istringstream exprStream(expression);
    OperatorStack operators;
    OperandStack operands;
    operators.push('#');

    char c;
    while (exprStream >> c, c != '#') {
        if (!isInOperatorSet(c) && !isdigit(c) && c != ' ') {
            throw std::runtime_error("Invalid character in expression");
        }
        if (isdigit(c)) {
            exprStream.putback(c);
            int num;
            exprStream >> num;
            operands.push(num);
        }
        else if (isInOperatorSet(c)) {
            while (!operators.isEmpty() && precedence(operators.peek(), c) != '<') {
                if (precedence(operators.peek(), c) == '>') {
                    char op = operators.pop();
                    int b = operands.pop();
                    int a = operands.pop();
                    operands.push(operate(a, op, b));
                }
                else if (precedence(operators.peek(), c) == '=') {
                    operators.pop();
                    break;
                }
            }
            if (precedence(operators.peek(), c) == '<') {
                operators.push(c);
            }
        }
    }

    return operands.pop();
}

int main() {
    try {
        std::cout << "Enter an expression terminated by #:\n";
        std::string expression;
        std::getline(std::cin, expression);  // Read the whole line of input
        int result = evaluateExpression(expression);
        std::cout << "Result: " << result << std::endl;
    }
    catch (const std::exception& e) {
        std::cerr << "Error: " << e.what() << std::endl;
    }
    return 0;
}

3. python

class OperandStack:
    def __init__(self):
        self.data = []

    def push(self, elem):
        self.data.append(elem)

    def pop(self):
        if not self.data:
            raise IndexError("Stack Underflow")
        return self.data.pop()

    def peek(self):
        if not self.data:
            raise IndexError("Stack Underflow")
        return self.data[-1]

    def is_empty(self):
        return len(self.data) == 0


class OperatorStack:
    def __init__(self):
        self.data = []

    def push(self, elem):
        self.data.append(elem)

    def pop(self):
        if not self.data:
            raise IndexError("Stack Underflow")
        return self.data.pop()

    def peek(self):
        if not self.data:
            raise IndexError("Stack Underflow")
        return self.data[-1]

    def is_empty(self):
        return len(self.data) == 0


OPERATOR_SET = "+-*/()#"
PRECEDENCE = {
    ('+', '+'): '>', ('+', '-'): '>', ('+', '*'): '<', ('+', '/'): '<', ('+', '('): '<', ('+', ')'): '>', ('+', '#'): '>',
    ('-', '+'): '>', ('-', '-'): '>', ('-', '*'): '<', ('-', '/'): '<', ('-', '('): '<', ('-', ')'): '>', ('-', '#'): '>',
    ('*', '+'): '>', ('*', '-'): '>', ('*', '*'): '>', ('*', '/'): '>', ('*', '('): '<', ('*', ')'): '>', ('*', '#'): '>',
    ('/', '+'): '>', ('/', '-'): '>', ('/', '*'): '>', ('/', '/'): '>', ('/', '('): '<', ('/', ')'): '>', ('/', '#'): '>',
    ('(', '+'): '<', ('(', '-'): '<', ('(', '*'): '<', ('(', '/'): '<', ('(', '('): '<', ('(', ')'): '=', ('(', '#'): ' ',
    (')', '+'): '>', (')', '-'): '>', (')', '*'): '>', (')', '/'): '>', (')', '('): ' ', (')', ')'): '>', (')', '#'): '>',
    ('#', '+'): '<', ('#', '-'): '<', ('#', '*'): '<', ('#', '/'): '<', ('#', '('): '<', ('#', ')'): ' ', ('#', '#'): '='
}


def operate(a, op, b):
    if op == '+':
        return a + b
    elif op == '-':
        return a - b
    elif op == '*':
        return a * b
    elif op == '/':
        if b == 0:
            raise ZeroDivisionError("Division by zero")
        return a / b
    else:
        raise ValueError("Invalid operator")


def evaluate_expression(expression):
    operators = OperatorStack()
    operands = OperandStack()
    operators.push('#')

    i = 0
    while i < len(expression):
        if expression[i].isdigit():
            num = 0
            while i < len(expression) and expression[i].isdigit():
                num = num * 10 + int(expression[i])
                i += 1
            operands.push(num)
            continue
        elif expression[i] in OPERATOR_SET:
            while not operators.is_empty() and PRECEDENCE[(operators.peek(), expression[i])] != '<':
                if PRECEDENCE[(operators.peek(), expression[i])] == '>':
                    op = operators.pop()
                    b = operands.pop()
                    a = operands.pop()
                    operands.push(operate(a, op, b))
                elif PRECEDENCE[(operators.peek(), expression[i])] == '=':
                    operators.pop()
                    break
            if PRECEDENCE[(operators.peek(), expression[i])] == '<':
                operators.push(expression[i])
        i += 1

    return operands.pop()


def main():
    expression = input("Enter an expression terminated by #:\n")
    expression = expression.strip('#\n')  # Remove the trailing '#' and newline for safety

    try:
        result = evaluate_expression(expression)
        print("Result:", result)
    except Exception as e:
        print("Error:", e)


if __name__ == "__main__":
    main()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值