Jump to content

From Structs to Class

- - - - -

This topic has been archived. This means that you cannot reply to this topic.
6 replies to this topic

#1
Hawk1

Hawk1

    Learning Programmer

  • Members
  • PipPipPip
  • 70 posts
I've almost achieved the goal of completing this project, but for some reason i did something wrong. can anyhelp fix this code for me?

// Header file first
#ifndef _ADDRESSBOOK
#define _ADDRESSBOOK
 
const int MAXADDRESS = 25;
 
struct PERSON
{
	char fName[25];
	char lName[25];
	char Address[100];
 
};
 
bool addPerson(const PERSON &p);
bool getPerson(PERSON &p);
bool findPerson(char *lastName, PERSON &p);
bool findPerson(char *lastName, char *firstName, PERSON &p);
void printBook();
 
 
#endif
 
 
// addressBook.cpp
 
#include "addressBook.h"
 
#include <cstring> // <--- RX: Needed by stricmp and other string functions
#include <iostream> // <--- RX: Needed cout and other I/O streams
 
using namespace std;
PERSON people[MAXADDRESS];
int head = 0;
int tail = -1;
 
bool addPerson(const PERSON &p)
{
	if(head < MAXADDRESS)
	{
		people[head] = p;
		head++;
		if(tail == -1)
			tail++;
		return true;
	}
	return false;
}
bool getPerson(PERSON &p)
{
	if(tail >=0)
	{
		if(tail >= MAXADDRESS)
			tail = 0;
		p = people[tail];
		tail++;
		return true;
	}
	return false;
}
bool findPerson(char *lastName, PERSON &p)
{
	for(int i = 0; i < head; i++)
	{
		if(!stricmp(people[i].lName, lastName))
		{
			p = people[i];
			return true;
		}
	}
	return false;
}
bool findPerson(char *lastName, char *firstName, PERSON &p)
{
	for(int i = 0; i < head; i++)
	{
		if(!stricmp(people[i].lName, lastName) && !stricmp(people[i].fName, firstName))
		{
			p = people[i];
			return true;
		}
	}
	return false;
}
void printBook()
{
 
	for(int i = 0; i < head; i++)
	{
		cout << people[i].fName << "\t" << people[i].lName << "\t" << people[i].Address << endl;
	}
 
}
 
// finally main.cpp
 
#include "addressbook.h"
 
 
using namespace std;
int printMenu();
void waitKey();
 
const int ADDPERSON = 1;
const int GETPERSON = 2;
const int FINDLAST = 3;
const int FINDBOTH = 4;
const int PRINT = 5;
const int EXIT = 0;
int main()
{
	int selection;
	PERSON p;
	bool status;
	char lName[50];
	char fName[50];
 
 
	selection = printMenu();
	while(selection != EXIT )
	{
		switch(selection)
		{
		case ADDPERSON :
			cout << "Enter First Name " << endl;
			cin >> p.fName;
			cout << "Enter last Name " << endl;
			cin >> p.lName;
			cout << "Enter Address " << endl;
			cin >> p.Address;
			status = addPerson(p);
			if(status == false)
				cout << "Sorry There is no more room in the address book " << endl;
			else
				cout << "Thanks for your Entry " << endl;
 
			waitKey(); 
			break;
		case GETPERSON :
			status = getPerson(p);
			if(status)
				cout << p.fName << "\t" << p.lName << " " << p.Address << endl;
			else
				cout << "Sorry The address book is empty " << endl;
 
			waitKey();
 
			break;
		case FINDLAST :
			cout << "Enter a last name " << endl;
			cin >> lName;
			status = findPerson(lName,p);
			if(status)
				cout << p.fName << "\t" << p.lName << " " << p.Address << endl;
			else
				cout << "Sorry, Name not found " << endl;
 
			waitKey();
			break;
 
		case FINDBOTH :
			cout << "Enter last name " << endl;
			cin >> lName;
			cout << "Enter first name " << endl;
			cin >> fName;
			status = findPerson(lName, fName,p);
			if(status)
				cout << p.fName << "\t" << p.lName << " " << p.Address << endl;
			else
				cout << "Sorry, Name not found " << endl;
 
			waitKey();
			break;
 
		case PRINT :
			printBook();
			waitKey();
			break;
		case EXIT :
			cout << "Thanks for using the address book " << endl;
			exit(0);
		}
		selection = printMenu();
	}
}
 
