Reputation: 17
I have written a pop function that pops a linked list stack of character operators (+, *, - , /) and returns the value popped. The problem is I am getting a "conflicting types error". And I can't seem to figure out whats wrong. My linkedCharStack struct is declared as:
typedef struct linkedcharStack
{
char elem;
struct linkedcharStack* next;
};
The head of the stack is declared in another function outside of pop(not global but pointer) as:
struct linkedcharStack * opstack = malloc(sizeof(struct linkedStack));
And my actual pop function is:
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;
}
Upvotes: 0
Views: 202
Reputation: 33631
It's more general and may be easier to understand/use if we split into two structs: one for stack control and another for elements in that stack:
// 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));
}
Note that I've added a "head" to the stack control and "prev" to elem_t. This allows the stack_t to be a doubly linked list and can implement a queue in addition to a stack, etc. if desired. Also, I've added a "precendence" to elem_t--more on that below.
Here's your original function [with corrections similar to 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;
}
Now, "(*s1)" has been replaced with "stk->tail". We've avoided passing "**" and the code will execute just as fast.
But, if all you're ever going to need is "elem", I'd consider reimplementing your op stack as just a reallocable array (e.g. "char *opstack").
Using the linked list approach is more suitable for returning more complex stuff. That's why I added "precedence". Here's your original function tweaked so you can get at both "elem" and "precedence":
// 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;
}
Note that this function still does the "free" internally. But, it's passing the struct back by value. Almost never a good thing.
Here's the final version where it returns a pointer to the popped 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;
}
You now have to free the pointer on your own--that's the downside. But the upside is that elem_t can have many data elements, not just elem and precedence and will execute quickly with no needless extra data copying.
A further benefit of splitting out stack_t is that you can hide the details of how the stack is implemented. It could be a singly linked list [as you've done], a doubly linked list, or the realloc array I spoke of earlier.
If you so desire, as an exercise, reimplement stack_t as a reallocable array. That's why I added "maxcnt" and "curcnt". If the array approach turns out to be more suitable, then "prev" and "next" can be eliminated from elem_t altogether.
As a further hint: you only need to realloc during a push and only if curcnt is about to overflow maxcnt. Do the the realloc as maxcnt + slop_factor to prevent doing too many realloc's. This will make it "smart".
This might be the best implementation for you--YMMV
Upvotes: 0
Reputation: 29352
In addition to the compile error, i can see a problem in your code: You are not correctly implementing poptheop, because the change you are doing to the s1 pointer will not be reported to the caller. What you shoould do is pass a pointer to that pointer:
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;
}
You need to do it this way, otherwise your top of stack will not be modified after you pop.
Upvotes: 1