郁闷的C小加(三)

郁闷的C小加(三)

时间限制: 1000 ms  |  内存限制: 65535 KB
难度: 4
描述
聪明的你帮助C小加解决了中缀表达式到后缀表达式的转换(详情请参考“郁闷的C小加(一)”),C小加很高兴。但C小加是个爱思考的人,他又想通过这种方法计算一个表达式的值。即先把表达式转换为前缀和后缀表达式,再求值。这时又要考虑操作数是小数和多位数的情况。
输入
第一行输入一个整数T,共有T组测试数据(T<10)。
每组测试数据只有一行,是一个长度不超过1000的字符串,表示这个运算式,每个运算式都是以“=”结束。这个表达式里只包含+-*/与小括号这几种符号。其中小括号可以嵌套使用。数据保证输入的操作数中不会出现负数并且小于1000000。
数据保证除数不会为0。
输出
对于每组测试数据输出结果包括三行,先输出转换后的前缀和后缀表达式,再输出计算结果,结果保留两位小数。
样例输入
2
1+2=
(19+21)*3-4/5=
样例输出
+ 1 2 =
1 2 + =
3.00
- * + 19 21 3 / 4 5 =
19 21 + 3 * 4 5 / - =
119.20
哈哈哈,180行代码;
将中缀表达式转换为前缀表达式:
 遵循以下步骤:
 (1) 初始化两个栈:运算符栈S1和储存中间结果的栈S2;
 (2) 从右至左扫描中缀表达式;。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
 (3) 遇到操作数时,将其压入S2;
 (4) 遇到运算符时,比较其与S1栈顶运算符的优先级:
 (4-1) 如果S1为空,或栈顶运算符为右括号“)”,则直接将此运算符入栈;
 (4-2) 否则,若优先级比栈顶运算符的较高或相等,也将运算符压入S1;//**************************************注意当运算级别相等的时候也要压进去,不弹出来,这点和转后缀不同,转后缀是运算级别相等的时候弹出来,出栈**********************************************************
 (4-3) 否则,将S1栈顶的运算符弹出并压入到S2中,再次转到(4-1)与S1中新的栈顶运算符相比较;
 (5) 遇到括号时:
 (5-1) 如果是右括号“)”,则直接压入S1;
 (5-2) 如果是左括号“(”,则依次弹出S1栈顶的运算符,并压入S2,直到遇到右括号为止,此时将这一对括号丢弃;
 (6) 重复步骤(2)至(5),直到表达式的最左边;
 (7) 将S1中剩余的运算符依次弹出并压入S2;
 (8) 依次弹出S2中的元素并输出,结果即为中缀表达式对应的前缀表达式。
前缀表达式的计算机求值:
 从右至左扫描表达式,遇到数字时,将数字压入堆栈,遇到运算符时,弹出栈顶的两个数,用运算符对它们做相应的计算(栈顶元素 op 次顶元素),并将结果入栈;重复上述过程直到表达式最左端,最后运算得出的值即为表达式的结果。
 例如前缀表达式“- × + 3 4 5 6”:
 (1) 从右至左扫描,将6、5、4、3压入堆栈;
 (2) 遇到+运算符,因此弹出3和4(3为栈顶元素,4为次顶元素,注意与后缀表达式做比较),计算出3+4的值,得7,再将7入栈;
 (3) 接下来是×运算符,因此弹出7和5,计算出7×5=35,将35入栈;
 (4) 最后是-运算符,计算出35-6的值,即29,由此得出最终结果。
 可以看出,用计算机计算前缀表达式的值是很容易的。
将中缀表达式转换为后缀表达式:
 与转换为前缀表达式相似,遵循以下步骤:
 (1) 初始化两个栈:运算符栈S1和储存中间结果的栈S2;
 (2) 从左至右扫描中缀表达式;。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
 (3) 遇到操作数时,将其压入S2;
 (4) 遇到运算符时,比较其与S1栈顶运算符的优先级:
 (4-1) 如果S1为空,或栈顶运算符为左括号“(”,则直接将此运算符入栈;
 (4-2) 否则,若优先级比栈顶运算符的高,也将运算符压入S1(注意转换为前缀表达式时是优先级较高或相同,而这里则不包括相同的情况);
 (4-3) 否则,将S1栈顶的运算符弹出并压入到S2中,再次转到(4-1)与S1中新的栈顶运算符相比较;
 (5) 遇到括号时:
 (5-1) 如果是左括号“(”,则直接压入S1;
 (5-2) 如果是右括号“)”,则依次弹出S1栈顶的运算符,并压入S2,直到遇到左括号为止,此时将这一对括号丢弃;
 (6) 重复步骤(2)至(5),直到表达式的最右边;
 (7) 将S1中剩余的运算符依次弹出并压入S2;
 (8) 依次弹出S2中的元素并输出,结果的逆序即为中缀表达式对应的后缀表达式(转换为前缀表达式时不用逆序)。
后缀表达式的计算机求值  与前缀表达式类似,只是顺序是从左至右:
 从左至右扫描表达式,遇到数字时,将数字压入堆栈,遇到运算符时,弹出栈顶的两个数,用运算符对它们做相应的计算(次顶元素 op 栈顶元素),并将结果入栈;重复上述过程直到表达式最右端,最后运算得出的值即为表达式的结果。
 例如后缀表达式“3 4 + 5 × 6 -”:
 (1) 从左至右扫描,将3和4压入堆栈;
 (2) 遇到+运算符,因此弹出4和3(4为栈顶元素,3为次顶元素,注意与前缀表达式做比较),计算出3+4的值,得7,再将7入栈;
 (3) 将5入栈;
 (4) 接下来是×运算符,因此弹出5和7,计算出7×5=35,将35入栈;
 (5) 将6入栈;
 (6) 最后是-运算符,计算出35-6的值,即29,由此得出最终结果。

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<iostream>
using namespace std;
int we(char a)
{
    switch(a)
    {
    case '-' :
    case '+' :
        return 1;
        break;
    case '/' :
    case '*' :
        return 2;
        break;
    case '(' :
        return 0;
        break;
    default :
        return -1;
    }
}
int main()
{
    int j,k,n,t,top,p;
    scanf("%d",&n);
    while(n--)
    {
        int you=-1,l=0;
        char s7[1010];
        char s8[1010];
        int f=0,k=0;
        char s[15];
        char s2[1000+10],s3[1000+10],s1[1000+10];
        double s4[10010];
        memset(s4,0,sizeof(s4));
        scanf("%s",s1);
        t=strlen(s1);
        int j=-1,top=0;
        for(int i=0; i<t; i++)//转化为后缀
        {
            if((s1[i]>='0'&&s1[i]<='9')||s1[i]=='.')
            {
                s3[++j]=s1[i];
            }
            else if(s1[i]=='(')
            {
                s2[++top]=s1[i];
            }
            else if(s1[i]==')')
            {
                while(s2[top]!='(')
                {
                    s3[++j]=' ';
                    s3[++j]=s2[top];
                    --top;
                }
                --top;
            }
            else if(s1[i]=='/'||s1[i]=='*'||s1[i]=='-'||s1[i]=='+')
            {
                while(we(s1[i])<=we(s2[top]))
                {
                    s3[++j]=' ';
                    s3[++j]=s2[top];
                    --top;
                }
                s3[++j]=' ';
                s2[++top]=s1[i];
            }
        }
        while(top>=1)
        {
            s3[++j]=' ';
            s3[++j]=s2[top];
            --top;
            if(s2[1]=='(')
                break;
        }
        s3[++j]='\0';
        for(int i=t-1; i>=0; i--)//转换为前缀
        {
            if((s1[i]>='0'&&s1[i]<='9')||s1[i]=='.')
            {
                s7[++you]=s1[i];
            }
            else if(s1[i]==')')
            {
                s8[++l]=s1[i];
            }
            else if(s1[i]=='(')
            {
                while(s8[l]!=')')
                {
                    s7[++you]=' ';
                    s7[++you]=s8[l];
                    --l;
                }
                --l;
            }
            else if(s1[i]=='/'||s1[i]=='*'||s1[i]=='-'||s1[i]=='+')
            {
                while(we(s1[i])<we(s8[l]))
                {
                    s7[++you]=' ';
                    s7[++you]=s8[l];
                    --l;
                }
                s7[++you]=' ';
                s8[++l]=s1[i];
            }
        }
        while(l>=1)
        {
            s7[++you]=' ';
            s7[++you]=s8[l];
            --l;
            if(s8[1]==')')
                break;
        }
        s7[++you]='\0';
     for(int i=you-1;i>=0;i--)
     {
          printf("%c",s7[i]);
     }
     printf(" =\n");
        printf("%s =\n",s3);
        int p=0;
        k=0;
        for(int i=0; i<j; i++)//利用后缀表达式求值
        {
            if(s3[i]>='0'&&s3[i]<='9'||s3[i]=='.')
            {
                s[k++]=s3[i];
                f=1;
                continue;
            }
            if(f)
            {
                s[k]='\0';
                s4[p++]=atof(s);
                f=0,k=0;
            }
            else if(s3[i]==' ') continue;
            else if(s3[i]=='+'||s3[i]=='-'||s3[i]=='*'||s3[i]=='/')
            {
                double we;
                double ni,ha;
                p=p-1;
                ni=s4[p];
                ha=s4[--p];
                if(s3[i]=='+')
                {
                    we=ni+ha;
                    s4[p++]=we;
                }
                if(s3[i]=='-')
                {
                    we=ha-ni;
                    s4[p++]=we;
                }
                if(s3[i]=='*')
                {
                    we=ha*ni;
                    s4[p++]=we;
                }
                if(s3[i]=='/')
                {
                    we=ha/ni;
                    s4[p++]=we;
                }
            }

        }
  printf("%.2lf\n",s4[p-1]);
    }
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值