简体   繁体   English

在C中使用表达式树评估后缀表达式

[英]Evaluating a postfix expression using expression tree in C

I can't seem to get this program to work, it is a doubly linked list representation of expression tree. 我似乎无法使该程序正常工作,它是表达式树的双向链接列表表示形式。 After creating the tree I need to evaluate the result but I can't seem to figure out how. 创建树后,我需要评估结果,但是我似乎不知道如何做。

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
typedef struct node
{
    char item;
    struct node * left;
    struct node * right;
}*Btree;

Btree root;
void operandFunc(char);
void operatorFunc(char);
void push(Btree);
Btree pop();
void infix(Btree);
void postfix(Btree);
void prefix(Btree);
int solve(Btree);
int calculate(char,int,int);
int isOperand(char); 
char expression[25];
Btree stack[25];
int stackPtr = -1;

int main()
{
    int count = 0;
    printf("Please enter a postfix expression\n");
    while((expression[count++]=getchar())!='\n');
    expression[--count] = '\0';
    //puts(expression);

    for(count = 0;expression[count]!='\0';count++)
    {
        switch(expression[count])
        {
            case '+':
            case '-':
            case '*':
            case '/':
            case '^':
            case '%':
            case '$':
                operatorFunc(expression[count]);
                break;
            default:
                operandFunc(expression[count]);
        }
    }
    if(stackPtr != 0)
    {
        printf("Incomplete / Incorrect postfix expression given!\n");
    }
    else
    {
        printf("\n\nThe result = %d",solve(stack[stackPtr])+'0');
        printf("\n\n");
        return 0;
    }
}

void prefix(Btree root)
{
    Btree temp = root;
    if(temp)
    {
        printf("%c ",temp->item);
        prefix(temp->left);
        prefix(temp->right);        
    }
}

void infix(Btree root)
{
    Btree temp = root;
    if(temp != NULL)
    {
        infix(temp->left);
        printf("%c ",temp->item);       
        infix(temp->right);     
    }
}

void postfix(Btree root)
{
    Btree temp = root;
    if(temp)
    {
        postfix(temp->left);
        postfix(temp->right);       
        printf("%c ",temp->item);       
    }
}

void push(Btree root)
{
    stack[++stackPtr] = root;
}

Btree pop()
{
    return (stack[stackPtr--]);
}

void operandFunc(char var)
{
    Btree root = (Btree)malloc(sizeof(struct node));
    root->item= var;
    root->left= NULL;
    root->right= NULL;
    push(root);
}

void operatorFunc(char var)
{
    Btree root = (Btree)malloc(sizeof(struct node));
    root->item = var;
    root->right = pop();
    root->left = pop();
    push(root);
}

int solve(Btree root)
{
    Btree temp = root;
    char num1,num2;
    char operator;
    int result;
    if(temp)
    {
        Btree LEFTP = temp->left;
        Btree RIGHTP = temp->right; 

        if(LEFTP)
        {
            if(isOperand(LEFTP->item))
            {
                num1 = LEFTP->item;
            }   
            else
            {
                num1 = solve(LEFTP);
            }
        }

        if(RIGHTP)
        {
            if(isOperand(RIGHTP->item))
            {
                num2 = RIGHTP->item;
            }   
            else
            {
                num2 = solve(RIGHTP);
            }
        }

        operator = temp->item;
        printf("Test 1 = %c, num1 = %c, num2 = %c\n",operator,num1,num2);
        result = calculate(operator,num1-'0',num2-'0');
        printf("Test Result = %d\n",result);
        temp->item = (result+'0');
        printf("Root Item = %c and %d\n",temp->item,temp->item);
        return result;
    }

    return NULL;
}

