This repository was archived by the owner on Dec 7, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathBooks.c
More file actions
466 lines (420 loc) · 12.4 KB
/
Books.c
File metadata and controls
466 lines (420 loc) · 12.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Books.h"
/*
* @author - Patrick Quinlan
* SID - 575275
* Last Edit - 4/3/24
*
* File to define the list of books and funnctions for interacting with it
*/
//make a string lowercase
String to_lowercase(String str) {
String low_str = malloc(strlen(str + 1));
for (int i = 0; i<strlen(low_str); i++) {
low_str[i] = tolower(str[i]);
}
return low_str;
}
// Function to create and return a new empty list of books.
Books new_books_list() {
Books temp;
temp.head = NULL;
return temp;
}
BookNodePtr create_book(String title, String author, String genre, int year)
{
BookNodePtr new_book = malloc(sizeof * new_book);
set_title(new_book, malloc(100));
set_title(new_book, title);
set_author(new_book, malloc(100));
set_author(new_book, author);
set_genre(new_book, malloc(100));
set_genre(new_book, genre);
set_year(new_book, malloc(4*(sizeof(int))));
set_year(new_book, year);
set_next(new_book, NULL);
set_prev(new_book, NULL);
return new_book;
}
//Author getter
String get_author(BookNodePtr b)
{
return b->author;
}
//title getter
String get_title(BookNodePtr b)
{
return b->title;
}
//publication year getter
int get_year(BookNodePtr b)
{
return b->year;
}
//Genre getter
String get_genre(BookNodePtr b)
{
return b->genre;
}
//Get next node
BookNodePtr get_next(BookNodePtr b)
{
return b->next;
}
//Get previous node
BookNodePtr get_prev(BookNodePtr b)
{
return b->prev;
}
//Author setter
void set_author(BookNodePtr b, String a)
{
b->author = a;
}
//title setter
void set_title(BookNodePtr b, String t)
{
b->title = t;
}
//publication year setter
void set_year(BookNodePtr b, int y)
{
b->year = y;
}
//Genre setter
void set_genre(BookNodePtr b, String g)
{
b->genre = g;
}
//Set next node
void set_next(BookNodePtr b, BookNodePtr n)
{
b->next = n;
}
//Set previous node
void set_prev(BookNodePtr b, BookNodePtr p)
{
b->prev = p;
}
// Function to print the contents of a list. Mainly used for debugging and to see what data is in the lists
void print_list(Books* self) {
BookNodePtr current = self->head;
while (current != NULL) {
printf_s("\n%30s\t%20s\t%10d\t%10s",get_title(current),get_author(current),get_year(current),get_genre(current));
current = get_next(current);
if (current != NULL)
printf(", ");
}
printf("\n");
}
//delete a book
BookNodePtr delete_book_node(BookNodePtr self, BookNodePtr book)
{
if (strcmp(get_author(book),get_author(self)) == 0 &&
strcmp(get_title(book),get_title(self))== 0 &&
strcmp(get_genre(book),get_genre(self)) == 0 &&
get_year(book) == get_year(self))
{
if (get_prev(self) == NULL) // deleting head
{
set_prev(get_next(self), NULL);
}
else if (get_next(self) == NULL)//deleting tail
{
set_next(get_prev(self), NULL);
}
else //deleting from middle
{
set_next(get_prev(self), get_next(self));
set_prev(get_next(self), get_prev(self));
}
free(self);
return NULL;
}
else
{
return delete_book_node(get_next(self), book);
}
}
// Function to delete a book from a list
void delete_book(Books* self, BookNodePtr book)
{
delete_book_node(self->head, book);
}
//add a book
BookNodePtr add_book_node(BookNodePtr self, BookNodePtr book)
{
if (self == NULL)
{
return book;
}
set_next(book, self);
set_prev(self, book);
return book;
}
// Function to add a book to a list
void add_book(Books* self, BookNodePtr book)
{
self->head = add_book_node(self->head, book);
}
//find a book
BookNodePtr find_book_node(BookNodePtr self, String book)
{
if (self != NULL)//empty node
{
if (strstr(to_lowercase(get_title(self)), to_lowercase(book)) != NULL || //check if it matches the title
strstr(to_lowercase(get_author(self)), to_lowercase(book)) != NULL || //check if it matches the author
strstr(to_lowercase(get_genre(self)),to_lowercase(book)) != NULL ||
get_year(self) == atoi(book))
{
printf_s("\n%30s\t%20s\t%10d\t%10s", get_title(self), get_author(self), get_year(self), get_genre(self));
return find_book_node(get_next(self), book);
}
else
{
return find_book_node(get_next(self), book);
}
}
return;
}
// Function to find a book
void find_book(Books* self, String book)
{
find_book_node(self->head, book);
}
BookNodePtr add_book_in_title_order(BookNodePtr self, BookNodePtr book)
{
if (self == NULL)
{
return book;
}
BookNodePtr current = self;
while (current != NULL)
{
if ((strcmp(get_title(current), get_title(book)) > 0))
{
if (get_prev(current) == NULL)
{
set_next(book, current);
set_prev(current, book);
return book;
}
set_next(book, current);
set_prev(book, get_prev(current));
set_next(get_prev(current), book);
set_prev(current, book);
return self;
}
else if (get_next(current) == NULL) //end
{
set_next(current, book);
set_prev(book, current);
return self;
}
current = get_next(current);
}
return self;
}
// Function to add book in Title order
void add_in_title_order(Books* self, BookNodePtr book)
{
self->head = add_book_in_title_order(self->head, book);
}
BookNodePtr add_book_in_year_order(BookNodePtr self, BookNodePtr book)
{
if (self == NULL)
{
return book;
}
BookNodePtr current = self;
while (current != NULL)
{
if (get_year(current)-get_year(book) > 0)
{
if (get_prev(current) == NULL)
{
set_next(book, current);
set_prev(current, book);
return book;
}
set_next(book, current);
set_prev(book, get_prev(current));
set_next(get_prev(current), book);
set_prev(current, book);
return self;
}
else if (get_next(current) == NULL) //end
{
set_next(current, book);
set_prev(book, current);
return self;
}
current = get_next(current);
}
return self;
}
// Function to add book in year order
void add_in_year_order(Books* self, BookNodePtr book)
{
self->head = add_book_in_year_order(self->head, book);
}
// Function to add node in order of author name
BookNodePtr add_book_in_author_order(BookNodePtr self, BookNodePtr book)
{
if (self == NULL)
{
return book;
}
BookNodePtr current = self;
while (current != NULL)
{
if ((strcmp(get_author(current), get_author(book)) > 0))
{
if (get_prev(current) == NULL)//add at front
{
set_next(book, current);
set_prev(current, book);
return book;
}
//add in middle
set_next(book, current);
set_prev(book, get_prev(current));
set_next(get_prev(current), book);
set_prev(current, book);
return self;
}
else if (get_next(current) == NULL) //add at end
{
set_next(current, book);
set_prev(book, current);
return self;
}
current = get_next(current);
}
return self;
}
// Function to add book in author order
void add_in_author_order(Books* self, BookNodePtr book)
{
self->head = add_book_in_author_order(self->head, book);
}
void add_ordered(Books* self, BookNodePtr book, int order_type)
{
BookNodePtr cloned_book = clone_book(book);
if (order_type == 0)
{
add_in_year_order(self, cloned_book);
}
else if (order_type == 1)
{
add_in_title_order(self, cloned_book);
}
else if (order_type == 2)
{
add_in_author_order(self, cloned_book);
}
else
{
add_book(self, cloned_book);
}
}
//clone a linked list node
BookNodePtr clone_book(BookNodePtr book)
{
if (book == NULL) {
return NULL;
}
BookNodePtr clone = create_book(get_title(book),get_author(book),get_genre(book),get_year(book));
return clone;
}
//Test bench for book list
void book_list_tests()
{
Books book_list = new_books_list();
Books* book_list_ptr = &book_list;
printf("Test insert and print book function");
BookNodePtr book1 = create_book("Echoes of Eternity", "Sarah Montgomery", "Fantasy", 2023);
BookNodePtr book2 = create_book("Whispers in the Dark", "Jackson Pierce", "Mystery", 2022);
BookNodePtr book3 = create_book("The Forgotten Kingdom", "Emily Clarke", "Historical Fiction", 2024);
BookNodePtr book4 = create_book("Starsong", "Alexander Grant", "Science Fiction", 2023);
BookNodePtr book5 = create_book("The Shadow's Embrace", "Olivia West", "Thriller", 2022);
BookNodePtr book6 = create_book("A Symphony of Secrets", "Sophia Larson", "Romance", 2024);
BookNodePtr book7 = create_book("The Lost Heirloom", "Benjamin Roberts", "Mystery", 2023);
BookNodePtr book8 = create_book("Beyond the Horizon", "Lucas Hayes", "Adventure", 2022);
BookNodePtr book9 = create_book("Under a Crimson Sky", "Isabella Greene", "Historical Fiction", 2024);
BookNodePtr book10 = create_book("Soul of Steel", "Nathan Knight", "Fantasy", 2023);
BookNodePtr book11 = create_book("The Silent Witness", "Rachel Taylor", "Thriller", 2022);
BookNodePtr book12 = create_book("Stardust Serenade", "Michael Reynolds", "Science Fiction", 2024);
BookNodePtr book13 = create_book("A Whisper in Time", "Chloe Bennett", "Romance", 2023);
BookNodePtr book14 = create_book("The Last Enigma", "Ethan Parker", "Mystery", 2022);
BookNodePtr book15 = create_book("Sands of Destiny", "Harper Davis", "Adventure", 2024);
BookNodePtr book16 = create_book("Daughter of the Moon", "Lily Johnson", "Fantasy", 2023);
BookNodePtr book17 = create_book("Blood on the Vine", "Daniel Adams", "Mystery", 2022);
BookNodePtr book18 = create_book("Empires of Dust", "Ava Thompson", "Historical Fiction", 2024);
BookNodePtr book19 = create_book("Quantum Dreams", "Isaac Hughes", "Science Fiction", 2023);
BookNodePtr book20 = create_book("In the Shadow of Angels", "Madison Scott", "Thriller", 2022);
BookNodePtr book21 = create_book("Whispers of the Heart", "Jacob Carter", "Romance", 2024);
BookNodePtr book22 = create_book("The Cursed Crypt", "Samantha White", "Mystery", 2023);
BookNodePtr book23 = create_book("Windswept Odyssey", "Caleb Foster", "Adventure", 2022);
BookNodePtr book24 = create_book("The Crimson Rose", "Grace Evans", "Fantasy", 2023);
BookNodePtr book25 = create_book("Echoes of Betrayal", "Noah Bennett", "Thriller", 2022);
BookNodePtr book26 = create_book("Chronicles of Tomorrow", "Emma Roberts", "Science Fiction", 2024);
BookNodePtr book27 = create_book("Love's Resonance", "Ethan Parker", "Romance", 2023);
BookNodePtr book28 = create_book("The Vanishing Hour", "Natalie King", "Mystery", 2022);
BookNodePtr book29 = create_book("Echoes of Atlantis", "Benjamin Adams", "Historical Fiction", 2024);
BookNodePtr add_at_end_book = create_book("Ape Time", "AAAAAAAAAAH", "Very Fiction", 2002);
add_book(book_list_ptr, book1);
add_book(book_list_ptr, book2);
add_book(book_list_ptr, book3);
add_book(book_list_ptr, book4);
add_book(book_list_ptr, book5);
add_book(book_list_ptr, book6);
print_list(book_list_ptr);
printf("\nTest for finding a book from string data\n");
find_book(book_list_ptr,"Crispy G");
find_book(book_list_ptr, "The");
printf("\nTest delete book\n");
delete_book(book_list_ptr, book1);
print_list(book_list_ptr);
printf("\nTest delete book\n");
delete_book(book_list_ptr, book3);
print_list(book_list_ptr);
Books author_ordered_list = new_books_list();
printf("\nStarting new list to test");
printf("\nTest add in Author Name order\n");
add_in_author_order(&author_ordered_list, book7);
add_in_author_order(&author_ordered_list, add_at_end_book);
add_in_author_order(&author_ordered_list, book8);
add_in_author_order(&author_ordered_list, book9);
add_in_author_order(&author_ordered_list, book10);
add_in_author_order(&author_ordered_list, book11);
add_in_author_order(&author_ordered_list, book12);
add_in_author_order(&author_ordered_list, book13);
print_list(&author_ordered_list);
Books title_ordered_list = new_books_list();
printf("\nStarting new list to test");
printf("\nTest add in Title Name order\n");
add_in_title_order(&title_ordered_list, book14);
add_in_title_order(&title_ordered_list, book15);
add_in_title_order(&title_ordered_list, book16);
add_in_title_order(&title_ordered_list, book17);
add_in_title_order(&title_ordered_list, book18);
add_in_title_order(&title_ordered_list, book19);
add_in_title_order(&title_ordered_list, book20);
print_list(&title_ordered_list);
Books year_ordered_list = new_books_list();
printf("\nStarting new list to test");
printf("\nTest add in Year Name order\n");
add_in_year_order(&year_ordered_list, book21);
add_in_year_order(&year_ordered_list, book22);
add_in_year_order(&year_ordered_list, book23);
add_in_year_order(&year_ordered_list, book24);
add_in_year_order(&year_ordered_list, book25);
add_in_year_order(&year_ordered_list, book26);
add_in_year_order(&year_ordered_list, book27);
add_in_year_order(&year_ordered_list, book28);
add_in_year_order(&year_ordered_list, book29);
print_list(&year_ordered_list);
}