Moving from CString to string in C++

Pages: 12
Well this is the type of thing I had in mind:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
struct PERSON {
	string m_fName;
	string m_lName;
	string m_Address;

	PERSON() {}
	PERSON(const string& fname, const string& lname, const string& address )
	: m_fName(fname),
	m_lName(lname),
	m_Address(address)
	{}
	~PERSON() {
		
	}
};


But the addPerson function looks like this:

1
2
3
4
5
6
7
8
9
10
bool addressBook::addPerson(const string& fName, const string& lName, const string& address) {
	PERSON *pPERSON = new PERSON(fName, lName, address );
	people.push_back(*pPERSON);
	delete pPERSON;
	
	if(tail == -1) {
		tail++;
	}
	return true;
}


Which is a bit of a hack - you were right in how you were doing in the first place !! It seems that default value lists only work if one has direct access to the member variable - that is not inside a vector of a composite member. I tried all kinds of ways to get it to work.

I made a number of changes to your code & put comments to show why I changed it. There are more things that could be done as well.

So here it is:

addressbook.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#ifndef _ADDRESSBOOK
#define _ADDRESSBOOK
#include <vector>
#include<string>

#include <iostream>
//using namespace std;



using std::string;
using std::vector;

using std::istream;
using std::ostream;

const int MAXADDRESS =25;

struct PERSON
{

	string m_fName;
	string m_lName;
	string m_Address;

	PERSON() {}
	PERSON(const string& fname, const string& lname, const string& address )
	: m_fName(fname),
	m_lName(lname),
	m_Address(address)
	{}
	~PERSON() {
		
	}
	
};


class addressBook
{
private:
	
	vector<PERSON> people;
	
	int head;
	int tail;
	
public:
	
	addressBook();
	
	addressBook(const PERSON &p);
	addressBook(const PERSON p[], int size);
	addressBook(const string &fName, const string &lName, const string &address);
	
	bool addPerson(const PERSON &p);
	
	bool addPerson(const string& fName, const string& lName, const string& address) ;
	
	bool sortcomp(const PERSON& p1, const PERSON& p2);
	bool getPerson( PERSON& p);
	bool findPerson(const string& lastName, PERSON& p) const;
	bool findPerson(const string& lastName, const string& firstName, PERSON& p) const;
	
	void PrintPerson(const string& lastName) const ;
	void PrintPerson(const PERSON& p) const ;
	
	void bubbleSort(int *array,int length);
	void printBook() const;
	void sort();
	
	friend ostream &operator << (ostream &, addressBook &);
	
	addressBook &operator +=(const PERSON &p); 
	addressBook operator [](int x); 
	
};
#endif  


addressBook.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196

#include <iostream>
#include<string>

#include "addressBook.h"
//using namespace std;

using std::string;
using std::cout;
using std::endl;

addressBook::addressBook()
: head(0), tail(-1)
{
	
}

addressBook::addressBook(const PERSON &p)
: head(0), tail(-1)
{
	addPerson(p);
}

addressBook::addressBook(const PERSON p[], int size)
: head(0), tail(-1)
{
	for(int i = 0; i < size; i++)
		addPerson(p[i]);
	
}


addressBook::addressBook(const string& fName, const string& lName, const string& address)  {
	
	//this is a bit of a hack
	PERSON *pPERSON = new PERSON(fName, lName, address );
	people.push_back(*pPERSON);
	delete pPERSON;
}

bool addressBook::addPerson(const PERSON &p)
{
	
	
	people.push_back(p);
	
	if(tail == -1) {
		tail++;
	}
	return true;
	
}

bool addressBook::addPerson(const string& fName, const string& lName, const string& address) {
	PERSON *pPERSON = new PERSON(fName, lName, address );
	people.push_back(*pPERSON);
	delete pPERSON;
	
	if(tail == -1) {
		tail++;
	}
	return true;
}

bool addressBook::getPerson(PERSON& p) 
{
	if(tail >=0)
	{
		//need this because tail can be -ve, so it has to be signed
		if(tail >= static_cast<int>(people.size())){
			tail = 0;
		}
		p = people[tail];
		tail++;
		return true;
	}
	return false;
}
bool addressBook::findPerson(const string& lastName, PERSON& p) const
{
	for(size_t i = 0; i < people.size(); i++)
	{
		//I got rid of strcmp - only need that if comparing some of the chars
		//to compare the whole thing just use ==
		if(people[i].m_lName == lastName)
		{
			p = people[i];
			return true;
		}
	}
	return false;
}
bool addressBook::findPerson(const string& lastName, const string& firstName, PERSON& p) const
{
	for(size_t i = 0; i < people.size(); i++)
	{
		if(people[i].m_lName == lastName && people[i].m_fName == firstName)
		{
			p = people[i];
			return true;
		}
	}
	return false;
}