int printMenu()
{
	int selection;
 
	system("CLS");
	cout << "1. Add A Person" << endl;
	cout << "2. Get A Person " << endl;
	cout << "3. Find A person By Last Name " << endl;
	cout << "4. Find A person By First and Last Name " << endl;
	cout << "5. Print the address book" << endl;
	cout << "0. Exit this program " << endl;
	cin >> selection;
 
	return selection;
 
}
 
#include <cstdlib> // <--- RX: For the system() function
void waitKey()
{
 
	// <--- RX: On Windows just use system("pause");
	//cout << "Press a key to continue " << endl;
	
	//while(!kbhit())
	//	;
 
	//getch();
	//fflush(stdin);
 
	system("pause"); // This only works on Windows!
 
}
 

is code that works fine ^^^^

now to move it to classes i tried to do this:

// Header file first
 
 
#ifndef _ADDRESSBOOK
#define _ADDRESSBOOK
 
const int MAXADDRESS = 25;
 
class PERSON
{
private:
	char fName[25];
	char lName[25];
	char Address[100];
	char people[MAXADDRESS];
 
public:
	
	bool addPerson(const PERSON &p);
	bool getPerson(PERSON &p);
	bool findPerson(char *lastName, PERSON &p);
	bool findPerson(char *lastName, char *firstName, PERSON &p);
	void printBook(PERSON &p);
};
 
 
#endif
 
//Now the cpp with all the functions...
 
#include <iostream>
using namespace std;
#include "definitionsAddressBook.h"
 
using namespace std;
 
int head = 0;
int tail = -1;
 
 
bool PERSON::addPerson(const PERSON &p)
{
	
if(head < MAXADDRESS)
{
 
	people[head] = p;
	head++;
	if(tail == -1)
		tail++;
	return true;
}
return false;
}
bool PERSON::getPerson(PERSON &p)
{
 
	if(tail >=0)
	{
 
		if(tail >= MAXADDRESS)
			tail = 0;
		p = people[tail];
		tail++;
		
		return true;
 
	}
return false;
}
bool PERSON::findPerson(char *lastName, PERSON &p)
{
 
	for(int i = 0; i < head; i++)
	{
		if(!_stricmp(people[i].lName, lastName))
 
		{
			p = people[i];
			return true;
 
		}
 
	}
return false;
}
bool PERSON::findPerson(char *lastName, char *firstName, PERSON &p)
{
 
	for(int i = 0; i < head; i++)
	{
 
		if(!_stricmp(people[i].lName, lastName) && !_stricmp(people[i].fName, firstName))
 
		{
			p = people[i];
			return true;
 
		}
 
	}
return false;
}
void printBook(PERSON &p)
{
 
 
	for(int i = 0; i < MAXADDRESS; i++)
	{
 
		cout << people[i].fName << "\t" << people[i].lName << "\t" << people[i].Address << endl;
 
	}
 
}
 
 
 
// Now the main cpp
 
#include <iostream>
using namespace std;
 
#include "definitionsAddressBook.h"
#include "conio.h"
 
 
using namespace std;
int printMenu();
void waitKey();
 
