#include <iostream>
#include <cctype>
#include <cstdlib>
#include <string>
#include <vector>
#include <stack>
#define ADD '+'
#define SUB '-'
#define MUL '*'
#define DIV '/'
//字符转字符串
#define to_str(c) std::string({c, '\0'})
//获取运算符的优先级
int priority(char oper)
{
switch (oper)
{
case ADD: case SUB: return 1;
case MUL: case DIV: return 2;
}
return 0;
}
//获取中缀表达式
std::vector<std::string> toInfix(std::string& expression)
{
std::vector<std::string> infix;
char *buf = new char[256]; //缓冲区用于读取数字
int index = 0;
for (int i = 0; i < expression.size(); i++)
{
char c = expression[i];
//处理第一个数字带符号的情况
if (i == 0 && (c == ADD || c == SUB))
infix.push_back("0");
if (isdigit(c) || c == '.')
buf[index++] = c;
else
{
if (index != 0)
{
buf[index] = '\0';
infix.push_back(buf);
index = 0;
}
infix.push_back(to_str(c));
//处理括号内的第一个数字带符号的情况
if (c == '(' && (expression[i + 1] == ADD || expression[i + 1] == SUB))
infix.push_back("0");
}
}
if (index)
{
buf[index] = '\0';
infix.push_back(buf);
}
delete buf;
return infix;
}
//获取逆波兰式
std::vector<std::string> toSuffix(std::vector<std::string>& infix)
{
std::stack<std::string> stack;
std::vector<std::string> suffix;
for (auto& str : infix)
{
if (isdigit(str[0]))
suffix.push_back(str); //数字直接入栈
else
{
char c = str[0];
switch (c)
{
case '(':
//取到左括号,直接入栈
stack.push(str);
break;
case ')':
//取到右括号,将栈中的数字依次弹出加入到后缀式中直到遇见左括号
while (stack.top()[0] != '(')
{
suffix.push_back(stack.top());
stack.pop();
}
stack.pop(); //弹出左括号
break;
default:
//取到运算符,若栈顶运算符优先级高则将栈顶运算符弹出加入后缀式
while (!stack.empty() && priority(c) <= priority(stack.top()[0]))
{
suffix.push_back(stack.top());
stack.pop();
}
stack.push(str); //将运算符入栈
break;
}
}
}
//将剩下的数字入栈
while (!stack.empty())
{
suffix.push_back(stack.top());
stack.pop();
}
return suffix;
}
double calculate(double num1, double num2, char oper)
{
switch (oper)
{
case ADD: return num2 + num1;
case SUB: return num2 - num1;
case MUL: return num2 * num1;
case DIV: return num2 / num1;
}
return 0;
}
double calculate(std::vector<std::string>& suffix)
{
std::stack<double> stack;
for (auto& item : suffix)
{
if (isdigit(item[0]))
stack.push(atof(item.c_str())); //遇见数字直接入栈
else
{
//遇见运算符时弹出两个数计算后入栈
double num1 = stack.top();
stack.pop();
double num2 = stack.top();
stack.pop();
stack.push(calculate(num1, num2, item[0]));
}
}
return stack.top();
}
double calculate(std::string& expression)
{
auto infix = toInfix(expression);
auto suffix = toSuffix(infix);
return calculate(suffix);
}
int main()
{
std::string input;
while (std::cin >> input)
printf(" = %.4lf\n\n", calculate(input));
return 0;
}
逆波兰计算器 - C++实现
于 2021-04-23 20:15:00 首次发布