Untitled

mail@pastecode.io avatar
unknown
plain_text
2 years ago
8.2 kB
6
Indexable
Never
 /*
 *  ContactList.cpp
 *
 *  Interviewer:
 *  Candidate:
 */

#include <string>
#include <iostream>
#include "console.h"
#include "simpio.h"
#include "strlib.h"
#include "hashcode.h"

using namespace std;

class ContactList {
public:
    /*
     * Contructor for ContactList
     */
    ContactList();

    /*
     * Destructor for ContactList
     */
    ~ContactList();

    /*
     * Method: putContact
     * Usage: list.putContact("NAME", "###-####", "BIRTHDAY");
     * ---------------------------
     * Places a contact with a name, phone number, and birthday, into the ContactList.
     * If a phone number is not in the format ###-####, insert “unknown” as the phone
     * number for the contact, instead of the inputted number.
     * Assume that all birthday strings entered are valid. Also, assume that no two users
     * in the ContactList will ever have the same name, and that names are case sensitive.
     */
    void putContact(string name, string number, string birthday);

    /*
     * Method: printContact
     * Usage: list.printContact("NAME");
     * ---------------------------
     * Prints and returns the birthday and phone number of a contact.
     * Format must look like this:
     * "Contact: CONTACT, Phone Number: NUMBER, Birthday: BIRTHDAY"
     *
     * If contact not in list return the following string: "Contact not found."
     */
    string printContact(string name);

    /*
     * Method: changePhoneNumber
     * Usage: list.changePhoneNumber("NAME", ###-####);
     * ---------------------------
     * Changes the phone number associated with a contact.
     * If a phone number is not in the format ###-####, insert “unknown” as the phone
     * number for the contact, instead of the inputted number.
     * If the contact is not in the ContactList, throw any string literal exception.
     */
    void changePhoneNumber(string name, string number);

private:
    struct HashNode {
        string number;
        string birthday;
        string name;
        HashNode *next;
    };

    HashNode** table;

    const int NUM_BUCKETS = 1000;
    int hashCode(string key);

    void deleteLinkedList(HashNode* head);
    HashNode* getTail(HashNode* head);
    string validateNumber(string number);
    // TODO add private members and function declarations here
};

// TODO implement public (and optional private) functions below

ContactList::ContactList(){
    /* TODO: Your implementation here */
    table = new HashNode*[NUM_BUCKETS];
    for (int i = 0; i < NUM_BUCKETS; i++) {
        table[i] = nullptr;
    }
}

ContactList::~ContactList(){
    /* TODO: Your implementation here */
    for (int i = 0; i < NUM_BUCKETS; i++) {
        deleteLinkedList(table[i]);
    }
    delete table;
}

void ContactList::deleteLinkedList(HashNode* head) {
    HashNode* temp;
    while (head->next) {
        temp = head;
        head = head->next;
    }
}

string ContactList::validateNumber(string number) {
    if (number.size() != 8) return "unknown";
    for (char c: number.substr(0, 3)) {
        if (!isdigit(c)) return "unknown";
    }

    if (number[3] != "-") return "unknown";

    for (char c: number.substr(4, 4)) {
        if (!isdigit(c)) return "unknown";
    }

    return number;
}

int ContactList::hashCode(string key) {
      int hashVal = 0;
      for (int i = 0; i <= key.length(); i++) {
         hashVal = (127 * hashVal + key[i]) % NUM_BUCKETS;
      }
      return hashVal;
}

void ContactList::putContact(string name, string number, string birthday){
    HashNode* newNode = new HashNode();

    newNode->number = validateNumber(number);
    newNode->birthday = birthday;
    newNode->name = name;
    newNode->next = nullptr;
    HashNode* head = table[hashCode(name)];

    if (head == nullptr) {
        table[hashCode(name)] = newNode;
    }


    else {
        HashNode* temp = head->next;
        while (temp) {
            head = head->next;
            temp = temp->next;
        }
        temp->next = newNode;
    }

}