const int ADDPERSON = 1;
const int GETPERSON = 2;
const int FINDLAST = 3;
const int FINDBOTH = 4;
const int PRINT = 5;
const int EXIT = 0;
int main()
{
 
	int selection;
	PERSON p;
	PERSON access;
	bool status;
	char fName[50];
	char lName[50];
	char Address[100];
	char *firstName;
	char *lastName;
	char *address2;
 
 
 
	selection = printMenu();
	while(selection != EXIT )
		{
			switch(selection)
				{
			case ADDPERSON :
				
				cout << "Enter First Name " << endl;
				cin >> p.fName;
				cout << "Enter last Name " << endl;
				cin >> p.lName;
				cout << "Enter Address " << endl;
				cin >> p.Address;
 
 
				status = access.addPerson(p);
				if(status == false)
					cout << "Sorry There is no more room in the address book " << endl;
 
				else
					cout << "Thanks for your Entry " << endl;
 
 
				waitKey(); 
				break;
 
			case GETPERSON :
 
				status = access.getPerson(p);
				if(status)
					cout << p.fName << "\t" << p.lName << " " << p.Address << endl;
				else
					cout << "Sorry The address book is empty " << endl;
 
				waitKey();
				break;
 
 
			case FINDLAST :
 
 
				cout << "Enter a last name " << endl;
				cin >> lName;
				status = access.findPerson(lName, p);
 
				if(status)
					cout << p.fName << "\t" << p.lName << " " << p.Address << endl;
				else
					cout << "Sorry, Name not found " << endl;
				waitKey();
 
				break;
 
 
			case FINDBOTH :
 
				cout << "Enter last name " << endl;
				cin >> lName;
				cout << "Enter first name " << endl;
				cin >> fName;
				status = access.findPerson(lName, fName, p);
 
				if(status)
					cout << p.fName << "\t" << p.lName << " " << p.Address << endl;
				else
					cout << "Sorry, Name not found " << endl;
 
				waitKey();
				break;
 
 
			case PRINT :
 
				printBook();
				waitKey();
 
				break;
			case EXIT :
 
				cout << "Thanks for using the address book " << endl;
				exit(0);
 
			}
			selection = printMenu();
 
	}
}
 
int printMenu()
{
 
	int selection;
 
 
	system("CLS");
 
	cout << "1. Add A Person" << endl;
	cout << "2. Get A Person " << endl;
	cout << "3. Find A person By Last Name " << endl;
	cout << "4. Find A person By First and Last Name " << endl;
	cout << "5. Print the address book" << endl;
	cout << "0. Exit this program " << endl;
	cin >> selection;
 
	return selection;
 
}
 
void waitKey()
{
 
	cout << "Press a key to continue " << endl;
 
	while(!kbhit())
		;
 
	getch();
	fflush(stdin);
 
}// Header file first
 
 
#ifndef _ADDRESSBOOK
#define _ADDRESSBOOK
 
const int MAXADDRESS = 25;
 
class PERSON
{
private:
	char fName[25];
	char lName[25];
	char <strong class="highlight">Address</strong>[100];
	char people[MAXADDRESS];
 
public:
	
	bool addPerson(const PERSON &p);
	bool getPerson(PERSON &p);
	bool findPerson(char *lastName, PERSON &p);
	bool findPerson(char *lastName, char *firstName, PERSON &p);
	void printBook(PERSON &p);
};
 
 
#endif
 
//Now the cpp <strong class="highlight">with</strong> all the functions...
 
#include <iostream>
using namespace std;
#include "definitionsAddressBook.h"
 
using namespace std;
 
int head = 0;
int tail = -1;
 
 
bool PERSON::addPerson(const PERSON &p)
{
	
if(head < MAXADDRESS)
{
 
	people[head] = p;
	head++;
	if(tail == -1)
		tail++;
	return true;
}
return false;
}
bool PERSON::getPerson(PERSON &p)
{
 
	if(tail >=0)
	{
 
		if(tail >= MAXADDRESS)
			tail = 0;
		p = people[tail];
		tail++;
		
		return true;
 
	}
return false;
}
bool PERSON::findPerson(char *lastName, PERSON &p)
{
 
	for(int i = 0; i < head; i++)
	{
		if(!_stricmp(people[i].lName, lastName))
 
		{
			p = people[i];
			return true;
 
		}
 
	}
return false;
}
bool PERSON::findPerson(char *lastName, char *firstName, PERSON &p)
{
 
	for(int i = 0; i < head; i++)
	{
 
		if(!_stricmp(people[i].lName, lastName) && !_stricmp(people[i].fName, firstName))
 
		{
			p = people[i];
			return true;
 
		}
 
	}
return false;
}
void printBook(PERSON &p)
{
 
 
	for(int i = 0; i < MAXADDRESS; i++)
	{
 
		cout << people[i].fName << "\t" << people[i].lName << "\t" << people[i].Address << endl;
 
	}
 
}
 
 
 
