算术表达式求值(栈和队列)

本文介绍了一种使用算符优先法计算包含加减乘除、平方根、自然对数的算术表达式的方法。通过读取键盘输入的合法表达式,程序会展示计算过程中操作数和运算符栈的变化,并最终输出结果。示例中,程序计算了表达式 '#(7+15)*(23-28/4)#',得到了结果 91.9908。代码详细解释了如何处理实数、运算符和括号,以及如何根据运算符优先级决定何时入栈和出栈。
摘要由CSDN通过智能技术生成

问题描述:一个算术表达式是由操作数(operand)、运算符(operator)和界限符(delimiter)组成的。
假设操作数是正整数,运算符只含加减乘除等四种运算符,界限符有左右括号和表达式起始、结束符“#”,
如:#(7+15)*(23-28/4)#。
引入表达式起始、结束符是为了方便。编程利用“算符优先法”求算术表达式的值。
基本要求:从键盘读入一个合法的算术表达式,输出正确的结果;显示输入序列和栈的变化过程,操作数类型扩充到实数。

如计算例题:
在这里插入图片描述
结果为:91.9908



#include <bits/stdc++.h>
using namespace std;

void shishu(char a[],int &i,double &c)//检测后面是否有数字
{
    double d=0.1;
    c=a[i]-'0';
    i++;
    while('0'<=a[i]&&a[i]<='9')//小数点前操作
    {
        c=10*c+a[i]-'0';//进行进位操作
        i++;
    }
    if(a[i]=='.')//小数点后操作
    {
        i++;
        while('0'<=a[i]&&a[i]<='9')//进行每次加0.1的多少次方操作
        {
            c+=(a[i]-'0')*d;
            d=0.1*d;
            i++;
        }
    }
}
char youxian(int e1,char e[],char c)//符号优先级判断
{
    if(c==')')
    return '=';
    if(e[e1]=='#')
        return '<';
    if(c=='(')
        return '<';
    if(e[e1]=='(')
        return '<';
    if(e[e1]=='^')
        return '>';
    if(c=='^')
        return '<';
    if((e[e1]=='s'||e[e1]=='l')&&(c!='s'&&c!='l'))
        return '>';
    if(c=='s'||c=='l')
        return '<';
    if(e[e1]=='*'||e[e1]=='/')//别弄错了/方向;
        return '>';
    if(c=='*'||c=='/')
        return '<';
    if(e[e1]=='+'||e[e1]=='-')
        return  '>';
}

void chuzan(double d[],int &d1,char e[],int &e1)//出栈操作
{
    double a1,a2;
    if(e[e1]=='s'||e[e1]=='l')//只要出实数栈顶一个数的操作符ln和sqrt
    {
        //cout"d1chuzan

        a1=d[d1];
        d1--;
        cout<<a1<<"出栈";
        d1++;
        if(e[e1]=='s')
        {
            cout<<"sqrt出栈";
            d[d1]=sqrt(a1);
        }
        else
        {
            cout<<"ln出栈";
            d[d1]=log(a1);
        }
        e1--;
        cout<<d[d1]<<"入栈";
        //cout"schuazan
        //cout"d1ruzan
    }
    else//实数栈顶两个数都要出的操作符
    {

        a2=d[d1];
        d1--;
        cout<<a2<<"出栈";
        a1=d[d1];
        d1--;
        cout<<a1<<"出栈";
        d1++;
        if(e[e1]=='^')
        {
            cout<<"^出栈";
            d[d1]=pow(a1,a2);
        }
        if(e[e1]=='+')
        {
            cout<<"+出栈";
            d[d1]=a1+a2;
        }
        if(e[e1]=='-')
        {
            cout<<"-出栈";
            d[d1]=a1-a2;

        }
        if(e[e1]=='*')
        {
            cout<<"*出栈";
            d[d1]=a1*a2;
        }
        if(e[e1]=='/')
        {
            cout<<"/出栈";
            d[d1]=a1/a2;
        }
        cout<<d[d1]<<"入栈";
        e1--;
    }
    cout<<endl;

}

int main()
{
    char a[100];//存储输入字符串
    double d[100];//实数栈
    char e[30];//符号栈
    int d1,e1,i=0,flag;
    double c;
    char c1;
    d1=e1=-1;
    e1++;
    e[e1]='#';//字符串肯定以#开始(题目可知),刚好可以作为栈底的标志
    gets(a);
    i++;//字符串肯定以#开始(题目可知),直接跳过a[0]
    while(a[i]!='#')
    {
        flag=0;//作为标志判断是运算符还是实数
        if('1'<=a[i]&&a[i]<='9')
        {
            shishu(a,i,c);
            flag=1;//实数时flag=1;
        }
        else//运算符时
        {
            switch(a[i])
            {
            case 'l':
                c1=a[i];
                i=i+2;//为了方便ln化为符号l,后面肯定为n,直接跳过+2;
                break;
            case 's':
                c1=a[i];
                i=i+4;//为了方便sqrt化为符号s,后面肯定为qrt,直接跳过+4;
                break;
            default:
                c1=a[i];
                i++;
            }
        }
        if(flag==1)
        {
            d1++;
            d[d1]=c;
           cout<<d[d1]<<"入栈"<<endl;
        }
        else
        {
            if( youxian(e1,e,c1)=='<')//c1的优先度高于运算符栈顶要入栈
            {
                e1++;
                e[e1]=c1;
                if(c1=='l')//用else if不知道怎么弄的报错
                    cout<<"ln入栈"<<endl;
                 if(c1=='s')
                    cout<<"sqrt入栈";
                if(c1!='s'&&c1!='l')
                cout<<c1<<"入栈";

            }
            else if(youxian(e1,e,c1)=='=')//表示运算符栈里一定有‘(’
            {
                while(e[e1]!='(')//一定得要找到运算符栈里面的‘(’
                {
                    chuzan(d,d1,e,e1);
                }
                e1--;//chuzan'('
                cout<<"(出栈";
            }
            else
            {
                while(youxian(e1,e,c1)=='>')//最重要
                //每次一定得让要入栈的c1大于运算符栈的栈顶
                 //运算符出栈后与出栈后的栈顶再次比优先度大小  
                //最后才可以让运算符栈的优先度从栈底到栈顶依次增大    
                {
                    chuzan(d,d1,e,e1);
                }
                e1++;
                e[e1]=c1;
                  if(c1=='l')
                   cout<<"ln入栈"<<endl;
                 if(c1=='s')
                    cout<<"sqrt入栈";
                if(c1!='s'&&c1!='l')
                cout<<c1<<"入栈";


            }

        }

    }
    while(e[e1]!='#')//以栈底‘#’作为结束标志,持续出栈
    {
        chuzan(d,d1,e,e1);
    }
   cout<<d[0]<<"出栈"<<",结果为"<<d[0]<<endl;//最后肯定就剩下一个数了

}



  • 7
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值