I think your plan is fine, using pointers for authors
and main_characters
. As you're using intrusive linked lists for the books and the authors and main characters, you might find it helpful to factor out the linked list structure and operations.
If you declare a structure like this:
struct node
{
struct node *next;
struct node *previous;
};
typedef struct node node;
You can embed it into each of your types as the first element:
struct name
{
node linked_list;
char name_prefix[10];
char name_first[50];
char name_middle[50];
char name_last[50];
char name_suffix[5];
};
struct book
{
node linked_list;
name *authors;
name *main_characters;
/* variables for book */
char title[100]; /* the title of the book */
char publisher[100]; /* publisher */
//etc.
};
This makes your types convertible to the node
type. You can then define linked list operations in terms of the node
type:
void
node_add_node(node **head, node *object)
{
if (*head == NULL) {
*head = object;
}
else {
node *current, *previous;
for (current = *head; current != NULL; current = current->next) {
previous = current;
}
previous->next = object;
}
}
And then define type-safe operations to add books to a list of books and names to books:
void
books_add_book(struct book **books, struct book *book)
{
node_add_node((node**)books, (node*)book);
}
void
book_add_author(struct book *book, struct name *author)
{
node_add_node((node**)&book->authors, (node*)author);
}
void
book_add_main_character(struct book *book, struct name *character)
{
node_add_node((node**)&book->main_characters, (node*)character);
}
Then, implement the constructors:
void node_init(node *node)
{
node->previous = NULL;
node->next = NULL;
}
struct book *
book_create(const char *title, const char *publisher)
{
struct book *b = malloc(sizeof(book));
if (b) {
node_init(&b->linked_list);
b->authors = NULL;
b->main_characters = NULL;
strcpy(b->title, title);
strcpy(b->publisher, publisher);
}
return b;
}
struct name *
name_create(const char *prefix, const char *first, const char *middle,
const char *last, const char *suffix)
{
name *n = malloc(sizeof(name));
if (n) {
node_init(&n->linked_list);
strcpy(n->name_prefix, prefix);
strcpy(n->name_first, first);
strcpy(n->name_middle, middle);
strcpy(n->name_last, last);
strcpy(n->name_suffix, suffix);
}
return n;
}
And then you can create books like this (NOTE: I increased the size of your name_prefix
to 10):
struct book *books = NULL;
struct book *b = book_create("War and Peace", "Wordsworth");
struct name *n = name_create("Count", "Lev", "Nikolayevich", "Tolstoy", "");
book_add_author(b, n);
n = name_create("Count", "Pyotr", "Kirillovich", "Bezukhov", "");
book_add_main_character(b, n);
n = name_create("Countess", "Natalya", "Ilyinichna", "Rostova", "");
book_add_main_character(b, n);
books_add_book(&books, b);