void addressBook::printBook() const
{
	for(size_t i = 0; i < people.size(); i++)
	{
		
		std::cout << people[i].m_fName << "\t" << people[i].m_lName << "\t" << people[i].m_Address << std::endl;
	}
}

bool addressBook::sortcomp(const PERSON& p1, const PERSON& p2) {
	
	if ( p1.m_lName.compare(p2.m_lName) ){
		return true ;
	}
	//if ( result < 0 )
	else {	
		return false ;
	}
	//return std::strcmp(p1.m_fName, p2.m_fName) > 0 ;
}

void addressBook::sort() 
{
	bool didSwap ;
	
	do
	{
		didSwap = false ;
		
		for ( size_t i=1; i<people.size(); ++i )
			if ( sortcomp(people[i-1], people[i]) )
			{
				std::swap(people[i-1], people[i]) ;
				didSwap = true ;
			}
			
	} while ( didSwap ) ;
}

addressBook &addressBook::operator +=(const PERSON &p)
{
	addPerson(p);
	return *this;
}

addressBook addressBook::operator [](int x)
{
	return people[x];
}

ostream &operator << (ostream &output, addressBook &ab)
{
	PERSON tmp;
	ab.getPerson(tmp);
	output << tmp.m_fName << " " << tmp.m_lName << " " << tmp.m_Address << std::endl;
	return output;
}
/*
void addressBook::PrintPerson(const string& lastName) {
	for(size_t i = 0; i < people.size(); i++) {
		if(people[i].m_lName == lastName) {
			cout << people[i].m_fName << "  ";
			cout << people[i].m_lName << "  ";
			cout << people[i].m_Address << endl;	
		}
	}
}
*/

//an easier way to iterate over the whole object
//compare to the commented out code above
void addressBook::PrintPerson(const string& lastName) const {
	for(auto &P : people) {
		if(P.m_lName == lastName) {
			cout << P.m_fName << "  ";
			cout << P.m_lName << "  ";
			cout << P.m_Address << endl;
		}
	}
}

void addressBook::PrintPerson(const PERSON& p) const {
	for(size_t i = 0; i < people.size(); i++) {
		if(people[i].m_lName == p.m_lName) {
			cout << people[i].m_fName << "  ";
			cout << people[i].m_lName << "  ";
			cout << people[i].m_Address << endl;
		}
	}
}


main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
#include <iostream>
#include <cstdlib>
//#include <conio.h>
#include <string>

#include "addressBook.h"

//using namespace std;

using std::cout;
using std::cin;
using std::endl;

using std::string;

int printMenu();

//I disabled anything to do with conio - not standard
//void waitKey();



//Not sure what the advantage of doing this is
//could just have case 1: in the switch for example
//they shouldn't be global

const int ADDPERSON = 1;
const int GETPERSON = 2;
const int FINDLAST = 3;
const int FINDBOTH = 4;
const int PRINT = 5;
const int NAMESORT = 6;
const int EXIT = 0;



