📅  最后修改于: 2023-12-03 14:56:17.784000             🧑  作者: Mango
本文将介绍如何用C/C++编写一个简单的计算器程序。
计算器程序需要具备以下功能:
我们可以通过读取用户输入的算式,将其转换为逆波兰表达式,然后再对逆波兰表达式进行计算,得到最终的结果。在这个过程中,我们需要用到以下两个数据结构:
实现思路如下:
代码实现分为如下几个部分:
C++ 中可以使用 STL 中的 stack 和 queue 实现栈和队列的数据结构。
#include<stack>
#include<queue>
using namespace std;
stack<double> numStack; // 存储数字的栈
queue<string> rpnQueue; // 存储逆波兰表达式的队列
将中缀表达式转换为逆波兰表达式需要遍历中缀表达式,将数字和运算符按照一定的规则压入栈中。这里我们使用的是经典的双栈算法,即一个存储运算符的栈,一个存储数字和括号的栈。
具体实现见以下代码:
// 运算符优先级表
map<char, int> priority = {{'+', 1}, {'-', 1}, {'*', 2}, {'/', 2}, {'(', 0}};
// 将中缀表达式转换为逆波兰表达式
void inFixToPostFix(string inFixExpression) {
numStack = stack<double>(); // 清空之前计算的结果
rpnQueue = queue<string>(); // 清空队列
stack<char> operStack; // 用于存储运算符的栈
int i = 0;
while (i < inFixExpression.length()) {
if (inFixExpression[i] >= '0' && inFixExpression[i] <= '9' || inFixExpression[i] == '.') {
// 如果是数字,则直接加入队列
string num = "";
while (i < inFixExpression.length() && (inFixExpression[i] >= '0' && inFixExpression[i] <= '9' || inFixExpression[i] == '.')) {
num += inFixExpression[i];
i++;
}
rpnQueue.push(num);
} else {
// 如果是运算符,则判断优先级,并将栈中的运算符加入队列
if (operStack.empty() || priority[operStack.top()] < priority[inFixExpression[i]]) {
operStack.push(inFixExpression[i]);
i++;
} else if (inFixExpression[i] == ')') {
// 如果是右括号,则将栈中的运算符取出并加入队列
while (operStack.top() != '(') {
string oper = "";
oper += operStack.top();
rpnQueue.push(oper);
operStack.pop();
}
operStack.pop(); // 将左括号出栈
i++;
} else {
// 如果是运算符,且栈中运算符的优先级 >= 当前运算符的优先级,则将栈中的运算符取出并加入队列
while (!operStack.empty() && priority[operStack.top()] >= priority[inFixExpression[i]]) {
string oper = "";
oper += operStack.top();
rpnQueue.push(oper);
operStack.pop();
}
operStack.push(inFixExpression[i]);
i++;
}
}
}
// 将栈中的剩余运算符加入队列
while (!operStack.empty()) {
string oper = "";
oper += operStack.top();
rpnQueue.push(oper);
operStack.pop();
}
}
对逆波兰表达式进行计算需要将数字压入栈中,并在遇到运算符时弹出栈中两个数字进行计算,再将结果压入栈中。
具体实现如下:
// 对逆波兰表达式进行计算
double calculate() {
while (!rpnQueue.empty()) {
string exp = rpnQueue.front();
rpnQueue.pop();
if (exp == "+") {
double num1 = numStack.top();
numStack.pop();
double num2 = numStack.top();
numStack.pop();
numStack.push(num2 + num1);
} else if (exp == "-") {
double num1 = numStack.top();
numStack.pop();
double num2 = numStack.top();
numStack.pop();
numStack.push(num2 - num1);
} else if (exp == "*") {
double num1 = numStack.top();
numStack.pop();
double num2 = numStack.top();
numStack.pop();
numStack.push(num2 * num1);
} else if (exp == "/") {
double num1 = numStack.top();
numStack.pop();
double num2 = numStack.top();
numStack.pop();
numStack.push(num2 / num1);
} else {
double num = stod(exp);
numStack.push(num);
}
}
return numStack.top();
}
#include<iostream>
#include<stack>
#include<queue>
#include<map>
using namespace std;
stack<double> numStack; // 存储数字的栈
queue<string> rpnQueue; // 存储逆波兰表达式的队列
// 运算符优先级表
map<char, int> priority = {{'+', 1}, {'-', 1}, {'*', 2}, {'/', 2}, {'(', 0}};
// 将中缀表达式转换为逆波兰表达式
void inFixToPostFix(string inFixExpression) {
numStack = stack<double>(); // 清空之前计算的结果
rpnQueue = queue<string>(); // 清空队列
stack<char> operStack; // 用于存储运算符的栈
int i = 0;
while (i < inFixExpression.length()) {
if (inFixExpression[i] >= '0' && inFixExpression[i] <= '9' || inFixExpression[i] == '.') {
// 如果是数字,则直接加入队列
string num = "";
while (i < inFixExpression.length() && (inFixExpression[i] >= '0' && inFixExpression[i] <= '9' || inFixExpression[i] == '.')) {
num += inFixExpression[i];
i++;
}
rpnQueue.push(num);
} else {
// 如果是运算符,则判断优先级,并将栈中的运算符加入队列
if (operStack.empty() || priority[operStack.top()] < priority[inFixExpression[i]]) {
operStack.push(inFixExpression[i]);
i++;
} else if (inFixExpression[i] == ')') {
// 如果是右括号,则将栈中的运算符取出并加入队列
while (operStack.top() != '(') {
string oper = "";
oper += operStack.top();
rpnQueue.push(oper);
operStack.pop();
}
operStack.pop(); // 将左括号出栈
i++;
} else {
// 如果是运算符,且栈中运算符的优先级 >= 当前运算符的优先级,则将栈中的运算符取出并加入队列
while (!operStack.empty() && priority[operStack.top()] >= priority[inFixExpression[i]]) {
string oper = "";
oper += operStack.top();
rpnQueue.push(oper);
operStack.pop();
}
operStack.push(inFixExpression[i]);
i++;
}
}
}
// 将栈中的剩余运算符加入队列
while (!operStack.empty()) {
string oper = "";
oper += operStack.top();
rpnQueue.push(oper);
operStack.pop();
}
}
// 对逆波兰表达式进行计算
double calculate() {
while (!rpnQueue.empty()) {
string exp = rpnQueue.front();
rpnQueue.pop();
if (exp == "+") {
double num1 = numStack.top();
numStack.pop();
double num2 = numStack.top();
numStack.pop();
numStack.push(num2 + num1);
} else if (exp == "-") {
double num1 = numStack.top();
numStack.pop();
double num2 = numStack.top();
numStack.pop();
numStack.push(num2 - num1);
} else if (exp == "*") {
double num1 = numStack.top();
numStack.pop();
double num2 = numStack.top();
numStack.pop();
numStack.push(num2 * num1);
} else if (exp == "/") {
double num1 = numStack.top();
numStack.pop();
double num2 = numStack.top();
numStack.pop();
numStack.push(num2 / num1);
} else {
double num = stod(exp);
numStack.push(num);
}
}
return numStack.top();
}
// 主函数
int main() {
string inFixExpression;
cout << "请输入要计算的算式:" << endl;
cin >> inFixExpression;
inFixToPostFix(inFixExpression);
double result = calculate();
cout << "计算结果为:" << result << endl;
return 0;
}