string ContactList::printContact(string name){
    /* TODO: Your implementation here */
    HashNode* head = table[hashCode(name)];
    string output = "Contact not found.";
    while (head) {
        if (head->name == name) {
            output = "Contact: " + head->name + ", Phone Number: " + head->number + ", Birthday: " + head->birthday;
            cout << output << endl;
        }
        head = head.next;
    }

//  "Contact: CONTACT, Phone Number: NUMBER, Birthday: BIRTHDAY"

    return output;
}

void ContactList::changePhoneNumber(string name, string number){
    /* TODO: Your implementation here */
    HashNode* head = table[hashCode(name)];
    while (head) {
        cout << "CORRECT NAME: " << name << endl;
        cout << head->name << endl;
        if (head->name == name) {
            head->number = validateNumber(number);
            return;
        }
        head = head->next;

    }

    error("string literal error");
}




/* ------------------------------------------------------------------------------
 * Code beyond this line is a bug-free test harness. You may edit code below this line
 * if desired to add tests, but there are no bugs that need to be fixed in the section
 * below.
 * ------------------------------------------------------------------------------
 */

void confirmPrint(ContactList& list, string expectedName, string expectedNumber, string expectedBirth, bool found) {
    bool passed;
    if (!found) {
        cout << "Expected output: " << "Contact not found." << endl << "Student output: ";
        passed = list.printContact(expectedName) == "Contact not found.";
    } else {
        stringstream ss;
        ss << "Contact: " << expectedName;
        ss << ", Phone Number: " << expectedNumber;
        ss << ", Birthday: " << expectedBirth;
        cout << "Expected output: " << ss.str() << endl << "Student output: ";
        passed = list.printContact(expectedName) == ss.str();
    }

    if (passed) {
        cout << "TEST CASE PASSED!" << endl;
    } else {
        cout << "TEST CASE FAILED!" << endl;
    }
}

int main() {
    string testnames [6] = {"Lisa", "Shubham", "David", "Jeremiah", "Clyde", "Kate"};
    string testnumbers [6] = {"666-7777", "408-625-4897", "443-8856", "494-89565", "563-8425", "i forgot"};
    string testbirths [6] = {"1/23/1997", "8/21/1965", "4/7/1983", "8/21/1993", "9/21/2000", "5/4/1995"};

    ContactList list;

    cout << "Test Case 1: Add one contact." << endl;
    list.putContact(testnames[0], testnumbers[0], testbirths[0]);
    confirmPrint(list, testnames[0], testnumbers[0], testbirths[0], true);
    cout << endl << endl;

    cout << "Test Case 2: Add one contact with an invalid phone number." << endl;
    list.putContact(testnames[1], testnumbers[1], testbirths[1]);
    confirmPrint(list, testnames[1], "unknown",  testbirths[1], true);
    cout << endl << endl;

    cout << "Test Case 3: Checking for a nonexistent contact." << endl;
    confirmPrint(list, "Jerry", "", "", false);
    cout << endl << endl;

    cout << "Test Case 4: Adding some more contacts." << endl;
    for (int i = 2; i < 6; i++) {
        list.putContact(testnames[i], testnumbers[i], testbirths[i]);
    }
    for (int i  = 2; i < 6; i++) {
        confirmPrint(list, testnames[i], i % 2 == 0 ? testnumbers[i] : "unknown", testbirths[i], true);
    }
    cout << endl << endl;

    cout << "Test Case 5: Changing one phone number to something valid." << endl;
    list.changePhoneNumber(testnames[5], testnumbers[0]);
    confirmPrint(list, testnames[5], testnumbers[0], testbirths[5], true);
    cout << endl << endl;

    cout << "Test Case 6: Changing one phone number to something invalid." << endl;
    list.changePhoneNumber(testnames[4], testnumbers[1]);
    confirmPrint(list, testnames[4], "unknown", testbirths[4], true);
    cout << endl << endl;

    cout << "Test Case 7: Changing every phone number." << endl;
    for (int i = 2; i < 6; i++) {
        list.changePhoneNumber(testnames[5-i], testnumbers[i]);
    }
    for (int i = 2; i < 6; i++) {
        confirmPrint(list, testnames[5-i], i % 2 == 0 ? testnumbers[i] : "unknown", testbirths[5-i], true);
    }
    cout << endl << endl;

    return 0;
}