How to Pop different types of Structs from a Stack

2019-08-04 14:27发布

问题:

I have a stack that contains two types of struct. Struct Stud and Struct Prof. When I want to push something I created two Push functions for both structs. Although I would like it to be with one function but its ok I can bear with it.

Now to Pop. If I want to Pop a student from the Stack, do I have to make a Pop function specifically for Students only? The same with Professors?

How can I store the item if I don't know what type is it? What type must the element be, to store the item there?

Here are the structs:

struct MyStack
{
    int head;
    void **stack;
    int size;
};
typedef struct MyStack STACK;

struct stud
{
    char flag;
    char fname[50];
    int semester;
};
struct prof
{
    char flag;
    char fname[50];
    char course[30];
};

Now to create the Pop function. What do type of item do I pass in the function?

int Pop(STACK *stack,int *head,??? *elem)
{
if(stack->head<=-1)
    return 0;

*elem=stack->stack[*head];
*head--;
return 1;
}

回答1:

You have to encode the type information when you push, simplest is probably to type tag:

#define STUD 0
#define PROF 1

struct stack_entry {
    int type;
    void *item;
};

struct MyStack
{
    int head;
    struct stack_entry *stack;
    int size;
};

Then change your push functions to attach the right tag when you push. Then, in pop, simplest again is probably to just return a stack_entry struct, and let the calling function figure it out. At that point you might want a snazzier name than "stack_entry" though. Also, it would be slightly preferable to use a union:

struct stack_entry {
    int type;
    union {
        struct stud *stud;
        struct prof *prof;
    } item;
}

Because then the compiler can help you out a bit, but of course you still have to be more or less as careful as you would be with a void *.

Edit: initialization...

You don't have to mark then end of the buffer with anything, since you have a size variable in the struct. But if you wanted to do that I would have that be its own type

#define END_OF_BUFFER 1
#define STUD 2
#define PROF 3

And then for init you could do:

stack->size = size; 
stack->stack = calloc(sizeof(*stack->stack), size + 1); 
stack->stack[size].type = END_OF_BUFFER; 
stack->head=-1; 

Though I tend to use "head" to refer to a pointer that points to the next place to write to, but I'm not sure how standard that is. But the buffer is an array of strack_entries, not void *'s.



标签: c struct stack