【问题标题】:Going from infix to postfix从中缀到后缀
【发布时间】:2015-06-11 12:46:55
【问题描述】:
#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);

}

此文件是程序的一部分,该程序使用堆栈结构对输入文件执行中缀到后缀。其他功能已经过测试并且工作正常,但是当我尝试添加这部分并实际执行操作时,程序分段错误。调试器说它出现在 infix_to_postfix 函数中,但是它没有说哪一行,我不知道在哪里。有谁知道为什么这会出现故障?

【问题讨论】:

    标签: c data-structures stack infix-notation


    【解决方案1】:

    你做错了几件事:

        if(isNumeric(&symbol) != 1)
    

    函数isNumeric() 需要一个以空字符结尾的字符串作为输入,而不是指向单个字符的指针。

            strcat(postfix, &symbol);
    

    这里同样适用。

            strcat(postfix, &next);
    

    我猜这也是错误的。如果你想把单个字符变成一个字符串,你可以这样做:

    char temp[2] = {0};
    
    temp[0] = symbol;
    strcat(postfix, temp);
    

    【讨论】:

      【解决方案2】:
      static int isNumeric(char* num)
      {
          if(atoi(num) == 0)
          {
              return 0;
          }
                  return 1;
      }
      

      如果字符串是"0"怎么办?考虑改用strtol,因为它提供了一种更强大的方法来测试结果是否成功。

      一个不相关的风格说明:你的第一个函数在我看来过于复杂。尽管我这样做的方式也很可能过于复杂。

      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;
      }
      

      如果一个函数执行从一个集合到另一个集合的简单映射,通常可以更简单(更快)地执行数组查找。所以我会从一串输入字符开始。

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

      请注意,编译器会将它们连接成带有空终止符的单个字符串值。

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

      那么测试一个char是否是一个操作符就是:

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

      获得优先级变为:

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

      如果有更多值与运算符相关联,我会考虑使用 X-Macro 生成一个表和一组关联的 enum 值以用作符号索引。

      【讨论】:

        猜你喜欢
        • 2015-06-14
        • 1970-01-01
        • 2016-07-22
        • 1970-01-01
        • 2013-03-28
        • 1970-01-01
        • 1970-01-01
        • 2011-04-28
        相关资源
        最近更新 更多