表达式的转换

                        表达式的转换

Time Limit:   5000MS          Memory Limit:   65535KB
Submissions:   56          Accepted:   19

 

Description

平常我们书写的表达式称为中缀表达式,因为它将运算符放在两个操作数中间,许多情况下为了确定运算顺序,括号是不可少的,而后缀表达式就不必用括号了。后缀标记法:书写表达式时采用运算紧跟在两个操作数之后,从而实现了无括号处理和优先级处理,使计算机的处理规则简化为:从左到右顺序完成计算,并用结果取而代之。例

如:8-(3+2*6)/5+4可以写为:8 3 2 6*+5/-4+ 其计算步骤为:

(1):8 3 2 6 * + 5 / -4 +    

(2):8 3 12 + 5 / - 4 +

(3):8 15 5 / - 4 +

(4):8 3- 4 +

(5):5 4 +

(6):9

编写一个程序,完成这个转换,要求输出的每一个数据间都留一个空格。

 

 

Input

就一行,是一个中缀表达式。输入的符号中只有这些基本符号“0123456789+-*/^()”,并且不会出现形如2*-3的格式。表达式中的基本数字也都是一位的,不会出现形如12形式的数字。所输入的字符串不要判错。

 

 

Output

若干个中缀表达式,第I+1行比第I行少一个运算符和一个操作数,最后一行只有一个数字,表示运算结果。运算的结果可能为负数,“/”以整除运算。并且中间每一步都不会超过2^31。

 

 

Sample Input

 

8-(3+2*6)/5+4

 

Sample Output

 

8  3   2  6  *  +  5  /  -  4  + 
8  3  12  +  5  /  -  4  + 
8  15  5  /  -  4  + 
8  3  -  4  + 
5  4  + 
9

 

Hint

温馨提示:优先级'^'  >  '*'  =  '/'  >  '+'   = ‘-’

 

 

 

分析:

 

求后缀式过程:
如果是'^'、'*'、'/'、'+'、'-'、'('、')',就与前一位运算符比较;看是进运算符栈,还是进后缀式;
如果是数字,就直接进入后缀式;
最后将没进后缀式的运算符压进后缀式

 

对后缀式求值过程:
先遍历后缀式,将数字都记录在数值栈中,遇到运算符就将前两位的数字弹出并进行运算,压入运算结果;
就这样不断循环就可得出结果

 

# include<stdio.h>
# include<iostream>
# include<malloc.h>
# include<math.h>
# define N 1000
using namespace std;
char postexp[N];//后缀表达式
struct Node
{
    char ch;//符号
    int pri;//优先级
}
lpri[8]={{'=',0},{'(',1},{'^',7},{'*',5},{'/',5},{'+',3},{'-',3},{')',8}},
rpri[8]={{'=',0},{'(',8},{'^',6},{'*',4},{'/',4},{'+',2},{'-',2},{')',1}};
typedef struct node1//运算符栈
{
    char data[N];
    int top;
}SeqStack;
struct node2//数值栈
{
    int data[N];
    int top;
}st;
int leftpri(char chr)
{
    int i;
    for(i=0;i<8;i++)
    {
        if(lpri[i].ch==chr)
            return lpri[i].pri;
    }
}
int rightpri(char chr)
{
    int i;
    for(i=0;i<8;i++)
    {
        if(rpri[i].ch==chr)
            return rpri[i].pri;
    }
}
int InOp(char chr)//确定是运算符
{
    if(chr=='('||chr==')'||chr=='+'||chr=='-'||chr=='*'||chr=='/'||chr=='^')
        return 1;
    else return 0;
}
int Precede(char chr1,char chr2)//确定优先级的大小
{
    int lsign=leftpri(chr1);//这样记录,就不用重复调用函数了
    int rsign=rightpri(chr2);
    if(lsign==rsign)
        return 0;
    else if(lsign<rsign)
        return -1;
    else return 1;
}
int trans(char *exp)
{
    SeqStack op;
    int i=0;
    op.top=-1;
    op.top++;
    op.data[op.top]='=';//为结束做标记,并且让第一位有所对比
    while(*exp!='\0')
    {
        if(!InOp(*exp))
        {
            while(*exp>='0'&&*exp<='9')//就本题而言,这里不用循环;但循环就可读入一位以上的数
            {
                postexp[i++]=*exp;
                exp++;
            }
            postexp[i++]=' ';//空格在这里有两个用处,一可以隔开区别数字,二可以方便最后输出
        }
        else
        {
            switch(Precede(op.data[op.top],*exp))
            {
            case -1://如果进入的运算符优先级大于前一位的话,继续压入运算符栈
                {
                    op.top++;
                    op.data[op.top]=*exp;
                    exp++;
                }
                break;
            case 0://如果进入的运算符优先级等于前一位的话,弹出前一位运算符,这种情况只有是括号才行
                {
                    op.top--;
                    exp++;
                }
                break;
            case 1://如果进入的运算符优先级小于前一位的话,弹出前一位运算符,进入后缀表达式
                {
                    postexp[i++]=op.data[op.top];
                    postexp[i++]=' ';
                    op.top--;
                }
                break;
            }
        }
    }
    while(op.data[op.top]!='=')//将剩余的运算符压入后缀表达式
    {
        postexp[i++]=op.data[op.top];
        postexp[i++]=' ';
        op.top--;
    }
    postexp[i]='\0';
    return i;//返回后缀表达式的长度
}
int solve(int num1,int num2,char ch)
{
    switch(ch)
    {
    case '+':return num1+num2;break;
    case '-':return num1-num2;break;
    case '*':return num1*num2;break;
    case '/':return num1/num2;break;
    case '^':return (int)pow((double)num1,(double)num2);break;
    }
}
void compvalue(int len)
{
    int j,num1,num2,d,cnt=0;
    st.top=-1;
    while(postexp[cnt]!='\0')
    {
        if(postexp[cnt]>='0'&&postexp[cnt]<='9')
        {
            d=0;
            while(postexp[cnt]!=' ')//将符号转换成数字
            {
                d=10*d+postexp[cnt]-'0';
                cnt++;
            }
            st.top++;
            st.data[st.top]=d;//进入数值栈
        }
        else
        {
            num2=st.data[st.top];
            st.top--;
            num1=st.data[st.top];
            st.data[st.top]=solve(num1,num2,postexp[cnt]);
            for(j=0;j<=st.top-1;j++)//前一部分肯定是数字,就用数值栈就行
            {
                printf("%d ",st.data[j]);
            }
            printf("%d",st.data[j]);
            for(j=cnt+1;j<len-1;j++)//接着将后缀式的后部分输出就行了
            {
                printf("%c",postexp[j]);
            }
            printf("\n");
            cnt++;
        }
        cnt++;//跳过空格
    }
    
}
int main()
{
    char exp[N];
    int len,i;
    scanf("%s",exp);
    len=trans(exp);//求后缀式
    for(i=0;i<len-1;i++)
    {
        printf("%c",postexp[i]);
    }
    printf("\n");
    compvalue(len);//计算后缀式的值
    return 0;
}

 

 

 

 

posted on 2012-09-22 21:37  即为将军  阅读(361)  评论(0)    收藏  举报

导航