int calculate(char operator,int op1,int op2)
{
    printf("Operator = %c , num1 = %d, num2 = %d\n",operator,op1,op2);
    switch(operator)
    {
        case '+':   return(op1+op2);
                    break;
        case '-':   return(op1-op2);
                    break;
        case '*':   return(op1*op2);
                    break;
        case '/':   return(op1/op2);
                    break;
        case '%':   return(op1%op2);
                    break;
        case '$':   return pow(op1,op2);
                    break;
        default:    printf("\n illegal operation.");
                    exit;
    }
}

int isOperand(char var)
{
    switch(var)
    {
        case '+': 
        case '-':
        case '*':
        case '/':
        case '$':
        case '%':
                    return 0;
        default:
                    return 1;
    }
}

I'm having trouble converting and returning the characters as integers. 我在转换和返回整数字符时遇到麻烦。

UPDATE 1: I was able to make it solve single digit number inputs to recieve a multi digit result. 更新1:我能够使它解决一位数字输入,以获得多位数的结果。 I'm still working on a new data structure to compute multi digit numbers. 我仍在研究一种新的数据结构以计算多位数。 Here's the updated code below. 这是下面的更新代码。

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
typedef struct node
{
    char item;
    struct node * left;
    struct node * right;
}*Btree;

Btree root;
void operandFunc(char);
void operatorFunc(char);
void push(Btree);
Btree pop();
void infix(Btree);
void postfix(Btree);
void prefix(Btree);
int solve(Btree);
int calculate(char,int,int);
int isOperand(char); 
char expression[25];
Btree stack[25];
int stackPtr = -1;

int main()
{
    int count = 0;
    printf("Please enter a postfix expression\n");
    while((expression[count++]=getchar())!='\n');
    expression[--count] = '\0';
    //puts(expression);

    for(count = 0;expression[count]!='\0';count++)
    {
        switch(expression[count])
        {
            case '+':
            case '-':
            case '*':
            case '/':
            case '^':
            case '%':
            case '$':
                operatorFunc(expression[count]);
                break;
            default:
                operandFunc(expression[count]);
        }
    }
    if(stackPtr != 0)
    {
        printf("Incomplete / Incorrect postfix expression given!\n");
    }
    else
    {
        printf("\n\nThe result = %d",solve(stack[stackPtr])-'0');
        printf("\n\n");
        return 0;
    }
}

void prefix(Btree root)
{
    Btree temp = root;
    if(temp)
    {
        printf("%c ",temp->item);
        prefix(temp->left);
        prefix(temp->right);        
    }
}

void infix(Btree root)
{
    Btree temp = root;
    if(temp != NULL)
    {
        infix(temp->left);
        printf("%c ",temp->item);       
        infix(temp->right);     
    }
}

void postfix(Btree root)
{
    Btree temp = root;
    if(temp)
    {
        postfix(temp->left);
        postfix(temp->right);       
        printf("%c ",temp->item);       
    }
}

void push(Btree root)
{
    stack[++stackPtr] = root;
}

Btree pop()
{
    return (stack[stackPtr--]);
}

void operandFunc(char var)
{
    Btree root = (Btree)malloc(sizeof(struct node));
    root->item= var;
    root->left= NULL;
    root->right= NULL;
    push(root);
}

void operatorFunc(char var)
{
    Btree root = (Btree)malloc(sizeof(struct node));
    root->item = var;
    root->right = pop();
    root->left = pop();
    push(root);
}

int solve(Btree root)
{
    Btree temp = root;
    char num1,num2;
    char operator;
    int result;
    if(temp)
    {
        Btree LEFTP = temp->left;
        Btree RIGHTP = temp->right; 

        if(LEFTP)
        {
            if(isOperand(LEFTP->item))
            {
                num1 = LEFTP->item;
            }   
            else
            {
                num1 = solve(LEFTP);
            }
        }

        if(RIGHTP)
        {
            if(isOperand(RIGHTP->item))
            {
                num2 = RIGHTP->item;
            }   
            else
            {
                num2 = solve(RIGHTP);
            }
        }

        operator = temp->item;
        printf("Test 1 = %c, num1 = %c, num2 = %c\n",operator,num1,num2);
        result = calculate(operator,num1-'0',num2-'0');
        printf("Test Result = %d\n",result);
        temp->item = (result+'0');
        printf("Root Item = %c and %d\n",temp->item,temp->item);
        return root->item;
    }

    return NULL;
}

