我编写了一个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;
}
答案 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