码迷,mamicode.com
首页 > 其他好文 > 详细

逆波兰表达式

时间:2015-04-06 06:22:06      阅读:226      评论:0      收藏:0      [点我收藏+]

标签:

一个简单的四则运算的中缀转后缀,以及后缀的求值。已测试

中缀转后缀:

#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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!