Click to See Complete Forum and Search --> : Loop with Pointers to Objects


matthewmonkan
February 11th, 2008, 05:31 PM
Hey guys. I'm creating a Student class as shown below. I read in student data from a text file (this all works by the way as the class and its functions are written) into multiple Student objects (Student a, Student b, etc...). However, I need to create an array of pointers to student objects. I'm guaranteed in the data file that there is no more than 100 students, so I made this:


Student * studentArray[100];


But I have no idea how to go about reading in a list of data during runtime so that the data goes into each object and each object goes into an array. I'm looking through textbooks and online resources and am so lost....I would greatly appreciate any help. If you look at my code, all I know how to do is hardcode Student objects.



#include <iostream>
#include <cassert>
#include <cstring>
#include <string>
#include <fstream>
using namespace std;




//----- Student Class -----//

class Student
{
public:
Student() {};
Student( int s, string ln, string fn, char mn, string c, string st, string phone,
char gend, char yr, int cred, double gpa, string mjr );
void display();

private:
int studentID, credits;
char gender, middleName, year;
double gpa;
string city, firstName, lastName, major, phoneNumber, state;
};

Student::Student ( int s, string ln, string fn, char mn, string c, string st, string phone,
char gend, char yr, int cred, double g, string mjr )
{
studentID = s;
lastName = ln;
firstName = fn;
middleName = mn;
city = c;
state = st;
phoneNumber = phone;
gender = gend;
year = yr;
credits = cred;
gpa = g;
major = mjr;
}

void Student::display()
{
cout.setf(ios::fixed);
cout.setf(ios::showpoint);
cout.precision(2);

cout << endl;
cout << studentID << " " << lastName << " " << firstName << " " << middleName << endl;
cout << city << " " << state << endl;
cout << phoneNumber << endl;
cout << gender << " " << year << " " << credits << " " << gpa << " " << endl;
cout << major << endl;
}

//----- End of Student Class -----//



int main()
{
// 1. Prompt user for name of file containing the student data.

cout << "Enter the name for the input file: ";
string inputFileName;
getline(cin, inputFileName);


ifstream fin;
fin.open(inputFileName.data());
assert( fin.is_open() );


int studentID, credits;
char gender, middleName, year;
double gpa;
string city, firstName, lastName, major, phoneNumber, state;
Student * studentArray[100];

fin >> studentID >> lastName >> firstName >> middleName >> city >> state
>> phoneNumber >> gender >> year >> credits >> gpa >> major;


Student a (studentID, lastName, firstName, middleName, city, state,
phoneNumber, gender, year, credits, gpa, major);

fin >> studentID >> lastName >> firstName >> middleName >> city >> state
>> phoneNumber >> gender >> year >> credits >> gpa >> major;

Student b (studentID, lastName, firstName, middleName, city, state,
phoneNumber, gender, year, credits, gpa, major);

fin >> studentID >> lastName >> firstName >> middleName >> city >> state
>> phoneNumber >> gender >> year >> credits >> gpa >> major;

Student c (studentID, lastName, firstName, middleName, city, state,
phoneNumber, gender, year, credits, gpa, major);

a.display();
b.display();
c.display();


// 2. Read in file and store contents in an array of pointers to
// student objects. How do I do this?

return 0;
}



The data file I read from looks like this:
(Every five lines there is a new student)

10103 Johnson, James L
Waupun, Wisconsin
7345229
M 1 15 3.15
ENGR
10104 Andrews, Peter J
Grand-Rapids, Michigan
9493301
M 2 42 2.78
CPSC
10110 Peters, Andrew J
Lynden, Washington
3239550
M 5 63 2.05
ART
10113 VandenVander, Vanessa V
Fremont, Michigan
5509237
F 4 110 3.74
HIST
10126 Aristotle, Alice A
Chino, California
3330861
F 3 78 3.10
PHIL

The whole list has about 60 or so students.

If I need to clarify anything, feel free to ask; I'll be monitoring every 10 minutes or so...but please, I really need some help...I'm just lost. Thanks!

Bench_
February 11th, 2008, 05:49 PM
What you're attempting to do is probably easier if you avoid pointers altogether (And avoid arrays for that matter too).

You could create a vector<Student> - which is essentially a "C++ Array" storing student objects. There's no need to create pointers, provided that all your objects are students (Assuming you're not going to derive from your student class)

#include <vector> std::vector<Student> my_students; fin >> studentID >> lastName >> firstName >> middleName >> city >> state
>> phoneNumber >> gender >> year >> credits >> gpa >> major;

Student temp (studentID, lastName, firstName, middleName, city, state,
phoneNumber, gender, year, credits, gpa, major);

my_students.push_back(temp);

matthewmonkan
February 11th, 2008, 06:28 PM
I've tried using the vectors (and I've used them before) but my compiler (Eclipse) keeps throwing out of range errors and closing itself. Sometimes it gives me an error along the lines of:

"make: vfork: Resource temporarily unavailable".
But let's skip that for the moment.

I'd prefer help with generating an array of pointers to Student objects as mentioned earlier just so I can learn how it's done. Later, I will need to be able to change some contents of student objects by searching for a string and replacing it with user input.

For example, I might want to change a major for a specific student, or add in a new GPA grade.

I don't want to sound like I'm lazy, but if anyone can point me to example code or show me some steps, it would help immensely; I've been reading books and browsing the web forever.

Again, my goal is to create an array of pointers to student objects, as read in from a data file. (See my first post for a snippet.) But I can't visualize how that's done. And when I am done, how would I even print out the students in each array subscript or access them? Is there a way to give each Student object in the array a different name (Student a, Student b, Student c, etc...) and then I just do a.display(), b.display etc?

