1

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;
}
Iain Samuel McLean Elder
  • 19,791
  • 12
  • 64
  • 80
CosmaOne
  • 21
  • 5

1 Answers1

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.

user26347
  • 594
  • 3
  • 4
  • so the initialization of the stack must be: stack->size = size; stack->stack = malloc((size + 1) * sizeof(void *)); stack->stack[size].item = NULL; stack->head=-1; – CosmaOne Mar 29 '14 at 16:36
  • @CosmaOne it has to be sizeof(struct stack_entries), I've updated the answer – user26347 Mar 29 '14 at 17:34
  • why calloc instead of malloc? also i think *struct->stack is wrong...maybe you mean *stack->stack? – CosmaOne Mar 29 '14 at 18:22
  • @CosmaOne yeah stack->stack. wild pointers are a pain to debug, setting pointers to null when they're not pointing at anything is a good idea. A null pointer is not always represented by zeroed out memory, but it is on every platform I've used. – user26347 Mar 31 '14 at 16:37