1358:中缀表达式值(expr)

【题目描述】

输入一个中缀表达式(由0-9组成的运算数、加+减-乘*除/四种运算符、左右小括号组成。注意“-”也可作为负数的标志,表达式以“@”作为结束符),判断表达式是否合法,如果不合法,请输出“NO”;否则请把表达式转换成后缀形式,再求出后缀表达式的值并输出。

注意:必须用栈操作,不能直接输出表达式的值。

【输入】

一行为一个以@结束的字符串。

【输出】

如果表达式不合法,请输出“NO”,要求大写。

如果表达式合法,请输出计算结果。

【输入样例】

1+2*8-9@

【输出样例】

8

思路: 

检查:
1.括号匹配
2.开头的负号和‘(’后的负号前都要加零
3.两个符号连在一起就是错的。除非是)后有符号和(前有符号

计算:
1.中缀转后缀

方法:
a.遇到操作数,直接放入后缀表达式的队列中
b.遇到运算符,首先把符号栈中,从栈顶开始循环把优先级大于等于它的符号放入后缀表达式。然后把符号存入符号栈
c.遇到'(',直接入栈
d.遇到')',把符号栈中的符号从栈顶开始循环加入后缀表达式中,直到遇见'(',直接弹出'('不加入

2.计算后缀表达式

代码:

 

#include<bits/stdc++.h>
using namespace std;
string a;
bool check()
{
    //括号匹配
    int t=0;
    for(int i=0;i<a.length()-1;i++)
    {
        if(a[i]=='(')t++;
        if(a[i]==')'){
            if(t>0)t--;
            else{
                return false;
            }
        }
    }
    if(t!=0)return false;
    //在-前面插入0
    for(int i=0; i<a.length()-1;i++)
    {
        if(i==0&&a[i]=='-')
            a='0'+a;
        else if(a[i]=='-'&&a[i-1]=='(')//右括号后面的负号
            a.insert(i,"0");//在第i位置插入0
    }
    //除了首位的'('与末尾的')',其余情况首尾不能为运算符
    for(int i=0;i<a.length()-1;i++)
    {
        if(!(a[i]>='0'&&a[i]<='9')&&!(a[i+1]>='0'&&a[i+1]<='9')){
            if(a[i]==')'&&a[i+1]=='(')return false;
            else if(!(a[i]==')'||a[i+1]=='('))return false;
        }
    }
    return true;
}
void jisuan()
{
    //中缀转后缀
    map<char, int> p;
    p['+']=p['-']=1;
    p['*']=p['/']=2;
    p['(']=0;
    queue<char> h;//后缀
    stack<char> f;//符号
    for(int i=0;i<a.length()-1;i++)
    {
        if(a[i]>='0'&&a[i]<='9'){
        	h.push(a[i]);
        	if(!(a[i+1]>='0'&&a[i+1]<='9')){
        		h.push(' ');
			}
		}
        else{
            if(a[i]=='('){
                f.push(a[i]);
            }
            else if(a[i]==')'){
                while(f.top()!='(')
                {
                    h.push(f.top());
                    f.pop();
                }
                f.pop();
            }
            else
            {
                while(f.size()&&p[f.top()]>=p[a[i]]){
                    h.push(f.top());
                    f.pop();
                }
                f.push(a[i]);
            }

    	}
    }
    while(f.size()){
    	h.push(f.top());
    	f.pop();
	}
    //求后缀
	stack<int> s;
	int t=0;
    while(h.size()){
    	char b=h.front();
    	h.pop();
    	int c=0,d=0;
    	int sum=0;
    	if(b==' '){
       	 	s.push(t);
       	 	t=0;
   	 	}
    	else if(b>='0'&&b<='9')
    	{
    	    t=t*10+int(b-'0');
    	}
   		else{
        	d=s.top();
        	s.pop();
        	c=s.top();
        	s.pop();
        	if(b=='+')sum=c+d;
        	else if(b=='-')sum=c-d;
        	else if(b=='*')sum=c*d;
       	 	else sum=c/d;
        	s.push(sum);
    	}
	}
    cout<<s.top()<<endl;
}
int main()
{
    cin>>a;
    if(check()){
        jisuan();
    }
    else cout<<"NO"<<endl;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值