Bench, thanks for your response! I understood what you were doing, but I couldn't get it to work, and I don't understand how I would've accessed each Student object in the vector if I had gotten it to work.

matthewmonkan
February 11th, 2008, 06:46 PM
Here is another attempt. Maybe someone can point out what I'm misunderstanding? Is this a start?



#include <iostream>
#include <cassert>
#include <cstring>
#include <string>
#include <fstream>
using namespace std;




//----- Student Class -----//

class Student
{
public:
Student() {};
Student( int s, string ln, string fn, char mn, string c, string st, string phone,
char gend, char yr, int cred, double gpa, string mjr );
void display();

private:
int studentID, credits;
char gender, middleName, year;
double gpa;
string city, firstName, lastName, major, phoneNumber, state;
};

Student::Student ( int s, string ln, string fn, char mn, string c, string st, string phone,
char gend, char yr, int cred, double g, string mjr )
{
studentID = s;
lastName = ln;
firstName = fn;
middleName = mn;
city = c;
state = st;
phoneNumber = phone;
gender = gend;
year = yr;
credits = cred;
gpa = g;
major = mjr;
}

void Student::display()
{
cout.setf(ios::fixed);
cout.setf(ios::showpoint);
cout.precision(2);

cout << endl;
cout << studentID << " " << lastName << " " << firstName << " " << middleName << endl;
cout << city << " " << state << endl;
cout << phoneNumber << endl;
cout << gender << " " << year << " " << credits << " " << gpa << " " << endl;
cout << major << endl;
}

//----- End of Student Class -----//



int main()
{
// 1. Prompt user for name of file containing the student data.

cout << "Enter the name for the input file: ";
string inputFileName;
getline(cin, inputFileName);


ifstream fin;
fin.open(inputFileName.data());
assert( fin.is_open() );


int studentID, credits;
char gender, middleName, year;
double gpa;
string city, firstName, lastName, major, phoneNumber, state;
Student * studentArray[100];

fin >> studentID >> lastName >> firstName >> middleName >> city >> state
>> phoneNumber >> gender >> year >> credits >> gpa >> major;


Student * temp (studentID, lastName, firstName, middleName, city, state, phoneNumber, gender, year, credits, gpa, major);

int i=0;

while (fin)
{
fin >> studentID >> lastName >> firstName >> middleName >> city >> state
>> phoneNumber >> gender >> year >> credits >> gpa >> major;
Student temp (studentID, lastName, firstName, middleName, city, state,
phoneNumber, gender, year, credits, gpa, major);
studentArray[i] = temp;
i++;
}


// 2. Read in file and store contents in an array of pointers to
// student objects. How do I do this?

return 0;
}

NMTop40
February 11th, 2008, 06:47 PM
If you are going to have a collection of pointers you will have to manage them. Now you can go through at the end and call delete on each one, or you can use a type of smart pointer that will do that for you.

Reference-counted smart-pointers, known as shared_ptr will very soon be part of the standard, so you may as well learn to start using them.

matthewmonkan
February 11th, 2008, 07:57 PM
What you're attempting to do is probably easier if you avoid pointers altogether (And avoid arrays for that matter too).

You could create a vector<Student> - which is essentially a "C++ Array" storing student objects. There's no need to create pointers, provided that all your objects are students (Assuming you're not going to derive from your student class)

#include <vector> std::vector<Student> my_students; fin >> studentID >> lastName >> firstName >> middleName >> city >> state
>> phoneNumber >> gender >> year >> credits >> gpa >> major;

Student temp (studentID, lastName, firstName, middleName, city, state,
phoneNumber, gender, year, credits, gpa, major);

my_students.push_back(temp);



Okay, I tried this and got this to work. Now, if I put a loop around it so that it keeps reading in more students, would that create a distinct Student object named "temp" in each vector subscript? Or would I have to type into my main function 60 different things (Student a, Student b, Student c, Student d, Student e, Student f....etc) and copy & paste code?

Paul McKenzie
February 11th, 2008, 08:05 PM
Okay, I tried this and got this to work. Now, if I put a loop around it so that it keeps reading in more students, would that create a distinct Student object named "temp" in each vector subscript?The std::vector stores copies of your object, not the original object.

Regards,

Paul McKenzie

code_carnage
February 12th, 2008, 12:47 AM
Reference-counted smart-pointers, known as shared_ptr will very soon be part of the standard, so you may as well learn to start using them.

Only refrence counting smart pointer is not enough..Unless class of which pointer are being crteated supports refrence counting...shared_ptr can hardly do anything...

Bench_
February 12th, 2008, 03:18 AM
Okay, I tried this and got this to work. Now, if I put a loop around it so that it keeps reading in more students, would that create a distinct Student object named "temp" in each vector subscript? Or would I have to type into my main function 60 different things (Student a, Student b, Student c, Student d, Student e, Student f....etc) and copy & paste code?
They wouldn't be named anything - as Paul McKenzie said, you'll get copies inserted into your vector. Variable names such as "temp" are stripped out by the compiler anyway - so from a runtime point of view, names are meaningless. The important factor is that you'll have multiple student objects stored by the vector, because push_back is able to add extra memory to the vector for you, which will store each student object separately.

You can access them the same way you would with a normal array (Vectors let you use the [ ] subscript notation. alternatively, you could use the .at() function. eg, for position 3 in the vector, you've got a choice of,
my_students[3];
my_students.at(3);
This notation gives direct access to objects which you've already added to the vector (it keeps the size of the vector the same). adding new objects should normally be done by push_back, or another similar function, since the vector needs to be re-sized.

The benefit of doing this without pointers, is that you've got no memory worries - everything is automatically created and deleted for you by the vector. When you start pointing to objects, you generally need to manually create them with new, and destroy them with delete. This gets messy really quickly.