简体   繁体   English

从中缀到后缀

[英]Going from infix to postfix

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include "stack.h"

#define MAX_EQU_LEN 100

static int prec(char operator)
{
    switch (operator)
    {
        case '*':
            return 5;
        case '/':
            return 4;
        case '%':
            return 3;
        case '+':
            return 2;
        case '-':
            return 1;
        default:
            break;
    }

    return 0;
}

static int isNumeric(char* num)
{
    if(atoi(num) == 0)
    {
        return 0;
    }
            return 1;
}

char* infix_to_postfix(char* infix)
{
    char* postfix = malloc(MAX_EQU_LEN);
    stack* s = create_stack();
    s->size = strlen(infix);
    node* tempPtr = s->stack;
    unsigned int i;
    char symbol,next;

    for(i = 0; i < s->size ; i++)
    {
        symbol = *((infix + i));
        tempPtr = s->stack;
        if(isNumeric(&symbol) != 1)
        {
            strcat(postfix, &symbol);
        }
        else if(symbol == '(')
        {
            push(s, symbol);
        }
        else if(symbol == ')')
        {
            while(s->size != 0 && top(s) != '(')
            {
                next = tempPtr->data;
                pop(s);
                strcat(postfix, &next);
                tempPtr = s->stack;
                if(tempPtr->data == '(')
                {
                    pop(s);
                }
            }
        }
        else
        {
            while(s->size != 0 && prec(top(s)) > prec(symbol))
            {
                next = tempPtr->data;
                pop(s);
                strcat(postfix, &next);
                push(s,next);
            }
        }
        while(s->size != 0)
        {
            next = tempPtr->data;
            pop(s);
            strcat(postfix, &next);
        }
    }
    return postfix;

}

int evaluate_postfix(char* postfix) {

    //For each token in the string
        int i,result;
        int right, left;
        char ch;
        stack* s = create_stack();
        node* tempPtr = s->stack;

        for(i=0;postfix[i] < strlen(postfix); i++){
            //if the token is numeric
            ch = postfix[i];
            if(isNumeric(&ch)){
                //convert it to an integer and push it onto the stack
                atoi(&ch);
                push(s, ch);
            }
            else
            {
                pop(&s[i]);
                pop(&s[i+1]);
                //apply the operation:
                //result = left op right
                       switch(ch)
                       {
                           case '+': push(&s[i],right + left);
                                     break;
                           case '-': push(&s[i],right - left);
                                     break;
                           case '*': push(&s[i],right * left);
                                     break;
                           case '/': push(&s[i],right / left);
                                     break;
                       }
                }
        }
        tempPtr = s->stack;
        //return the result from the stack
        return(tempPtr->data);

}

This file is part of a program that uses a stack struct to perform an infix to postfix on an input file. 该文件是程序的一部分,该程序使用堆栈结构对输入文件执行后缀缀。 The other functions have been tested and work fine but when I try to add this part and actually perform the operations the program segmentation faults. 其他功能已经过测试并且可以正常工作,但是当我尝试添加此部分并实际执行操作时,程序分段错误。 A debugger says it occurs in the infix_to_postfix function however it doesn't say which line and I can't figure out where. 调试器说它发生在infix_to_postfix函数中,但是它没有说出哪一行,我也不知道在哪里。 Does anyone know why this would seg fault? 有谁知道这会导致段错误吗?

You've done a few things wrong: 您做错了几件事:

    if(isNumeric(&symbol) != 1)

The function isNumeric() expects a null terminated string as input, not a pointer to a single character. 函数isNumeric()期望将一个以空终止的字符串作为输入,而不是指向单个字符的指针。

        strcat(postfix, &symbol);

Here the same thing applies. 这里同样适用。

        strcat(postfix, &next);

I'm guessing this is wrong too. 我猜这也是错误的。 If you want to turn a single character into a string, you can do this: 如果要将单个字符转换为字符串,可以执行以下操作:

char temp[2] = {0};

temp[0] = symbol;
strcat(postfix, temp);
static int isNumeric(char* num)
{
    if(atoi(num) == 0)
    {
        return 0;
    }
            return 1;
}

What if the string is "0" ? 如果字符串为"0"怎么办? Consider using strtol instead because it offers a more powerful means of testing the success of the outcome. 考虑改用strtol因为它提供了测试结果是否成功的更强大的方法。

An unrelated stylistic note: your first function looks overcomplicated to me. 无关的风格注释:我的第一个功能看起来过于复杂。 Although it's perfectly possible that the way I'd do it is also overcomplicated. 尽管我做的方法很可能也过于复杂。

static int prec(char operator)
{
    switch (operator)
    {
        case '*':
            return 5;
        case '/':
            return 4;
        case '%':
            return 3;
        case '+':
            return 2;
        case '-':
            return 1;
        default:
            break;
    }

    return 0;
}

If a function performs a simple mapping from one set to another, It could usually be performed more simply (and faster) as an array lookup. 如果函数执行从一组到另一组的简单映射,则通常可以更简单(更快)地执行数组查找。 So I'd start with a string of the input characters. 因此,我将从输入字符的字符串开始。

char *operators = "*" "/" "%" "+" "-";

Note that the compiler will concatenate these to a single string value with a null-terminator. 请注意,编译器会将它们连接为带有空终止符的单个字符串值。

int precedence[] = { 5, 4, 3, 2, 1, 0 };

Then testing whether a char is an operator is: 然后测试char是否是运算符是:

#include <string.h>
if (strchr(operators, chr))
    ...;

And getting the precedence becomes: 获得优先级变为:

p = precedence[strchr(operators, chr) - operators];

If there are more values to associate with the operator, I'd consider using an X-Macro to generate a table and a set of associated enum values to use as symbolic indices. 如果还有更多要与运算符关联的值,我会考虑使用X-Macro生成表和一组关联的enum值以用作符号索引。

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

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