// Now the main cpp
 
#include <iostream>
using namespace std;
 
#include "definitionsAddressBook.h"
#include "conio.h"
 
 
using namespace std;
int printMenu();
void waitKey();
 
const int ADDPERSON = 1;
const int GETPERSON = 2;
const int FINDLAST = 3;
const int FINDBOTH = 4;
const int PRINT = 5;
const int EXIT = 0;
int main()
{
 
	int selection;
	PERSON p;
	PERSON access;
	bool status;
	char fName[50];
	char lName[50];
	char <strong class="highlight">Address</strong>[100];
	char *firstName;
	char *lastName;
	char *address2;
 
 
 
	selection = printMenu();
	while(selection != EXIT )
		{
			switch(selection)
				{
			case ADDPERSON :
				
				cout << "Enter First Name " << endl;
				cin >> p.fName;
				cout << "Enter last Name " << endl;
				cin >> p.lName;
				cout << "Enter <strong class="highlight">Address</strong> " << endl;
				cin >> p.Address;
 
 
				status = access.addPerson(p);
				if(status == false)
					cout << "Sorry There is no more room in the <strong class="highlight">address</strong> <strong class="highlight">book</strong> " << endl;
 
				else
					cout << "Thanks for your Entry " << endl;
 
 
				waitKey(); 
				break;
 
			case GETPERSON :
 
				status = access.getPerson(p);
				if(status)
					cout << p.fName << "\t" << p.lName << " " << p.Address << endl;
				else
					cout << "Sorry The <strong class="highlight">address</strong> <strong class="highlight">book</strong> is empty " << endl;
 
				waitKey();
				break;
 
 
			case FINDLAST :
 
 
				cout << "Enter a last name " << endl;
				cin >> lName;
				status = access.findPerson(lName, p);
 
				if(status)
					cout << p.fName << "\t" << p.lName << " " << p.Address << endl;
				else
					cout << "Sorry, Name not found " << endl;
				waitKey();
 
				break;
 
 
			case FINDBOTH :
 
				cout << "Enter last name " << endl;
				cin >> lName;
				cout << "Enter first name " << endl;
				cin >> fName;
				status = access.findPerson(lName, fName, p);
 
				if(status)
					cout << p.fName << "\t" << p.lName << " " << p.Address << endl;
				else
					cout << "Sorry, Name not found " << endl;
 
				waitKey();
				break;
 
 
			case PRINT :
 
				printBook();
				waitKey();
 
				break;
			case EXIT :
 
				cout << "Thanks for using the <strong class="highlight">address</strong> <strong class="highlight">book</strong> " << endl;
				exit(0);
 
			}
			selection = printMenu();
 
	}
}
 
int printMenu()
{
 
	int selection;
 
 
	system("CLS");
 
	cout << "1. Add A Person" << endl;
	cout << "2. Get A Person " << endl;
	cout << "3. Find A person By Last Name " << endl;
	cout << "4. Find A person By First and Last Name " << endl;
	cout << "5. Print the <strong class="highlight">address</strong> book" << endl;
	cout << "0. Exit this program " << endl;
	cin >> selection;
 
	return selection;
 
}
 
void waitKey()
{
 
	cout << "Press a key to continue " << endl;
 
	while(!kbhit())
		;
 
	getch();
	fflush(stdin);
 
} 

