算术表达式的计算(基于逆波兰表达式)的c++实现
来源:互联网 发布:网络摄像头平台 编辑:程序博客网 时间:2024/06/07 04:50
以字符串的形式输入一个算术表达式,如何对其进行识别并计算出结果呢?
如果按照普通的算术表达式计算,由于需要考虑到操作符和括号的优先级,实现起来十分麻烦。但是基于逆波兰表达式(也称后缀表达式)来计算的话,可以忽略其优先级顺序进行计算,十分简便。
逆波兰表达式的定义及算法可以很方便的查询到,这里不再赘述。
程序的说明如下:
输入一个算术表达式,将其转换成为后缀表达式并输出计算结果。算术表达式中只能识别“+”、“-”、“*”、“/”四种运算符,负数需要用括号表示:如“(-1)”。对于除了操作数和运算符之外的字符自动忽略。
首先是栈的定义以及字符串转换为长整形long的函数:
<span style="font-size:14px;">template<typename T>class Stack {public:void pop() {if (empty())return ;data.pop_back();--topstack;}const T& top() {return data[topstack];}void push(const T& item) {data.push_back(item);++topstack;}bool empty() {return topstack == -1 ? true : false;}private:std::vector<T> data;int topstack = -1;};long str_to_num(const std::string& s) { //字符串转长整形std::istringstream str(s);long num;str >> num;return num;}</span>
程序实现的思路及代码如下:
1.读取表达式,构造vector<string>储存成为普通的中缀表达式。忽略无意义字符,对于负数,去除括号保存。
<span style="font-size:14px;">void expression(std::vector<std::string> &vec ,const std::string& s){ std::string num;bool neg = false; //判定是否负数for (auto iter = s.begin(); iter != s.end();/*空*/) {if (*iter >= 48 && 57 >= *iter) {num += *iter;++iter;}else if (*iter == '+' || *iter == '-' || *iter == '*' || *iter == '/') {if (num.size() != 0)vec.push_back(num);num = *iter;vec.push_back(num);num = "";++iter;}else if (*iter == '(') { //处理负数情况if (num.size() != 0) {vec.push_back(num);num = "";}if (*(++iter) == '-') {neg = true;num += '-';++iter;}else vec.push_back("(");}else if (*iter == ')') {if (num.size() != 0) {vec.push_back(num);if (!neg)vec.push_back(")");num = "";++iter;}}else ++iter;}if (num.size() != 0)vec.push_back(num);}</span>
2.历遍中缀vector<string>,利用栈构造后缀vector<string>:
(1)对于操作数和左括号“(”,直接放入栈中。
(2)对于操作符“+”、“-”,弹出栈内元素直至栈为空或者遇到“(”,将操作符放入栈中。
(3)对于操作符“*”、“/”,弹出栈内元素直至栈为空或者遇到“+”、“-”、“(”,将操作符放入栈中。
(4)对于右括号“)”,弹出栈内元素直至遇到左括号“(”。
(5)历遍结束后,弹出栈内所有元素。
<span style="font-size:14px;">void postfix_exp(std::vector<std::string> &p_vec, std::vector<std::string> &vec) { Stack<std::string> sta;for (auto &oper : vec) {if (oper == "+" || oper == "-") { //对于加号和减号while (true) {if (sta.empty() || sta.top() == "(")break;p_vec.push_back(sta.top());sta.pop();}sta.push(oper);}else if (oper == "*" || oper == "/") { //对于乘号和除号while (true) {if (sta.empty() || sta.top() == "+" ||sta.top() == "-" || sta.top() == "(")break;p_vec.push_back(sta.top());sta.pop();} sta.push(oper);}else if (oper == ")") { //对于右括号while (true) {if (sta.top() == "(") {sta.pop();break;}p_vec.push_back(sta.top());sta.pop();}}else sta.push(oper);}while (!sta.empty()) {p_vec.push_back(sta.top());sta.pop();}std::cout << "The postfix-expression is : ";for (auto &row : p_vec)std::cout << row<<" ";std::cout << std::endl;}</span>
3.历遍后缀vector<string>。对于操作数转换成为长整形long放入栈中;对于运算符则弹出两个操作数进行计算,然后将结果放入栈中。栈中剩余的最后一项便是计算的最终结果。
<span style="font-size:14px;">const long count(std::vector<std::string> &vec) { Stack<long> sta;for (auto &oper : vec) {long lhs = 0, rhs = 0;if (oper=="+") {rhs = sta.top();sta.pop();lhs = sta.top();sta.pop();sta.push(lhs + rhs);}else if (oper == "-") {rhs = sta.top();sta.pop();lhs = sta.top();sta.pop();sta.push(lhs - rhs);}else if (oper == "*") {rhs = sta.top();sta.pop();lhs = sta.top();sta.pop();sta.push(lhs * rhs);}else if (oper == "/") {rhs = sta.top();sta.pop();lhs = sta.top();sta.pop();sta.push(lhs / rhs);}elsesta.push(str_to_num(oper));}if (!sta.empty())return sta.top();elsereturn 0;}</span>
最后则是main()函数的代码:
<span style="font-size:14px;">int main() {while (true) {std::string str;std::cout << "Enter the expression,or q for quit : ";std::cin >> str;if (str == "q")break;std::vector<std::string> exp;std::vector<std::string> p_exp;expression(exp, str);postfix_exp(p_exp, exp);std::cout << "The result is : " << count(p_exp) <<"."<< std::endl<<std::endl;}}</span>
新手一枚,欢迎大大们的建议和指导!
0 0
- 算术表达式的计算(基于逆波兰表达式)的c++实现
- android逆波兰表达式的应用(四)逆波兰表达式的计算实现 -----小达
- 堆栈的应用(2) 中缀算术表达式到后缀(逆波兰记法reverse polish notation)的转换及其计算 C++实现
- 堆栈的应用(2) 中缀算术表达式到后缀(逆波兰记法reverse polish notation)的转换及其计算 C++实现
- 算术表达式计算C实现
- 算术表达式的计算
- 算术表达式的计算
- 计算表达式的值c++逆波兰式实现方法
- android 逆波兰表达式的应用(二)逆波兰表达式的计算 -----小达
- 通过栈实现算术表达式的计算
- JAVA实现字符表达式的计算的实现(一)--逆波兰式的实现
- 逆波兰表达式的生成及计算
- 逆波兰表达式的生成及计算
- 逆波兰表达式的计算问题
- 续前篇-关于逆波兰表达式的计算
- 逆波兰表达式的产生及计算
- 实现逆波兰表达式(后缀表达式)的运算结果
- 基于逆波兰表达式的计算器
- Halcon对象Hobject转换为.net对象Bitmap
- Android中shape的使用
- 【bzoj1925】【SCOI2009】【最长距离】【spfa】
- XML解析的两种方式:DOM方式和SAX方式
- random_shuffle函数改变vector容器中元素的次序
- 算术表达式的计算(基于逆波兰表达式)的c++实现
- 项目中ibatis的isNotNull和isNotEmpty区别
- hadoop查询一条数据
- 面试准备:java Thread详解
- Android中解压zip中文乱码处理
- 打印1到最大的n位数
- C语言-交换
- 利用break和continue窥探空格输入与回车输入
- 面向对象的设计原则