This repository has been archived on 2024-01-06. You can view files and clone it, but cannot push or open issues or pull requests.
justhomework/SoftwareDesign/Code/2-2-5_enhanced/cal.cpp

76 lines
2.4 KiB
C++
Raw Normal View History

2022-03-29 08:42:01 +00:00
#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();
}