strings and function inside a class for beginners

Hi, how can I play with strings in functions? I would like to achieve something similar but of course it does not work. Actually these are only few lines I have just drafted here, hope it gives you an idea, the code I am working on is much different (and longer)..

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
#include <ctime>
#include <cstdlib>

using namespace std;

class MyClass {
                public:
                        string pickOneString();
                private:
                        string name;
                        string names[] = { "abc", "def", "ghi" };
};

string MyClass::pickOneString() {
        name = names[ (rand() % 20) ];
        cout << name << endl;
};
If the names array never change and is the same for all objects you can declare it outside the class definition. If you have source and header files you should put it in the source file.
static const string names[] = { "abc", "def", "ghi" };
Thanks, actually it changes, or better, the strings which contains are different among the various class I am defining. To let you understand, I want to have many class of this kind, but each of them contains different strings in the array "names". So that I can get different strings

 
MyClass1::pickOneString()

I get one string among those in the names array for that class.

 
MyClass2::pickOneString()

I get a different string among those in the names array for another class etc etc..

Hope it makes sense, I am not even sure this is the simplest way to achieve this...
In that case it will work. Each class will just have to use it's own array. You could make the array a static member but I see no benefits in doing so.
Don't forget to return a value in your function:

1
2
3
4
5
string MyClass::pickOneString() {
        name = names[ (rand() % 20) ];
        cout << name << endl;
        return name;
};


From what I see, you just want a container that holds an array of strings and will return them randomly. For your application, you may want to use just one class type and declare a bunch of objects with that class type. Then set your strings one by one for each class:
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
#include <iostream>
#include <string> //Don't forget to include this!
#include <ctime>
#include <cstdlib>

using namespace std;

class MyClass {
public:
	string pickOneString();
	void   addOneString(string input);

	MyClass(); // Your initializations should go in a constructor.
private:
	int Num_Strings;
	string names[10000]; //Meh, memory is cheap
};

string MyClass::pickOneString() {
	string name = names[ (rand() % Num_Strings) ];
	return name;
}

void MyClass::addOneString(string input) {
	names[Num_Strings++] = input;
}

MyClass::MyClass() { 
	Num_Strings = 0; // We need to initialize a value here. 
}

int main()
{
	MyClass A, B;
	A.addOneString("abc");
	A.addOneString("def");
	B.addOneString("ghi");
	B.addOneString("jkl");

	cout << A.pickOneString() << B.pickOneString();
	return 0;
}


Edit: Increased the size of names to support the code below.
Last edited on
To show you how doing less with a function or class can be better, we can read in a text file containing a list of strings for a class. Say if I was trying to choose a first and middle name for my daughter randomly. I would put the potential first names into a file and the potential middle names into a file. THen I would write this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int main()
{
	MyClass A, B;

	ifstream ReadA("FirstNames.txt"), ReadB("LastNames.txt"); //#include <fstream> above
	string temp;

	while (getline(ReadA,temp))
		A.addOneString(temp); // We've just written possibly thousands of names into A with only two lines of code.

	while (getline(ReadB,temp))
		B.addOneString(temp); // Writing to B is as simple as using another text file and ifstream object.

	cout << "Selected Name: " << A.pickOneString() << " " << B.pickOneString() << endl;

	return 0;
}


We can also see that these lines:
1
2
3
4
5
while (getline(ReadA,temp))
	A.addOneString(temp);

while (getline(ReadB,temp))
	B.addOneString(temp);


reuse the same code. If we wanted, we could put that into the constructor and then we'd just specify the filename as an argument for the constructor and voila, we can merge lines 3-12 into a single line. That means even less code!
Last edited on
If we wanted to save memory and make things a little easier for us, we could use vectors instead of arrays:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
#include <string>
#include <vector> // New vector header
#include <fstream>
#include <ctime>
#include <cstdlib>

using namespace std;

class MyClass {
public:
	string pickOneString();
	void   addOneString(string input);
private:
	vector<string> names;
};

string MyClass::pickOneString() {
	return names[ rand() % names.size() ];
}

void MyClass::addOneString(string input) {
	names.push_back(input);
}


This will work with the main above and reduces the stuff you have to do even further.
Last edited on
Hi, this explains a lot, many thanks. WIth your comments I ended up with the following code:

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
#include <iostream>
#include <string>
#include <ctime>
#include <iomanip>
#include <cstdlib>
#include <vector>

using namespace std;

class Name {
	public:
		string pickOne();

	private:
		string generateFirst();
		string generateLast();
		string name;
		vector<string> names;
};

string Name::generateFirst() {
	names.push_back("bob");
	names.push_back("michael");
	names.push_back("joe");
	
	name = names[ (rand() % names.size() ) ];
	name[0] = toupper(name[0]);
	names.clear();
	return name;
};

string Name::generateLast() {
	names.push_back("smith");
	names.push_back("black");
	names.push_back("murd");

	name = names[ (rand() % names.size() ) ];
	name[0] = toupper(name[0]);
	names.clear();
	return name;
};

string Name::pickOne() {
	
	srand((long)time(NULL));
	
	Name A;
	A.generateFirst();
	string name = A.generateFirst();
	
	A.generateLast();
	name += " ";
        name +=	A.generateLast();
	return name;
};


So, I also thought to work reading files and it actually makes much more sense, but I wanted to have everything in the code for this example. So I went for the vector solution, however, I could not find any better solution than set the strings one by one, isn't possible to use the push_back function to set many strings in once?

As you see I wanted to hide as much as possible and leave public only the function pickOne(), so that in main, which is in another file, I can simply get a full name of a person just creating a Name object and calling the function pickOne(). To achieve this, I could find a better way to have this function creating an object of its class itself... hope this is not something not suggested... does it make sense?
You seed the random number generator with the current time in pickOne() so if you call pickOne() many times in the same second you will get the same name each time. It is much better to only call srand once at the start of the program.
Topic archived. No new replies allowed.