Leaving the implementation of the CD / DVD data structures up to you, as well as the implementation of the linked list, you would probably want to do something like this:
enum ptype {
PTYPE_BOOK,
PTYPE_CD,
PTYPE_DVD,
};
struct book {
char *author;
char *title;
char *publisher;
char *isbn;
};
struct product {
enum ptype type;
void *data;
};
struct product_list {
struct product *product;
struct product_list *next;
};
The enumeration is responsible for distinguishing the type of product being pointed to. To create a book, for instance:
struct product *
create_book(char *author, char *title, char *publisher, char *isbn)
{
struct product *p;
struct book *b;
p = calloc(1, sizeof (*p));
if (p == NULL) {
return NULL;
}
p->type = PTYPE_BOOK;
p->data = calloc(1, sizeof(*b));
if (p->data == NULL) {
free(p);
return NULL;
}
b = p->data;
b->author = author;
b->title = title;
b->publisher = publisher;
b->isbn = isbn;
return p;
}
This is a typical interface when unions can't be used for whatever reason. It's unfortunate in that it requires much more memory allocation (and in reality, you'll probably have to strdup(3)
author / title / publisher / isbn).
To retrieve a book from a product, you might like to have something like this:
static inline struct book *
get_book(struct product *p)
{
assert(p->type == PTYPE_BOOK);
return p->data;
}
You don't need to (and shouldn't) cast a void pointer in C. If you're using or supporting a C++ compiler, you may need to use return (struct book *)p->data;
. You'd implement something similar for your CD and DVD types. Then, when you need to extract the product:
switch (p->type) {
case PTYPE_BOOK:
b = get_book(p);
break;
case PTYPE_CD:
c = get_cd(p);
break;
case PTYPE_DVD:
d = get_dvd(p);
break;
}
You may also want to look at using something other than a linked list for storing these things, especially if they will be read / traversed many times after they are created. (A vector would not be a bad idea). If you know how many items you'll have, this can help reduce the number of allocations you must perform, and the contiguous memory access will improve speed.
If you need to search entries, I suspect you'll need an external searchable data structure anyway.