In this homework, you will get practice with custom classes (constructors, getters, setters), composition, passing objects to functions, overloading operators, reading data from a file, objects with a vector member variable, the initializer list syntax, and more. To do this, you will be creating a set of classes for managing an Address Book.
In this homework, you will have three custom classes: AddressBook, Contact, and Address. In addition to your main.cpp file, you should have a header (.h) and source (.cpp) file for each of the three above classes.
1. Define an Address class in the file Address.h and implement the Address class in Address.cpp.
a. This class should have two private data members, m_city and m_state, that are strings for storing the city name and state abbreviation for some Address.
b. Define and implement public getter and setter member functions for each of the two data members above. Important: since these member functions deal with objects (in this case strings), ensure that your setters are passed a const reference to a string, and ensure that your getters return a const reference to the appropriate data member. Also ensure that your getters follow the "Principle of Least Privilege."
c. Define and implement a single, two-value constructor that allows for the city and state to be provided in the creation of an Address object. Using constructor default values, if no parameters are passed, the city and state data members should automatically be set to empty string.
d. Override the stream insertion operator (<<) and the equality operator (==) for Address.
2. Define a Contact class in the file Contact.h and implement the Contact class in Contact.cpp.
a. This class should have three private data members, m_firstName and m_lastName, that are strings for storing the Contact's first and last names, and m_address that is of type Address.
b. Define and implement public getter and setter member functions for each of the three data members above. Important: since these member functions deal with objects, ensure that your setters are passed a const reference, and ensure that your getters return a const reference to the appropriate data member. Also ensure that your getters follow the "Principle of Least Privilege."
c. Define and implement a single, four-value constructor that allows for a Contact's first name, last name, city, and state to be provided in the creation of a Contact object. Using constructor default values, if no parameters are passed, the all values should automatically be set to empty string.
d. Override the stream insertion operator (<<) and the equality operator (==) for Contact. Hint: use the << and == operators of the Address class where appropriate.
3. Define an AddressBook class in the file AddressBook.h and implement the AddressBook class in AddressBook.cpp.
a. This class should have one private data members, m_contacts, that is an std::vector of Contact objects. Be sure to include < vector> in your .h file.
b. Define and implement a single, no-value (i.e., default) constructor.
c. Define and implement a public member function printAllContacts that prints out each contact object in the m_contacts vector. Ensure that this function follows the "Principle of Least Privilege." Hint: to simplify, use an overloaded operator of Contact.
d. Define and implement a public member function size that returns how many contact objects are currently in the m_contacts vector. Ensure that this function follows the "Principle of Least Privilege."
e. Define and implement a public member function addContact that adds a new contact to the m_contacts vector. This function should be passed a const reference to a Contact object.
f. Define and implement a public member function deleteAllContacts that removes (hint: clears) all contact objects in the m_contacts vector.
g. Define and implement a public member function searchByAddress that is passed a const reference to an Address object. Like the search by last name in Homework 2, this function should print out any contact that has an address that matches (same city and state) the passed in Address object. If no contact is printed, you should specify that the search found no match for this address. Ensure that this function follows the "Principle of Least Privilege." Hint: to simplify, use an overloaded operator of Address.
Notes:
It is highly recommended that you complete Part 1 and Part 3 of this homework before beginning on this Part. This will help to ensure that any issues that arise can be isolated to Part 2's functionality.
In your AddressBook class, define and implement a public member function importFromFile that is passed a const reference to a string. The string's value should be a file name to be imported (e.g., "input.txt"). This function should have a return type of bool.
This function should read in a text file (specified by filename) that is separated by spaces. For each contact, the file should list a contact's first name, last name, city, and state. Important: for simplicity in this homework, you can assume that there are no spaces in a contacts first name, last name, city, or state. For example, input.txt may be: "Will Smith Philadelphia Pennsylvania Fresh Prince Bel-Air California".
While reading in the file, you should create Contact object(s) and add them to your m_contacts vector. The example file content above would result in m_contacts containing two Contact objects. The function should return false if the file opening / reading fails; otherwise, the function should return true after all the file reading is finished.
Hint: To get started on this function, create a new file (right click project > New > File) named input.txt. In your CMakeList.txt file, ensure you've added the line configure_file(input.txt input.txt COPYONLY). Please see "lecture04_reviewPart2" to review this process and the basics of reading from files.
Write and document a simple main program to test your functions. You should create a single AddressBook object and multiple Contacts to be added to the address book. Your address book should have at least four (4) contact objects in it. Please create these using a combination of constructors and setters. As in previous homeworks, please provide tests of your member functions that print expected behavior vs. actual behavior. Below is a simple main program that shows example usages of this homework's classes.
int main()
{
AddressBook book;
Contact rick;
rick.setFirstName("Rick");
rick.setLastName("Astley");
Address newYork("New York", "NY");
rick.setAddress(newYork);
book.addContact(rick);
cout << "Number of contacts in address book: " << book.size() << endl;
book.printAllContacts();
cout << "Search results for address: " << newYork << endl;
book.searchByAddress(newYork);
cout << "Deleting all contacts..." << endl;
book.deleteAllContacts();
cout << "Number of contacts in address book: " << book.size() << endl;
cout << "Importing contacts..." << endl;
bool importSuccess = book.importFromFile("input.txt");
if (importSuccess) book.printAllContacts();
return 0;
}
For a file "input.txt" with the contents of Will Smith Philadelphia Pennsylvania Fresh Prince Bel-Air California the output of this program should be:
Number of contacts in address book: 1
Rick Astley
New York, NY
Search results for address: New York, NY
Rick Astley
New York, NY
Deleting all contacts...
Number of contacts in address book: 0
Importing contacts...
Successfully read in 2 contacts.
Will Smith
Philadelphia, Pennsylvania
Fresh Prince
Bel-Air, California