Files
ScienceCalculator/ScientificCalculator/InfixToPostfix.cpp
2025-07-01 23:00:11 +08:00

79 lines
2.6 KiB
C++

#include "InfixToPostfix.h"
#include <stdexcept>
//主函数:使用逆波兰表示法将中缀表达式转换为后缀表达式
vector<Token> InfixToPostfix::run(const vector<Token>& infix) {
vector<Token> output;// 运算符栈
stack<Token> opStack;//输出后缀表达式
for (const Token& token : infix) {
if (token.is_num() || token.is_var())
//数字或变量直接放入输出队列
output.push_back(token);
else if (token.is_fun())
//函数压入运算符栈(函数优先级最高)
opStack.push(token);
else if (token.is_ope()) {
if (token.value == "!")
//后缀操作符直接入栈,不与前面的运算符进行比较
opStack.push(token);
else {
//遇到普通运算符时,弹出栈中优先级更高或相同且结合性为左结合的运算符
while (!opStack.empty() && opStack.top().is_ope() &&
(precedence(opStack.top()) > precedence(token) ||
(precedence(opStack.top()) == precedence(token) && associativity(token) == Associativity::Left))) {
output.push_back(opStack.top());
opStack.pop();
}
//当前运算符入栈
opStack.push(token);
}
}
else if (token.is_LP())
//遇到左括号,直接入栈
opStack.push(token);
else if (token.is_RP())
//遇到右括号,弹出栈中运算符直到遇到左括号
pop_ULP(opStack, output);
}
//遍历完输入后,弹出栈中所有运算符
while (!opStack.empty()) {
if (opStack.top().is_LP() || opStack.top().is_RP())
throw runtime_error("括号不匹配");//左右括号不匹配时弹出错误
output.push_back(opStack.top());
opStack.pop();
}
return output;//返回后缀表达式序列
}
//返回运算符优先级,数字越大则优先级越高
int InfixToPostfix::precedence(const Token& token) const {
return token.precedence;
}
//返回运算符结核性,左/右
Associativity InfixToPostfix::associativity(const Token& token) const {
return token.associativity;
}
//处理右括号,弹出栈中运算符知道遇到左括号
void InfixToPostfix::pop_ULP(stack<Token>& opStack, vector<Token>& output) {
//弹出直到遇到左括号
while (!opStack.empty() && !opStack.top().is_LP()) {
output.push_back(opStack.top());
opStack.pop();
}
//如果为遇到左括号则抛出异常
if (opStack.empty())
throw runtime_error("括号不匹配:缺失左括号");
opStack.pop(); // 弹出左括号
//如果左括号之前是函数,则函数也出栈并加入输出
if (!opStack.empty() && opStack.top().is_fun()) {
output.push_back(opStack.top());
opStack.pop();
}
}