75 lines
2.4 KiB
C++
75 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();
|
||
}
|