中缀表达式求值

中缀表达式指的是形如(15+(32-1)×5+14÷2)的表达式,这种就是我们通常见到的书写算式顺序,但在实际的计算机运算中要计算中缀表达式则首先要将字符串转换为后缀表达式,

然后再根据后缀表达式的规则进行运算

输入一个字符串:

"(15+(32-1)×5+14÷2)"

输出:

177

要求:

1.不合法字符检查;

2.括号匹配错误检查;

3.运算错误检查,如除0操作;

/*
* 本题本质上是中缀表达式求值,需要先将中缀表达式转为后缀表达式,规则如下:
* 1)若当前的字符是数字,则连同其后面连续的数字作为一个整体操作数,以字符串的形式存入到后缀表达式数组;

* 2)若当前字符是左括号‘(’,则直接将其压入运算符栈中;

* 3)若当前字符是右括号‘)’,则将运算符栈中的运算符依放到后缀表达式数组中,每个运算符作为一项,直到遇到一个左括号‘(’,将该左括号出栈但不加入后缀表达式;

* 4)若当前字符是运算符,则将从栈顶开始优先级比当前运算符高或同优先级的依次出栈并加入后缀表达式中,直至 栈为空 | 栈顶字符为‘(’ | 栈顶运算符优先级比当前运算符低,然后将当前运算符压栈;

* 5)遍历完中缀表达式之后,将栈中剩下的运算符依次加入后缀表达式末尾。
* 后缀表达式计算方法如下:
* 6) 从左到右扫描后缀表达式,遇到integer压栈,遇到操作符从栈顶依次弹出两个数字参与运算。
* 7) 最后栈顶元素就是解
*/
#include <bits/stdc++.h>
using namespace std;
stack<char> s1;//字符栈
map<char,int> m;//建立hash来方便优先级比较
struct node//由于一个栈不能同时存放char和integer,所以建立结构体方便操作
{
    int x = 0;//存放数字
    char c;//存放字符
    node(int x,char c)//构造函数
    {
        this->x = x;
        this->c = c;
    }
};
vector<node> node1;//存放原始字符串
vector<node> a;//存放后缀后缀表达式
stack<node> s;//计算后缀表达式用的栈
int main()
{
    m['+'] = 1;
    m['-'] = 1;
    m['*'] = 2;
    m['/'] = 2;
    //确立字符优先级
    std::ios::sync_with_stdio(false);//加速cin
    string str = "";//以字符串的形式存下中缀表达式
    cout<<"请输入中缀表达式,退出请输入end"<<endl;
    while(cin>>str){
    if(str=="end")
    break;
    string temp = "";//存下连续的数字
    node1.clear();
    a.clear();
    for(int i = 0;i<str.length();i++)
    {
        if(str[i]-'0'>=0&&str[i]-'0'<=9)
            temp+=str[i];
        else if(m[str[i]]!=0||str[i]=='('||str[i]==')')//如果是合法操作符
        {
            if(temp!="")//temp不为空,记录了一个完整数字
            {
                istringstream is(temp);//建立stringstream转string为int
                int k;
                is>>k;
                node1.push_back(node(k,' '));
                temp = "";
            }
            node1.push_back(node(-9999,str[i]));//不是的话就放入字符
        }
        else
        {
            cout<<"非法字符"<<endl;
            exit(0);
        }
    }
            if(temp!="")//i=str.length()时temp可能不为空,这里要特判
            {
                istringstream is(temp);
                int k;
                is>>k;
                node1.push_back(node(k,' '));
                temp = "";
            }
    for(int i =0;i<node1.size();i++)//中缀转后缀
    {
        if(node1[i].x!=-9999)//参考1)
        {
            a.push_back(node1[i]);
        }
        else if(node1[i].c=='(')//参考2)
            s1.push('(');
        else if(node1[i].c==')')//参考3)
        {
        while(s1.top()!='(')
        {
            a.push_back(node(-9999,s1.top()));
            s1.pop();
            if(s1.empty())
            {
                cout<<"括号匹配错误"<<endl;
                exit(0);
            }
        }
        s1.pop();
        }
        else{
            while(!s1.empty()&&(m[s1.top()]>=m[node1[i].c]))//参考4)
            {
                a.push_back(node(-9999,s1.top()));
                s1.pop();
            }
            s1.push(node1[i].c);
        }
    }
    //cout<<s1.size()<<endl;
    while(s1.size()!=0)//参考5)
    {
        if(s1.top()!='('){
        a.push_back(node(-9999,s1.top()));
        s1.pop();
        }
        else
        {
            cout<<"括号匹配错误"<<endl;
            exit(0);
        }
    }
    for(int i =0;i<a.size();i++)//计算后缀表达式,参考6)
    {
        if(a[i].x!=-9999)
        {
            s.push(a[i]);
        }
        else{
            int x = s.top().x;
            s.pop();
            int y = s.top().x;
            s.pop();
            if(a[i].c=='+')
            {
                s.push(node(x+y,' '));
            }
            else if(a[i].c=='-')
            {
                s.push(node(y-x,' '));
            }
            else if(a[i].c=='*')
            {
                s.push(node(x*y,' '));
            }
            else{
                    if(x!=0)
                s.push(node(y/x,' '));
            else{
                cout<<"除0错误"<<endl;
                exit(0);
            }
            }
        }
    }
    cout<<s.top().x<<endl;//参考7)
    cout<<"请输入中缀表达式"<<endl;
    }
    return 0;
}

 

posted @ 2022-11-24 23:23  remarkableboy  阅读(165)  评论(0编辑  收藏  举报