后缀计算器遇到段错误

postfix calculator having trouble with segfaults

我正在尝试使用链表创建一个后缀计算器。 当我编译时,它没有显示任何错误,但是当它执行时,它会显示 Segmentation Fault。我不知道如何处理这个问题,请帮忙。 这是我的代码:

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

typedef struct node {
    int num;
    struct node *next;
} node;

void push(int num, node **head);
int pop(node **head);
void display(node **head);
int is_empty();
int evaluatePostfix();

struct node *head;

int main()  {
    head = NULL;
    char exp[1000]; // = "5 1 2 + 4 * + 3 -";
    printf("Input expression:\t");
    fgets(exp, 1000, stdin);
    for(int i = 1; i <= strlen(exp); i++) {
        if(exp[i] == '\n') {
            exp[i] = '[=10=]';
        }
        else if (exp[0] == '\n') {
            printf("stack is empty\n");
            exit(0);
        }
    }
    printf("%s = %d\n", exp, evaluatePostfix(exp));

    return 0;

}

int evaluatePostfix(char* exp)  {
    char * token;
    int counter = 0;
    char temp[256][256];
    token = strtok(exp, " ");
    while(token != NULL)    {
        strcpy(temp[counter], token);
        counter++;
        token = strtok(NULL, " ");  
    }

    for (int i = 0; temp[i]; ++i)   {
        if (isdigit(*(temp[i]))) {
            int val = atoi(temp[i]);
            push(val, &head);
        }
        else   {
            int val1 = pop(&head);
            int val2 = pop(&head);
            switch (exp[i]) {
                case '+':    push(val2 + val1, &head);
                             printf("%d\n", (*head).num);
                             break;
                case '-':    push(val2 - val1, &head);    break;
                case '*':    push(val2 * val1, &head);    break;
                case '/':    push(val1 / val2, &head);    break;
            }
        }
    }
    return pop(&head);
}


void push (int item, node **head) {
    node *temp;
    node * get_node(int);
    temp = get_node(item);
    temp->next = *head;
    *head = temp;
}

node *get_node(int item) {
    node *temp;
    temp = (node*)malloc(sizeof(node));
    if (temp == NULL)
        printf("\nMemory cannot be allocated");
    temp->num = item;
    temp->next = NULL;
    return(temp);
}


int pop(node **head)    {
    int item;
    node *temp;
    item = (*head)->num;
    temp = *head;
    *head = (*head)->next;
    free(temp);
    return(item);
}

int is_empty(node *temp) {
    if (temp == NULL)
        return 1;
    else
        return 0;
}


void display(node **head)   {
    node *temp;
    temp = *head;
    if(head == NULL)    {
        printf("stack is empty\n");
        return;
    }
    printf("\n");
    printf("=========\n");
    while(temp!=NULL)   {
        printf("%d\n", (*temp).num);
        temp = (*temp).next;
    }
    printf("=========\n");
}

鉴于此声明...

char temp[256][256];

...这里的循环终止条件是错误的:

for (int i = 0; temp[i]; ++i)   {

C 多维数组是 不是 Java 数组 references 样式的数组。它们是实际数组的数组。当 i 超过您写入数据的 temp[] 的元素数量时,表达式 temp[i] 不会为假。

看来你只是想要

for (int i = 0; i < counter; ++i)   {

。或者,在开始计算之前没有特别需要标记化。您可以轻松地将函数 evaluatePostfix() 中的两个循环合并为一个。这会更简单一些,并且会删除表达式中项数的任何固定限制。

更新: 可能看起来像这样:

for (token = strtok(exp, " "); token; token = strtok(NULL, " ")) {

    /* ... use token instead of temp[i] ... */

}

可以想象你的代码中还有其他错误,虽然我在扫描时没有发现任何错误。

"顺便说一句,标准库中函数的所有标识符都是保留的。 math.h 中有一个函数 exp(),所以 exp 属于这一类。 从技术上讲,在代码中使用保留标识符会导致未定义的行为。"

感谢大家的帮助!将 exp 更改为另一个变量名就可以了。到目前为止,这是工作代码:

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

typedef struct node {
    int num;
    struct node *next;
} node;

void push(int num, node **head);
int pop(node **head);
void display(node **head);
int is_empty(node *temp);
int evaluate(char *expression);

struct node *head;

int main()  {
    head = NULL;
    char expression[1000]; // = "5 1 2 + 4 * + 3 -";
    printf("Input expression:\t");
    fgets(expression, 1000, stdin);
    for(int i = 1; i <= strlen(expression); i++) {
        if(expression[i] == '\n') {
            expression[i] = '[=10=]';
        }
        else if (expression[0] == '\n') {
            printf("empty stack\n");
            exit(0);
        }
    }

    printf("Answer: %d\n", evaluate(expression) );
    return 0;

}

int evaluate(char* expression)  {
    char * token;
    int counter = 0;
    char temp[256][256];
    token = strtok(expression, " ");
    while(token != NULL)    {
        strcpy(temp[counter], token);
        token = strtok(NULL, " ");  
        counter++;
    }

    for (int i = 0; i < counter; i++)   {
        if (isdigit(*(temp[i]))) {
            int val = atoi(temp[i]);
            push(val, &head);
        }
        else   {
            int val1 = pop(&head);   //pop the last two values from stack
            int val2 = pop(&head);
            switch (*(temp[i])) {    //perform operation
                case '+':    push(val2 + val1, &head);  break;
                case '-':    push(val2 - val1, &head);  break;
                case '*':    push(val2 * val1, &head);  break;
                case '/':    push(val1 / val2, &head);  break;
            }
        }
    }
    return pop(&head);
}

void push (int item, node **head) {
    node *temp;
    node * get_node(int);
    temp = get_node(item);
    temp->next = *head;
    *head = temp;
}

node *get_node(int item) {
    node *temp;
    temp = (node*)malloc(sizeof(node));
    if (temp == NULL)
        printf("\nMemory cannot be allocated");
    temp->num = item;
    temp->next = NULL;
    return(temp);
}

int pop(node **head)    {
    int item;
    node *temp;
    item = (*head)->num;
    temp = *head;
    *head = (*head)->next;
    free(temp);
    return(item);
}

int is_empty(node *temp) {
    if (temp == NULL)
        return 1;
    else
        return 0;
}

void display(node **head)   {
    node *temp;
    temp = *head;
    if(head == NULL)    {
        printf("stack is empty\n");
        return;
    }
    printf("\n");
    printf("=========\n");
    while(temp!=NULL)   {
        printf("%d\n", (*temp).num);
        temp = (*temp).next;
    }
    printf("=========\n");
}