后缀计算器遇到段错误问题

时间:2015-05-04 15:50:59

标签: c linked-list segmentation-fault postfix-notation

我正在尝试使用链接列表创建一个后缀计算器。 当我编译时,它没有显示任何错误,但是当它被执行时,它将显示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] = '\0';
        }
        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");
}

2 个答案:

答案 0 :(得分:1)

鉴于此声明...

char temp[256][256];

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

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

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

看起来你只想要

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

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

更新:这可能如下所示:

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

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

}

可以想象您的代码中也存在其他错误,但我在扫描时没有发现任何错误。

答案 1 :(得分:0)

“顺便说一下,标准库中函数的所有标识符都是保留的。 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] = '\0';
        }
        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");
}