c/c++表达式求值,即包含加减乘除以及括号的式子(栈)

首先要了解前缀表达式,中缀表达式,后缀表达式

其实三者的区别用一句话就可概括,中缀表达式是给人算的,前缀,后缀表达式是给计算机计算的

它们都是对表达式的记法,因此也被称为前缀记法、中缀记法和后缀记法。它们之间的区别在于运算符相对与操作数的位置不同:前缀表达式的运算符位于与其相关的操作数之前;中缀和后缀同理。

举例:
(3 + 4) × 5 - 6 就是中缀表达式
- × + 3 4 5 6 前缀表达式
3 4 + 5 × 6 - 后缀表达式

中缀表达式(中缀记法)
中缀表达式是一种通用的算术或逻辑公式表示方法,操作符以中缀形式处于操作数的中间。中缀表达式是人们常用的算术表示方法。
虽然人的大脑很容易理解与分析中缀表达式,但对计算机来说中缀表达式却是很复杂的,因此计算表达式的值时,通常需要先将中缀表达式转换为前缀或后缀表达式,然后再进行求值。对计算机来说,计算前缀或后缀表达式的值非常简单。

下面附上将中缀表达式转换成后缀表达式的过程(因为我不会转成前缀表达式,好吧主要是懒得学两种)

首先将中缀表达式装换为后缀表达式

0.首先声明两个栈s1,s2,具体用处代码中有解释

1.从左到右开始扫中缀表达式,如果遇到数字直接压入s2栈中

1.2,如果遇见左括号,直接压入s1栈中

1.3如果遇见’*‘||‘/‘||’+‘||’-‘,检查s1中是否为空,如果为空或者栈顶为左括号直接压入栈s1,否则如果此运算符的优先级高于s1栈顶的优先级(注意是高于),则入栈,否则将s1栈的运算符压入s2中,知道符合要求。

2,扫完中缀表达式后,如果s1栈不为空,则全部依次压入s2中

3.再将s2中的元素逆序输出。

下面是计算后缀表达试

0.准备一个栈ans

1.0,将后缀表达式从左往右扫,如果为数字则压入ans中

1.1,如果为运算符+ *,则将ans栈顶和次栈顶弹出,进行运算,然后将结果在压入栈ans

1.2,如果运算符* /,则将根据次栈顶,栈顶的顺序进行运算,然后压入栈

2,扫完后,ans栈顶为答案

下面是c++代码,其实风格是c   --.--  这个版本对输入没有进行优化,也就是说只能输入1位的整数,如果想输入负数和小数,s1,s2的栈类型改为string类就行了,再做些细节的处理orz

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<stack>
#include<vector>
#include<iostream>
#include<sstream>
using namespace std;
stack<char>s1;//在装换为后缀表达式时,s1用于储存运算符。在计算后缀表达式时,用于储存运算数
stack<char>s2;//在转换为后缀表达式时,s2用于储存临时的后缀表达式,在计算后缀表达式时。用于储存运算符;
string middle;//中缀表达式的存储
string behind;//后缀表达式的存储
void input()
{
    cout<<"请输入表达式:(此版本为简单版本,不支持小数的输入,只支持一位数,只支持非负整数的四则运算以及括号)"<<endl;
    cin>>middle;
}
int trans_middle_to_behind()//将中缀表达式装换为后缀表达式
{
    int len=middle.size();
   // cout<<len<<endl;
    for(int i=0;i<len;i++)
    {
       if(middle[i]>='0'&&middle[i]<='9')
       {
           s2.push(middle[i]);
       }
       else if(middle[i]=='(')
            s1.push(middle[i]);
       else if(middle[i]=='+'||middle[i]=='-')
       {
           if(s1.empty()||s1.top()=='(')
           {
               s1.push(middle[i]);
           }
           else
           {
               while(!s1.empty()&&s1.top()!='(')
               {
                   s2.push(s1.top());
                   s1.pop();
               }
               s1.push(middle[i]);
           }
       }
       else if(middle[i]=='*'||middle[i]=='/')
       {
            if(s1.empty()||s1.top()=='('||s1.top()=='+'||s1.top()=='-')
                s1.push(middle[i]);
            else if(!s1.empty()&&s1.top()=='*'||s1.top()=='/')
            {
                while(!s1.empty()&&s1.top()=='*'||s1.top()=='/')
                {
                    s2.push(s1.top());
                    s1.pop();
                }
                s1.push(middle[i]);
            }
       }
       else if(middle[i]==')')
       {
           while(s1.top()!='(')
           {
               s2.push(s1.top());
               s1.pop();
           }
           s1.pop();
       }
       else
       {
           return 1;
       }
    }
    while(!s1.empty())
    {
        s2.push(s1.top());
        s1.pop();
    }
  //  cout<<"wokao"<<endl;
    return 0;
}
double cal()//计算后缀表达式的值
{
    int len=s2.size();
   // cout<<len<<endl;
    for(int i=len-1;i>=0;i--)
    {
     //   cout<<s2.top()<<endl;
        if(s2.top()>='0'&&s2.top()<='9')
        behind[i]=(s2.top()-'0');
        else
            behind[i]=s2.top();
        s2.pop();
    }
   // cout<<"wofan"<<endl;
    stack<double>ans;
    for(int i=0;i<len;i++)
    {
        if(behind[i]>=0&&behind[i]<=9)
            ans.push((double)behind[i]);
        else
        {
            double tmp;
            if(behind[i]=='+')
            {
                    tmp=0.0;
                    tmp+=(double)ans.top();
                    ans.pop();
                    tmp+=(double)ans.top();
                    ans.pop();
                    ans.push(tmp);
            }
            else if(behind[i]=='*')
            {
                tmp=1.0;
                tmp*=(double)ans.top();
                ans.pop();
                tmp*=(double)ans.top();
                ans.pop();
                ans.push(tmp);
            }
            else if(behind[i]=='/')
            {
                tmp=(double)ans.top();
                ans.pop();
                tmp=(double)ans.top()/tmp;
                ans.pop();
                ans.push(tmp);
            }
            else
            {
                tmp=(double)ans.top();
                ans.pop();
                tmp=(double)ans.top()-tmp;
                ans.pop();
                ans.push(tmp);
            }
        }
    }
    return ans.top();
}
int main()
{
    input();
    while(trans_middle_to_behind())
    {
        cout<<"输入有误,请重新输入:"<<endl;
        input();
    }
    cout<<cal()<<endl;
}



  • 2
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值