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/Lab2/2-2-5_enhanced/cal.cpp

76 lines
2.4 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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();
}