Include Iostream, String, Fstream Using Namespace

Include Iostreaminclude Stringinclude Fstreamusing Name

Include Iostreaminclude Stringinclude Fstreamusing Name

include #include #include using namespace std; struct Address { int streetNumber; string street; string streetType; string city; string state; int zipcode; }; struct Contact { string firstName; string lastName; Address address; string phoneNumber; string emailAddress; string twitterHandle; Contact next; Contact prev; }; enum sortBy{ FIRST = 1, LAST, STREET, CITY, STATE, PHONE, EMAIL, TWITTER }; Contact loadList(string fileName); Contact remove_(Contact contact); Contact insert_(Contact contact); void saveList(Contact head, string fileName); Contact navigateRolodex(Contact start, Contact end); void displayContact(Contact contact); Contact search(Contact head); void addContact(Contact & head); void removeContact(Contact & head); void sort(Contact & head); int main() { string fileName = "contacts.txt"; Contact rolodex = loadList(fileName); if (rolodex != nullptr) { int command = 0; while (command != 6) { cout > command; switch (command) { case 1: navigateRolodex(rolodex, nullptr); break; case 2: search(rolodex); break; case 3: sort(rolodex); break; case 4: addContact(rolodex); break; case 5: removeContact(rolodex); break; case 6: break; default: cout loadList(string fileName) { ifstream fin; fin.open(fileName); if (!fin.is_open() && !fin.eof()) { cout head = nullptr; Contact currNode = head; Contact temp = nullptr; while (!fin.eof()) { temp = new Contact; temp->next = nullptr; temp->prev = nullptr; fin >> temp->firstName; fin >> temp->lastName; fin >> temp->address.streetNumber; fin >> temp->address.street; fin >> temp->address.streetType; fin >> temp->address.city; fin >> temp->address.state; fin >> temp->address.zipcode; fin >> temp->phoneNumber; fin >> temp->emailAddress; fin >> temp->twitterHandle; temp = remove_(temp); if (currNode == nullptr) { head = temp; currNode = head; } else { currNode->next = temp; temp->prev = currNode; currNode = currNode->next; } } fin.close(); return head; } //removes underscores from street name and city name Contact remove_(Contact contact) { for (int i = 0; i address.street.size(); i++) { if (contact->address.street[i] == '_') contact->address.street[i] = ' '; } for (int i = 0; i address.city.size(); i++) { if (contact->address.city[i] == '_') contact->address.city[i] = ' '; } return contact; } //replace spaces with underscores. Contact insert_(Contact contact) { for (int i = 0; i address.street.size(); i++) { if (contact->address.street[i] == ' ') contact->address.street[i] = '_'; } for (int i = 0; i address.city.size(); i++) { if (contact->address.city[i] == ' ') contact->address.city[i] = '_'; } return contact; } void saveList(Contact head, string fileName) { ofstream fout; fout.open(fileName); Contact currNode = head; while (currNode != nullptr) { currNode = insert_(currNode); fout firstName lastName address.streetNumber address.street address.streetType address.city address.state address.zipcode phoneNumber emailAddress twitterHandle; if (currNode->next != nullptr) cout next; } fout.close(); } Contact navigateRolodex(Contact start, Contact end) { //can't start navigating from nowhere. if (start == nullptr) return nullptr; //when end is nullptr, we want to go to the end of the list //so we need to change end to the last item of the list. if (end == nullptr) { end = start; while (end->next != nullptr) { end = end->next; } } Contact currContact = start; char command = ' '; while (command != 'q') { system("CLS"); displayContact(currContact); cout >"; cin >> command; switch (command) { case 'p': if (currContact != start) { currContact = currContact->prev; } break; case 'n': if (currContact != end) { currContact = currContact->next; } break; case 'q': break; default: cout contact) { cout firstName lastName address.streetNumber address.street address.streetType address.city address.state address.zipcode phoneNumber emailAddress twitterHandle & head) { //create new contact and make new head. Contact temp = new Contact; temp->next = head; temp->prev = nullptr; head->prev = temp; head = temp; //get information cout > temp->firstName >> temp->lastName; cout > temp->address.streetNumber >> temp->address.street >> temp->address.streetType; cout > temp->address.city; do { cout > temp->address.state; } while (temp->address.state.size() != 2); cout > temp->address.zipcode; cout > temp->phoneNumber; cout > temp->emailAddress; cout > temp->twitterHandle; remove_(temp); cout & head) { cout toDelete = search(head); if (toDelete != nullptr) { system("CLS"); cout > command; if (command == 'y' || command == 'Y') { if (toDelete == head) head = toDelete->next; if (toDelete->next != nullptr) toDelete->next->prev = toDelete->prev; if (toDelete->prev != nullptr) toDelete->prev->next = toDelete->next; delete toDelete; cout & head, Contact & contact1, Contact contact2) { //deal with head. if (contact1 == head) { head = contact2; } else if (contact2 == head) { head = contact1; } //take care of other things pointing at swappers, but only if they are not adjacent. . . if (contact1->next != nullptr && contact1->next != contact2) contact1->next->prev = contact2; if (contact2->next != nullptr && contact2->next != contact1) contact2->next->prev = contact1; if (contact1->prev != nullptr && contact1->prev != contact2) contact1->prev->next = contact2; if (contact2->prev != nullptr && contact2->prev != contact1) contact2->prev->next = contact1; //take care of swappers previous and next if (contact1->next == contact2) //adjacent, option 1 { contact1->next = contact2->next; contact2->next = contact1; contact2->prev = contact1->prev; contact1->prev = contact2; } else if (contact2->next == contact1) //adjacent, option 2 { contact2->next = contact1->next; contact1->next = contact2; contact1->prev = contact2->prev; contact2->prev = contact1; } else // not adjacent { Contact temp = contact1->next; contact1->next = contact2->next; contact2->next = temp; temp = contact1->prev; contact1->prev = contact2->prev; contact2->prev = temp; } contact1 = contact2; } void sort(Contact & head, sortBy sortKey) { Contact sorted = head; Contact currContact = nullptr; Contact smallest = nullptr; while (sorted != nullptr) { currContact = sorted; smallest = sorted; //find smallest while (currContact != nullptr) { bool smallestContact = false; switch (sortKey) { case FIRST: if (currContact->firstName firstName) smallestContact = true; break; case LAST: if (currContact->lastName lastName) smallestContact = true; break; case STREET: { string fullAddress = to_string(currContact->address.streetNumber) + " " + currContact->address.street + " " + currContact->address.streetType; string smallestFullAddress = to_string(smallest->address.streetNumber) + " " + smallest->address.street + " " + smallest->address.streetType; if (fullAddress address.city address.city) smallestContact = true; break; case STATE: if (currContact->address.state address.state) smallestContact = true; break; case PHONE: if (currContact->phoneNumber phoneNumber) smallestContact = true; break; case EMAIL: if (currContact->emailAddress emailAddress) smallestContact = true; break; case TWITTER: if (currContact->twitterHandle twitterHandle) smallestContact = true; break; } if (smallestContact) { smallest = currContact; } currContact = currContact->next; } //swap swap(head, sorted, smallest); sorted = sorted->next; } } void sort(Contact & head) { system("CLS"); cout > command; if (command != 9) sort(head, (sortBy)command); } Contact search(Contact head) { system("CLS"); //options are same as sortBy enum!!! cout > command; if (command != 9) { //sort the list sort(head, (sortBy)command); cout > searchString; //search the list Contact start = nullptr, end = nullptr, *currContact = head; bool found; do { found = false; switch (command) { case 1: if (currContact->firstName == searchString) found = true; break; case 2: if (currContact->lastName == searchString) found = true; break; case 3: { string fullAddress = to_string(currContact->address.streetNumber) + " " + currContact->address.street + " " + currContact->address.streetType; if (fullAddress == searchString) found = true; break; } case 4: if (currContact->address.city == searchString) found = true; break; case 5: if (currContact->address.state == searchString) found = true; break; case 6: if (currContact->phoneNumber == searchString) found = true; break; case 7: if (currContact->emailAddress == searchString) found = true; break; case 8: if (currContact->twitterHandle == searchString) found = true; break; } if (found) { if (start == nullptr) { start = currContact; end = currContact; //in case there is only one. . . } else { end = currContact; } } currContact = currContact->next; } while ((end == nullptr || found == true) && currContact != nullptr); if (start == nullptr && end == nullptr) { cout

