Code:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
/**********************************************************************
// Linked List Definitions
// Define your linked list node and pointer types
// here for use throughout the file.
//
//
// ADD STATEMENT(S) HERE*/
struct Book {
char *name;
char *author;
int rating;
char category;
struct Book *next;
};
/**********************************************************************
// Linked List Function Declarations
//
// Functions that modify the linked list.
// Declare your linked list functions here.
//
// ADD STATEMENT(S) HERE*/
struct Book *newBook();
int bookExists(struct Book *bookHead, char bookName[]);
struct Book *insertBook(struct Book *bookHead, struct Book *book);
int compareBook(struct Book *book1, struct Book *book2);
struct Book *deleteBook(struct Book *bookHead, char bookName[]);
void searchBook(struct Book *bookHead, char bookName[]);
void searchBookRatingsHigherThan(struct Book *bookHead, int rating);
void printBook(struct Book *book);
void printBooks(struct Book *bookHead);
struct Book *deleteBooks(struct Book *bookHead);
/*********************************************************************
// Support Function Declarations
/*/
void safegets (char s[], int arraySize); /*gets without buffer overflow*/
void bookNameDuplicate (char bookName[]); /*marker/tester friendly*/
void bookNameFound (char bookName[]); /*functions to print*/
void bookNameNotFound (char bookName[]); /*messages to user*/
void bookNameDeleted (char bookName[]);
void printInventoryEmpty (void);
void printInventoryTitle (void);
void printNoBooksWithHigherRating (int rating);
/**********************************************************************
// Program-wide Constants
//*/
const int MAX_LENGTH = 1023;
const char NULL_CHAR = '\0';
const char NEWLINE = '\n';
const char FICTION = 'F';
const char HISTORY = 'H';
const char PHILOSOPHY = 'P';
const char ART = 'A';
/**********************************************************************
// Main Program
/*/
int main (void)
{
const char bannerString[]
= "Online Bookstore Inventory Management Program.\n";
const char commandList[]
= "Commands are I (insert), D (delete), S (search by name),\n"
" V (search by rating), P (print), Q (quit).\n";
/* Declare linked list head.
// ADD STATEMENT(S) HERE TO DECLARE LINKED LIST HEAD.*/
struct Book *bookHead = NULL;
/* announce start of program*/
printf("%s", bannerString);
printf("%s", commandList);
char response;
char input[MAX_LENGTH+1];
do
{
printf("\nCommand?: ");
safegets(input, MAX_LENGTH + 1);
// Response is first char entered by user.
// Convert to uppercase to simplify later comparisons.
response = toupper(input[0]);
if (response == 'I')
{
// Insert a book entry into the linked list.
// Maintain the list in correct order (F, H, P, A).
// ADD STATEMENT(S) HERE
struct Book *book = newBook();
// USE THE FOLLOWING PRINTF STATEMENTS WHEN PROMPTING FOR DATA:
printf(" book: ");
safegets(book->name, 255);
printf(" author: ");
safegets(book->author, 255);
printf(" rating: ");
book->rating = getchar() - '0';
fflush(stdin);
printf(" category: ");
book->category = getchar();
bookHead = insertBook(bookHead, book);
fflush(stdin);
}
else if (response == 'D')
{
// Delete a book from the list.
printf("Enter the book name to delete: ");
// ADD STATEMENT(S) HERE
char bookName[10000];
safegets(bookName, 10000);
deleteBook(bookHead, bookName);
}
else if (response == 'S')
{
// Search for a book by a name.
printf("Enter the book name to search for: ");
// ADD STATEMENT(S) HERE
char bookName[10000];
safegets(bookName, 10000);
searchBook(bookHead, bookName);
}
else if (response == 'V')
{
/* Search for books that are rated higher than or equal to a rating.*/
printf("Enter rating: ");
// ADD STATEMENT(S) HERE
int rating = 0;
scanf("%d", &rating);
searchBookRatingsHigherThan(bookHead, rating);
fflush(stdin);
}
else if (response == 'P')
{
// Print the bookstore inventory.
// ADD STATEMENT(S) HERE
printBooks(bookHead);
}
else if (response == 'Q')
{
printf("\nThe book store inventory is empty"); /* do nothing, we'll catch this case below*/
return 0;
}
else
{
// do this if no command matched ...
printf("\nInvalid command.\n%s\n", commandList);
}
} while (response != 'Q');
// Delete the entire linked list that hold the bookstore invento
// ADD STATEMENT(S) HERE
bookHead = deleteBooks(bookHead);
// Print the linked list to confirm deletion.
// ADD STATEMENT(S) HERE
printBooks(bookHead);
return 0;
}
/***********************************************************************
Support Function Definitions*/
/* Function to get a line of input without overflowing target char array*/
void safegets (char s[], int arraySize)
{
int i = 0, maxIndex = arraySize - 1;
char c;
while (i < maxIndex && (c = getchar()) != NEWLINE)
{
s[i] = c;
i = i + 1;
}
s[i] = NULL_CHAR;
}
/* Function to call when a user is trying to insert a book name
// that is already in the inventory.*/
void bookNameDuplicate (char bookName[])
{
printf("An entry for <%s> is already in the bookstore inventory!\n", bookName);
printf("New entry not entered.\n");
}
/* Function to call when a book with this name was found in the inventory.*/
void bookNameFound (char bookName[])
{
printf("The book with name <%s> was found in the bookstore inventory.\n",bookName);
}
/* Function to call when a book with this name was not found in the inventory.*/
void bookNameNotFound (char bookName[])
{
printf("The book with name <%s> is not in the bookstore inventory.\n", bookName);
}
// Function to call when a name that is to be deleted
// was found in the inventory.
void bookNameDeleted (char bookName[])
{
printf("Deleting book with name <%s> from the bookstore inventory.\n", bookName);
}
// Function to call when printing an empty bookstore inventory.
void printInventoryEmpty (void)
{
printf("The bookstore inventory is empty.\n");
}
// Function to call to print title when the entire inventory is printed.
void printInventoryTitle (void)
{
printf("My Inventory: \n");
}
/* Function to call when no book in the bookstore inventory has higher*/
// or equal rating to the given rating
void printNoBooksWithHigherRating (int rating)
{
printf("No book(s) in the bookstore inventory is rated higher than or equal to <%d>.\n", rating);
}
//**********************************************************************
// Add your functions below this line.
// Allocates a memory space for the book
struct Book *newBook()
{
struct Book *book = (struct Book *)malloc(sizeof(struct Book));
book->author = malloc(255 * (sizeof(char)));
book->name = malloc(255 * (sizeof(char)));
book->rating = 0;
book->category = ' ';
book->next = NULL;
return book;
}
// Checks if the book already exists in the linked list
int bookExists(struct Book *bookHead, char bookName[])
{
if(bookHead == NULL)
// return false
return 0;
struct Book *bookCurrent = bookHead;
while(bookCurrent != NULL)
{
if(strcmp(bookCurrent->name, bookName) == 0)
// return true if match found
return 1;
bookCurrent = bookCurrent->next;
}
// return false
return 0;
}
// Compares two books and check if book 1 is more prioritized than book 2
int compareBook(struct Book *book1, struct Book *book2)
{
int book1Priority = 0;
int book2Priority = 0;
switch(book1->category)
{
case 'F': book1Priority = 4; break;
case 'H': book1Priority = 3; break;
case 'P': book1Priority = 2; break;
case 'A': book1Priority = 1; break;
}
switch(book2->category)
{
case 'F': book2Priority = 4; break;
case 'H': book2Priority = 3; break;
case 'P': book2Priority = 2; break;
case 'A': book2Priority = 1; break;
}
if(book1Priority > book2Priority)
return 1;
if(book1Priority < book2Priority)
return -1;
return 0;
}
// Inserts a new book into the linked list
struct Book *insertBook(struct Book *bookHead, struct Book *book)
{
if(bookExists(bookHead, book->name))
{
bookNameDuplicate(book->name);
return bookHead;
}
if(bookHead == NULL)
{
// insert at the root node if empty
bookHead = book;
return bookHead;
}
// otherwise detect the special order F,H,P,A
// find the root of the category of the book
struct Book *bookPrevious = NULL;
struct Book *bookCurrent = bookHead;
while(bookCurrent != NULL)
{
if(compareBook(book, bookCurrent) <= 0)
{
bookPrevious = bookCurrent;
bookCurrent = bookCurrent->next;
continue;
}
break;
}
if(bookPrevious == NULL)
{
// if book previous is null, meaning we're inserting in the head
book->next = bookHead;
bookHead = book;
}
else
{
// if not then we're inserting in either inbetween, or tail
book->next = bookPrevious->next;
bookPrevious->next = book;
}
return bookHead;
}
// Deletes a book from the linked list
struct Book *deleteBook(struct Book *bookHead, char bookName[])
{
// Check if the book exists
if(bookHead == NULL)
{
printInventoryEmpty();
return bookHead;
}
if(!bookExists(bookHead, bookName))
{
bookNameNotFound(bookName);
return bookHead;
}
// look for the book
struct Book *bookPrevious = NULL;
struct Book *bookCurrent = bookHead;
while(bookCurrent != NULL)
{
if(strcmp(bookCurrent->name, bookName) == 0)
break;
bookPrevious = bookCurrent;
bookCurrent = bookCurrent->next;
}
if(bookPrevious == NULL)
{
// if the book previous is NULL that means we are deleting the head
bookPrevious = bookHead;
bookHead = bookHead->next;
bookNameDeleted(bookPrevious->name);
free(bookPrevious);
}
else
{
// if we're not deleting the head, then we're deleting in between
bookPrevious->next = bookCurrent->next;
bookNameDeleted(bookPrevious->name);
free(bookCurrent);
}
return bookHead;
}
// Searches a book from the linked list
void searchBook(struct Book *bookHead, char bookName[])
{
// Check if the book exists
if(bookHead == NULL)
{
printInventoryEmpty();
return;
}
if(!bookExists(bookHead, bookName))
{
bookNameNotFound(bookName);
return;
}
// look for the book and display its details
struct Book *bookCurrent = bookHead;
while(bookCurrent != NULL)
{
if(strcmp(bookCurrent->name, bookName) == 0)
break;
bookCurrent = bookCurrent->next;
}
// display the book details
bookNameFound(bookCurrent->name);
printBook(bookCurrent);
}
// Searches a book that has higher rating than the given rating
void searchBookRatingsHigherThan(struct Book *bookHead, int rating)
{
if(bookHead == NULL)
{
printInventoryEmpty();
return;
}
// look for the book and display its details
int foundBooks = 0;
struct Book *bookCurrent = bookHead;
while(bookCurrent != NULL)
{
if(bookCurrent->rating >= rating)
{
printBook(bookCurrent);
foundBooks++;
}
bookCurrent = bookCurrent->next;
}
if(foundBooks == 0)
printNoBooksWithHigherRating(rating);
}
// Displays book details
void printBook(struct Book *book)
{
printf("\n%s\n", book->name);
printf("%s\n", book->author);
printf("%d\n", book->rating);
printf("%c\n", book->category);
}
// Displays all books in the inventory
void printBooks(struct Book *bookHead)
{
if(bookHead!= NULL)
{
printInventoryTitle();
}
if(bookHead == NULL)
{
printInventoryEmpty();
return;
}
struct Book *bookCurrent = bookHead;
while(bookCurrent != NULL)
{
printBook(bookCurrent);
bookCurrent = bookCurrent->next;
}
}
// Delete all books from the memory
struct Book * deleteBooks(struct Book *bookHead)
{
if(bookHead == NULL)
return bookHead;
struct Book *bookPrevious = NULL;
struct Book *bookCurrent = bookHead;
while(bookCurrent != NULL)
{
bookPrevious = bookCurrent;
bookCurrent = bookCurrent->next;
free(bookPrevious);
}
if(bookPrevious != NULL)
free(bookPrevious);
bookHead = NULL;
return bookHead;
}