中缀到Postfix荒谬的价值

时间:2014-06-24 17:26:15

标签: c algorithm

我编写了一个程序,将Infix表达式转换为Postfix表达式。

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

typedef struct Stack{
    int top;
    int capacity;
    char *array;
}Stack;

int isEmpty(Stack *s){
    return s->top == -1;
}
char pop(Stack *s){
    char c;
    if(isEmpty(s))
        return -1;
    c = s->array[s->top];
    s->array[s->top--] = '\0';
    return c;
}

void push(Stack *s,char c){
    s->array[++s->top] = c;
}

char peek(Stack *s){
    return s->array[s->top];
}

char *toString(char c){
    char *str = (char *)malloc(sizeof(char)*2);
    str[0] = c;
    str[1] = '\0';
    return str;
}

int hasGreaterPriority(char c1,char c2){
    if(c1 == '*' && (c2 == '+' || c2 == '-'))
        return 1;
    else if(c1 == '/' && (c2 == '+' || c2 == '-'))
        return 1;
    else
        return 0;
}

void infixtopostfix(char exp[]){
    int len = strlen(exp),i;
    char *out = (char *)malloc(sizeof(char));
    out[0] = '\0';

    Stack *stack = (Stack *)malloc(sizeof(Stack));
    stack->capacity = len;
    stack->top = -1;
    stack->array = malloc(sizeof(char)*len);

    for(i=0; i<len; i++){
        if(exp[i] >= 'a' && exp[i] <= 'z')
            strcat(out,toString(exp[i]));
        else if(exp[i] == ')'){
            while(peek(stack) != '(')
                strcat(out,toString(pop(stack)));
            pop(stack);
        }
        else{
            if(isEmpty(stack) || exp[i] == '(')
                push(stack,exp[i]);
            else if(hasGreaterPriority(peek(stack),exp[i])){
                strcat(out,toString(pop(stack)));
                push(stack,exp[i]);
            }
            else
                push(stack,exp[i]);
       }
    }
    /* UNTIL HERE */
    while(!isEmpty(stack))
        strcat(out,toString(pop(stack)));

    printf("Postfix Expression: %s\n",out);
}

int main(void) {
    char exp[] = "a+b*(c/d-e)/(f+g*h)-i\0";
    printf("Infix Expression: %s\n",exp);
    infixtopostfix(exp);
    return 0;
}

问题如下:

在infixtopostfix方法中,之前由&#34; UNTIL HERE&#34;表示。变量值似乎是正确的。我在gdb的帮助下检查过。在while循环的2次迭代之后,out变量中的值似乎也没问题。在最后一次迭代中,即在将+加入out时,该值变为如下

abcd/e-fgh*+/i-*\377\377\377\377\025+

\377\377\377\377\025+如何被添加到变量中?

预期值为abcd/e-fgh*+/i-*+

3 个答案:

答案 0 :(得分:4)

您已为空字符串分配空间:

char *out = (char *)malloc(sizeof(char));
out[0] = '\0';

然后你做:

strcat(out,toString(exp[i]));

没有足够的空间分配给out的末尾添加任何内容。可能会在某处重新分配,但它隐藏得很好。

从文体上讲,你有:

    if(exp[i] >= 'a' && exp[i] <= 'z')
        strcat(out,toString(exp[i]));
    else if(exp[i] == ')'){
        while(peek(stack) != '(')
            strcat(out,toString(pop(stack)));
        pop(stack);
    }
    else{
        if(isEmpty(stack) || exp[i] == '(')
            push(stack,exp[i]);
        else if(hasGreaterPriority(peek(stack),exp[i])){
            strcat(out,toString(pop(stack)));
            push(stack,exp[i]);
        }
        else
            push(stack,exp[i]);
   }

您可以通过以下方式避免嵌套级别:

    if(exp[i] >= 'a' && exp[i] <= 'z')
        strcat(out,toString(exp[i]));
    else if(exp[i] == ')'){
        while(peek(stack) != '(')
            strcat(out,toString(pop(stack)));
        pop(stack);
    }
    else if(isEmpty(stack) || exp[i] == '(')
        push(stack,exp[i]);
    else if(hasGreaterPriority(peek(stack),exp[i])){
        strcat(out,toString(pop(stack)));
        push(stack,exp[i]);
    }
    else
        push(stack,exp[i]);

这是自洽的;原件不是。


Valgrind报告

我接受了你的代码,在除static之外的每个函数之前添加了main()(主要是为了绕过我的默认编译选项),然后在valgrind下运行你的代码来获取输出:

$ valgrind ./pfx-infix
==17722== Memcheck, a memory error detector
==17722== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==17722== Using Valgrind-3.9.0 and LibVEX; rerun with -h for copyright info
==17722== Command: ./pfx-infix
==17722== 
Infix Expression: a+b*(c/d-e)/(f+g*h)-i
==17722== Invalid write of size 1
==17722==    at 0x4C2BEF3: strcat (mc_replace_strmem.c:268)
==17722==    by 0x4005D4: main (pfx-infix.c:67)
==17722==  Address 0x51f2041 is 0 bytes after a block of size 1 alloc'd
==17722==    at 0x4C2935F: malloc (vg_replace_malloc.c:291)
==17722==    by 0x4004FF: main (pfx-infix.c:57)
==17722== 
==17722== Invalid read of size 1
==17722==    at 0x4C2BEC4: strcat (mc_replace_strmem.c:268)
==17722==    by 0x4005D4: main (pfx-infix.c:67)
==17722==  Address 0x51f2041 is 0 bytes after a block of size 1 alloc'd
==17722==    at 0x4C2935F: malloc (vg_replace_malloc.c:291)
==17722==    by 0x4004FF: main (pfx-infix.c:57)
==17722== 
==17722== Invalid write of size 1
==17722==    at 0x4C2BEE0: strcat (mc_replace_strmem.c:268)
==17722==    by 0x4005D4: main (pfx-infix.c:67)
==17722==  Address 0x51f2041 is 0 bytes after a block of size 1 alloc'd
==17722==    at 0x4C2935F: malloc (vg_replace_malloc.c:291)
==17722==    by 0x4004FF: main (pfx-infix.c:57)
==17722== 
==17722== Invalid read of size 1
==17722==    at 0x4C2BEC4: strcat (mc_replace_strmem.c:268)
==17722==    by 0x400726: main (pfx-infix.c:77)
==17722==  Address 0x51f2041 is 0 bytes after a block of size 1 alloc'd
==17722==    at 0x4C2935F: malloc (vg_replace_malloc.c:291)
==17722==    by 0x4004FF: main (pfx-infix.c:57)
==17722== 
==17722== Invalid write of size 1
==17722==    at 0x4C2BEE0: strcat (mc_replace_strmem.c:268)
==17722==    by 0x400726: main (pfx-infix.c:77)
==17722==  Address 0x51f2044 is 3 bytes after a block of size 1 alloc'd
==17722==    at 0x4C2935F: malloc (vg_replace_malloc.c:291)
==17722==    by 0x4004FF: main (pfx-infix.c:57)
==17722== 
==17722== Invalid write of size 1
==17722==    at 0x4C2BEF3: strcat (mc_replace_strmem.c:268)
==17722==    by 0x400726: main (pfx-infix.c:77)
==17722==  Address 0x51f2045 is 4 bytes after a block of size 1 alloc'd
==17722==    at 0x4C2935F: malloc (vg_replace_malloc.c:291)
==17722==    by 0x4004FF: main (pfx-infix.c:57)
==17722== 
==17722== Invalid read of size 1
==17722==    at 0x4C2BEC4: strcat (mc_replace_strmem.c:268)
==17722==    by 0x4006A9: main (pfx-infix.c:70)
==17722==  Address 0x51f2041 is 0 bytes after a block of size 1 alloc'd
==17722==    at 0x4C2935F: malloc (vg_replace_malloc.c:291)
==17722==    by 0x4004FF: main (pfx-infix.c:57)
==17722== 
==17722== Invalid write of size 1
==17722==    at 0x4C2BEE0: strcat (mc_replace_strmem.c:268)
==17722==    by 0x4006A9: main (pfx-infix.c:70)
==17722==  Address 0x51f2046 is 5 bytes after a block of size 1 alloc'd
==17722==    at 0x4C2935F: malloc (vg_replace_malloc.c:291)
==17722==    by 0x4004FF: main (pfx-infix.c:57)
==17722== 
==17722== Invalid write of size 1
==17722==    at 0x4C2BEF3: strcat (mc_replace_strmem.c:268)
==17722==    by 0x4006A9: main (pfx-infix.c:70)
==17722==  Address 0x51f2047 is 6 bytes after a block of size 1 alloc'd
==17722==    at 0x4C2935F: malloc (vg_replace_malloc.c:291)
==17722==    by 0x4004FF: main (pfx-infix.c:57)
==17722== 
==17722== Invalid read of size 1
==17722==    at 0x4C2BEC4: strcat (mc_replace_strmem.c:268)
==17722==    by 0x40061E: main (pfx-infix.c:86)
==17722==  Address 0x51f2041 is 0 bytes after a block of size 1 alloc'd
==17722==    at 0x4C2935F: malloc (vg_replace_malloc.c:291)
==17722==    by 0x4004FF: main (pfx-infix.c:57)
==17722== 
==17722== Invalid write of size 1
==17722==    at 0x4C2BEE0: strcat (mc_replace_strmem.c:268)
==17722==    by 0x40061E: main (pfx-infix.c:86)
==17722==  Address 0x51f204e is 13 bytes after a block of size 1 alloc'd
==17722==    at 0x4C2935F: malloc (vg_replace_malloc.c:291)
==17722==    by 0x4004FF: main (pfx-infix.c:57)
==17722== 
==17722== Invalid write of size 1
==17722==    at 0x4C2BEF3: strcat (mc_replace_strmem.c:268)
==17722==    by 0x40061E: main (pfx-infix.c:86)
==17722==  Address 0x51f204f is 14 bytes after a block of size 1 alloc'd
==17722==    at 0x4C2935F: malloc (vg_replace_malloc.c:291)
==17722==    by 0x4004FF: main (pfx-infix.c:57)
==17722== 
==17722== Invalid read of size 1
==17722==    at 0x4E7D3B1: vfprintf (vfprintf.c:1630)
==17722==    by 0x4E858D8: printf (printf.c:35)
==17722==    by 0x400633: main (pfx-infix.c:88)
==17722==  Address 0x51f2041 is 0 bytes after a block of size 1 alloc'd
==17722==    at 0x4C2935F: malloc (vg_replace_malloc.c:291)
==17722==    by 0x4004FF: main (pfx-infix.c:57)
==17722== 
==17722== Invalid read of size 1
==17722==    at 0x4EAC184: _IO_file_xsputn@@GLIBC_2.2.5 (fileops.c:1330)
==17722==    by 0x4E7CF81: vfprintf (vfprintf.c:1630)
==17722==    by 0x4E858D8: printf (printf.c:35)
==17722==    by 0x400633: main (pfx-infix.c:88)
==17722==  Address 0x51f2050 is 15 bytes after a block of size 1 alloc'd
==17722==    at 0x4C2935F: malloc (vg_replace_malloc.c:291)
==17722==    by 0x4004FF: main (pfx-infix.c:57)
==17722== 
==17722== Invalid read of size 1
==17722==    at 0x4EAC199: _IO_file_xsputn@@GLIBC_2.2.5 (fileops.c:1330)
==17722==    by 0x4E7CF81: vfprintf (vfprintf.c:1630)
==17722==    by 0x4E858D8: printf (printf.c:35)
==17722==    by 0x400633: main (pfx-infix.c:88)
==17722==  Address 0x51f204f is 14 bytes after a block of size 1 alloc'd
==17722==    at 0x4C2935F: malloc (vg_replace_malloc.c:291)
==17722==    by 0x4004FF: main (pfx-infix.c:57)
==17722== 
==17722== Invalid read of size 16
==17722==    at 0x4EAC0DE: _IO_file_xsputn@@GLIBC_2.2.5 (fileops.c:1362)
==17722==    by 0x4E7CF81: vfprintf (vfprintf.c:1630)
==17722==    by 0x4E858D8: printf (printf.c:35)
==17722==    by 0x400633: main (pfx-infix.c:88)
==17722==  Address 0x51f2040 is 0 bytes inside a block of size 1 alloc'd
==17722==    at 0x4C2935F: malloc (vg_replace_malloc.c:291)
==17722==    by 0x4004FF: main (pfx-infix.c:57)
==17722== 
==17722== Invalid read of size 1
==17722==    at 0x4EAC100: _IO_file_xsputn@@GLIBC_2.2.5 (fileops.c:1362)
==17722==    by 0x4E7CF81: vfprintf (vfprintf.c:1630)
==17722==    by 0x4E858D8: printf (printf.c:35)
==17722==    by 0x400633: main (pfx-infix.c:88)
==17722==  Address 0x51f2050 is 15 bytes after a block of size 1 alloc'd
==17722==    at 0x4C2935F: malloc (vg_replace_malloc.c:291)
==17722==    by 0x4004FF: main (pfx-infix.c:57)
==17722== 
Postfix Expression: abcd/e-fgh*+/i-*+
==17722== 
==17722== HEAP SUMMARY:
==17722==     in use at exit: 72 bytes in 20 blocks
==17722==   total heap usage: 20 allocs, 0 frees, 72 bytes allocated
==17722== 
==17722== LEAK SUMMARY:
==17722==    definitely lost: 51 bytes in 19 blocks
==17722==    indirectly lost: 21 bytes in 1 blocks
==17722==      possibly lost: 0 bytes in 0 blocks
==17722==    still reachable: 0 bytes in 0 blocks
==17722==         suppressed: 0 bytes in 0 blocks
==17722== Rerun with --leak-check=full to see details of leaked memory
==17722== 
==17722== For counts of detected and suppressed errors, rerun with: -v
==17722== ERROR SUMMARY: 204 errors from 17 contexts (suppressed: 2 from 2)
$

这清楚地标识了超出范围的存储器访问;它也恰好产生了正确的&#39;回答。您还有许多应该修复的内存泄漏。

答案 1 :(得分:2)

stack->array = malloc(sizeof(sizeof(char)*len));

必须:

stack->array = malloc(len);

sizeof(sizeof(char)*len)) = sizeof(size_t)sizeof运营商返回的类型)

答案 2 :(得分:-1)

如果您想找到将中缀转换为后缀和前缀的确切答案,请访问此处。在这里,我没有使用指针编程。因此,在开始For infix expression to prefix and postfix

时很容易理解