int main()
{
	PERSON p;
	addressBook ad;
	addressBook ab;
	addressBook myBook;
	
	//this is a function declaration
	//addressBook newBook("Test1", "TEST2", "1234");
	
	addressBook newBook;
	
	//the trouble with this is that you have to use pBook
	//to access things
	addressBook *pBook = new addressBook("Test1", "TEST2", "1234");
	
	PERSON me = {"Johnny", "Rocket", "923 go"};
	
	PERSON me2 = {"CJ", "MZ", "123"};
	
	PERSON me3 = {"YEP", "NOPE", "4321"};
	
	newBook+=me;
	newBook+=me2;
	newBook+=me3;
	
	//adding PERSON's to the pBook object
	pBook->addPerson(me);
	pBook->addPerson(me2);
	pBook->addPerson(me3);
	
	//but the functions don't take an address book argument
	//and there is no interface to get at a PERSON details
	//so we could not see any data for this object
	
	//so I added this class function so we can see the data
	pBook->PrintPerson("Rocket");
	pBook->PrintPerson("MZ");
	pBook->PrintPerson("NOPE");
	pBook->PrintPerson("TEST2");
	
	cout << endl;
	//again but with person objects
	pBook->PrintPerson(me);
	pBook->PrintPerson(me2);
	pBook->PrintPerson(me3);
	
	cout << endl;
	//again but with person data
	pBook->addPerson("Fred", "Dagg", "9999");
	pBook->addPerson("Ginger", "Rogers", "1234 go");
	pBook->addPerson("Fred", "Astaire", "Slow foxtrot");
	pBook->addPerson("Dire", "Straights", "123 It Nevers Rains");
	
	cout << endl;
	
	pBook->PrintPerson("Dagg");
	pBook->PrintPerson("Rogers");
	pBook->PrintPerson("Astaire");
	pBook->PrintPerson("Straights");
	
	cout << endl;
	
	//this doesnt work
	//me3 = newBook[2];
	
	bool status;
	char lName[50];
	char fName[50];
	
	//moved this inside the loop
	//selection = printMenu();
	
	//altered this so the exit option will work
	//while(selection != EXIT )
	
	bool Quit = false;
	int selection;
	
	while(!Quit) {
		selection = printMenu();
		switch(selection) {
			
			//the code in these cases should be in the class functions IMO
			//the case should call the right member function
			//they all deal with 1 address book - but there are several address
			//books initialised - consider having an option to change address books
			
			case ADDPERSON :
				cout << "Enter First Name " << endl;
				cin >> p.m_fName;
				cout << "Enter last Name " << endl;
				cin >> p.m_lName;
				cout << "Enter Address " << endl;
				cin >> p.m_Address;
				status = ad.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 = ad.getPerson(p);
				if(status) {
					cout << p.m_fName << "\t" << p.m_lName << " " << p.m_Address << endl;
				}
				else {
					cout << "Sorry The address book is empty " << endl;
				}
				//waitKey();
				
				break;
			case FINDLAST :
				cout << "Enter a last name " << endl;
				cin >> lName;
				status = ad.findPerson(lName,p);
				if(status) {
					cout << p.m_fName << "\t" << p.m_lName << " " << p.m_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 = ad.findPerson(lName, fName,p);
				if(status) {
					cout << p.m_fName << "\t" << p.m_lName << " " << p.m_Address << endl;
				}
				else {
					cout << "Sorry, Name not found " << endl;
				}
				//waitKey();
				break;
				
			case NAMESORT :
				ad.sort();
				newBook.sort();
				myBook.sort();
				cout << "Your addressbook has been alphabetically sorted, choose print from the main menu to see the results " << endl;
				//waitKey();
				break;
				
			case PRINT :
				
				newBook.printBook();
				ad.printBook();
				myBook.printBook();
				//waitKey();
				break;
			case EXIT :
				cout << "Thanks for using the address book " << endl;
				Quit = true;
				break;
				//let execution contine after while loop
				//exit(0);
			default:
				cout << "Menu Selection Error" << endl;
				break;
		}
		//no need for this anymore
		//selection = printMenu();
	}
	cout << "Exiting main() function" << endl;
	return 0;
}

int printMenu()
{
	
	
	int selection;
	
	//not standard
	//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 << "6. Sort by last name " << 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);
	
}
*/



I haven't thoroughly tested it - but there are a number things that are better.

Any way, now I am going to bed - it's 5:00AM here in Melbourne, Australia!!
Well, the teacher called in sick today, so no go there. I'll probably hit him up in an email later. I want to show him what you came up with. I'm pretty sure it's miles beyond what he wants us doing, since so far all of his assingments have been simplistic in their solutions, and rewriting the addresbook to that degree is probably overkill. Still, I think its really cool what you came up with. I've spent over an hour going over what your doing here and referencing it all on-line to better understand it, and from what I can tell, your version is pretty damn efficient compared to what were working with.

I've been sitting in class and playing around with this for a bit, and although I seriously doubt this is what were supposed to do, I came up with a solution that uses strings. Have a look, and then have a laugh :

1
2
3
4
5
6
7
8
9
10
11
12
13
addressBook::addressBook(char *fName, char *lName, char *address)
: head(0), tail(-1)
{
 PERSON tmp;
 string str;
 string str1(strcpy(tmp.fName, fName));
 string str2(strcpy(tmp.lName, lName));
 string str3(strcpy(tmp.Address, address));
 str.append(str1);
 str.append(str2);
 str.append(str3);
addPerson(tmp);
}
This works as well, and I'm not wasting space using the .append that doesn't do anything anyway:

1
2
3
4
5
6
7
8
addressBook::addressBook(char *fName, char *lName, char *address)
: head(0), tail(-1)
{
 PERSON tmp;
 string str(strcpy(tmp.fName, fName),(strcpy(tmp.lName, lName),(strcpy(tmp.Address, address))));
addPerson(tmp);
}
the trick here, at least I think, is to figure out how to copy whatever is in the tmp.name over to its counterpart, just like strcpy did, but using a string command to do it... gonna have to chew on this a bit more, and do a lot of reading to see what string has to offer that runs similar to strcpy. I know .copy doesn't seem to want to do it, which is odd.
Last edited on
Not clear which definition of PERSON you're using.

If you're using TheIdeaMan's defintion using string members, then you're overly complicating your addressBook constructor.
1
2
3
4
5
6
7
8
addressBook::addressBook(char *fName, char *lName, char *address)
: head(0), tail(-1)
{  PERSON tmp;
    tmp.fName = fName;
    tmp.lName = lName;
    tmp.Address = address;
    addPerson(tmp);
}


If you're using the definition from the other thread with char arrays, then the following is appropriate:
1
2
3
4
5
6
7
8
9
addressBook::addressBook(char *fName, char *lName, char *address)
: head(0), tail(-1)
{
 PERSON tmp;
 strcpy(tmp.fName, fName);
 strcpy(tmp.lName, lName);
 strcpy(tmp.Address, address);
  addPerson(tmp);
}

No reason to use str. What you have two posts up will work, but is unconventional.
You're using the comma operator to only take the pointer returned by the last strcpy and then pass that in str's constructor, then you don't do anything with str.

Believe me, I think it's pointless to go from the cstring strcpy to the string stuff, but thats the homework we have. I have to convert the cstring stuff in my address book over to string. So I have to take the original, with the char arrays and do what I did with srtcpy, but do it with a non cstring string. Everything I've seen makes it look like doing so is just extra work, but thats the assignment, so I have to figure it out. I'm using this part of the address book because its not in the assignment, that way I can see code that I can learn off of without having to worry about somebody posting stuff that I don't want to see. Plus, this seems like a really good way to learn the differences between cstring and string.
strcpy and string are not designed to work together.
You can't strcpy into a string.

You can go from a char array to a string in one of two ways:
1) A string constructor will take a char arrary.
1
2
  char firstname[20];
  string str1 (firstname);


