|
//PhoneBook09.cpp // insertAtHead added 09 11/27/2000 // searchByName added // void swap(p,q) added // void swap(e1,e2) added // bool isSortedByName() added 06 11/08/2000 // void sortByName(void); added 05 //Overload << for output added 04 //Constructor CPhoneBook(ch) added 03 //////////////////////////////////////////////////////////// // project #6 Date Assigned 11/8/2000, Date Due 11/17/2000 // describe ten shuffling methods (20) // implement one of the ten methods (20) // write the testShuffle (10) // Five test runs (10) //////////////////////////////////////////////////////////// //include files //////////////////////////////////////////////////////////// #include <iostream.h> #include <string.h> #include <stdlib.h> //////////////////////////////////////////////////////////// //constants //////////////////////////////////////////////////////////// int const MAX_LEN = 10; int const MAX_COUNT = 10; int const TEST_COUNT = 5; //////////////////////////////////////////////////////////// //global variables //////////////////////////////////////////////////////////// int masterKey = 1; //////////////////////////////////////////////////////////// //test values //////////////////////////////////////////////////////////// const char *testNames[] = {"Bob", "Tom", "Ann", "Ron", "Ben", "Ken", "Rob", "Sam", "Don", "Dan", "Tim"}; const int MAX_NAMES = sizeof(testNames)/sizeof(testNames[0]); const char *testPhones[] = {"111-1111", "222-2222", "333-3333", "444-4444"}; const int MAX_PHONES = sizeof(testPhones)/sizeof(testPhones[0]); const char *testGroups[] = {"Group1", "Group2", "Group3", "Group4"}; const int MAX_GROUPS = sizeof(testGroups)/sizeof(testGroups[0]); //////////////////////////////////////////////////////////// //CPhoneEntry //////////////////////////////////////////////////////////// struct CPhoneEntry { char name[MAX_LEN+1]; char phone[14+1]; char group[10+1]; int key; CPhoneEntry *next; }; //////////////////////////////////////////////////////////// //CPhoneBook //////////////////////////////////////////////////////////// class CPhoneBook { private: CPhoneEntry *first; CPhoneEntry *last; int count; CPhoneEntry * addressOfEntryAt(int pos); public: CPhoneBook(void); bool insertAtEnd(char name[], char phone[], char group[], int key); void display(void); void deleteAll(void); ~CPhoneBook(void); CPhoneBook(char ch); void sortByName(void); bool isSortedByName(void); void displayReverse(void); void displayReverse2(void); friend ostream & operator << (ostream &os, const CPhoneBook &list); CPhoneEntry * searchByName(char name[]); bool insertAtHead(char name[], char phone[], char group[], int key); bool deleteByAddress(CPhoneEntry *p); bool deleteByName(char name[]); int deleteAllByName(char name[]); bool deleteByPosition(int pos); bool searchReplaceByName(char nameOld[], char nameNew[]); int searchReplaceAllByName(char nameOld[], char nameNew[]); int deleteDuplicates(void); }; //////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////// void testInsertAtHead(void) { { CPhoneBook myBook; myBook.display(); myBook.insertAtHead("John", "231-7000", "friend", 1); myBook.display(); myBook.insertAtHead("Tom", "231-7001", "enemy", 1); myBook.display(); } } bool CPhoneBook::insertAtHead(char name[], char phone[], char group[], int key) { CPhoneEntry *p; p = new CPhoneEntry; if (NULL == p) return false; strcpy(p->name, name); strcpy(p->phone, phone); strcpy(p->group, group); p->key = key; if (NULL == first) { first = p; last = p; p->next = NULL; } else { p->next = first; first = p; } count++; return true; } // p=first // if the found return p // else advance p and go to prev statement /* p = first while p <> NULL if at p the name we are looking for then return p else advance p end while return NULL */ void testSearchByName(void) { CPhoneBook b1('r'); char tName[MAX_LEN+1]; cout << b1; for (int i=1; i<=TEST_COUNT; i++) { strcpy(tName, testNames[rand()%MAX_NAMES]); cout << tName << " is at " << b1.searchByName(tName) << endl; } } CPhoneEntry * CPhoneBook::searchByName(char name[]) { CPhoneEntry *p; p = first; while (p != NULL) { if ((strcmp(p->name, name)==0)) return p; else p = p->next; } return NULL; } //CPhoneEntry * CPhoneBook::addressOfEntryAt(int pos) //Returns the address of node at position [0 to count-1] //Possibilities return //------------- ------ //Empty list NULL //Nonempty // pos=0 address of first node // pos [0,count-1] address of the node by advancing pos times // pos >= count NULL CPhoneEntry * CPhoneBook::addressOfEntryAt(int pos) { if (count <= 0) return NULL; if (pos < 0) return NULL; if (pos >= count) return NULL; CPhoneEntry *p; p = first; for (int steps=1; steps<=pos; steps++) p = p->next; return p; } //void CPhoneBook::displayReverse(void) void CPhoneBook::displayReverse2(void) { for (int pos=count-1; pos>=0; pos--) { CPhoneEntry *p; //better if put outside the loop p = addressOfEntryAt(pos); cout << p->name << ", "; cout << p->phone << ", "; cout << p->group << ", "; cout << p->key << endl; } cout << endl; } //////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////// void testDisplayReverse2(void) { for (int i=1; i<=TEST_COUNT; i++) { cout << "Test #" << i << ": "; CPhoneBook b1('r'); cout << "Original\n"; b1.display(); cout << "Reverse\n"; b1.displayReverse2(); } } //void CPhoneBook::displayReverse(void) /* start from the first, display the last node start from the first, display next to the last for pos=count to 1 step -1 do the following point to first advance pointer pos-1 times display the pointed node */ void CPhoneBook::displayReverse(void) { CPhoneEntry *p; for (int pos=count; pos>0; pos--) { p = first; for (int steps=1; steps<=pos-1; steps++) p = p->next; cout << p->name << ", "; cout << p->phone << ", "; cout << p->group << ", "; cout << p->key << endl; } cout << endl; } //////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////// void testDisplayReverse(void) { for (int i=1; i<=TEST_COUNT; i++) { cout << "Test #" << i << ": "; CPhoneBook b1('r'); cout << "Original\n"; b1.display(); cout << "Reverse\n"; b1.displayReverse(); } } //////////////////////////////////////////////////////////// //swap the records //////////////////////////////////////////////////////////// void swap(CPhoneEntry &e1, CPhoneEntry &e2) { char tName[MAX_LEN+1]; char tPhone[14+1]; char tGroup[10+1]; int tKey; //plug the e1 and e2 at the right places strcpy(tName, e1.name); strcpy(e1.name, e2.name); strcpy(e2.name, tName); strcpy(tPhone, e1.phone); strcpy(e1.phone, e2.phone); strcpy(e2.phone, tPhone); strcpy(tGroup, e1.group); strcpy(e1.group, e2.group); strcpy(e2.group, tGroup); tKey = e1.key; e1.key = e2.key; e2.key = tKey; } //////////////////////////////////////////////////////////// //swap the records through the pointers //////////////////////////////////////////////////////////// void swap(CPhoneEntry *p, CPhoneEntry *q) { char tName[MAX_LEN+1]; char tPhone[14+1]; char tGroup[10+1]; int tKey; strcpy(tName, p->name); strcpy(p->name, q->name); strcpy(q->name, tName); strcpy(tPhone, p->phone); strcpy(p->phone, q->phone); strcpy(q->phone, tPhone); strcpy(tGroup, p->group); strcpy(p->group, q->group); strcpy(q->group, tGroup); tKey = p->key; p->key = q->key; q->key = tKey; } //////////////////////////////////////////////////////////// //bool CPhoneBook::isSortedByName(void) //////////////////////////////////////////////////////////// //Go from left to right //if a pair is found to be out of order //then return false else return true bool CPhoneBook::isSortedByName(void) { CPhoneEntry *p, *q; if (first == last) return true; p = first; q = p->next; while (q != NULL) { if ((strcmp(p->name, q->name)>0)) return false; p = q; // or p = p->next q = q->next; } return true; } //////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////// void testIsSortedByName(void) { //for (int i=0; i<TEST_COUNT; i++) // { CPhoneBook b1('r'); cout << "Original: " << b1; if (b1.isSortedByName()) cout << "The list is SORTED\n"; else cout << "The list is NOT SORTED\n"; b1.sortByName(); cout << "Sorted: "<< b1; if (b1.isSortedByName()) cout << "The list is SORTED\n"; else cout << "The list is NOT SORTED\n"; // } } //////////////////////////////////////////////////////////// //void CPhoneBook::sortByName(void) //////////////////////////////////////////////////////////// //Algorithm /* do the following check pairs from left to right and put them in order until no change in order of the list if first = last then exit function do the following set sorted = true p = first q = p->next while q <> null if name at p > name at q then swap records at p and q except the pointers sorted = false end if p = q or p = p->next q = q->next end while while not sorted */ void CPhoneBook::sortByName(void) { if (first == last) return; bool sorted; CPhoneEntry *p, *q; do { sorted = true; p = first; q = p->next; while (q != NULL) { if ((strcmp(p->name, q->name)>0)) { //swap records at p and q except the pointers //swap(p, q); //using pointers swap(*p, *q); //using records sorted = false; } p = q; // or p = p->next q = q->next; } } while (!sorted); } //////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////// void testSortByName(void) { //for (int i=0; i<TEST_COUNT; i++) // { CPhoneBook b1('r'); cout << "Original: " << b1; b1.sortByName(); cout << "Sorted: "<< b1; // } } //////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////// ostream & operator << (ostream &dan, const CPhoneBook &list) { CPhoneEntry *p; dan << "Phonebook[" << list.count << "]\n"; p = list.first; while (p != NULL) { dan << p->name << ", "; dan << p->phone << ", "; dan << p->group << ", "; dan << p->key << endl; p = p->next; }; return dan; } //////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////// void testOperatorOutput(void) { //for (int i=0; i<TEST_COUNT; i++) // { CPhoneBook b1('r'), b2('r'); cout << b1 << b2; // } } //////////////////////////////////////////////////////////// //Constructor for CPhoneBook //////////////////////////////////////////////////////////// //'r' random elements //'u' distinct random elements //'s' sorted list //'i' enter from the keyboard CPhoneBook::CPhoneBook(char ch) { cout << "constructor called\n"; count = 0; first = NULL; last = NULL; if ('r' == ch) { char rName[MAX_LEN+1]; char rPhone[14+1]; char rGroup[10+1]; int rKey; for(int n = rand()%(MAX_COUNT+1); n>0; n--) { strcpy(rName, testNames[rand()%MAX_NAMES]); strcpy(rPhone, testPhones[rand()%MAX_PHONES]); strcpy(rGroup, testGroups[rand()%MAX_GROUPS]); rKey = masterKey++; insertAtEnd(rName, rPhone, rGroup, rKey); } } } //////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////// void testCPhoneBookConstructor(void) { for (int i=0; i<TEST_COUNT; i++) { CPhoneBook b1('r'); b1.display(); } } //////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////// CPhoneBook::~CPhoneBook(void) { cout << "destructor called\n"; deleteAll(); } //////////////////////////////////////////////////////////// //void CPhoneBook::deleteAll(void) //////////////////////////////////////////////////////////// //deletes all the nodes from the linked list void CPhoneBook::deleteAll(void) { while (first != NULL) { last = first->next; delete first; first = last; } count = 0; } //////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////// void CPhoneBook::display(void) { CPhoneEntry *p; cout << "Phonebook[" << count << "]\n"; p = first; while (p != NULL) { cout << p->name << ", "; cout << p->phone << ", "; cout << p->group << ", "; cout << p->key << endl; p = p->next; }; } //////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////// bool CPhoneBook::insertAtEnd(char name[], char phone[], char group[], int key) { CPhoneEntry *p; p = new CPhoneEntry; if (NULL == p) return false; strcpy(p->name, name); strcpy(p->phone, phone); strcpy(p->group, group); p->key = key; p->next = NULL; if (NULL == first) { first = p; last = p; } else { last->next = p; last = p; } count++; return true; } //////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////// void testInsertAtEnd(void) { { CPhoneBook myBook; myBook.display(); myBook.insertAtEnd("John", "231-7000", "friend", 1); myBook.display(); myBook.insertAtEnd("Tom", "231-7001", "enemy", 1); myBook.display(); } { CPhoneBook yourBook; yourBook.display(); } } //////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////// CPhoneBook::CPhoneBook(void) { cout << "constructor called\n"; count = 0; first = NULL; last = NULL; } //////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////// void main(void) { //testInsertAtEnd(); //testCPhoneBookConstructor(); //testOperatorOutput(); //testSortByName(); //testIsSortedByName(); //testDisplayReverse(); //testDisplayReverse2(); testSearchByName(); //testInsertAtHead(); } |