C

时间:2015-10-04 19:02:11

标签: c compiler-errors stack

我编写了一个pop函数,弹出一个字符运算符的链表列表(+,*, - ,/)并返回弹出的值。问题是我遇到了#34;冲突的类型错误"。我似乎无法弄清楚什么是错的。我的linkedCharStack结构声明为:

typedef struct linkedcharStack
{
char elem;
struct linkedcharStack* next;
};

堆栈的头部在pop(非全局但指针)之外的另一个函数中声明为:

struct linkedcharStack * opstack = malloc(sizeof(struct linkedStack));

我的实际弹出功能是:

char poptheop(struct linkedcharStack* s1){
struct linkedcharStack* temp;
if(s1==NULL){
    printf("NULL TOP ON POP VALUE STACK!");

}
char returnvalue = s1->elem;
temp = s1;
s1 = s1->next;
free(temp);
return returnvalue;
}

2 个答案:

答案 0 :(得分:1)

除了编译错误,我还可以看到代码中存在问题: 您没有正确实现poptheop,因为您对s1指针所做的更改将不会报告给调用者。你要做的是传递一个指向该指针的指针:

char poptheop(struct linkedcharStack** s1){
    struct linkedcharStack* temp;
    if(s1==NULL){
        printf("NULL TOP ON POP VALUE STACK!");
    }
    char returnvalue = (*s1)->elem;
    temp = *s1;
    *s1 = temp->next;
    free(temp);
    return returnvalue;
}

你需要这样做,否则弹出后你的堆栈顶部不会被修改。

答案 1 :(得分:0)

它更通用,如果我们分成两个结构,可能更容易理解/使用:一个用于堆栈控制,另一个用于堆栈中的元素:

// stack element
struct _stackelem;
typedef struct _stackelem elem_t;
struct _stackelem {
    elem_t *prev;
    elem_t *next;

    char elem;
    int precedence;
};

// stack control
struct _stack;
typedef struct _stack stack_t;
struct _stack {
    elem_t *head;
    elem_t *tail;
    long maxcnt;
    long curcnt;
};

stack_t opStack;

other_func()
{

    opStack.tail = malloc(sizeof(elem_t));
}

请注意,我已经添加了一个" head"到堆栈控制和" prev"到elem_t。这允许stack_t是双向链表,并且如果需要,除了堆栈等之外还可以实现队列。此外,我已经添加了一个"优先级"到elem_t - 更多关于以下内容。

这是您的原始功能[更正类似于A.S.H' s]:

// RETURNS: -1=empty stack
char
poptheop_original(stack_t *stk)
{
    elem_t *tmp;
    char retval;

    tmp = stk->tail;

    // stack is empty
    if (tmp == NULL)
        retval = -1;

    // pop last element
    else {
        retval = tmp->elem;
        stk->tail = tmp->next;
        free(tmp);
    }

    return retval;
}

现在,"(* s1)"已被" stk-> tail"取代。我们避免过关" **"并且代码执行速度也一样快。

但是,如果您所需要的只是" elem",我会考虑将您的操作系统重新实现为一个可重新排列的数组(例如" char * opstack& #34;。)

使用链表方法更适合返回更复杂的东西。这就是我添加"优先级"的原因。这是你的原始功能调整,所以你可以得到两个" elem"和"优先":

// RETURNS: elem is -1 on empty stack
elem_t
poptheop_struct(stack_t *stk)
{
    elem_t *tmp;
    elem_t retval;

    tmp = stk->tail;

    // stack is empty
    if (tmp == NULL) {
        retval.elem = -1;
        retval.precedence = -1;
    }

    // pop last element
    else {
        retval = *tmp;
        stk->tail = tmp->next;
        free(tmp);
    }

    return retval;
}

请注意,此功能仍可执行" free"内部。但是,它通过 value 传递结构。几乎从来都不是一件好事。

这是最终版本,它返回一个指向弹出的elem_t的指针:

// RETURNS: NULL is empty
elem_t *
poptheop_pointer(stack_t *stk)
{
    elem_t *retval;

    retval = stk->tail;

    // pop stack
    if (retval != NULL)
        stk->tail = retval->next;

    return retval;
}

你现在必须自己释放指针 - 这是缺点。但好处是elem_t可以有许多数据元素,不仅仅是元素和优先级,而且可以快速执行而无需额外的数据复制。

拆分stack_t的另一个好处是可以隐藏堆栈实现方式的细节。它可能是一个单链表[正如你已经完成],一个双向链表,或者我之前谈到的realloc数组。

如果您愿意,作为练习,请将stack_t重新实现为可重新排列的数组。这就是我添加" maxcnt"和" curcnt"。如果阵列方法更合适,那么" prev"和" next"可以从elem_t中完全消除。

作为进一步的提示:你只需要在推送期间重新分配,并且只有当curcnt即将溢出maxcnt时。将realloc作为maxcnt + slop_factor进行处理,以防止执行太多的realloc。这将使它变得聪明"。

这可能是您的最佳实施 - YMMV