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

int LENGTH = 1;
int TOP = -1;

void push(char**, char);
char pop(char*);
char peek(char*);
int isEmpty();
int isFull();

void convertToRPN(char*, char*, char*);
int isOperator(char);
int getPrecedence(char);


int main(void) {
    char* stack = (char*) malloc(sizeof(char) * LENGTH);
    if (!stack) {
        printf("Memory allocation failed./n");
        exit(1);
    }

    char expression[100];
    printf("Enter the mathematical expression: ");
    scanf("%s", expression);

    char rpn[100];
    convertToRPN(expression, stack, rpn);

    printf("The rpn: %s\n", rpn);

    free(stack);

    return 0;
}


int isOperator(char c) {
    return (c == '+' || c == '-' || c == '*' || c == '/');
}


int getPrecedence(char c) {
    if (c == '+' || c == '-')
        return 1;
    if (c == '*' || c == '/')
        return 2;
    return 0; 
}


void convertToRPN(char *expression, char* stack, char* rpn) {
    
    int j = 0;
    for (int i = 0; expression[i] != '\0'; i++) {
        if (expression[i] >= '0' && expression[i] <= '9') {
            rpn[j] = expression[i];
            j++;
        } else if (isOperator(expression[i])) {
            while (!isEmpty() && peek(stack) != '(' && getPrecedence(peek(stack)) >= getPrecedence(expression[i])) {
                rpn[j] = pop(stack);
                j++;
            }
            push(&stack, expression[i]);
        } else if (expression[i] == '(') {
            push(&stack, expression[i]);
        } else if (expression[i] == ')') {
            while (!isEmpty() && peek(stack) != '(') {
                rpn[j] = pop(stack);
                j++;
            }
            pop(stack);
        } else {
            printf("Unsupported character.\n");
            exit(2);
        }
    }

    while (!isEmpty()) {
        rpn[j] = pop(stack);
        j++;
    }

    rpn[j] = '\0';
}


void push(char **stack, char c) {
    if (isFull()) {
        *stack = (char *)realloc(*stack, sizeof(char) * (LENGTH + 1));
        if (!*stack) {
            printf("Memory reallocation failed.\n");
            exit(5);
        }
        LENGTH++;
    }
    TOP++;
    (*stack)[TOP] = c;
}


char pop(char *stack) {
    if (isEmpty()) {
        printf("POP: the stack is empty.\n");
        exit(3);
    } else {
        char item = stack[TOP];
        TOP--;
        return item;
    }
}


char peek(char *stack) {
    if (isEmpty()) {
        printf("PEEK: the stack is empty.\n");
        exit(4);
    }
    return stack[TOP];
}


int isEmpty() {
    return TOP == -1;
}


int isFull() {
    return TOP == LENGTH - 1;
}

此代码执行RPN(反向波兰记数法)转换,但在1个块中确定丢失. 根据valgrind的说法,代码存在内存泄漏问题.消息是神秘的,但我猜它在realloc()中. 也许是为了帮助传达这样的信息:

输入数学表达式:5+9+21 The rpn: 59+21+

无效的Free()/Delete/Delete[]/realloc() 在0x484810F:免费 由0x1092FE:Main(Eff1_2.c:34) 地址0x4a78040在大小为1的空闲块内为0字节 在0x484ABC0:realloc 按0x109616:推送(Exp1_2.c:92) 由0x1094BB:ConvertToRPN 按0x1092D4:Main 数据块被分配到 在0x4845828:Malloc 按0x109256:Main

堆摘要: 退出时使用:%1数据块中的%2个字节 总堆使用情况:4个分配,4个释放,分配了2,051字节

泄漏摘要: 明确丢失:%1个数据块中有2个字节 间接丢失:0个数据块中的0个字节 可能丢失:0个数据块中的0个字节 仍可访问:0个数据块中的0个字节 已 suppress :0个数据块中有0个字节

错误摘要:来自1个上下文的1个错误(禁止显示:0个)

总体而言,我想问题出在我的堆栈实现上.

推荐答案

程序中有一个错误.指针stack按值传递给函数convertToRPN

void convertToRPN(char*, char*, char*);

//...

convertToRPN(expression, stack, rpn);

因此,函数处理原始指针值的副本.原始指针保持不变.因此,指针具有无效值,并且在main中调用free

free(stack);

不释放在函数convertToRPN的执行期间分配的存储器.

您至少应该通过指向函数的指针来引用该函数来传递该指针.也就是说,应该像这样声明和调用函数

void convertToRPN(char*, char**, char*);

//...

convertToRPN(expression, &stack, rpn);

不过,如果堆栈的两个存储器都不是在main内分配的,情况会更好.在应该分配和释放存储器的函数convertToRPN中使用该堆栈.

并且声明一个 struct 堆栈会更好,例如

struct Stack
{
    size_t top;
    size_t size;  
    char *mem;
};

并使用 struct 的对象,而不是几个单独的变量.使用全局变量是一个非常糟糕的主意

int LENGTH = 1;
int TOP = -1;

我建议您重新设计代码.

C++相关问答推荐

是否定义了数组指针类型转换为指针类型?""""

C中的__attributor__((aligned(4),packed))与 struct 的用法

如何创建由符号组成的垂直结果图形?

使用额外的公共参数自定义printf

C编译器是否遵循restrict的正式定义?

使用GOTO从多个嵌套循环C继续

GLIBC:如何告诉可执行文件链接到特定版本的GLIBC

Rust FFI--如何用给出返回引用的迭代器包装C风格的迭代器?

为静态库做准备中的奇怪行为

CSAPP微型shell 实验室:卡在sigprocmask

轮询libusb_pollfd struct 列表的正确方式是什么?

Kdb:仅升级指定的列

在C++中允许使用字符作为宏参数

我错误地修复了一个错误,想了解原因

将char*铸造为空**

如何转义包含指令中的字符?

多行表达式:C 编译器如何处理换行符?

malloc:损坏的顶部大小无法找出问题

初始化动态分配的布尔二维数组的最佳方法是什么?

我如何(合规地)从 tmpfile() 读取?