前言
写过的四则运算相关的博客:
这里使用中缀转后缀,再计算的方法来实现四则运算。
思路:
图片来源(截图): https://www.cnblogs.com/chensongxian/p/7059802.html
代码
//
// Created by Andy Dennis on 2020/12/9.
// 使用中缀转后缀表达式来计算四则运算
//
#include <iostream>
#include <stack>
#include <cmath>
using namespace std;
int getPriority(char c);
double string2float(string s);
string infix2postfix(const string &infix);
double postfix2result(const string &postfix);
int main() {
string infixStr = "1+((2+3)*4)/2-5";
string postfixStr = infix2postfix(infixStr);
double result = postfix2result(postfixStr);
cout << "infix: " << infixStr << endl;
cout << "postfix: " << postfixStr << endl;
cout << "result: " << result << endl;
}
string infix2postfix(const string &infix) {
string postfix; // 后缀表达式
stack<char> op; // 保存中间结果
for (int i = 0; i < infix.length(); i++) {
if (infix[i] >= '0' && infix[i] <= '9') {
// 数字直接进入结果表示
string tempNumStr;
while (i < infix.length() && (infix[i] >= '0' && infix[i] <= '9' || infix[i] == '.')) {
tempNumStr += infix[i];
i++;
}
// double num = string2float(tempNumStr); 暂时不需要转换, 加入后缀表达式即可
postfix += tempNumStr;
postfix += " ";
}
if (op.empty() || op.top() == '(' || infix[i] == '(') {
// 中间结构栈为空,栈顶是左括号,遇到左括号,则运算符直接入栈
op.push(infix[i]);
} else if (infix[i] == ')') {
// 遇到左括号则一直取出中间结果栈的元素加到后缀表达式中
while (!op.empty()) {
char temp = op.top();
op.pop();
if (temp == '(') {
break;
}
postfix += temp;
postfix += " ";
}
} else if (getPriority(infix[i]) > getPriority(op.top())) {
op.push(infix[i]);
} else {
// getPriority(infix[i]) < getPriority(op.top())
char temp = op.top();
op.pop();
postfix += temp;
postfix += " ";
// 重新用当前的运算符继续判断
i--;
}
}
while (!op.empty()) {
char temp = op.top();
op.pop();
postfix += temp;
postfix += " ";
}
return postfix;
}
double postfix2result(const string &postfix) {
stack<double> numSt;
double n1, n2;
for (int i = 0; i < postfix.length(); i++) {
if (postfix[i] == ' ') // 处理一下空格
continue;
if (postfix[i] >= '0' && postfix[i] <= '9') {
// 数字直接进入结果表示
string tempNumStr;
while (i < postfix.length() && (postfix[i] >= '0' && postfix[i] <= '9' || postfix[i] == '.')) {
if (postfix[i] == ' ') {
i++; //处理一下空格
continue;
}
tempNumStr += postfix[i];
i++;
}
double num = string2float(tempNumStr);
numSt.push(num);
} else {
n2 = numSt.top();
numSt.pop();
n1 = numSt.top();
numSt.pop();
if (postfix[i] == '+')
n1 = n1 + n2;
else if (postfix[i] == '-')
n1 = n1 - n2;
else if (postfix[i] == '*')
n1 = n1 * n2;
else if (postfix[i] == '/') {
if (n2 > -0.00001 && n2 < 0.00001) {
cout << "Error! divided by zero!" << endl;
exit(EXIT_FAILURE);
}
n1 = n1 / n2;
} else {
cout << "undefined operation " << postfix[i] << " occur!" << endl;
exit(EXIT_FAILURE);
}
numSt.push(n1);
}
}
double result = numSt.top();
numSt.pop();
return result;
}
int getPriority(char c) {
int priority = -1; // -1代表错误
if (c == '+' || c == '-')
priority = 0;
if (c == '*' || c == '/')
priority = 1;
return priority;
}
// 字符串转数字
double string2float(string s) {
double n = 0;
bool isXiaoShu = false; // 判断当前的数字是不是小数部分
int xiaoShuLength = 0; // 记录小数部分的长度
for (int i = 0; i < s.length(); i++) {
if (s[i] >= '0' && s[i] <= '9') {
n = n * 10 + float(s[i] - '0');
if (isXiaoShu)
xiaoShuLength++;
} else if (s[i] == '.') {
isXiaoShu = true; //开始进入小数部分
}
}
return n * 1.0 / pow(10, xiaoShuLength);
}