标签:
一个简单的四则运算的中缀转后缀,以及后缀的求值。已测试
中缀转后缀:
#include<queue>
#include<iostream>
#include<stdlib.h>
#include<string>
#include<string.h>
#include<sstream>
#include<stack>
static stack<string> ss_out; //后缀求值时用来存放后缀表达式的元素 static stack<string> ss_optr; //中缀转后缀时用来存放运算符 static queue<string> qs; //中缀换后缀时用来存放后缀表达式的元素 typedef string::const_iterator IT;
bool IsNum(IT it){ if(*it-‘0‘>=0 && *it-‘9‘<=0) return true; else return false; } //将运算符栈中( )之间的运算符弹出并压入输出队列中; void GetParenth(void){ for(;ss_optr.top()!="(";qs.push(ss_optr.top()),ss_optr.pop()){} if(ss_optr.top()=="(") ss_optr.pop(); } void Push_qs(void){ qs.push(ss_optr.top()); ss_optr.pop(); } void Push_Optr_Top(IT& it){ ostringstream oss; oss << *it; string tmp=oss.str(); ss_optr.push(tmp); } //优先级处理:+ - * / 简单的四则运算,就直接列举出来了,还可以参照百科里面二维数组定优先级的方法 void Push_Optr(IT& it){ if(*it == ‘(‘) Push_Optr_Top(it); if(*it == ‘/‘){ while(!ss_optr.empty() && ss_optr.top()=="/") Push_qs(); Push_Optr_Top(it); } if(*it == ‘*‘){ while(!ss_optr.empty() && (ss_optr.top()=="/" || ss_optr.top()=="*")) Push_qs(); Push_Optr_Top(it); } if(*it == ‘-‘){ while(!ss_optr.empty() && (ss_optr.top()=="/" || ss_optr.top()=="*" || ss_optr.top()=="-")) Push_qs(); Push_Optr_Top(it); } if(*it == ‘+‘){ while(!ss_optr.empty() && ss_optr.top()!="(") Push_qs(); Push_Optr_Top(it); } } //中缀转后缀 void IntoPost(string const& str_in){ for( IT it_in = str_in.begin(); it_in!=str_in.end(); ++it_in){ ostringstream oss; while(IsNum(it_in)){ oss << *it_in; if(!IsNum(it_in+1) || it_in+1 == str_in.end()){ string tmp = oss.str(); qs.push(tmp); //遇到符号将输出流转化成字符串存入输出队列; break; } ++it_in; } if(!IsNum(it_in)){ if(*it_in==‘)‘) GetParenth(); //将运算符栈中( )之间的运算符弹出并压入输出队列中; else{ Push_Optr(it_in); } } } while(!ss_optr.empty()){ qs.push(ss_optr.top()); ss_optr.pop(); } }
后缀求值,只写了支持int型的,没写模板,将就看了:
void Clear_s(stack<string>& ss){ while(!ss.empty()){ ss.pop(); } } //栈顶2元素运算,并将结果入栈 void Calculate(IT& it,stack<string>& ss_out){ string str_tmp = ss_out.top(); int result = atoi(str_tmp.c_str());//栈顶元素转为int; ss_out.pop(); str_tmp = ss_out.top(); ss_out.pop(); switch(*it){ case ‘+‘:result = atoi(str_tmp.c_str()) + result; break; case ‘-‘:result = atoi(str_tmp.c_str()) - result; break; case ‘*‘:result = atoi(str_tmp.c_str()) * result; break; case ‘/‘:result = atoi(str_tmp.c_str()) / result; break; } ostringstream oss; oss << result; str_tmp = oss.str();//计算结果转为string ss_out.push(str_tmp); } //后缀表达式求值 void Post_Val(string const& str_post){ Clear_s(ss_out); for(IT it_out = str_post.begin(); it_out!=str_post.end(); ++it_out){ ostringstream oss; while(IsNum(it_out)){ oss << *it_out; if(!IsNum(it_out+1)){ string tmp = oss.str(); ss_out.push(tmp); //遇到符号将输出流内数字转化成字符串存入栈; } ++it_out; } if(!IsNum(it_out)){ if(*it_out == ‘,‘) continue; else Calculate(it_out,ss_out); } } }
测试:
void Show_Post(){ while(!qs.empty()){ cout << qs.front() << " " << flush; qs.pop(); } cout << endl; } void test(){ string str_post; string str_in; cout << "Input infix expression:" << endl; cin >> str_in; IntoPost(str_in); Show_Post(); cout << "Input postfix expression:" << endl; cin >> str_post; Post_Val(str_post); cout << ss_out.top() << endl; } int main(void){ test(); return 0; }
例如,输入13+(30-((600/2/15-2-3*4)/2)*10-50) -> 输出为 13 30 600 2 / 15 2 - 3 4 * - 2 / 10 * - 50 - +
输入: 13 30 600 2 / 15 2 - 3 4 * - 2 / 10 * - 50 - + ->输出:-37
改进:
1.运算符优先级处理方面可以更通用、更优化
2.检查用户输入的合法性
3.求值可以写成模板形式以更通用
写了很多C、C++的,感觉各有千秋,C++简化了指针用起来很舒服,但是C往往更简单粗暴,真是麻烦。
标签:
原文地址:http://www.cnblogs.com/young8848/p/4395303.html