我在下面写了一个程序把中缀表达式转换成后缀表达式。

#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方法中,before-while用“until-here”表示出来的变量值似乎是正确的。我在gdb的帮助下查过了。经过两次while循环的迭代后,in out变量的值看起来也不错在最后一次迭代中,即在向外添加+时,该值如下所示
abcd/e-fgh*+/i-*\377\377\377\377\025+

如何将\377\377\377\377\025+添加到输出变量?
预期值将abcd/e-fgh*+/i-*+

最佳答案

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

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]);

这是自洽的;原始的不是。
瓦尔格林报告
我获取了您的代码,在每个函数之前添加了static(主要是为了绕过我的默认编译选项),然后在main()下运行您的代码以获得输出:
$ 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)
$

这清楚地标识了超出范围的内存访问;它也碰巧产生了“正确”的答案你也有一些内存泄漏应该被修复。

10-08 03:03