but it is NOT working. :(

what have i done wrong, this is so discouraging. i really really hate c++ now. lol
:(

Edited by WingedPanther, 18 December 2008 - 06:47 PM.


#2
WingedPanther

WingedPanther

    A spammer's worst nightmare

  • Moderators
  • 16,831 posts
Well, my immediate observation is that you are changing the data types of components. people[MAXADDRESS] isn't supposed to by of type char or part of the struct, for example. If you fundamentally change the data types, things are pretty much guaranteed to break.
Programming is a branch of mathematics.
My CodeCall Blog | My Personal Blog

#3
Lance

Lance

    Programming Professional

  • Members
  • PipPipPipPipPip
  • 276 posts
Let's handle it in an evolutionary way.

This program can most probably compile

class Person
{
private:
	char fName[25];
	char lName[25];
	char Address[100];
	char people[MAXADDRESS];
};

int main()
{
      Person p;

      return 0;
}

It compiles but does nothing meanful. Let add more stuff to it.

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

class Person
{
private:
	char fName[25];
	char lName[25];
	char Address[100];
	char people[MAXADDRESS];
public:
        void set_first_name(const char * first){ 
             strncpy(fName, first, sizeof(fName)-1);
             fName[sizeof(fName)-1]='\0';
        }
        void set_last_name(const char * last){ 
             strncpy(lName, last, sizeof(lName)-1);
             lName[sizeof(lName)-1]='\0';
        }
        const char * get_first_name()const{ return fName; }
        const char * get_last_name()const{ return lName; }
        
        // ditto for Address, etc.
       void print(std::ostream& stream)const{
             stream<<"Name: "<<lName<<", "<<fName<<std::endl;
       }
};

int main()
{
      Person p;
      p.set_first_name("Leon");
      p.set_last_name("Smith");

      p.print(std::cout);

      return 0;
}

You may prefer the more friendly syntax like std::cout<<p<<std::endl. This can be achieved with operator overloading.

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

class Person
{
private:
	char fName[25];
	char lName[25];
	char Address[100];
	char people[MAXADDRESS];
public:
        void set_first_name(const char * first){ 
             strncpy(fName, first, sizeof(fName)-1);
             fName[sizeof(fName)-1]='\0';
        }
        void set_last_name(const char * last){ 
             strncpy(lName, last, sizeof(lName)-1);
             lName[sizeof(lName)-1]='\0';
        }
        const char * get_first_name()const{ return fName; }
        const char * get_last_name()const{ return lName; }
        
        // ditto for Address, etc.
       void print(std::ostream& stream)const{
             stream<<"Name: "<<lName<<", "<<fName<<std::endl;
       }
};

std::ostream& operator<<(std::ostream& stream, const Person& p)
{
     stream<<"Name: "<<p.get_last_name()<<", "<<p.get_first_name();
     return stream;
}

int main()
{
      Person p;
      p.set_first_name("Leon");
      p.set_last_name("Smith");

      //p.print(std::cout);
      std::cout<<p /* <<"Some other string\n"<<1234<<std::endl */;

      return 0;
}

Now let's consider if it's really a good idea to have
bool addPerson(const PERSON &p);
bool getPerson(PERSON &p);
bool findPerson(char *lastName, PERSON &p);
bool findPerson(char *lastName, char *firstName, PERSON &p);
void printBook(PERSON &p);
As member of the Person class?

The answer is most probably no. We'll examine some other options later.

Edited by Lance, 19 December 2008 - 07:32 PM.


#4
Lance

Lance

    Programming Professional

  • Members
  • PipPipPipPipPip
  • 276 posts
Let's say now you have 2 Persons, Smith and Peter.
Person p, s;
p.set_first_name("Peter");
s.set_first_name("Smith");

Would you think it's logical to have
p.addPerson(s);
or
s.addPerson(p);
or
p.findPerson(s); // I am not referring to your original function signatures, just the probable semantics

I don't think so. These functionalities belong to some container class, eg. a PersonManager class, or as you call it, a People class.

 
const unsigned max_person=30;
class PersonManager{
public:
     void addPerson(const Person&p);
     bool findPerson(const Person &p)const;
     bool findPerson(const char * last)const;
     bool findPerson(const char* first, const char * last)const;
     unsigned countOfPersons()const{ return count_of_person; }
    //...

private:
       Person people[max_person];
       unsigned count_of_person;
};

void PersonManager::addPerson(const Person&p)
{
      if(count_of_person == max_person )
            throw "Sorry, I am unable to manage so many person. You beat me!";
      people[count_of_person++]=p;
      /* as you get more familiar with C++, you'll come to know that for this operation to be performed, a operator = 
          is required for the Person class. To good news is, the compiler will synthesize one for you, and in this particular
         situation, this synthesized operator = (assignment operator) happen to work just fine. 
      */
}
// Find the first person with give last name
// return true is one is found; false otherwise
//
// Note: this is not the best way for the function prototype. What if you want to find the next?...
// But for now, let's pretend it meets our needs
//
bool PersonManager::findPerson(const char * last)const
{
      for(unsigned i=0; i<count_of_persion; ++i){
             if(strcmp(last, people[i].get_last_name())==0)
                     return true;
     }
     return false;
}


You can pretty much implement the other 2 findPerson function with the similar technique. But, since we need to compare for equiality, define the operator == for Person would be the most logical approach.

...
class Person{
...
public:
..
     bool operator == (const Person& rhs)const;
};

bool Person::operator == (const Person& rhs)const
{
         return strcmp(fName, rhs.fName)==0 && strcmp(lName, rhs.lName)==0;
         // let's say no two Person would have the same name. An ID field would be more appropriate.
}


// now we can sort of 
//
bool findPerson(const Person& p)const
{
     for(unsigned i=0; i<count_of_person; ++i)
           if(people[i]==p)
                 return true;
      return false;    
}


Edited by Lance, 19 December 2008 - 07:35 PM.


#5
Lance

Lance

    Programming Professional

  • Members
  • PipPipPipPipPip
  • 276 posts
I vaguely remember there is a requirement to find out all person by a last name. What would you consider to be the best way of doing that?

obviously you can do something like
class PersonManager
{
...
public:
.. void findAndPrintAllPersonWithLastName(const char* lastname)const;
};

void  PersonManager::findAndPrintAllPersonWithLastName(const char* lastname)const
{
          for(int i=0; i<count_of_person; ++i)
                  if(strcmp(people[i].lName, lastname)==0)
                        std::cout<<people[i]<<std::endl;
}


But what if you need to perform some other function on the Person's who has given last name?

I'll stop right here. I guess I have already brought out too much stuff to risk further confuse you instead of clarifying the issue.

Basically:
1. You have access privillage problem. A private member (either variable or function) can not be directly accessed by anything other than its own member functions or friends.
2. Design flaw. Allright, even even you would like to simplify the design by omitting PersonManager and incorporate its functionality in Person as you did, you would be best to have them as static functions. As these functions do not rely on information of the left handed object. eg.
smith.findPerson(peter);
You don't find peter from smith. The code is acceptible, but it's symantically equivalent to
Person::findPerson(peter);
provide you implemented findPerson as a static member function.


I hope I have not frightened you. Learning C++ is a iterative process. You don't need to know all aspects of the language to make good use of it.

#6
Lance

Lance

    Programming Professional

  • Members
  • PipPipPipPipPip
  • 276 posts
I didn't test any of above code in a compiler, so if you get stuck somewhere and can figure it out by yourself, feel free to ask. Me or somebody else can surely fix it.

#7
Lance

Lance

    Programming Professional

  • Members
  • PipPipPipPipPip
  • 276 posts
BTW, it's perfectly OK to use C ascz string in C++. But you may consider using std::string to avoid certain common errors. With a little bit sacrifice in speed, you gain more freedom and make less mistakes. Just a suggestion. Some people who have strong C background may choose to use C string when it make sense; for people who have no prior C experience, they may find std::string mare friendly to use.