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; }
相关文章推荐
- 如何组织构建多文件 C 语言程序(二)
- 如何写好 C main 函数
- 肯特·贝克:改变人生的代码整理魔法
- 你应该学习哪种编程语言?
- [转]我们需要一种其他人能使用的编程语言
- 书评:《算法之美( Algorithms to Live By )》
- DB2编程序技巧(1)
- DB2编程序技巧 (四)
- 女人VS编程_国庆快乐
- DB2编程序技巧 (六)
- DB2编程序技巧 (三)
- DB2编程序技巧 (九)
- DB2编程序技巧 (七)
- DB2编程序小小技巧
- DB2编程序技巧 (五)
- 动易2006序列号破解算法公布
- DB2编程序技巧 (一)
- DB2编程序技巧 (八)
- DB2编程序技巧 (十)
- VBS基础编程教程 (第1篇)