READ BEFORE YOU START Please read the given Word document
// READ BEFORE YOU START: // Please read the given Word document for the project description with an illustrartive diagram. // You are given a partially completed program that creates a list of dogs for an adoption shelter. // Each dog has the corresponding information: name, breed, and a linked list of checkups. // Please read the instructions above each required function and follow the directions carefully. // If you modify any of the given code, return types, or parameters, you risk failing test cases. // // Note, Textbook Section 2.10 gives a case study on complex linked list operations. // This project is based on that case study. Make sure you read the code in section 2.10. // The following will be accepted as input in the following format: \"name:breed\" // Example Input: \"Spot:Terrier\" or \"Daisy:Poodle\" // Valid name: String containing alphabetical letters beginning with a capital letter // Valid breed: String containing alphabetical letters beginning with a capital letter // Valid date: String in the following format: \"MM/DD/YYYY\" ex: \"01/01/2010\" // All input will be a valid length and no more than the allowed number of dogs will be added to the linked list. #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> // included to check for memory leaks #define CRTDBG_MAP_ALLOC #include <crtdbg.h> #pragma warning(disable: 4996) // used to create a linked list of containers, each contaning a \"dog\" struct container { struct dog *dog; struct container *next; } *list = NULL; // used to hold dog information and linked list of \"checkups\" struct dog { char name[30]; char breed[30]; struct checkup *checkups; }; // used to create a linked list of checkups containing \"dates\" struct checkup { char date[30]; struct checkup *next; }; // forward declaration of functions that have already been implemented void flush(); void branching(char); void helper(char); void remove_all(struct container*); void display(struct container*); // the following forward declarations are for functions that require implementation // return type // name and parameters // points void add_dog(char*, char*); // 5 struct dog* search_dog(char*); // 5 void add_checkup(char*, char*); // 10 char* last_checkup(char*); // 15 void remove_one(char*); // 15 // Total: 50 points for hw07 struct container* list_of_breed(char*); // 25 struct container* list_by_name(); // 25 // Total: 50 points for hw08 int main() { char ch = \'i\'; printf(\"Dog Adoption Center\ \ \"); do { printf(\"Please enter your selection:\ \"); printf(\"\\ta: add a new dog to the list\ \"); printf(\"\\ts: search for a dog on the list\ \"); printf(\"\\tr: remove a dog from the list\ \"); printf(\"\\tc: add a checkup date for dog\ \"); printf(\"\\tl: display last checkup for a dog\ \"); printf(\"\\tn: display list of dogs by name\ \"); printf(\"\\tb: display list of dogs of breed\ \"); printf(\"\\tq: quit\ \"); ch = tolower(getchar()); flush(); branching(ch); } while (ch != \'q\'); remove_all(list); list = NULL; _CrtDumpMemoryLeaks(); // check for memory leaks (VS will let you know in output if they exist) return 0; } // consume leftover \'\ \' characters void flush() { int c; do c = getchar(); while (c != \'\ \' && c != EOF); } // branch to different tasks void branching(char c) { switch (c) { case \'a\': case \'s\': case \'r\': case \'c\': case \'l\': case \'b\': case \'n\': helper(c); break; case \'q\': break; default: printf(\"Invalid input!\ \"); } } // This function will determine what info is needed and which function to send that info to. // It uses values that are returned from some functions to produce the correct ouput. // There is no implementation needed here, but you should trace the code and know how it works. // It is always helpful to understand how the code works before implementing new features. // Do not change anything in this function or you risk failing the automated test cases. void helper(char c) { if (c == \'a\') { char input[100]; printf(\"\ Please enter the dog\'s info in the following format:\ \"); printf(\"name:breed\ \"); fgets(input, sizeof(input), stdin); // discard \'\ \' chars attached to input input[strlen(input) - 1] = \'\\0\'; char* name = strtok(input, \":\"); // strtok used to parse string char* breed = strtok(NULL, \":\"); struct dog* result = search_dog(name); if (result == NULL) { add_dog(name, breed); printf(\"\ Dog added to list successfully\ \ \"); } else printf(\"\ That dog is already on the list\ \ \"); } else if (c == \'s\' || c == \'r\' || c == \'c\' || c == \'l\') { char name[30]; printf(\"\ Please enter the dog\'s name:\ \"); fgets(name, sizeof(name), stdin); // discard \'\ \' chars attached to input name[strlen(name) - 1] = \'\\0\'; struct dog* result = search_dog(name); if (result == NULL) printf(\"\ That dog is not on the list\ \ \"); else if (c == \'s\') printf(\"\ Breed: %s\ \ \", result->breed); else if (c == \'r\') { remove_one(name); printf(\"\ Dog removed from the list\ \ \"); } else if (c == \'c\') { char date[30]; printf(\"\ Please enter the date of the checkup:\ \"); fgets(date, sizeof(date), stdin); // discard \'\ \' chars attached to input date[strlen(date) - 1] = \'\\0\'; add_checkup(name, date); printf(\"\ Checkup added\ \ \"); } else if (c == \'l\') { char* result = last_checkup(name); if (result == NULL) printf(\"\ No checkups documented.\ \ \"); else printf(\"\ Last checkup: %s\ \ \", result); } } else if (c == \'b\') { char breed[30]; printf(\"\ Please enter the breed:\ \"); fgets(breed, sizeof(breed), stdin); // discard \'\ \' chars attached to input breed[strlen(breed) - 1] = \'\\0\'; struct container* result = list_of_breed(breed); printf(\"\ List of dogs with breed type %s:\ \ \", breed); display(result); remove_all(result); result = NULL; } else // c = \'n\' { struct container* result = list_by_name(); printf(\"\ List of dogs sorted by name:\ \ \"); display(result); remove_all(result); result = NULL; } } // This function recursively removes all dogs from the linked list of containers // Notice that all of the checkups for all of the dogs must be removed as well void remove_all(struct container* dogs) { struct checkup* temp; if (dogs != NULL) { remove_all(dogs->next); while (dogs->dog->checkups != NULL) { temp = dogs->dog->checkups; dogs->dog->checkups = dogs->dog->checkups->next; free(temp); } free(dogs->dog); free(dogs); } } // This function prints the list of dogs in an organized format // It may be useful to trace this code before you get started void display(struct container* dogs) { struct container* container_traverser = dogs; if (container_traverser == NULL) { printf(\"\ There are no dogs on this list!\ \ \"); return; } while (container_traverser != NULL) // traverse list of dogs { printf(\"Name: %s\ \", container_traverser->dog->name); printf(\"Breed: %s\ \", container_traverser->dog->breed); printf(\"Checkups on file: \"); struct checkup* ptr = container_traverser->dog->checkups; if (ptr == NULL) { printf(\"No checkups documented.\"); } else { while (ptr != NULL) // traverse list of checkups { printf(\"\ %s\", ptr->date); ptr = ptr->next; } } printf(\"\ \ \"); // formatting container_traverser = container_traverser->next; } } // hw07 Q1 : add (5 points) // This function should add dog to the head of the list of containers. // The function search_dog() is called before calling this function, // therefore you can assume that the dog is not already on the list. void add_dog(char* name, char* breed) { } // hw07 Q2 : search (5 points) // In this function, you are passed the name of a dog to find its breed. // If the dog exists on the list, return a pointer to the requested dog. If not, return NULL. // (You must return a pointer to a node in your list. Do not create a pointer that just includes the breed) // (Remember that it is enough to search for a dog by only their name since no 2 dogs will have the same name) struct dog* search_dog(char* name) { return NULL; } // hw07 Q3: add_checkup (10) // In this function, you are passed the name of a dog and a date of a checkup. // You should add the date to the tail of the linked list of the dogs \"checkups\". // You can assume that all checkups will be added in chronological order. // The function search_dog() is called before calling this function, // therefore you can assume that the dog is not already on the list. void add_checkup(char* name, char* date) { } // hw07 Q4: last_checkup (15) // In this function, you are passed the name of a dog to find the date of its last checkup. // Remember that checkups are stored in chronological order, // therefore the last checkup will be at the tail of the linked list of checkups. // If the dog has not yet had a checkup added to its list of checkups, return NULL. // The function search_dog() is called before calling this function, // therefore you can assume that the dog is not already on the list. char* last_checkup(char* name) { return NULL; } // hw07 Q5: remove_one (15) // In this function, you are passed the name of a dog to remove the corresponding dog from the list. // The search function is called before this function so you can assume that the dog is on the list. // You will need to find the dog and remove it using proper memory management to ensure no memory leaks. void remove_one(char* name) { } // hw08 Q1: list_of_breed (25) // This function is used to construct a linked list of containers from the global list of containers. // The returned list should only contain dogs which are of the breed type parameter (container->dog->breed). // The list that you return will be cleaned up for you by the remove_all() function (see helper() function), // however you will need to make sure that you leave no dangling references (those cause memory leaks too). // Notice that the returned list will need to contain all dog and checkup information to be displayed. struct container* list_of_breed(char* breed) { return NULL; } // hw08 Q2: list_by_name (25) // This function is used to construct a linked list of containers from the global list of containers. // The returned list should be sorted alphabetically by each container\'s dog\'s name (container->dog->name). // The list that you return will be cleaned up for you by the remove_all() function (see helper() function), // however you will need to make sure that you leave no dangling references (those cause memory leaks too). // Notice that the returned list will need to contain all dog and checkup information to be displayed. // You can again assume that for this assignment, no 2 dogs on the list will have the same name. // You may want to use the function that you have written above as a blueprint for this function. struct container* list_by_name() { return NULL; } Solution
Please find the answer to the above problem as follows:-
// The following will be accepted as input in the following format: \"name:breed\"
// Example Input: \"Spot:Terrier\" or \"Daisy:Poodle\"
// Valid name: String containing alphabetical letters beginning with a capital letter
// Valid breed: String containing alphabetical letters beginning with a capital letter
// Valid date: String in the following format: \"MM/DD/YYYY\" ex: \"01/01/2010\"
// All input will be a valid length and no more than the allowed number of dogs will be added to the linked list.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include\"DogAdoptionFunctions.cpp\"
// included to check for memory leaks
// used to create a linked list of containers, each containing a \"dog\"
struct container {
struct dog *dog;
struct container *next;
} *List = NULL;
// used to hold dog information and linked list of \"checkups\"
struct dog {
char name[30];
char breed[30];
struct checkup *checkups;
};
// used to create a linked list of checkups containing \"dates\"
struct checkup {
char date[30];
struct checkup *next;
};
// forward declaration of functions that have already been implemented
void flush();
void branching(char);
void helper(char);
void remove_all(struct container*);
void display(struct container*);
// the following forward declarations are for functions that require implementation
// return type // name and parameters // points
void add_dog(char*, char*); // 5
struct dog* search_dog(char*); // 5
void add_checkup(char*, char*); // 10
char* last_checkup(char*); // 15
void remove_one(char*); // 15
// Total: 50 points for hw07
struct container* list_of_breed(char*); // 25
struct container* list_by_name(); // 25
// Total: 50 points for hw08
int main()
{
char ch = \'i\';
printf(\"Dog Adoption Center\ \ \");
do
{
printf(\"Please enter your selection:\ \");
printf(\"\\ta: add a new dog to the list\ \");
printf(\"\\ts: search for a dog on the list\ \");
printf(\"\\tr: remove a dog from the list\ \");
printf(\"\\tc: add a checkup date for dog\ \");
printf(\"\\tl: display last checkup for a dog\ \");
printf(\"\\tn: display list of dogs by name\ \");
printf(\"\\tb: display list of dogs of breed\ \");
printf(\"\\tq: quit\ \");
ch = tolower(getchar());
flush();
branching(ch);
} while (ch != \'q\');
remove_all(List);
List = NULL;
free(List);
return 0;
}
// consume leftover \'\ \' characters
void flush()
{
int c;
do c = getchar(); while (c != \'\ \' && c != EOF);
}
// branch to different tasks
void branching(char c)
{
switch (c)
{
case \'a\':
case \'s\':
case \'r\':
case \'c\':
case \'l\':
case \'b\':
case \'n\': helper(c); break;
case \'q\': break;
default: printf(\"Invalid input!\ \");
}
}
// This function will determine what info is needed and which function to send that info to.
// It uses values that are returned from some functions to produce the correct ouput.
// There is no implementation needed here, but you should trace the code and know how it works.
// It is always helpful to understand how the code works before implementing new features.
// Do not change anything in this function or you risk failing the automated test cases.
void helper(char c)
{
if (c == \'a\')
{
char input[100];
printf(\"\ Please enter the dog\'s info in the following format:\ \");
printf(\"name:breed\ \");
fgets(input, sizeof(input), stdin);
// discard \'\ \' chars attached to input
input[strlen(input) - 1] = \'\\0\';
char* name = strtok(input, \":\"); // strtok used to parse string
char* breed = strtok(NULL, \":\");
struct dog* result = search_dog(name);
if (result == NULL)
{
add_dog(name, breed);
printf(\"\ Dog added to list successfully\ \ \");
}
else
printf(\"\ That dog is already on the list\ \ \");
}
else if (c == \'s\' || c == \'r\' || c == \'c\' || c == \'l\')
{
char name[30];
printf(\"\ Please enter the dog\'s name:\ \");
fgets(name, sizeof(name), stdin);
// discard \'\ \' chars attached to input
name[strlen(name) - 1] = \'\\0\';
struct dog* result = search_dog(name);
if (result == NULL)
printf(\"\ That dog is not on the list\ \ \");
else if (c == \'s\')
printf(\"\ Breed: %s\ \ \", result->breed);
else if (c == \'r\')
{
remove_one(name);
printf(\"\ Dog removed from the list\ \ \");
}
else if (c == \'c\')
{
char date[30];
printf(\"\ Please enter the date of the checkup:\ \");
fgets(date, sizeof(date), stdin);
// discard \'\ \' chars attached to input
date[strlen(date) - 1] = \'\\0\';
add_checkup(name, date);
printf(\"\ Checkup added\ \ \");
}
else if (c == \'l\')
{
char* result = last_checkup(name);
if (result == NULL)
printf(\"\ No checkups documented.\ \ \");
else
printf(\"\ Last checkup: %s\ \ \", result);
}
}
else if (c == \'b\')
{
char breed[30];
printf(\"\ Please enter the breed:\ \");
fgets(breed, sizeof(breed), stdin);
// discard \'\ \' chars attached to input
breed[strlen(breed) - 1] = \'\\0\';
struct container* result = list_of_breed(breed);
printf(\"\ List of dogs with breed type %s:\ \ \", breed);
display(result);
remove_all(result);
result = NULL;
}
else // c = \'n\'
{
struct container* result = list_by_name();
printf(\"\ List of dogs sorted by name:\ \ \");
display(result);
remove_all(result);
result = NULL;
}
}
// This function recursively removes all dogs from the linked list of containers
// Notice that all of the checkups for all of the dogs must be removed as well
void remove_all(struct container* dogs)
{
struct checkup* temp;
if (dogs != NULL)
{
remove_all(dogs->next);
while (dogs->dog->checkups != NULL)
{
temp = dogs->dog->checkups;
dogs->dog->checkups = dogs->dog->checkups->next;
free(temp);
}
free(dogs->dog);
free(dogs);
}
}
// This function prints the list of dogs in an organized format
// It may be useful to trace this code before you get started
void display(struct container* dogs)
{
struct container* container_traverser = dogs;
if (container_traverser == NULL)
{
printf(\"\ There are no dogs on this list!\ \ \");
return;
}
while (container_traverser != NULL) // traverse list of dogs
{
printf(\"Name: %s\ \", container_traverser->dog->name);
printf(\"Breed: %s\ \", container_traverser->dog->breed);
printf(\"Checkups on file: \");
struct checkup* ptr = container_traverser->dog->checkups;
if (ptr == NULL)
{
printf(\"No checkups documented.\");
}
else
{
while (ptr != NULL) // traverse list of checkups
{
printf(\"\ %s\", ptr->date);
ptr = ptr->next;
}
}
printf(\"\ \ \"); // formatting
container_traverser = container_traverser->next;
}
}
// hw07 Q1 : add (5 points)
// This function should add dog to the head of the list of containers.
// The function search_dog() is called before calling this function,
// therefore you can assume that the dog is not already on the list.
void add_dog(char* name, char* breed)
{
if(List==NULL){
List = (struct container*)malloc(sizeof(struct container));
struct dog *newDog = (struct dog*)malloc(sizeof(struct dog));
strcpy(newDog->breed, breed);
strcpy(newDog->name, name);
newDog->checkups = NULL;
List->dog = newDog;
List->next = NULL;
}else{
struct dog *newDog = (struct dog*)malloc(sizeof(struct dog));
strcpy(newDog->breed, breed);
strcpy(newDog->name, name);
newDog->checkups = NULL;
struct container *traverser = List;
while(traverser->next!=NULL){
traverser = traverser->next;
}
struct container *newDogContainer = (struct container*)malloc(sizeof(struct container));
newDogContainer->dog = newDog;
newDogContainer->next = NULL;
traverser->next = newDogContainer;
}
}
// hw07 Q2 : search (5 points)
// In this function, you are passed the name of a dog to find its breed.
// If the dog exists on the list, return a pointer to the requested dog. If not, return NULL.
// (You must return a pointer to a node in your list. Do not create a pointer that just includes the breed)
// (Remember that it is enough to search for a dog by only their name since no 2 dogs will have the same name)
struct dog* search_dog(char* name)
{
struct container *traverser = List;
while(traverser!=NULL){
if(strcmp(name, traverser->dog->name)==0){
return traverser->dog;
}
traverser = traverser->next;
}
return NULL;
}
// hw07 Q3: add_checkup (10)
// In this function, you are passed the name of a dog and a date of a checkup.
// You should add the date to the tail of the linked list of the dogs \"checkups\".
// You can assume that all checkups will be added in chronological order.
// The function search_dog() is called before calling this function,
// therefore you can assume that the dog is not already on the list.
void add_checkup(char* name, char* date)
{
struct dog *myDog = search_dog(name);
if(myDog!=NULL){
struct checkup *newCheckup = (struct checkup*)malloc(sizeof(struct checkup));
strcpy(newCheckup->date, date);
newCheckup->next = NULL;
struct checkup *traverser = myDog->checkups;
if(traverser==NULL){
myDog->checkups = newCheckup;
}else{
while(traverser->next!=NULL){
traverser = traverser->next;
}
traverser->next = newCheckup;
}
}
}
// hw07 Q4: last_checkup (15)
// In this function, you are passed the name of a dog to find the date of its last checkup.
// Remember that checkups are stored in chronological order,
// therefore the last checkup will be at the tail of the linked list of checkups.
// If the dog has not yet had a checkup added to its list of checkups, return NULL.
// The function search_dog() is called before calling this function,
// therefore you can assume that the dog is not already on the list.
char* last_checkup(char* name)
{
struct dog *myDog = search_dog(name);
if(myDog!=NULL){
struct checkup *traverser = myDog->checkups;
while(traverser->next!=NULL){
traverser = traverser->next;
}
return traverser->date;
}else
return NULL;
}
// hw07 Q5: remove_one (15)
// In this function, you are passed the name of a dog to remove the corresponding dog from the list.
// The search function is called before this function so you can assume that the dog is on the list.
// You will need to find the dog and remove it using proper memory management to ensure no memory leaks.
void remove_one(char* name)
{
struct container *traverser = List;
if(strcmp(traverser->dog->name, name)==0){
List = List->next;
return;
}else{
struct container *prev = NULL;
while(strcmp(traverser->dog->name, name)!=0){
prev = traverser;
traverser = traverser->next;
}
prev->next = traverser->next;
free(traverser);
}
}
// hw08 Q1: list_of_breed (25)
// This function is used to construct a linked list of containers from the global list of containers.
// The returned list should only contain dogs which are of the breed type parameter (container->dog->breed).
// The list that you return will be cleaned up for you by the remove_all() function (see helper() function),
// however you will need to make sure that you leave no dangling references (those cause memory leaks too).
// Notice that the returned list will need to contain all dog and checkup information to be displayed.
struct container* list_of_breed(char* breed)
{
int counter = 0;
struct container *list_breed = (struct container *)malloc(sizeof(struct container));
struct container *traverser = List;
struct container *current;
while(traverser!=NULL){
if(strcmp(traverser->dog->breed, breed)==0){
current = (struct container *)malloc(sizeof(struct container));
struct dog *myDog = (struct dog *)malloc(sizeof(struct dog));
current->dog = myDog;
strcpy(current->dog->breed, traverser->dog->breed);
strcpy(current->dog->name, traverser->dog->name);
current->dog->checkups=NULL;
struct checkup *list_checkup = NULL;
struct checkup *ccurrent = NULL;
int ccounter = 0;
while(traverser->dog->checkups!=NULL){
struct checkup *newCheckup = (struct checkup*)malloc(sizeof(struct checkup));
strcpy(newCheckup->date, traverser->dog->checkups->date);
newCheckup->next = NULL;
if(ccounter == 0){
list_checkup = newCheckup;
}else{
ccurrent = list_checkup;
while(ccurrent->next!=NULL){
ccurrent = ccurrent->next;
}
ccurrent->next=newCheckup;
}
traverser->dog->checkups= traverser->dog->checkups->next;
}
current->dog->checkups = list_checkup;
if(counter==0){
current->next = NULL;
counter = 1;
}else
current->next = list_breed;
list_breed = current;
}
traverser = traverser->next;
}
traverser = NULL;
current = NULL;
free(traverser);
free(current);
display(list_breed);
return list_breed;
}
// hw08 Q2: list_by_name (25)
// This function is used to construct a linked list of containers from the global list of containers.
// The returned list should be sorted alphabetically by each container\'s dog\'s name (container->dog->name).
// The list that you return will be cleaned up for you by the remove_all() function (see helper() function),
// however you will need to make sure that you leave no dangling references (those cause memory leaks too).
// Notice that the returned list will need to contain all dog and checkup information to be displayed.
// You can again assume that for this assignment, no 2 dogs on the list will have the same name.
// You may want to use the function that you have written above as a blueprint for this function.
struct container* list_by_name()
{
struct container *list_name = (struct container *)malloc(sizeof(struct container));
struct container *traverser = List;
struct container *temp = list_name;
list_name = NULL;
while(traverser!=NULL){
temp = list_name;
struct container *current = (struct container *)malloc(sizeof(struct container));
struct dog *myDog = (struct dog *)malloc(sizeof(struct dog));
current->dog = myDog;
strcpy(current->dog->breed, traverser->dog->breed);
strcpy(current->dog->name, traverser->dog->name);
current->dog->checkups=NULL;
struct checkup *list_checkup = NULL;
struct checkup *ccurrent = NULL;
int ccounter = 0;
while(traverser->dog->checkups!=NULL){
struct checkup *newCheckup = (struct checkup*)malloc(sizeof(struct checkup));
strcpy(newCheckup->date, traverser->dog->checkups->date);
newCheckup->next = NULL;
if(ccounter == 0){
list_checkup = newCheckup;
}else{
ccurrent = list_checkup;
while(ccurrent->next!=NULL){
ccurrent = ccurrent->next;
}
ccurrent->next=newCheckup;
}
traverser->dog->checkups= traverser->dog->checkups->next;
}
current->dog->checkups = list_checkup;
if(temp==NULL){
current->next = NULL;
list_name = current;
traverser = traverser->next;
continue;
}
if(strcmp(traverser->dog->name, temp->dog->name)<0){
current->next = temp;
list_name = current;
traverser = traverser->next;
continue;
}
struct container *prev = NULL;
bool inserted = false;
while(temp->next!=NULL){
prev = temp;
temp = temp->next;
if(strcmp(traverser->dog->name, temp->dog->name)<0){
current->next = temp;
prev->next = current;
inserted = true;
break;
}
}
if(!inserted){
current->next = NULL;
temp->next = current;
}
traverser = traverser->next;
}
return list_name;
}








