OpenJudge题目解析-中缀表达式的值

题目描述

中缀表达式的值http://stepbystep.openjudge.cn/stackqueue/10/

思路要点

  1. 输入字符串,而后解析得到操作符和操作数(用字符串数组存储)
  2. 利用操作符栈和操作数栈对表达式进行求解

代码

#include <iostream>
#include <string>
#include <vector>
#include <assert.h>
#include <stack>
#include <cstdlib>
using namespace std;

//把表达式分解为运算符和操作符的数组
void parseExprStr(string expr, vector<string>& expVct);
//打印运算符和操作符的数组
void printExpVct(vector<string>& expVct);
//求解表达式结果
int getResult(vector<string>& expVct);


int main()
{
    int expNum;
    cin >> expNum;
    string line;
    getline(cin, line);
    for (int i = 0; i < expNum; i++)
    {
        getline(cin, line);
        vector<string> expVct;
        parseExprStr(line, expVct);
        //printExpVct(expVct);
        cout << getResult(expVct) << endl;
    }
}

void parseExprStr(string expr, vector<string>& expVct)
{
    assert(!expr.empty());
    int i = 0;
    while (i < expr.length())
    {
        if (isdigit(expr[i]))
        {
            string digitStr(1, expr[i]);
            i++;
            while (i < expr.length() && isdigit(expr[i]))
            {
                digitStr += expr[i];
                i++;
            }
            expVct.push_back(digitStr);
        }
        else
        {
            expVct.push_back(string(1, expr[i]));
            i++;
        }
    }
}

void printExpVct(vector<string>& expVct)
{
    cout << "The expression is: ";
    for (int i = 0; i < expVct.size(); i++)
        cout << expVct[i] << " ";
    cout << endl;
}

void handleCalculation(char opt, stack<int> &operands)
{
    assert(operands.size() >= 2);
    int right = operands.top();
    operands.pop();
    int left = operands.top();
    operands.pop(); 
    switch(opt)
    {
    case '+':
        operands.push(left + right);
        break;
    case '-':
        operands.push(left - right);
        break;
    case '*':
        operands.push(left * right);
        break;
    case '/':
        operands.push(left / right);
        break;
    }
}

int getLevel(char opt)
{
    switch(opt)
    {
    case '(':
        return 1;
    case '+':
    case '-':
        return 2;
    case '*':
    case '/':
        return 3;
    }
}

//leftOp优先级高于或等于rightOp,则返回true,否则返回false
bool higherThan(char leftOpt, char rightOpt)
{
    return getLevel(leftOpt) >= getLevel(rightOpt);
}

void handlePriorOperators(char opt, stack<int> &operands, stack<char>& opts)
{
    while (!opts.empty() && higherThan(opts.top(), opt) )
    {
        handleCalculation(opts.top(), operands);
        opts.pop();
    }
    return;
}

void handleOperator(char opt,stack<int> &operands, stack<char>& opts)
{
    switch(opt)
    {
    case '(':
        opts.push(opt);
        break;
    case ')':
        while(!opts.empty() && opts.top() != '(')
        {
            handleCalculation(opts.top(), operands);
            opts.pop();
        }
        if (!opts.empty()) 
            opts.pop();  //'('
        break;
    case '+':
        handlePriorOperators('+', operands, opts);
        opts.push('+');
        break;
    case '-':
        handlePriorOperators('+', operands, opts);
        opts.push('-');
        break;
    case '*':
        handlePriorOperators('*', operands, opts);
        opts.push('*');
        break;
    case '/':
        handlePriorOperators('/', operands, opts);
        opts.push('/');
        break;
    }
}

int getResult(vector<string>& expVct)
{
    stack<int> operands;  //操作数栈
    stack<char> opts;       //操作符栈
    for (int i = 0; i < expVct.size(); i++)
    {
        string op = expVct[i];
        if (isdigit(op[0]))
        {
            operands.push(atoi(op.c_str()));
        }
        else
        {
            handleOperator(op[0], operands, opts);
        }
    }
    while(!opts.empty())
    {
        handleCalculation(opts.top(), operands);
        opts.pop();
    }
    assert(operands.size() == 1);
    return operands.top();
}
中缀表达式转后缀表达式(也称为逆波兰表示法,Reverse Polish Notation,RPN),可以通过数据结构来完成。以下是简单的C语言代码实现: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> // 定义运算符优先级 #define PRECEDENCE(op) ((op)=='+' || (op)=='-' ? 1 : ((op)=='*' || (op)=='/' ? 2 : 0)) void infixToRPN(char* input, char* output) { stack<int> s; int i = 0; while (input[i] != '\0') { if (isalnum(input[i])) { // 遇到数字,直接放入output output[strlen(output)] = input[i]; output[strlen(output) + 1] = '\0'; i++; } else if (input[i] == '(') { // 遇到左括号,入 s.push(i); } else if (input[i] == ')') { // 遇到右括号,直到左括号出 while (!s.empty() && input[s.top()] != '(') output[strlen(output)] = input[s.pop()]; s.pop(); // 出左括号 } else { // 遇到操作符 while (!s.empty() && precedence(input[i]) <= precedence(input[s.top()])) { output[strlen(output)] = input[s.pop()]; } s.push(i); } i++; } // 把剩余的操作符依次压入结果 while (!s.empty()) { output[strlen(output)] = input[s.pop()]; } } int main() { char input[] = "A+B*C-(D+E)"; char output[100]; infixToRPN(input, output); printf("Infix expression: %s\n", input); printf("Postfix expression: %s\n", output); return 0; } ``` 这段代码首先定义了一个,遍历输入的中缀表达式。遇到数字直接加入输出,遇到左括号就入,遇到右括号则将左括号与之对应的运算符全部出。最后,把剩余的操作符依次压入结果。 运行这段代码会得到从给定的中缀表达式转换成的后缀表达式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值