2) You can assign a char array to string.
1
2
3
  char firstname[20];
  string str1;
  str1 = firstfname;

I'm not trying to strcpy into a string, I'm trying to replace the use of strcpy with a string, if that makes sense.

Heres my original code:

1
2
3
4
5
6
7
8
9
addressBook::addressBook(char *fName, char *lName, char *address)
: head(0), tail(-1)
{
 PERSON tmp;
 strcpy(tmp.fName, fName);
 strcpy(tmp.lName,lName);
 strcpy(tmp.Address, address);
 addPerson(tmp);
}


I'm trying to replace strcpy which is a cstring function, with a c++ string function, like std::string. I know this example below doesnt work, but just to get an idea heres this:

1
2
3
4
5
6
7
8
9
10
addressBook::addressBook(char *fName, char *lName, char *address)
: head(0), tail(-1)
{
 PERSON tmp;
string str;
 str.copy(tmp.fName, fName);
 str.copy(tmp.lName,lName);
 str.copy(tmp.Address, address);
 addPerson(tmp);
}


I know you can't do a copy like that with string, but thats what I'm trying to figure out. How do I remove the CString strcpy and replace it with a string function that does the same thing?
Last edited on
You didn't answer my question about which declaration of PERSON you're using.
Please post your current declaration of PERSON.

How do I remove the CString strcpy and replace it with a string function?

Assuming you're using something that looks like TheIdeaMan's struct declaration with string elements, I gave you the answer 4 posts back.

1
2
3
4
5
6
7
8
addressBook::addressBook(char *fName, char *lName, char *address)
: head(0), tail(-1)
{  PERSON tmp;
    tmp.fName = fName;  // assign the char array to the string
    tmp.lName = lName;
    tmp.Address = address;
    addPerson(tmp);
}


See the second definition of the string assignment operator here:
http://www.cplusplus.com/reference/string/string/operator=/
Last edited on
No, I'm using this one, in my header...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

