76 lines
2.4 KiB
C++
76 lines
2.4 KiB
C++
|
#include <algorithm> // remove()
|
|||
|
#include <cmath> // pow()
|
|||
|
#include <iostream>
|
|||
|
#include <stack> // stack<T>
|
|||
|
#include <stdexcept> // runtime_error
|
|||
|
#include <string> // string
|
|||
|
using std::string;
|
|||
|
|
|||
|
// 返回运算符的优先级,值越大,优先级越高
|
|||
|
inline size_t precedence(const char op) {
|
|||
|
if (op == '+' || op == '-')
|
|||
|
return 1;
|
|||
|
if (op == '*' || op == '/')
|
|||
|
return 2;
|
|||
|
if (op == '^')
|
|||
|
return 3;
|
|||
|
throw std::runtime_error{string{"表达中包含无效的运算符"} + op};
|
|||
|
}
|
|||
|
// 计算
|
|||
|
double execute(std::stack<char> &ops, std::stack<double> &operands) {
|
|||
|
double result{};
|
|||
|
double rhs{operands.top()}; // 得到右操作数
|
|||
|
operands.pop();
|
|||
|
double lhs{operands.top()}; // 得到做操作数
|
|||
|
operands.pop();
|
|||
|
switch (ops.top()) // 根据两个操作数之间的运算符,执行相应计算
|
|||
|
{
|
|||
|
case '+':
|
|||
|
result = lhs + rhs;
|
|||
|
break;
|
|||
|
case '-':
|
|||
|
result = lhs - rhs;
|
|||
|
break;
|
|||
|
case '*':
|
|||
|
result = lhs * rhs;
|
|||
|
break;
|
|||
|
case '/':
|
|||
|
result = lhs / rhs;
|
|||
|
break;
|
|||
|
case '^':
|
|||
|
result = std::pow(lhs, rhs);
|
|||
|
break;
|
|||
|
default:
|
|||
|
throw std::runtime_error{string{"invalid operator: "} + ops.top()};
|
|||
|
}
|
|||
|
ops.pop(); //计算完成后,该运算符要弹栈
|
|||
|
operands.push(result); //将新计算出来的结果入栈
|
|||
|
return result;
|
|||
|
}
|
|||
|
double cal(string exp) {
|
|||
|
static std::stack<double> operands; //存储表达式中的运算符
|
|||
|
static std::stack<char> operators; //存储表达式中的数值
|
|||
|
//移除用户输入表达式中包含的无用的空格
|
|||
|
size_t index{};
|
|||
|
//每个表达式必须以数字开头,index表示该数字的位数
|
|||
|
operands.push(std::stod(exp, &index)); // 将表达式中第一个数字进栈
|
|||
|
while (true) {
|
|||
|
operators.push(exp[index++]); // 将运算符进栈
|
|||
|
size_t i{};
|
|||
|
operands.push(
|
|||
|
std::stod(exp.substr(index),
|
|||
|
&i)); //将运算符后的数字也进栈,并将数字的位数赋值给 i。
|
|||
|
index += i; //更新 index
|
|||
|
if (index == exp.length()) {
|
|||
|
while (!operators.empty()) //如果 operators不为空,表示还没有计算完
|
|||
|
execute(operators, operands);
|
|||
|
break;
|
|||
|
}
|
|||
|
//如果表达式还未遍历完,但子表达式中的运算符优先级比其后面的运算符优先级大,就先计算当前的子表达式的值
|
|||
|
while (!operators.empty() &&
|
|||
|
precedence(exp[index]) <= precedence(operators.top()))
|
|||
|
execute(operators, operands);
|
|||
|
}
|
|||
|
return operands.top();
|
|||
|
}
|