如何将中缀转换为多位数操作数的后缀表达式?

时间:2015-02-08 03:54:36

标签: c++ stack notation infix-notation

我能够将中缀转换为后缀并使用一位数进行计算,但我无法转换为后缀并使用N位数进行计算。 PLZ有人帮帮我!谢谢!

这是我的单位数代码

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>

using namespace std;

class infix2postfix
{
public:
    void push(int symbol);
    int pop();
    void infix_to_postfix();
    int priority(char symbol);
    int isEmpty();
    int white_space(char);
    int eval_post();
};

char infix[100], postfix[100];
int stack[100];
int top;

int main()
{
    infix2postfix ip;
    top=-1;
    cout<<"Enter infix : ";
    gets(infix);
    ip.infix_to_postfix();
    cout<<"Postfix : "<<postfix<<endl;
    cout<<"Result is : "<<ip.eval_post()<<endl;
    return 1;
}

void infix2postfix :: infix_to_postfix()
{
    int i,p=0;
    char next;
    char symbol;
    for(i=0; i<strlen(infix); i++)
    {
        symbol=infix[i];
        if(!white_space(symbol))
        {
            switch(symbol)
            {
            case '(':
                push(symbol);
                break;
            case ')':
                while((next=pop())!='(')
                    postfix[p++] = next;
                break;
            case '+':
            case '-':
            case '*':
            case '/':
            case '%':
            case '^':
                while( !isEmpty( ) &&  priority(stack[top])>= priority(symbol) )
                    postfix[p++]=pop();
                push(symbol);
                break;
            default: /*if an operand comes*/
                postfix[p++]=symbol;
            }
        }
    }
    while(!isEmpty( ))
        postfix[p++]=pop();
    postfix[p]='\0'; /*End postfix with'\0' to make it a string*/
}

/*This function returns the priority of the operator*/
int infix2postfix :: priority(char symbol)
{
    switch(symbol)
    {
    case '(':
        return 0;
    case '+':
    case '-':
        return 1;
    case '*':
    case '/':
    case '%':
        return 2;
    case '^':
        return 3;
    default :
        return 0;
    }
}

void infix2postfix :: push(int symbol)
{
    if(top>100)
    {
        cout<<"Stack overflow\n";
        exit(1);
    }
    stack[++top]=symbol;
}

int infix2postfix :: pop()
{
    if( isEmpty() )
    {
        cout<<"Stack underflow\n";
        exit(1);
    }
    return (stack[top--]);
}

int infix2postfix :: isEmpty()
{
    if(top==-1)
        return 1;
    else
        return 0;
}

int infix2postfix :: white_space(char symbol)
{
    if( symbol == ' ' || symbol == '\t' )
        return 1;
    else
        return 0;
}

int infix2postfix :: eval_post()
{
    int a,b,i,temp,result;
    for(i=0; i<strlen(postfix); i++)
    {
        if(postfix[i]<='9' && postfix[i]>='0')
            push(postfix[i]-'0');
        else
        {
            a=pop();
            b=pop();
            switch(postfix[i])
            {
            case '+':
                temp=b+a;
                break;
            case '-':
                temp=b-a;
                break;
            case '*':
                temp=b*a;
                break;
            case '/':
                temp=b/a;
                break;
            case '%':
                temp=b%a;
                break;
            case '^':
                temp=pow(b,a);
            }
            push(temp);
        }
    }
    result=pop();
    return result;
}

我的问题是:如何获得超过1位数操作数的结果? 我试过单位数,但我怎么能得到多位数?

1 个答案:

答案 0 :(得分:1)

您当前正在单独推送堆栈上的数字,因此数字值10将在堆栈上推送两个符号:10

在运算符逻辑中,每个操作数从堆栈中弹出一个符号。因此,多位操作数将不起作用并产生完全错误的结果。

有很多方法可以解决这个问题。例如,您可以在读取它们时将多个数字融合到同一个堆栈符号中(例如,如果两个数字都是数字,则将当前处理的数字与堆栈顶部组合在一起)。

执行此操作的位置将在push内。以下是如何执行此操作:

void infix2postfix :: push(int symbol)
{
    if(top>100)
    {
        cout<<"Stack overflow\n";
        exit(1);
    }
    if (! isEmpty() && stack[top] >= 0 && stack[top] <= 9) {
      stack[top] *= 10;
      stack[top] += symbol;
    }
    else {
      stack[++top]=symbol;
    }
}

只要数字操作数适合int的范围,这就可以工作。更大的数字只会溢出。

还会有问题,因为除了其他堆栈符号之外,不能告诉数字。使用多位数字,您现在可以拥有与运算符具有相同int值的符号。解决此问题的方法是将负int值分配给运算符符号,并为数字指定非负值。这将适用于您的情况,因为您的语法似乎没有一元减号。 这种方法也与您在eval_post中的操作一致,您可以将堆栈上的计算结果作为单个整数值推送,无论可能包含多少位数。

最强大但最复杂的替代方法是编写语法并使用解析器生成器。我推荐GNU bison。这将完全接管为解析器生成代码,因此您所要做的就是为表达式编写语法以及实际的中缀到后缀转换(对于野牛来说这将是微不足道的)。它还可以帮助您轻松检测无效输入并提供相应的错误消息。

然而,如果你以前从未使用它,那么开始使用野牛可能很难。