#ifndef _ADDRESSBOOK
#define _ADDRESSBOOK
#include <vector>
#include<string>
using std::string;
#include <iostream>
using namespace std;

using std::istream;
using std::ostream;

const int MAXADDRESS =25;

struct PERSON
{
 char fName[25];
 char lName[25];
 char Address[100];
};

class addressBook
{
private:
vector<PERSON> people;

 int head;
 int tail;

public:

 addressBook();

 addressBook(const PERSON &p);
 addressBook(const PERSON p[], int size);
 addressBook(char *fName, char *lName, char *address);
 bool addPerson(const PERSON &p);
 bool sortcomp(const PERSON& p1, const PERSON& p2);
 bool getPerson(PERSON &p);
 bool findPerson(char *lastName, PERSON &p);
 bool findPerson(char *lastName, char *firstName, PERSON &p);
 void bubbleSort(int *array,int length);
 void printBook();
 void sort();

friend ostream &operator << (ostream &, addressBook &);

addressBook &operator +=(const PERSON &p); 
addressBook operator [](int x); 

};
#endif


I get how the other one would work that way, but if I switch to that version of PERSON, I end up having to change a ton of stuff in the rest of the program. I suppose that if it comes down to that then I would do it, but I'm trying to see if there is a less obtrusive way of doing it. I personally wouldn't change this at all if it were not part of an assignment. I understand that it's meant to teach us about strings, but sheesh, if it ain't broke...
Hi xanthian23,

If you look at the code I posted, it uses strings exclusively, and there is no strcmp or strcpy. I thought that was the whole idea of the assignment. I did have to change quite a few things to achieve that - but I used find & replace to do it. Same for the renaming of member variables.

The STL string is a really good thing, there is so much functionality in them - so much better than char arrays. You have now seen the assignment and equality testing, but lots of other things too like concatenation with the + and += operators. All kinds of good things here:

http://www.cplusplus.com/reference/string/string/


