您的位置:首页 > 编程语言 > C语言/C++

C++四则运算代码

2016-04-07 22:23 471 查看

问题概述

编程实现直接求解字符串形式的四则运算表达式是一个算法问题,这个问题随着加入乘除运算,以及括号运算而难度增加。

问题的解决需要下述三个步骤

将输入的表达式,也就是我们一般见到的表达式称之为中缀表达式,转换为后缀表达式。

直接使用后缀表达式借助栈数据结构来实现计算四则运算表达式。

具体的代码首先将中缀表达式适当的分割到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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息