// READ BEFORE YOU START: // Please read the given Word document for the project
ID: 3921227 • Letter: #
Question
// 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(" a: add a new dog to the list "); printf(" s: search for a dog on the list "); printf(" r: remove a dog from the list "); printf(" c: add a checkup date for dog "); printf(" l: display last checkup for a dog "); printf(" n: display list of dogs by name "); printf(" b: display list of dogs of breed "); printf(" q: 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] = ''; 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] = ''; 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] = ''; 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] = ''; 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; }
Explanation / Answer
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(" a: add a new dog to the list ");
printf(" s: search for a dog on the list ");
printf(" r: remove a dog from the list ");
printf(" c: add a checkup date for dog ");
printf(" l: display last checkup for a dog ");
printf(" n: display list of dogs by name ");
printf(" b: display list of dogs of breed ");
printf(" q: 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] = '';
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] = '';
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] = '';
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] = '';
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;
}
Related Questions
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.