The main thing about your code is the interface (I don't mean the menu) - the way that class member variables are accessed & set. You have a bunch of functions that return a bool status, but the actual work is done the switch in main(). One of the benefits of good design is re-usability - you don't have this because to do so you would have the same code as what is in the switch in main, written again somewhere else. As my comments indicated, It would be better to put the code into the class - that way anything to do with the address book is in the addressbook class.

Another thought I had was to make PERSON a class of it's own, in it's own header file with an interface. I know a struct is almost the same thing as a class, but you have it a global lumped in with addressBook. Renaming it to CPerson or CAddrBkEntry would cause a bit of work with Find / Replace. My IDE allows me to do this globally.

I also have some more naming conventions - some of them are just my preference, others don't like them because it reminds them of Hungarian notation - which is bad when taken too far.

I put a leading C on my class names & use CamelCase for all variables, so I would have this:
class CAddressBook;

Sometimes this makes it easier to name objects.

Consistency in naming is a good thing - AddressBook & m_FName rather than addressBook & fName.

I also have a leading p for pointer variables, as in: pMyAddrBk . It is important to know that a variable is a pointer.

CAddressBook *pMyAddrBk = new CAddressBook();

There you go some more things to think about.

Here is the constructor again, but with const strings for parameters instead of char arrays


1
2
3
4
5
6
7
8
addressBook::addressBook(const string fName, const string lName, const string address)
: head(0), tail(-1)
{  PERSON tmp;
    tmp.m_fName = fName;
    tmp.m_lName = lName;
    tmp.m_Address = address;
    addPerson(tmp);
}


When you said some things were a bit of overkill - did you mean the use of pointers?

I did that way because that seemed the only way of calling this constructor was with the new operator. That gives a pointer, which means that everything has to happen through the pointer.

The other way was to do what you were doing by creating a Person & adding it - then you wouldn't have this constructor. Although it should really be through the Person constructor & not in main as I mentioned in my last post.
Well, after doing a LOT of reading, I had to succumb to the fact that I was going to have to make a change to my PERSON struct. I dropped the char, converted them all over to strings, and then just went ahead with the tmp.name=name thing. I realised that I had to use the = operator to do the job, and I could only do that if my struct was full of happy strings, and not char arrays.

Of course, after I did that, there were a few things that didn't like that I did that, and so I had to make some changes. Most are pretty similar to what TheIdeasMan offered up for the addressBook.cpp file, although slightly different. Thanks to having to look so much of this up, I actually understood what I had to do. M sorter had to be modified a little bit different than what TheIdeasMan showed, but it all works well now, so thank you to both of you, you guys made it really easy to figure out how the sort works compared to CStrings, and I will have to begrudgingly admit that it's actually more efficient.

I can't post what I did for the homework part until Monday, after the teacher posts the solutions for all to see, just in case people from class pop on in, but I will be sure to do so, that way you can see what I did, assuming your still interested.

So, thank you once again, and now I'm off to go play with the strings in something else. I want to see how append, assign, insert and replace work, and what I can do with those.
When you said some things were a bit of overkill - did you mean the use of pointers?

I did that way because that seemed the only way of calling this constructor was with the new operator. That gives a pointer, which means that everything has to happen through the pointer.

The other way was to do what you were doing by creating a Person & adding it - then you wouldn't have this constructor. Although it should really be through the Person constructor & not in main as I mentioned in my last post.


The teacher tends to go for the simplest solution when he presents a problem. As for not wanting to change the rest of the stuff, I was hoping to just change that one part I was working on, so I could get a feel for how strings worked, that way I could do the rest.

As for the layout of the address book, I agree that it would be more efficient to include a lot of this stuff in the header, but he wants them all separated, I assume for grading purposes. That way he can look at our constructors and overloads, and then go look at the functions we used. He rarely looks at what we have in main. I think he just wants to be able to see that we understand the point of the lesson, and doing it this way makes it easier for him to grade, and us to learn the concepts.

Not that much of this matters. I think were going to start working our way to doing what you've suggested. Our next assignment is to integrate a menu program we did at the start of class. Have look, I think I have a pretty good idea how this should be done, and I'll probably star up a new post for this since I think doing so with these lessons are a great reference for others that want to learn this stuff.

Here's the assignment


Implement the menu you crated in lab 1 for use inside your addressBook. Because the menu is setup to take pointers to void functions you are going to have to create a layer of functionality that sits between the two. This kind of structure can be thought of as a three tier approach.

Here is a simplistic example

addressBook ab;
Menu m;

void addPerson();

int main()
{

m.addMenu("1. Add Person", addPerson);
m.runMenu();

}


void addPerson()
{
PERSON p;
// get the persons information from the keyboard and store it in p

ab.addPerson(p);
m.waitKey();

}

You will have to create functions for each of your menu items which inturn call corresponding funcitons in the addressBook. Also, notice that global variables are being used. For now, this is acceptable.
:

And here is what we created in Lab #1:

HEADER:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#ifndef MENU
#define MENU

const int MAXCOUNT = 20;

struct menuItem
{
	void (*funct) ();
	char descript[50];

};

class Menu
{

private:

	menuItem mi[MAXCOUNT];
	int count;
	void runSelection ();

public:
	Menu();
	void addMenu(char *Description, void (*f) () );
	void runMenu();

}


#endif



MENU.CPP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include<iostream>
#include <cstdlib>
#include "menu.h"
;
using namespace std;


Menu::Menu()
		: count()
{

}


void Menu::addMenu(char *Description, void (*f) () )

{

	if(count < MAXCOUNT)
	{

		this->mi[count].funct = f;
		strcpy(this->mi[count].descript, Description);
		count++;
	}
}


void Menu::runMenu()

{
		for(;;)
		{
			system("CLS");;
			for(int i = 0; i < count; i++)
			{
				cout << this->mi[i].descript << endl;
			}

		runSelection();
		
		}
}

	

		void Menu::runSelection()
		{

		int select;

		cin >> select;

		if(select <= count)
			this->mi[select - 1].funct();

		}


MAIN.CPP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include<iostream>
#include <cstdlib>
#include "menu.h"
;
using namespace std;

void func1();
void func2();
void func3();
void Exit();

int main()
{



	Menu m;
	m.addMenu("1. Function 1 ", func1);
	m.addMenu("2. Function 2 ", func2);
	m.addMenu("3. Function 3 ", func3);
	m.addMenu("4. Exit ", Exit);

	m.runMenu();

}

void func1()

{
	char c;
	cout << "hello from function 1 " ;
	cin >> c;
}

void func2()

{
	char c;
	cout << "hello from function 2 " ;
	cin >> c;
}

void func3()

{
	char c;
	cout << "hello from function 3 " ;
	cin >> c;
}

void Exit()

{

	cout << "Goodbye! " << endl;
	exit(0);

}


So there's that. I'll be playing with it today to see if I understand how it should all work.
Thanks again for the help.
Topic archived. No new replies allowed.
Pages: 12