Moving from CString to string in C++

Pages: 12
Ok, so I have to switch over from the CStrings we've been using to regular strings, and I decided to start with one of my older assingments to test this out, but no matter what I do, I either get errors, memory printing to the scrren, or my program crashes.

I'm trying to go from using strcpy to using a string function, which I had assumed was just str.copy, but it wont let me do it unless its pointing to my PERSON struct through a pointer *. When I do that, it only prints up the memory block junk and then moves on to the last name. Can somebody please tell me what I'm doing wrong?

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);
 strcpy(tmp.lName,lName);
 strcpy(tmp.Address, address);
 addPerson(tmp);
}
User the assignment operator. And strings. They are objects -- not a collection of functions.
Last edited on
..... but no matter what I do, I either get errors, memory printing to the scrren, or my program crashes.


If you have compilation errors - then post them.

There is an entire reference & articles & tutorial section at the top left of this page. Check it out.

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


Did you include the <string> header file?

If you are going to use strings, then use them - use std::string rather than char *

It seems a little strange that you have an addressBook object that consists of just a PERSON object - are there other member variables you haven't shown? Because the other rule is that you should always initialise ALL of the member variables - partial initialisation doesn't really make sense.

It is also a bit strange that you create a temporary PERSON object, initialise it, then call a member function to add it into the object. Why not refer to member variables directly?

There is a convention that member variables can start with m_ as in m_fName. This makes it easier for naming things - m_fName = fName;

It is preferable to initialise variables with default values, as you have done with head & tail, as opposed to to assignment. ( I learnt this recently myself.) This is because the default constructor initialises variables first, then they get reassigned by your constructor straight away, so using the initialiser list is more efficient. And to always use const wherever you can:

1
2
3
4
5
6
7
8
addressBook::addressBook(const std::string fName, const std::string lName, const std::string address)
: head(0), 
tail(-1),
m_fName(fName),
m_lName(lName),
m_address(address) {
//other code here - if any
}


This code is just an example starting with your code, I am not sure of what the entire structure of your class is, or whether you might change it after seeing my comments above.

Hope all goes well.



Based on your post here, I'm assuming PERSON is the same struct.
http://www.cplusplus.com/forum/beginner/93761/

Your use of string and copy at lines 5 and 6 is flawed.
copy() will copy characters out of string, but str is empty.
The second argument to copy() is a length argument, not a source string.
http://www.cplusplus.com/reference/string/string/copy/

Your strcpy's at 7 and 8 should be okay, but as others have said use strings, not char arrays.



Yeah, I have a whole program. I had thought it wouldn't be nessasary to post the whole thing, but it seems that I was wrong, so heres what I have for my address book

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
#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 


And my 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
#include <iostream>
#include<string>
using std::string;
#include "addressBook.h"
using namespace std;

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(char *fName, char *lName, char *address)
: head(0), tail(-1)
{
 PERSON tmp;
 string str;
 str.copy(tmp.fName,fName);
 strcpy(tmp.lName,lName);
 strcpy(tmp.Address, address);
 addPerson(tmp);
}

bool addressBook::addPerson(const PERSON &p)
{
 
 
 people.push_back(p);

 if(tail == -1)
 tail++;
 return true;
 
}
bool addressBook::getPerson(PERSON &p)
{
 if(tail >=0)
 {
 if(tail >= people.size())
 tail = 0;
 p = people[tail];
 tail++;
 return true;
 }
 return false;
}
bool addressBook::findPerson(char *lastName, PERSON &p)
{
 for(int i = 0; i < people.size(); i++)
 {
 if(!stricmp(people[i].lName, lastName))
 {
 p = people[i];
 return true;
 }
 }
 return false;
}
bool addressBook::findPerson(char *lastName, char *firstName, PERSON &p)
{
 for(int i = 0; i < people.size(); i++)
 {
 if(!stricmp(people[i].lName, lastName) && !stricmp(people[i].fName, firstName))
 {
 p = people[i];
 return true;
 }
 }
 return false;
}


void addressBook::printBook()
{
 for(int i = 0; i < people.size(); i++)
 {

 cout << people[i].fName << "\t" << people[i].lName << "\t" << people[i].Address << endl;
 }
}

 bool addressBook::sortcomp(const PERSON& p1, const PERSON& p2)
{
    int result = std::strcmp(p1.lName, p2.lName) ;

    if ( result > 0 )
        return true ;
    if ( result < 0 )
        return false ;
    return std::strcmp(p1.fName, p2.fName) > 0 ;
}

