CPhoneBook07
Home ] Up ]

 

//PhoneBook07.cpp

// 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 * addressOfAt(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);
    CPhoneEntry * searchByName(char name[]);
    void sortByName(void);
    bool isSortedByName(void);
    void displayReverse(void);
    void displayReverse2(void);

    bool insert(CPhoneEntry entry);
    bool modifyPhone(char name[], char newPhone[]);
    friend ostream & operator << (ostream &os, const CPhoneBook &list);
  };



//CPhoneEntry * CPhoneBook::addressOfAt(int pos)
//Returns the address of node at position [0 to count-1]
//Possibilities   return
//Empty list      NULL
//pos=0           address of first node
//pos 0-count-1   address of the node by advancing pos times
//pos >= count    NULL

CPhoneEntry * CPhoneBook::addressOfAt(int pos)
  {
  if (count <= 0)
      return NULL;
  if (pos < 0)
      return NULL;
  if (pos >= count)
      return NULL;

  CPhoneEntry *p;
  p = first;

  for (int steps=0; steps<pos; steps++)
    p = p->next;

  return p;
  }

//void CPhoneBook::displayReverse(void)
/* build an array of pointers of size count
   use this array in reverse order to display the contents
*/
void CPhoneBook::displayReverse2(void)
  {
  cout << "count = " << count << endl;
  for (int pos=count-1; pos>=0; pos--)
    {
    CPhoneEntry *p = addressOfAt(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');
    b1.display();
    b1.displayReverse2();
    }
  }


//void CPhoneBook::displayReverse(void)
/* build an array of pointers of size count
   use this array in reverse order to display the contents
*/
void CPhoneBook::displayReverse(void)
  {
  CPhoneEntry *p;
  cout << "count = " << count << endl;
  for (int pos=count; pos>0; pos--)
    {
    p = first;
    for (int steps=1; steps<pos; 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');
    b1.display();
    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;

  /*
  char tName[MAX_LEN+1];
  char tPhone[14+1];
  char tGroup[10+1];
  int  tKey;
  */


  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();

  }