using arrays and copy constructors

well I have a class of type student. Each student has two data members: a name ( char pointer ) and a gpa (double ). In main I create a array of type student able to hold 10 students. After filling it, I decide to test out my copy constructor, but creating a new student and giving it the value of one of the array students. However, the name of the new student ends up containing garbage even tho the student name in the array was sized exactly!

I decided to overload my assignment operator for copying but i'll start by showing my copy constructor:



student ( const student& rhs )
{

int len;
len = strLen(rhs.name);
name = new char[ len ];
gpa = rhs.gpa;
strCpy( rhs.name, name );

}

and here is my assignment operator:


student& student::operator=( const student &rhs )
{

if( this == &rhs )
{
return *this;
}

delete[] this->name;

int len;
len = strLen(rhs.name);
if( rhs.name != '\0')
{
name = new char[ len+1 ];
gpa = rhs.gpa;
strCpy( rhs.name, name );
}


return *this;
}


Any my implementation in Main. All im doing here is creating a new student and trying to make it equal to the fourth portion of my student array.


student greg = room[4];


but when i print out the name for greg by just cout << greg.name in a print function, it contains garbage! Any help would be greatly apppreciated, thankyou.
reckeck your use of the strCpy function - particularly the order of the parameters
I made my own string copy function with the source being first and the dest being second, so I know thats not the problem. It seems that after using my copy constructor, and I pass the new student to a print function to get printed, the name results in partly garbage. the name is there, but it is followed by garbage. And this same occurence happens when i try to reprint the student I copied from even tho this student name obviously did not contain any garbage before. However if i create a new print funtion where i pass the address of the student instead:

print( &room[4] ) INSTEAD OF print( room[4] )

it prints the name fine! Im just wondering why this is, because i should just be able to pass a student and have it print correctly.
I knew there was a windows function with that exact same name - so that will be an error on my part. I suppose the function to calculate the sting length is also your design?

Can you post the whole code, including your string functions>
sure. Well I'll start with my header file:


class student{
double gpa;
char* name;

public:

student()
{
gpa = 0;
name = '\0';
}

student( double x, char* y )
{

gpa = x;
int len = strLen( y );
name = new char[len+1];
strCpy( y, name );

}

~student()
{
delete[] name;
}


student ( const student& rhs )
{

int len;
len = strLen(rhs.name);
name = new char[ len ];
gpa = rhs.gpa;
strCpy( rhs.name, name );

}

int pop( student* &arr, char* filename );
void print(student* arr);
int strLen( char *pointer );
void strCpy( char* source, char* dest );
student& operator=( const student &rhs);
void print2( student arr );
};


And here are the implementations of my functions, including the string functions:

#include "student1.h"
#include <iostream>
#include <fstream>

using namespace std;

int student :: pop( student* &arr, char* filename )
{
int size;
int count;
char* tmp = new char [20];
int len;
ifstream fin;
char* nam;
double gp;

fin.open( filename );
fin >> size;

arr = new student [size+10];
for( count = 0; count<= size; count++ )
{
fin >> tmp;
len = arr->strLen(tmp);
nam = new char[ len+1 ];
arr->strCpy( tmp, nam );
fin >> gp;
arr[count] = student( gp, nam );
}

fin.close();
return size;
}

// the following print function prints using the address of each student and prints the name correctly
void student :: print( student* arr )
{

cout << strLen((*arr).name) << (*arr).name << (*arr).gpa << endl;

}

// the following print function prints using the student object, and prints extra garbage along with the name
void student :: print2( student arr )
{

cout << strLen(arr.name)<< ' '<< arr.name << arr.gpa << endl;

}

int student::strLen( char *pointer )
{
int count=0;

// increment counter and pointer while pointer does not equal null
while( *pointer != '\0' )
{
pointer++;
count++;
}
return count;
}

void student::strCpy( char* source, char* dest )
{


// while pointer does not equal null char, copy contents
while( *source != '\0' )
{
*dest = *source;
source++;
dest++;
}


}

student& student::operator=( const student &rhs )
{

if( this == &rhs )
{
return *this;
}

delete[] name;

int len;
len = strLen(rhs.name);
if( rhs.name != '\0')
{
name = new char[ len+1 ];
gpa = rhs.gpa;
strCpy( rhs.name, name );
}

cout << "overloaded assignment used";
return *this;
}

and in my main I call the copy constructor, If youd like me to post all of my main let me know, but i didn't think it necessary

cout<< "using copy constructor";
student greg(room[4]);

// here i print out using student which shows extra garbage in the name
dum.print2( room[4] );
dum.print2( greg );

// and here i print out using addresses and they print out correctly.
dum.print( &room[4] );
dum.print( &greg );
To start with,
your strCpy function is not doing the copy correctly - it is not terminating the destination correctly (it is not putting the '\0' terminator in the destination string) - fatal error.

EDIT: (I will add these errors as I find them)
The copy constructor is incorrect- The value specified for the Length (name = new char[ len ]; ) is not enough - fatal error

EDIT:
This one isn't particularly an error - more of a design flaw.
For the print functions, you pass a student object or a pointer_to_student to the function.
1
2
void print(student* arr);
void print2( student arr );


This means that a student object doesn't print itself directly.
For example - this means that for a student object to print itself you have to do this:
1
2
3
4
student s;
s.print(&s); //pass a pointer of itself  to it self for printing
//or
s.print2(s); //pass a  copy of itself to  itself for printing 

The second method is particulary bad as it means uneccessary copying of the object.

The print functions could be reduced to a single function that takes no parameters
1
2
3
4
void student::print()
{
     cout << strLen(name)<< ' '<< name << gpa << endl;
}

Last edited on
THANKS SO MUCH!, your print advice really helped me out. Before I didn't realize what I was printing out but now I realize that

greg.print()

prints out all of the components of greg while something like

greg.print( alex );

prints out a foreign address from greg resulting in garbage.

so the problem just lied with my print function! lol
Topic archived. No new replies allowed.