Paper For Above instruction

The provided code sketch illustrates a comprehensive implementation of a digital rolodex—an electronic contact management system—using C++. The core components involve data organization, file handling, user interaction, and contact management functionalities, which altogether exemplify important programming concepts such as linked list manipulation, file I/O, and user-centered design.

Introduction

The digital rolodex serves as a modern evolution of traditional paper-based contact management tools. This implementation utilizes doubly linked lists to enable efficient navigation, addition, deletion, and sorting of contact entries. Persistent storage is handled via file operations, allowing users to save and load their contact data across sessions. The program also offers a user-friendly menu-driven interface for navigating through contacts, searching, sorting, adding, and removing entries.

Data Structures and Object Modeling

At the heart of the design are two structures: Address and Contact. The Address contains physical location details, including street number, street name, city, state, and zipcode. The Contact encompasses personal data—name, contact details, social media handle—and an Address object, creating a composite data model. The linked list is doubly linked, with each Contact node holding pointers to previous and next nodes, enabling bidirectional traversal critical for navigation functions.

File Handling and Data Persistence

The functions loadList and saveList manage reading from and writing to a data file named "contacts.txt". Contacts are loaded into the linked list via sequential file reads, where each contact's data fields are parsed and stored. The save operation writes contact data back into the file, utilizing underscore-to-space conversions to maintain data integrity for addresses. These functionalities emphasize the importance of file stream manipulation, error handling, and data formatting techniques.

Core Functionalities

Navigation

The navigateRolodex function allows users to traverse contacts forward and backward within the linked list. Its user interface prompts for commands ('p' for previous, 'n' for next, 'q' to quit), and updates the current contact accordingly. This traversal leverages the doubly linked nature of the list, illustrating effective pointer usage and control flow in interactive applications.

Display

The displayContact function outputs the contact's details in a formatted manner, aiding user comprehension. Formatting involves concatenating address components and displaying contact info clearly, ensuring data is accessible and easy to interpret.

Adding New Contacts

The addContact function dynamically creates a new contact node, links it as the new head of the list, and prompts users for input. Address components and other details are collected via input streams, with validation—for instance, confirming the second letter of the state abbreviation. The function also converts spaces to underscores for address strings, which facilitates file storage compatibility.

Removing Contacts

The removeContact function initiates a search process to locate a contact, then confirms deletion with the user before removing the node from the list and freeing memory. Pointer adjustments ensure list integrity is maintained during deletion, exemplifying linked list management.

Sorting and Searching

The sort functions provide sorting capabilities based on different contact attributes, such as name, address, phone number, etc. The sort procedure employs a selection sort algorithm, repeatedly finding the smallest element according to the chosen key and swapping nodes. The search function sorts the list before performing linear searches on user-defined criteria, coupled with navigation