C++四则运算代码
问题概述编程实现直接求解字符串形式的四则运算表达式是一个算法问题,这个问题随着加入乘除运算,以及括号运算而难度增加。问题的解决需要下述三个步骤:将输入的表达式,也就是我们一般见到的表达式称之为中缀表达式,转换为后缀表达式。直接使用后缀表达式借助栈数据结构来实现计算四则运算表达式。具体的代码首先将中缀表达式适当的分割到vector容器中,然后对容器中的元素,按照一定的算法转换成后缀...
·
问题概述
编程实现直接求解字符串形式的四则运算表达式是一个算法问题,这个问题随着加入乘除运算,以及括号运算而难度增加。
问题的解决需要下述三个步骤:
将输入的表达式,也就是我们一般见到的表达式称之为中缀表达式,转换为后缀表达式。
直接使用后缀表达式借助栈数据结构来实现计算四则运算表达式。
具体的代码首先将中缀表达式适当的分割到vector容器中,然后对容器中的元素,按照一定的算法转换成后缀表达式,最后求解后缀表达式。
最后的代码对这些步骤做了一定的分割,也就是说虽然是使用了C++编程,但是基本是按照面向过程的C语言的形式进行了编程。
部分算法阐述
最麻烦的部分算法是中缀表达式转换成后缀表达式算法。具体的步骤如下:
- 遇到操作数:直接输出(添加到后缀表达式中)
- 栈为空时,遇到运算符,直接入栈
- 遇到左括号:将其入栈
- 遇到右括号:执行出栈操作,并将出栈的元素输出,直到弹出栈的是左括号,左括号不输出。
- 遇到其他运算符:加减乘除:弹出所有优先级大于或者等于该运算符的栈顶元素,然后将该运算符入栈
- 最终将栈中的元素依次出栈,输出。
计算后缀表达式算法
- 从左到右遍历表达式的每个数字和符号
- 遇到数字就进栈
- 遇到符号就将栈顶的两个元素出栈(第一个出栈的
是操作数B,第二个出栈的是被操作数A) - 然后做运算A 操作符 B,将计算的结果进栈
- 一直到获得最终结果。
实现代码使用到的一些辅助代码
- 使用boost库提供的数据类型转换函数–lexical_cast, 当然代码之中也使用了功能基本等同的使用STL流操作实现的数据类型转换,关于其性能的差异没有做更深入的研究。
- 更多的使用到STL提供的vector线性容器,以及对应的栈数据结构stack。程序员前辈都说,如果已经有了轮子,就没有必要重复发明轮子,除非你不知道有这个轮子。
完整代码
#include <iostream>
#include <string>
#include <stack>
#include <vector>
#include <boost/lexical_cast.hpp>
using namespace std;
using namespace boost;
/*
ConvertDataType: This function can convert data type from in to out. This
function has the same function as lexical_cast function, So this function can
replace the function provided by lexical_cast.
*/
template<class out, class in>
out ConvertDataType(const in& a)
{
std::stringstream temp;
temp << a;
out b;
temp >> b;
return b;
}
/*
isOper: This function used to check whether oper is +, -, *, /, (, )
The other isOper function is overload function for same use.
*/
bool isOper(string oper);
bool isOper(char oper);
/*
getPriority: This function used to get priority of math operator which will
used in converting Prefix Expression To Postfix Expression.
The other same name function is a ovlerload function for same function.
*/
int getPriority(char oper);
int getPriority(string oper);
/*
doMath: This function used to real calculate of add sub multiply and divide.
The other same name function is a ovlerload function for same function.
*/
double doMath(double operOne, double operTwo, char oper);
double doMath(double operOne, double operTwo, string oper);
/*
splitPrefixExpression: split the string to vector whic contains every element of equaltion
in same order, like 9+(3-1)*3+10/2 -> 9, +, (, 3, -, 1, ), *, 3, +, 10, /, 2
*/
vector<string> splitPrefixExpression(string prefixExpression);
/*
convertPrefixExpressionToPostfixExpression: convert Prefix Expression To Postfix Expression.
*/
vector<string> convertPrefixExpressionToPostfixExpression(vector<string> prefixExpression);
/*
calculatePostfixExpression: calculate Postfix Expression.
*/
double calculatePostfixExpression(vector<string> postfixExpression);
bool isOper(string oper) {
if (1 == oper.size()) {
return isOper(oper[0]);
}
return false;
}
bool isOper(char oper) {
return ('+' == oper || '-' == oper || '*' == oper ||
'/' == oper || '(' == oper || ')' == oper )? true : false;
}
int getPriority(char oper) {
switch (oper) {
case '+':
case '-':
return 1;
case '*':
case '/':
return 2;
case '(':
case ')':
return 0;
default:
return -1;
}
}
int getPriority(string oper) {
if (1 == oper.size()) {
return getPriority(oper[0]);
}
return -1;
}
double doMath(double operOne, double operTwo, char oper) {
switch(oper){
case '+':
return operOne + operTwo;
case '-':
return operOne - operTwo;
case '*':
return operOne * operTwo;
case '/':
return operOne / operTwo;
default:
return 0.0f;
}
}
double doMath(double operOne, double operTwo, string oper) {
if (1 == oper.size()) {
return doMath(operOne, operTwo, oper[0]);
}
return 0.0f;
}
vector<string> splitPrefixExpression(string prefixExpression) {
vector<string> result;
int tempIndex = 0;
for (int index = 0; index < prefixExpression.size(); index++) {
/*below statements of if is to get the operator in the equaltion*/
if (isOper(prefixExpression[index])) {
result.push_back(prefixExpression.substr(index, 1));
continue;
}
/*filter away the spaces which may be exist in equaltion*/
if (' ' == prefixExpression[index]) {
continue;
}
/*below while statements which will get numbers(maybe more than one bits
or may have dot in that(float))*/
tempIndex = index;
while (prefixExpression[index] >= '0' && prefixExpression[index] <= '9') {
if (' ' == prefixExpression[index + 1] || isOper(prefixExpression[index + 1]) ||
index == prefixExpression.size() - 1) {
result.push_back(prefixExpression.substr(tempIndex, index - tempIndex + 1));
//index--;
break;
}
index++;
}
}
return result;
}
/*
中缀表达式转后缀表达式的方法:
1.遇到操作数:直接输出(添加到后缀表达式中)
2.栈为空时,遇到运算符,直接入栈
3.遇到左括号:将其入栈
4.遇到右括号:执行出栈操作,并将出栈的元素输出,直到弹出栈的是左括号,左括号不输出。
5.遇到其他运算符:加减乘除:弹出所有优先级大于或者等于该运算符的栈顶元素,然后将该运算符入栈
6.最终将栈中的元素依次出栈,输出。
*/
vector<string> convertPrefixExpressionToPostfixExpression(vector<string> prefixExpression) {
vector<string> result;
stack<string> tool;
for (auto const& item : prefixExpression) {
if (isOper(item)) {
if (tool.empty() || "(" == item) {
tool.push(item);
} else if (")" == item) {
while ("(" != tool.top()) {
result.push_back(tool.top());
tool.pop();
}
tool.pop();
} else {
while (!tool.empty() && (getPriority(item) <= getPriority(tool.top()))) {
result.push_back(tool.top());
tool.pop();
}
tool.push(item);
}
} else {
result.push_back(item);
}
}
while (!tool.empty()){
result.push_back(tool.top());
tool.pop();
}
return result;
}
/*
从左到右遍历表达式的每个数字和符号,遇到数字就进栈,遇到符号就将栈顶的两个元素出栈(第一个出栈的
是操作数B,第二个出栈的是被操作数A),然后做运算A 操作符 B,将计算的结果进栈,一直到获得最终结果。
*/
double calculatePostfixExpression(vector<string> postfixExpression) {
stack<double> tool;
double operOne = 0.0f;
double operTwo = 0.0f;
for (auto const & item : postfixExpression) {
if (!isOper(item)){
/*
below two line code implements same function with different function.
*/
//tool.push(lexical_cast<double>(item));
tool.push(ConvertDataType<double>(item));
} else {
operTwo = tool.top();
tool.pop();
operOne = tool.top();
tool.pop();
tool.push(doMath(operOne, operTwo, item));
}
}
return tool.top();
}
int main() {
string expression = "9 + 6*(3 - (3 + 9) *1) * 3 + 10 / 2";
cout << calculatePostfixExpression(convertPrefixExpressionToPostfixExpression(splitPrefixExpression(expression))) << endl;
return 0;
}
更多推荐
已为社区贡献1条内容
所有评论(0)