//////////////////////////////////////// // Spam Cupcakes, the pointed view // HINTS AND GUIDELINE // You should do this assignment in the following order: // - Make the changes to the Customer class // - Test the Customer class using the provided test main // - Make the changes to the CustomerList class // - Test the CustomerList class using the provided test main // - Make changes to your main so that it works //////////////////////////////////////// // Standard included things #include #include #include #include using namespace std; //////////////////////////////////////// // Function prototypes void print_menu(); void print_vector(vector); //////////////////////////////////////// // Class definitions // A self-referential class to hold customer information class Customer{ friend ostream &operator<<(ostream &, Customer); friend istream &operator>>(istream &, Customer &); public: Customer (); Customer (string , string); string getName(); string getEmail(); Customer * getNextCustomer(); void setName(string); void setEmail(string); void setNextCustomer(Customer *); private: string name; string email; // The private variable below is the pointer to the next customer on the list. // It is null if there is no next customer Customer * nextCustomer; }; ostream &operator<<(ostream &output, Customer c){ output << setw(40) << c.email << setw(40) << c.name; return output; } istream &operator>>(istream &input, Customer & c){ input >> c.email; input.ignore(); getline(input, c.name); return input; } Customer::Customer(){ // All you need to do here is make sure that the nextCustomer is null. nextCustomer = NULL; } Customer::Customer (string newName, string newEmail){ // Set the values of name and email to the new things passed in as parameters // Also, make sure the nextCustomer is null name = newName; email = newEmail; nextCustomer = NULL; } string Customer::getName(){ return name; } string Customer::getEmail(){ return email; } Customer * Customer::getNextCustomer(){ // This returns the next customer on the list // The thing it returns should be a pointer return nextCustomer; } void Customer::setName(string newName) { name = newName; } void Customer::setEmail(string newEmail){ email = newEmail; } void Customer::setNextCustomer(Customer * next){ // This sets the next customer on the list to the pointer passed in // as a vector // Notice the parameter is a pointer nextCustomer = next; } // A class to hold the customer email list // Using pointers, not vector class CustomerList{ public: CustomerList(); CustomerList(string); void loadFile(string); void showNames(); void showEmails(); void showList(); int countNameAppearances(string); int countEmailAppearances(string); int deleteCustomer(string); void addCustomer(string, string); private: // The pointer below is the head of the customerList. It replaces // the vector of Customers from the last assignment. In short, this is // pointer that points to the first Customer. The first Customer points to // the second Customer, and so on. The last Customer on the list points to NULL. Customer * head; // This is a private method that will delete all the elements on the Customer list. void clearCustomerList(); }; CustomerList::CustomerList(){ // Here we need to make sure that our initial head pointer is null head = NULL; } CustomerList::CustomerList(string filename){ // Here we need to make sure that our initial head pointer is null // and call loadFile to read in a file. head = NULL; loadFile(filename); } void CustomerList::loadFile(string filename) { // This method loads all the customers in from a file. // For each line in the file, which represents a single customer // we need to: // - Create a new customer using the new command // - Input from the file into the new Customer using the >> operator // - Add the new customer to the list by setting its nextCustomer using setNextCustomer // and then change the head pointer to point at the new Customer // - Delete any unused Customer object clearCustomerList(); ifstream inputFile; Customer * current; // open file if it is there inputFile.open(filename.c_str()); if (!inputFile) { cerr << "Could not open file: "<< filename << " for reading." << endl; exit(1); } current = new Customer; while (inputFile >> *current){ current->setNextCustomer(head); head = current; current = new Customer; } delete current; } void CustomerList::showNames(){ // This should traverse the list from the head on down and print out each name // from each customer on the list Customer * current = head; while (current != NULL){ cout << setw(40) << current->getName() << endl; current = current->getNextCustomer(); } } void CustomerList::showEmails(){ // This should traverse the list from the head on down and print out each email // from each customer on the list Customer * current = head; while (current != NULL){ cout << setw(40) << current->getEmail() << endl; current = current->getNextCustomer(); } } void CustomerList::showList(){ // This should traverse the list from the head on down and print out each email // and name from each customer on the list cout << setw(40) << "Names" << setw(40) << "Emails" << endl; Customer * current = head; while (current != NULL){ cout << setw(40) << current->getName() << setw(40) << current->getEmail() << endl; current = current->getNextCustomer(); } } int CustomerList::countNameAppearances(string name){ // This should traverse the list from the head on down and count how many times // the name provided as a parameter appears on the list. int count = 0; Customer * current = head; while (current != NULL){ if (name == current->getName()){ count ++; } current = current->getNextCustomer(); } return count; } int CustomerList::countEmailAppearances(string email){ // This should traverse the list from the head on down and count how many times // the email provided as a parameter appears on the list. int count = 0; Customer * current = head; while (current != NULL){ if (email == current->getEmail()){ count ++; } current = current->getNextCustomer(); } return count; } int CustomerList::deleteCustomer(string email){ // This method should traverse down the list and delete any Customer that contains the // email provided as a parameter. It should count how many it deleted, and return that number // Notice that deleting an item that is the head of the list is different than deleting // an item that is not on the head. int count = 0; Customer * current = head; Customer * temp; Customer * prev; // Delete everything from the head of the list while ((current != NULL) && (email == current->getEmail())){ temp = current; head = current->getNextCustomer(); delete temp; count ++; current = head; } while (current != NULL){ if (current->getEmail() == email){ prev->setNextCustomer(current->getNextCustomer()); delete current; count ++; current = prev->getNextCustomer(); } // take care of the end of list case if (current != NULL){ prev = current; current = current->getNextCustomer(); } } return count; } void CustomerList::addCustomer(string email, string name){ // This should: // Create a new Customer that has the given email and name // Add the customer to the list Customer * newCust = new Customer(name, email); newCust->setNextCustomer(head); head = newCust; } void CustomerList::clearCustomerList(){ Customer * temp; while (head != NULL) { temp = head; head = head->getNextCustomer(); delete temp; } } //////////////////////////////////////// // Main function // /* start of comment out working main int main () { CustomerList theList; char choice; bool done = false; string input, input2; int count = 0; vector temp; string filename; do { // Print the menu for the user print_menu(); cin >> choice; switch(choice){ case 'L': case 'l': cout << "What file would you like to load: "; cin >> filename; theList.loadFile(filename); break; case 'S': case 's': theList.showList(); break; case 'M': case 'm': theList.showNames(); break; case 'R': case 'r': theList.showEmails(); break; case 'C': case 'c': cout << "What name do you want to use: "; cin.ignore(); getline(cin,input); count = theList.countNameAppearances(input); cout << endl << "\"" << input << "\" appeared " << count << " times." << endl; break; case 'V': case 'v': cout << "What email address do you want to use: "; cin >> input; count = theList.countEmailAppearances(input); cout << endl << "\"" << input << "\" appeared " << count << " times." << endl; break; case 'A': case 'a': cout << "What email address do you want to add: "; cin >> input; cin.ignore(); cout << "What name goes with that: "; getline(cin, input2); theList.addCustomer(input, input2); break; case 'D': case 'd': cout << "What email address do you want to delete: "; cin >> input; count = theList.deleteCustomer(input); cout << "Deleted " << count << " instances of " << input << endl; break; case 'X': case 'x': case 'Q': case 'q': done = true; cout << "Goodbye" << endl; break; default: cout << "Bad command option." << endl; } // end switch } while (!done); return 0; } */ //end of comment out working main //////////////////////////////////////// // A giant, insane test main int main(int argc, char *argv[]){ string progname = argv[0]; string outputname = progname + ".out"; cout << outputname << endl; ofstream OUTPUT; OUTPUT.open(outputname.c_str()); if (!OUTPUT){ cerr << "Crap! Output file creation failed" << endl; exit(1); } int points = 100; OUTPUT << "Testing Customer::Customer " << endl; Customer * cPtr= new Customer; if (cPtr->getNextCustomer() != NULL){ OUTPUT << "-3 ERR: nextCustomer is not null." << endl; points -= 3; cout << "Customer::Customer failed" << endl; } delete (cPtr); string name = "Clay"; string email = "clay@cs.georgetown.edu"; OUTPUT << "Testing Customer::Customer(string) " << endl; cPtr= new Customer(name, email); if (cPtr->getNextCustomer() != NULL){ OUTPUT << "-3 ERR: nextCustomer is not null." << endl; points -= 3; cout << "Customer::Customer(string) failed" << endl; } OUTPUT << "Testing Customer::setNextCustomer: " << endl; Customer * c2Ptr = new Customer; cPtr->setNextCustomer(c2Ptr); if (cPtr->getNextCustomer() != c2Ptr){ OUTPUT << "-3 ERR: nextCustomer is " << cPtr << " but it should be " << c2Ptr << endl; points -= 3; cout << "Customer::setNextCustomer failed" << endl; } CustomerList list; OUTPUT << "Testing customerList constructor and showList" << endl; cout << "Testing customerList constructor and showList" << endl; cout << "Shouldn't crash, but should there should be nothing before the line" << endl; list.showList(); cout << "----------------------------------------------------------------" << endl; cout << "Was the result correct (y/n): "; char correct; cin >> correct; if ((correct == 'n')||(correct == 'N')){ OUTPUT << "-5 ERR:CustomerList constructor failed." << endl; points -= 5; } // test add customers OUTPUT << "Testing addCustomer and showList" << endl; list.addCustomer("clay@cs.georgetown.edu","Clay"); list.addCustomer("quinn@cs.georgetown.edu","Quinn"); list.addCustomer("alex@cs.georgetown.edu","Alex"); // test show list OUTPUT << "Testing addCustomer and ShowList" << endl; cout << "To pass, the output should contain these three items (order doesn't matter)" << endl << endl; cout << setw(10) << "Alex" << setw(25) << "alex@cs.georgetown.edu" << endl; cout << setw(10) << "Quinn" << setw(25) << "quinn@cs.georgetown.edu" << endl; cout << setw(10) << "Clay" << setw(25) << "clay@cs.georgetown.edu" << endl; cout << "----------------------------------------------------------------" << endl; list.showList(); cout << endl << endl; cout << "Was the result correct (y/n): "; cin >> correct; if ((correct == 'n')||(correct == 'N')){ OUTPUT << "-18 ERR: addCustomer or showList failed." << endl; points -= 18; cout << "Other tests may be invalid. :(" << endl; } // test show emails OUTPUT << "Testing showEmails." << endl; cout << "To pass, the output should contain these three items (order doesn't matter)" << endl << endl; cout << setw(25) << "alex@cs.georgetown.edu" << endl; cout << setw(25) << "quinn@cs.georgetown.edu" << endl; cout << setw(25) << "clay@cs.georgetown.edu" << endl; cout << "----------------------------------------------------------------" << endl; list.showEmails(); cout << "Was the result correct (y/n): "; cin >> correct; if ((correct == 'n')||(correct == 'N')){ OUTPUT << "-6 ERR: showEmails failed." << endl; points -= 6; } // test show names OUTPUT << "Testing showNames." << endl; cout << "To pass, the output should contain these three items (order doesn't matter)" << endl << endl; cout << setw(10) << "Alex" << endl; cout << setw(10) << "Quinn" << endl; cout << setw(10) << "Clay" << endl; cout << "----------------------------------------------------------------" << endl; list.showNames(); cout << "Was the result correct (y/n): "; cin >> correct; if ((correct == 'n')||(correct == 'N')){ OUTPUT << "-6 ERR: showNames failed." << endl; points -= 6; } // test countNameAppearances bool pass = true; OUTPUT << "Testing countNameAppearances: " << endl; list.addCustomer("alex@cs.georgetown.edu","Alex"); list.addCustomer("alex@cs.georgetown.edu","Alex"); int count = list.countNameAppearances("Alex"); if (count != 3) { OUTPUT << "ERR: countNameAppearances should have returned 3, but it returned: " << count << endl; pass = false; } if (pass) { count = list.countNameAppearances("Clay"); if (count != 1) { OUTPUT << "ERR: countNameAppearances should have returned 1, but it returned: " << count << endl; pass = false; } } if (pass) { count = list.countNameAppearances("Wally"); if (count != 0) { OUTPUT << "ERR: countNameAppearances should have returned 0, but it returned: " << count << endl; pass = false; } } if (!pass){ OUTPUT << "-8 ERR: Failure" << endl; points -= 8; } // test countEmailAppearances pass = true; OUTPUT << "Testing countEmailAppearances: " << endl; count = list.countEmailAppearances("alex@cs.georgetown.edu"); if (count != 3) { OUTPUT << "ERR: countEmailAppearances should have returned 3, but it returned: " << count << endl; pass = false; } if (pass) { count = list.countEmailAppearances("clay@cs.georgetown.edu"); if (count != 1) { OUTPUT << "ERR: countEmailAppearances should have returned 1, but it returned: " << count << endl; pass = false; } } if (pass) { count = list.countEmailAppearances("wally@cs.georgetown.edu"); if (count != 0) { OUTPUT << "ERR: countEmailAppearances should have returned 0, but it returned: " << count << endl; pass = false; } } if (!pass){ OUTPUT << "-8 ERR: Failure" << endl; } // Testing delete customer OUTPUT << "Testing Delete Customer" << endl; pass = true; count = list.deleteCustomer("alex@cs.georgetown.edu"); if (count != 3){ cout << "ERR: deleteCustomer should have returned 3, but it returned: " << count << endl; pass = false; } count = list.deleteCustomer("clay@cs.georgetown.edu"); if (count != 1){ cout << "ERR: deleteCustomer should have returned 1, but it returned: " << count << endl; pass = false; } if (pass){ cout << "If there was no crash, then it is a good sign" << endl; cout << "To pass, the output should contain only this item:" << endl << endl; cout << setw(10) << "Quinn" << setw(25) << "quinn@cs.georgetown.edu" << endl; cout << "----------------------------------------------------------------" << endl; list.showList(); cout << "Was the result correct (y/n): "; cin >> correct; if ((correct == 'n')||(correct == 'N')){ pass = false; OUTPUT << "ERR: something else was wrong" << endl; } cout << endl << endl; } if (!pass){ OUTPUT << "-12 ERR: Failure" << endl; } // Test load file OUTPUT << "Testing loadFile" << endl; CustomerList newList; newList.loadFile("p5-test-data.txt"); pass = true; count = newList.countEmailAppearances("alex@bornsoon.com"); if (count != 2) { OUTPUT << "ERR: countEmailAppearances should have returned 2, but it returned: " << count << endl; pass = false; } if (pass) { cout << "To pass, the output should contain these four items (order doesn't matter)" << endl << endl; cout << setw(10) << "Alex" << setw(25) << "alex@bornsoon.com" << endl; cout << setw(10) << "Quinn" << setw(25) << "quinn@cs.aol.com" << endl; cout << setw(10) << "Clay" << setw(25) << "clay@cs.georgetown.edu" << endl; cout << setw(10) << "Alex Bob" << setw(25) << "alex@bornsoon.com" << endl; cout << "----------------------------------------------------------------" << endl; newList.showList(); cout << "Was the result correct (y/n): "; cin >> correct; if ((correct == 'n')||(correct == 'N')){ pass = false; } } if (!pass){ OUTPUT << "-15 ERR: loadFile seems to have failed" << endl; points -= 15; } if (pass){ newList.loadFile("p5-test-data.txt"); count = newList.countEmailAppearances("alex@bornsoon.com"); if (count != 2) { OUTPUT << "-5 ERR: loadFile doesn't clear the list before a new load " << count << endl; points -= 5; } } OUTPUT << "Testing CustomerList(string)" << endl; CustomerList finalList("p5-test-data.txt"); pass = true; count = finalList.countEmailAppearances("alex@bornsoon.com"); if (count != 2) { OUTPUT << "ERR: countEmailAppearances should have returned 2, but it returned: " << count << endl; pass = false; } if (pass) { cout << "To pass, the output should contain these four items (order doesn't matter)" << endl << endl; cout << setw(10) << "Alex" << setw(25) << "alex@bornsoon.com" << endl; cout << setw(10) << "Quinn" << setw(25) << "quinn@cs.aol.com" << endl; cout << setw(10) << "Clay" << setw(25) << "clay@cs.georgetown.edu" << endl; cout << setw(10) << "Alex Bob" << setw(25) << "alex@bornsoon.com" << endl; cout << "----------------------------------------------------------------" << endl; finalList.showList(); cout << "Was the result correct (y/n): "; cin >> correct; if ((correct == 'n')||(correct == 'N')){ pass = false; } } if (!pass){ OUTPUT << "-5 ERR: CustomerList(string) seems to have failed" << endl; points -= 5; } if (pass){ finalList.loadFile("p5-test-data.txt"); count = finalList.countEmailAppearances("alex@bornsoon.com"); if (count != 2) { OUTPUT << "-2 ERR: CustomerList(string) doesn't clear the list before a new load " << count << endl; points -= 2; } } OUTPUT << "Final points: " << points << endl << endl; } //////////////////////////////////////// // print the menu so users know what options they have void print_menu(){ cout << endl << endl; cout << "Menu options:" << endl; cout << setw(50) << "Load a file:" << setw(3) << "L" << endl; cout << setw(50) << "Show file contents:" << setw(3) << "S" << endl; cout << setw(50) << "Show all emails:" << setw(3) << "R" << endl; cout << setw(50) << "Show all names:" << setw(3) << "M" << endl; cout << setw(50) << "Count name appearances:" << setw(3) << "C" << endl; cout << setw(50) << "Count email appearances:" << setw(3) << "V" << endl; cout << setw(50) << "Add a customer:" << setw(3) << "A" << endl; cout << setw(50) << "Delete an customer:" << setw(3) << "D" << endl; cout << setw(50) << "Exit:" << setw(3) << "X" << endl << endl; cout << "Your choice: "; } //////////////////////////////////////// void print_vector(vector vec){ for (int i = 0; i < vec.size(); i++){ cout << setw(40) << vec[i] << endl; } }