int calculate(char operator,int op1,int op2)
{
    printf("Operator = %c , num1 = %d, num2 = %d\n",operator,op1,op2);
    switch(operator)
    {
        case '+':   return(op1+op2);
                    break;
        case '-':   return(op1-op2);
                    break;
        case '*':   return(op1*op2);
                    break;
        case '/':   return(op1/op2);
                    break;
        case '%':   return(op1%op2);
                    break;
        case '$':   return pow(op1,op2);
                    break;
        default:    printf("\n illegal operation.");
                    exit;
    }
}

int isOperand(char var)
{
    switch(var)
    {
        case '+': 
        case '-':
        case '*':
        case '/':
        case '$':
        case '%':
                    return 0;
        default:
                    return 1;
    }
}

In operandFunc(expression[count]); operandFunc(expression[count]); you are only processing one character. 您只处理一个字符。 That means you cannot work with multi-character operands like 10 or 123 . 这意味着您不能使用10123类的多字符操作数。 If these occur, you push each digit separately. 如果发生这种情况,请分别按每个数字。 So your language is limited to single digit numbers (OK; your decission). 因此,您的语言仅限于一位数字(确定;您的决定)。

In solve you say printf("Root Item = %c and %d\\n",temp->item,temp->item); solve您说printf("Root Item = %c and %d\\n",temp->item,temp->item); . Here, the second argument must be converted to an int: temp->item-'0' . 在这里,第二个参数必须转换为int: temp->item-'0' You have to do that whenever you use %d in the printf format. 每当您以printf格式使用%d时,都必须这样做。

The rest of your code looks fine. 您的其余代码看起来不错。 Maybe set a higher warning level when compiling to find more errors? 也许在发现更多错误时设置了更高的警告级别?

EDIT/ADDITION: How to handle multi-digit numbers? 编辑/添加:如何处理多位数字?

The following snippet handles multi-digit numbers. 以下代码段处理多位数的数字。 You must adapt your struct to make a difference between chars and ints and change operandFunc to handle these numbers: 您必须调整结构以使char和ints之间有所区别,并更改operandFunc以处理以下数字:

while((c=getchar())!='\n')
{
    switch(c)
    {
        case '+':
        case '-':
        case '*':
        case '/':
        case '^':
        case '%':
        case '$':
            operatorFunc(c);
            break;
        default:    // assume digit(s)
            num= c-'0';
            while ((c=getchar())!='\n' && isdigit(c)) num= num*10+c-'0';
            operandFunc(num);
            ungetc(c,stdin);
    }
}

We can evaluate the postfix expression using the binary tree by keeping in mind the two conditions 我们可以通过记住两个条件来使用二叉树评估后缀表达式

if eval(root) is an operator we use recursion, eval(root->llink) + eval(root->rlink) else we return root->info - '0' 如果eval(root)是运算符,则使用递归,eval(root-> llink)+ eval(root-> rlink)否则,我们返回root-> info-'0'

Function for evaluation 评估功能

float evaluate(NODE root)
{
    float num;
    switch(root->info)
{
   case '+' : return eval(root->llink) + eval(root->rlink);

   case '-' : return eval(root->llink) - eval(root->rlink);

   case '/' : return eval(root->llink) / eval(root->rlink); 

   case '*' : return eval(root->llink) * eval(root->rlink);

       case $ :
       case ^ : return pow( eval(root->llink) ,eval(root->rlink));

       default : if(isalpha(root->info))
                 {
                    printf("%c" = root->info);
                    scanf("%f",&num);
                    return num;
                 }
                else 
                  return root->info - '0';
      }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM