   ### FILE tperxon.cpp 
// tperson.cpp - main to test/use Person class
#include "perx.hpp"

int main()
{
  char* temp = NULL;
  char  input[81] = "\n";
  int err = 0;                  // holds error code
  Person me;
  Person uncle("rogers", "fred");

  temp = get_person_data();     // get input
  err = me.update(temp);
  if (err) cerr << "Premature end of string" << endl;
  temp = me.display();
  cout << temp << endl;
  temp = uncle.display();
  cout << temp << endl;
  cin >> input;                 // wait ( to read screen)
  return 0;
}
   ### FILE get_perx.cpp
// get_pers.cpp - data input for person class update

#include <iostream.h>
#include <string.h>

//----- function prototypes
char* get_address_data(void);


char* get_person_data(void)
{
  // list of fields to be input
  // --- better if this were passed as a parameter
  char* fields[] =
  {
	 "Last Name    : ",
	 "First Name   : ",
	 "Age          : ",
	 "Worth        : "
  };

  char input[81] = "\0";                // for each input
  static char output[256] = "\0";       // to build/pass output
  int error = 0;                        // holds error code to return
  int k = 0;                            // loop control

  for (k = 0; k < sizeof(fields) / sizeof(char *); k++)
  {
		// for each input field ...
		cout << "Enter " << fields[k];
		cin.getline(input, sizeof(input), '\n');
		strcat(output, input);
		strcat(output, "\n");
  }
  strcat(output, get_address_data());   // get address stuff
  return output;
}


   ### FILE perxpbf.cpp
// perxpbf.cpp - public functions for class person
#include <string.h>
#include <stdlib.h>
#include <stdio.h>       // for sprint()

/* *** not needed except for inserter and extractor
	#include <iostream.h>
*/
#include "perx.hpp"

//-----CONSTRUCTORS

//------ default constructor

Person::Person(void)
{
  emptyValues();
}

//------ other constructors
Person::Person(char* ln, char* fn)
{
  emptyValues();
  strcpy(lastname, ln);
  strcpy(firstname, fn);
}

//-----ACCESSORS

char* Person::display(void)
{
  static char temp[256] = "\0";
  sprintf(temp, "%s %s\n %d\n %9.2f\n", firstname, lastname, age, worth);
  strcat(temp, home.display());
  return temp;
}


int Person::isOld(void)
{
  return (age > 64);
}

int Person::isRich(void)
{
  return (worth > 1000.00);
}

//-----MUTATORS
int Person::update(char* data)
{
	int error = 0;                          // returns error code
	char temp[1024] = "\n"; // holds copy of input (destroyed by strtok())
	char* tptr = NULL;              // holds pointer to token, returned from strtok()

	strcpy(temp, data);             // save a copy of input

	tptr = strtok(temp, "\n");              // (next) token - lastname
	if (tptr == NULL) return -1;    // premature end of string
	strcpy(lastname, tptr);                 // update field

	tptr = strtok(NULL, "\n");              // (next) token - firstname
	if (tptr == NULL) return -1;    // premature end of string
	strcpy(firstname, tptr);                        // update field

	tptr = strtok(NULL, "\n");              // (next) token - age
	if (tptr == NULL) return -1;    // premature end of string
	age = atoi(tptr);                                       // update field

	tptr = strtok(NULL, "\n");              // (next) token - worth
	if (tptr == NULL) return -1;    // premature end of string
	worth = (float) atof(tptr);             // update field

	tptr = tptr + strlen(tptr) + 1;    // point to address data
	error = home.update(tptr);              // and update address home

	return error;
}

/* **** not covered yet **********
	// IOSTREAM OPERATORS for class Person

	//----- inserter
	ostream& operator<< (ostream& s, Person& X)
	{
		cout    << X.lastname << endl
				<< X.age << endl
				<< X.worth << endl;
		return s;
	}

	//----- extractor
	istream& operator>> (istream& s, Person& X)
	{
	// ********incomplete *******
		return s;
	}
*/

// PRIVATE FUNCTIONS for class person
void Person::emptyValues(void)
{
  lastname[0] = '\0';
  firstname[0] = '\0';
  age = 0;
  worth = 0.0;
}



   ### FILE get_addr.cpp
// get_addr.cpp - data input for address class update

#include <iostream.h>
#include <string.h>

char* get_address_data(void)
{
  // list of fields to be input
  // --- better if this were passed as a parameter
  char* fields[] =
  {
	 "Street       : ",
	 "City         : ",
	 "Province     : ",
	 "Postal code  : ",
	 "Country      : "
  };

  char input[81] = "\0";                                // for each input
  static char output[256] = "\0";       // to build/pass output
  int error = 0;                                                        // holds error code to return
  int k = 0;                                                            // loop control

  for (k = 0; k < sizeof(fields) / sizeof(char *); k++)
  {
                // for each input field ...
                cout << "Enter " << fields[k];
                cin.getline(input, sizeof(input), '\n');
                strcat(output, input);
                strcat(output, "\n");
  }
  return output;
}

  
   ### FILE addrpbf.cpp 
// addrpbf.cpp - public function definitions for class Address

#include <stdio.h>              // for sprintf() only
#include <string.h>             // for strtok(), strcpy() etc
#include "addr.hpp"

//-----CONSTRUCTORS

//------ default constructor

Address::Address(void)
{
        emptyValues();
}

//------ other constructors

//-----ACCESSORS

char* Address::display(void)
{
        static char temp[256] = "\0";
        sprintf( temp, "%s\n%s\n%s\n%s\n%s\n",
                                        street, city, province, postcode, country);
        return temp;
}
//-----MUTATORS

int Address::update(char* data)
{
        int error = 0;                          // returns error code
        char temp[1024] = "\n"; // holds copy of input (destroyed by strtok())
        char* tptr = NULL;              // holds pointer to token, returned from strtok()

        strcpy(temp, data);             // save a copy of input

        tptr = strtok(temp, "\n");              // (next) token - street
        if (tptr == NULL) return -1;    // premature end of string
        strcpy(street, tptr);                   // update field

        tptr = strtok(NULL, "\n");              // (next) token - city
        if (tptr == NULL) return -1;    // premature end of string
        strcpy(city, tptr);                     // update field

        tptr = strtok(NULL, "\n");              // (next) token - province
        if (tptr == NULL) return -1;    // premature end of string
        strcpy(province, tptr);                 // update field

        tptr = strtok(NULL, "\n");              // (next) token - postcode
        if (tptr == NULL) return -1;    // premature end of string
        strcpy(postcode, tptr);                 // update field

        tptr = strtok(NULL, "\n");              // (next) token - country
        if (tptr == NULL) return -1;    // premature end of string
        strcpy(country, tptr);                  // update field

        return 0;
}

/* ************not covered yet *****
// IOSTREAM OPERATORS for class Address

//----- inserter

ostream& operator<< (ostream& s, Address& X)
{
        return s;
}
//----- extractor

istream& operator>> (istream& s, Address& X)
{
        return s;
}
 ************not covered yet ***** */

//--------------------------------
//--------private member functions
//--------------------------------
void Address::emptyValues(void)
{
        // appropriate null or zero valued to member variables
        street[0] = '\0';
        city[0] = '\0';
        province[0] = '\0';
        postcode[0] = '\0';
        country[0] = '\0';
}


  
   ### FILE perx.hpp 
// perx.hpp - class declaration for Person

#if ! defined PERSON__HPP
#define PERSON__HPP

#include <iostream.h>
#include "addr.hpp"

class Person
{
        protected:

        // protected class data
  char lastname[31];
  char firstname[31];
  Address home;
  int age;
  float worth;

        public:

        // public function prototypes

        #include "perxpbf.hpp"


        private:

        // private function prototypes

        void emptyValues(void);
};

//-------function prototypes
char* get_person_data(void);

#endif     // #if ! defined PERSON__HPP


  
   ### FILE addr.hpp 
// addr.hpp - class declaration for Address

#if ! defined ADDRESS__HPP
#define ADDRESS__HPP

#include <iostream.h> // for cin, cout etc.

class Address
{
        protected:

        char street[51];
        char city[31];
        char province[3];
        char postcode[15];
        char country[31];

        // protected class data

        public:

        // public function prototypes

        #include "addrpbf.hpp"

        private:

        void emptyValues(void);

};

//-----function prototype
char* get_address_data(void);

#endif     // #if ! defined ADDRESS__HPP

   ### FILE perxpbf.hpp

// perspbf.hpp - public function prototypes for class Person

#if ! defined PERSONPBF__HPP
#define PERSONPBF__HPP

#include "perx.hpp"

//-----CONSTRUCTORS

//------ default constructor

Person(void);

//------ other constructors
Person(char* lastname, char* firstname);


//-----ACCESSORS

int     isOld(void);     // returns TRUE if old
int     isRich(void);    // returns TRUE if rich
char*    display(void);   // displays each member variable

//-----MUTATORS
int update(char* data); // data hasa fields separated by '\n'

/* *** operators not covered until later ***
        // IOSTREAM OPERATORS as friends

        friend ostream& operator<< (ostream& s, Person& X);

        friend istream& operator>> (istream& s, Person& X);
*/

#endif     // #if ! defined PERSONPBF__HPP

// addrpbf.hpp - public function prototypes for class Address
   
   ### FILE addrpbf.hpp

#if ! defined ADDRESSPBF__HPP
#define ADDRESSPBF__HPP
#include "addr.hpp"

//-----CONSTRUCTORS

//------ default constructor

Address(void);

//------ other constructors

//-----ACCESSORS

char* display(void);

//-----MUTATORS

int update( char* data);

/* *******not covered yet *****
// IOSTREAM OPERATORS as friends

friend ostream& operator<< (ostream& s, Address& X);

friend istream& operator>> (istream& s, Address& X);
 ********* not covered yet */

#endif     // #if ! defined ADDRESSPBF__HPP