void addressBook::sort() 
{
    bool didSwap ;

    do
    {
        didSwap = false ;

        for ( unsigned 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;
};

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

ostream &operator << (ostream &output, addressBook &ab)
{
	PERSON tmp;
    ab.getPerson(tmp);
	output << tmp.fName << " " << tmp.lName << " " << tmp.Address << endl;
	return output;
}


And finally, my 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
#include <iostream>
#include <cstdlib>
#include <conio.h>
#include <string>
using std::string;
#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 NAMESORT = 6;
const int EXIT = 0;

int main()
{
	PERSON p;
	addressBook ad;
	addressBook ab;
	addressBook myBook;

	addressBook newBook("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;

	me3 = newBook[2];
	

int selection;

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 = 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.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 = ad.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 = ad.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 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;
				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 << "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 figured I'd start on one of the older assignments, and since strcpy is just copying, it seemed like all I would have to do is just convert it to str.copy. I'm assuming I have to convert all my chars in my PERSON struct over to strings first?
Last edited on

Based on your post here, I'm assuming PERSON is the same struct.
http://www.cplusplus.com/forum/beginner/93761/

Your use of string and copy at lines 5 and 6 is flawed.
copy() will copy characters out of string, but str is empty.
The second argument to copy() is a length argument, not a source string.
http://www.cplusplus.com/reference/string/string/copy/

Your strcpy's at 7 and 8 should be okay, but as others have said use strings, not char arrays.


Ok, since copy is copying out of the string, would I instead try to assign my tmp to the string since that functions job is to copy what I've posted in main over to the struct so it can be added to the address book?
Last edited on
There is a convention that member variables can start with m_ as in m_fName. This makes it easier for naming things - m_fName = fName;

It is preferable to initialise variables with default values, as you have done with head & tail, as opposed to to assignment. ( I learnt this recently myself.) This is because the default constructor initialises variables first, then they get reassigned by your constructor straight away, so using the initialiser list is more efficient. And to always use const wherever you can:
1
2
3
4
5
6
7
8 addressBook::addressBook(const std::string fName, const std::string lName, const std::string address)
: head(0),
tail(-1),
m_fName(fName),
m_lName(lName),
m_address(address) {
//other code here - if any
}



This code is just an example starting with your code, I am not sure of what the entire structure of your class is, or whether you might change it after seeing my comments above.

Hope all goes well.


Ok, that actually makes sense, and I didn't know about the m_ convention either. The lectures we get are usually pretty brief, so this helps. Since I have to change my operator to strings in my addressBook.cpp, I assume then that I should also follow suit in my header as well?
Sorry for the delay - my browser threw a wobbly & I had to type everything again.

I assume then that I should also follow suit in my header as well?


Yes, they need to be consistent.

Now your constructor can look like this:

1
2
3
4
5
6
7
8
addressBook::addressBook(const std::string fName, const std::string lName, const std::string address)
: head(0),
tail(-1),
people.m_fName(fName),
people.m_lName(lName),
people.m_address(address) {
//other code here - if any
}


I wouldn't have bothered with lines 12-18 in main(), if you really wanted to they could be an enum.

You should always put a default clause in a switch to catch bad input - just like an else in an if statement.

Just thinking the code in the switch cases should be part of member functions, which the switch would call. That way everything is encapsulated in the class.

You should always put a default clause in a switch to catch bad input - just like an else in an if statement.

Just thinking the code in the switch cases should be part of member functions, which the switch would call. That way everything is encapsulated in the class


OK, I don't think we've covered that, what is a default clause? The teacher could care less about what we have in main, he doesn't ever look at it or grade off of it, so that may be why we've never covered it. He was the one who provided the main for us to test our homework off of. It was based off of stuff from the level 1 class, but it's miles beyond what we did in that class.

As for the people.n_fName stuff, I actually forgot we had put in a vector called people. I was trying to get to what you were showing me through creating PERSON tmp, an then doing tmp.m_fName, which wasn't working.

So this would then take the vector that ties into the struct, create m_fName, and then tie it into th fName from the struct itself, which would then get added to the addPErson function? If so, how do I tie that into addPerson? Right now I have it as addPerson(tmp);. Would I instead just do it as addPerson(people?);

Thanks for the help by the way, this is actually starting to make some sense now.
Oh, and if I've already included std::string; up at the top, do I still need it in the constructor?
1
2
3
4
5
6
7
8
9
10
......
case EXIT :
	cout << "Thanks for using the address book " << endl;
	exit(0);
        break;
default:
        //some sort of error
        //fix it
        break;
} //end of switch 


http://www.cplusplus.com/doc/


There is lots of info in the reference section at the top left of this page - check it out.

So this would then take the vector that ties into the struct, create m_fName, and then tie it into th fName from the struct itself, which would then get added to the addPErson function? If so, how do I tie that into addPerson? Right now I have it as addPerson(tmp);. Would I instead just do it as addPerson(people?);


No need, my code snippet initialises the variables, nothing else needs to be done. It works because the default access levels for structs is public, this is the only difference between classes & structs. It's OK because the people struct is private in the class. Remember class functions have direct access to member variables.

Thanks for the help by the way, this is actually starting to make some sense now.


No worries, It's cool when someone learns something.
Oh, and if I've already included std::string; up at the top, do I still need it in the constructor?


The best thing is to not have
using namespace std;
anywhere in your code , I do this for frequently used things:

1
2
3
4
5
using std::cout;
using std::cin;
using std::endl;

using std::string;


Edit: Then you can use these without qualification.

The scope of these is the rest of the file. If it is in a header file, then it will apply to whatever file the header is included in.


And then I put std:: before any other STL thing, that doesn't appear very often, like std::find say.

A lot of people put std:: everywhere and don't have any using statements at all.

The reason for this is that
using namespace std;
brings the whole of the std namespace into the global namespace polluting it. Did you know that there is a std::distance ?

Any reasonable sized app should have it's own namespace - read up about it.
Last edited on
AHA! I was wondering if there were a way to call up a problem when the user enters something wrong. It was never covered in class, but I noticed that if you enter a letter and not a number, the program crashes. Now I know.

As for the code, I tried it out, and entered the constructor into the header, but the compiler doesn't like it. I get a couple of errors...


Error 1 error C2059: syntax error : '.' c:\users\cj\documents\visual studio 2012\projects\address\address\addressbook.cpp 36 1 address
6 IntelliSense: expected a '(' c:\Users\CJ\Documents\Visual Studio 2012\Projects\address\address\addressbook.cpp 36 7 address
8 IntelliSense: expected a '(' c:\Users\CJ\Documents\Visual Studio 2012\Projects\address\address\addressbook.cpp 37 7 address
10 IntelliSense: expected a '(' c:\Users\CJ\Documents\Visual Studio 2012\Projects\address\address\addressbook.cpp 38 7 address
7 IntelliSense: member "addressBook::people" has already been initialized c:\Users\CJ\Documents\Visual Studio 2012\Projects\address\address\addressbook.cpp 37 1 address
9 IntelliSense: member "addressBook::people" has already been initialized c:\Users\CJ\Documents\Visual Studio 2012\Projects\address\address\addressbook.cpp 38 1 address
Warning 3 warning C4018: '<' : signed/unsigned mismatch c:\users\cj\documents\visual studio 2012\projects\address\address\addressbook.cpp 68 1 address
Warning 4 warning C4018: '<' : signed/unsigned mismatch c:\users\cj\documents\visual studio 2012\projects\address\address\addressbook.cpp 80 1 address
Warning 5 warning C4018: '<' : signed/unsigned mismatch c:\users\cj\documents\visual studio 2012\projects\address\address\addressbook.cpp 94 1 address
Warning 2 warning C4018: '>=' : signed/unsigned mismatch c:\users\cj\documents\visual studio 2012\projects\address\address\addressbook.cpp 58 1 address



This is why I decided to try and work this out on a part of the program thats not a part of the homework. I figured that if I could get this one to work, then I would have a better understanding of how to get this to work on the parts that count. Plus, if I screw it up, it wont matter ;-)
Last edited on
It's my fault I think - people is a vector, so we would normally need either a subscript or the at function. Because it is a constructor you could use the [0] subscript.

Can you post your new code for addressbook.cpp so we can match up the other errors with line numbers?
Last edited on
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
#include <iostream>
#include<string>
using std::string;
#include "addressBook.h"
using namespace std;

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 std::string fName, const std::string lName, const std::string address)
: head(0),
tail(-1),
people.m_fName(fName),
people.m_lName(lName),
people.m_address(address) 
{
	
}

bool addressBook::addPerson(const PERSON &p)
{
 
 
 people.push_back(p);

 if(tail == -1)
 tail++;
 return true;
 
}
bool addressBook::getPerson(PERSON &p)
{
 if(tail >=0)
 {
 if(tail >= people.size())
 tail = 0;
 p = people[tail];
 tail++;
 return true;
 }
 return false;
}
bool addressBook::findPerson(char *lastName, PERSON &p)
{
 for(int i = 0; i < people.size(); i++)
 {
 if(!stricmp(people[i].lName, lastName))
 {
 p = people[i];
 return true;
 }
 }
 return false;
}
bool addressBook::findPerson(char *lastName, char *firstName, PERSON &p)
{
 for(int i = 0; i < people.size(); i++)
 {
 if(!stricmp(people[i].lName, lastName) && !stricmp(people[i].fName, firstName))
 {
 p = people[i];
 return true;
 }
 }
 return false;
}


void addressBook::printBook()
{
 for(int i = 0; i < people.size(); i++)
 {

 cout << people[i].fName << "\t" << people[i].lName << "\t" << people[i].Address << endl;
 }
}

 bool addressBook::sortcomp(const PERSON& p1, const PERSON& p2)
{
    int result = std::strcmp(p1.lName, p2.lName) ;

    if ( result > 0 )
        return true ;
    if ( result < 0 )
        return false ;
    return std::strcmp(p1.fName, p2.fName) > 0 ;
}

void addressBook::sort() 
{
    bool didSwap ;

    do
    {
        didSwap = false ;

        for ( unsigned 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.fName << " " << tmp.lName << " " << tmp.Address << endl;
	return output;
}


This is what you gave me. I tried adding a pointer to the fName, Lname and address, but that didn't work either. this is what's in the header...

 
addressBook(const std::string fName, const std::string lName, const std::string address);


I also tried making that a friend function, giving it access to the vector in private,

 
friend PERSON addressBook(const std::string fName, const std::string lName, const std::string address);


No luck there either, it just didn't like the people.
Last edited on
I only have to do this with my findPerson function, that's the only part of the actual program that uses the old CString, but I figured using it here would help me understand how these things work. The findPerson uses a compare, as opposed to what were working on, which should just copy one string to another. Am I just overdoing it? I tend to overdo what required sometimes, but I want to actually understand what I'm doing.
Just started playing around with subscripts, (haven't been taught them yet, or at least I dont think we have). I tried this:

1
2
3
4
5
6
7
8
9
10
addressBook::addressBook(const std::string *fName, const std::string *lName, const std::string *address)
: head(0),
tail(-1)
{
	
	string a[1] = {*fName};
	string b[1] = {*lName};
	string c[1] = {*address};
	
}


That stopped giving me errors, most likely because its not doing anything I'm guessing, but it refuses to play nice with the input I had for this function in main (an address entry through addressbook and the PERSON struct). I'm guessing I'm about a million miles off what a subscript should do, but I thought it would be interesting to at least try.
1
2
3
4
5
6
7
8
9
addressBook::addressBook(const std::string fName, const std::string lName, const std::string address)
: head(0),
tail(-1),
people[0].m_fName(fName),
people[0].m_lName(lName),
people[0].m_address(address) 
{
	
}


That should work, as long as you change the PERSON struct to look like this:

1
2
3
4
5
6
struct PERSON
{
 char m_fName[25];
 char m_lName[25];
 char m_address[100];
};


The subscript for a vector is the same idea as the subscript for an array - [0] is the first item in the container. This should work for any container that has an [] operator, which is the case for vector.

Also, this shouldn't change anything for other functions - all we have done is access the data directly in the initialiser list. Of course you can change findPerson so it deals with strings, but it would be better to fix the constructor first.

Any way the whole idea i am trying to convey is: using the initialisation list; and referring to things directly.

Sorry for messing you around a bit.
Last edited on
I have just put your code into my compiler to help fix it.

Will get back to you, but still let me know how you get on.

EDIT: I have to go out for about an hour or so, will be back.
Last edited on
Tried that last bit, still giving me the same errors. This thing just doesn't like strings. Calling it a night, and will have another go at it tomorrow. The teacher has office hours tomorrow afternoon. I'm gonna run this by him, he's usually really good at explaining things face to face. Theres just something I'm not grasping about this. I get what your telling me, and it all makes perfect sense. I've even done a bunch of reading on all of this, but I am clueless as to why this isn't working, theres gotta be something I'm missing.

Thanks again for all the help, seeing the code and working it out is how I actually learn stuff, and you've been a ton of help. I'll let you know what the teacher extols upon me tomorrow.
Pages: 12