Overloading operators to accept array of objects

I am trying to overload "==" so I can compare two arrays that holds objects.
I am suppose to compare the id numbers of the Student objects.

This is the object parameters Student.h
Student(int id, string name, string school);

//Student.cpp
1
2
3
4
5
6
7
Student::Student (int id, string name, string school) {

	Fid = id;
	Fname = name;
	Fschool = school;

}


Student.h
bool operator == (const Student &other) const;

Student.cpp
1
2
3
4
5
6
7
8
  bool Student::operator == (const Student &other) const {
	if(this->Fid==other.Fid) { // This is where I can't get to work
		return true;
	}

	return false;
}


I need to overload this to use sort function with the Student object
1
2
3
4
5
6
7
8
9
10
bool Student::operator < (const Student &other) const {
	if(this->Fid<other.Fid) { 
		return true;
	}
	
	return false;
}





This is an example to show what I need "==" to do.
It should take two different arrays that contains Student objects and check if they are the same with linear search
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
Student* findCommonStudents1(Student group1[], int len1, Student group2[],
		int len2, int numCommon) {
	
	Student *commonArray1 = new Student[numCommon];//An array that will hold the common students
	
	int counter=0;
	
	for(int i=0;i<len1;i++) {
		
		for(int a=0;a<len2;a++) {
			
			if(group1[i]==group2[a]) { //Suppose to check if the id numbers are matching
				commonArray1[counter]=group1[i];
				counter++;

			}//enf of if statment
		
		}//end of inner for loop
	
	}//end of outer for loop

	return commonArray1;

}//end of findCommonStudents1





Last edited on
Does it give you an error message or what?
A window pops up with this

First-chance exception at 0x012B11E9 in programmingProject1.exe: 0xC0000005: Access violation reading location 0x00000004.

If there is a handler for this exception, the program may be safely continued.



It gives an option for me to break where the exception is and when I do that it show the line with this
if(this->Fid==other.Fid)


And this is the output when I end the program
First-chance exception at 0x011011E9 in programmingProject1.exe: 0xC0000005: Access violation reading location 0x00000004.
Unhandled exception at 0x011011E9 in programmingProject1.exe: 0xC0000005: Access violation reading location 0x00000004.
First-chance exception at 0x011011E9 in programmingProject1.exe: 0xC0000005: Access violation reading location 0x00000004.
Unhandled exception at 0x011011E9 in programmingProject1.exe: 0xC0000005: Access violation reading location 0x00000004.
First-chance exception at 0x011011E9 in programmingProject1.exe: 0xC0000005: Access violation reading location 0x00000004.
Unhandled exception at 0x011011E9 in programmingProject1.exe: 0xC0000005: Access violation reading location 0x00000004.
First-chance exception at 0x011011E9 in programmingProject1.exe: 0xC0000005: Access violation reading location 0x00000004.
The thread 0x4770 has exited with code -1073741510 (0xc000013a).
The program '[19108] programmingProject1.exe' has exited with code -1073741510 (0xc000013a).
closed account (48T7M4Gy)
1
2
3
4
5
6
7
 bool Student::operator == ( const Student &student1, const Student &student2)
{
   if student1. id == student2.id;
   etc 
   ...
   return truth;
}


This is the sort of method you need.

== takes two parameters not just one.
Last edited on
kemort when I do that compiler highlights it and says "too many parameters for this operator function"
closed account (48T7M4Gy)
hmm I'll have to try it
I am just gonna post the whole code, because I have no idea what this error means.
I think it is due to a mistake(or several mistakes) in the code.
Or it might be my compiler going crazy.

main
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
#include <iostream>
#include <fstream>
#include <sstream>
#include <algorithm>
#include <ctime>
#include "Student.h"
using namespace std;




/*
 * Read in a file containing student records and create an array of Student
 * objects
 *
 * @param file The filename
 * @param num The number of students in the file
 * @return An array of Student objects
 */
Student* readStudentsFromFile(string filename, int num) {
	ifstream studentsStream;
	studentsStream.open(filename.c_str());
	
	string line, name, school, sid;
	int id;

	static Student* readArray = new Student [num]; //An array of student object that will contain the read objects
	
	if (!studentsStream.is_open()) {
		cerr << "Couldn't open the file " << filename << endl;
		return NULL;
	}
	
	while (!studentsStream.eof()) {
		
		for(int i=0;i<num;i++) {

			getline(studentsStream, line); 
			istringstream iss(line);
			getline(iss, name, ',');
			getline(iss, sid, ',');
			getline(iss, school, ',');
			istringstream idConv(sid);
			idConv >> id;
			
			readArray[i] = Student(id,name,school); //An array of Student objects
		}//End of for loop
	}//End of while


	studentsStream.close();


	return readArray;
}//End of readStudentsFromFile





/*
 * Write an array of Student objects to a file
 *
 * @param students The array of Student objects to write out
 * @param filename The output filename
 */
void writeStudentsToFile(Student students[], int num, string filename) {

	ofstream output(filename.c_str());
	output.open(filename);
	

	for(int i=0;i<num;i++) {
		string str=students[i].toString();
		output << str<<"\n"<<endl;
	}//End of for loop



	output.close();
}//End of writeStudentsToFile







/*
 * Find students belonging to both groups.
 *
 * This function checks each student in group1 for membership in group2 by
 * comparing it with every student in group2.
 *
 * @param group1 A group of Students
 * @param group2 A group of Students
 * @param numCommon number of students belonging to both groups
 * @return An array of Students which belong to both group1 and group2
 */
Student* findCommonStudents1(Student group1[], int len1, Student group2[],
		int len2, int numCommon) {
	
	Student *commonArray1 = new Student[numCommon];//An array that will hold the common students
	
	int counter=0;
	
	for(int i=0;i<len1;i++) {
		
		for(int a=0;a<len2;a++) {
			
			if(group1[i]==group2[a]) {
				commonArray1[counter]=group1[i];
				counter++;

			}//enf of if statment
		
		}//end of inner for loop
	
	}//end of outer for loop

	return commonArray1;

}//end of findCommonStudents1






/*
 * Find students belonging to both groups.
 *
 * This function checks each student in group1 for membership in group2 by
 * doing a binary search on group2.
 *
 * @param group1 A group of Students
 * @param group2 A group of Students
 * @param numCommon number of students belonging to both groups
 * @return An array of Students which belong to both group1 and group2
 */
Student* findCommonStudents2(Student group1[], int len1, Student group2[],
		int len2, int numCommon) {
	
		int counter=0;

		sort(group1, group1 + len1);
		sort(group2, group2 + len2);
		
		Student *commonArray2 = new Student[numCommon];

		/*
		 * library function to binary search an array for the given value
		 * Note that values must be comparable with the < operator
		 */
		for(int i=0;i<len1;i++) {
			
			bool found = binary_search(group2, group2 + len2, group1[i]);

			if(found==true){

				commonArray2[counter]=group1[i];
				
				counter++;

			}//End of if loop

		}//End of for loop

	return commonArray2;

}//End of findCommonStudents2


int main() {

			/*
			 * DO NOT CHANGE ANY OF THE CODE BELOW
			 * Here just to help you with testing and timing your functions
			 */

	/***** These files provided to help you with initial testing *****/
	const int UC_SIZE = 10;
	const int SMC_SIZE = 5;
	const int SMC_UC_GRADS_SIZE = 2;
	Student* uc = readStudentsFromFile("sample_uc_students.txt", UC_SIZE);
	Student* smc = readStudentsFromFile("sample_smc_grads.txt", SMC_SIZE);

	/********************************** Use these files for the output you submit *************************/
	//const int UC_SIZE = 350000;
	//const int SMC_SIZE = 75000;
	//const int SMC_UC_GRADS_SIZE = 25000;
	//Student* uc = readStudentsFromFile("uc_students.txt", UC_SIZE);
	//Student* smc = readStudentsFromFile("smc_grads.txt", SMC_SIZE);




	// Rough timing
	time_t start, end;

	time(&start);
	Student* common1 = findCommonStudents1(uc, UC_SIZE, smc, SMC_SIZE,
			SMC_UC_GRADS_SIZE);
	time(&end);
	cout << "Using linear search it took " << difftime(end, start) << " seconds."
			<< endl;





	/*
	 * library sort function to sort an array: sort(arr, arr+size)
	 * Note that values must be comparable with the < operator
	 */
	sort(common1, common1 + SMC_UC_GRADS_SIZE);
	writeStudentsToFile(common1, SMC_UC_GRADS_SIZE, "smc_grads_at_uc_1.txt");

	time(&start);
	Student* common2 = findCommonStudents2(uc, UC_SIZE, smc, SMC_SIZE,
			SMC_UC_GRADS_SIZE);
	time(&end);
	cout << "Using binary search it took " << difftime(end, start)
			<< " seconds." << endl;





	sort(common2, common2 + SMC_UC_GRADS_SIZE);
	writeStudentsToFile(common2, SMC_UC_GRADS_SIZE, "smc_grads_at_uc_2.txt");

	delete[] smc;
	delete[] uc;
	delete[] common1;
	delete[] common2;
	return 0;
}


Student.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
#include "Student.h"
#include <iostream>
#include <fstream>
#include <sstream>
#include <algorithm>
#include <ctime>
using namespace std;

Student::Student() {
	
}

Student::Student (int id, string name, string school) {

	Fid = id;
	Fname = name;
	Fschool = school;

}

Student::~Student(){


}



	/*
	 * Returns a string representation of a student object
	 * like "Caroline Greene,10537229,SMC"
	 */
string Student::toString() {

	string str;						

	ostringstream convert;		//Converting the ID number to string
	convert << Fid;				//	
	str=convert.str();			//

	string toString;
	
	return toString.append(Fname).append(",").append(str).append(",").append(Fschool);//Returning added strings
}





	/*
	 * Compares two students by ID for equality
	 */
bool Student::operator == (const Student &other) const {
	if(this->Fid==other.Fid) {
		return true;
	}

	return false;
}



	/*
	 * Compares two students by ID for ordering
	 */
bool Student::operator < (const Student &other) const {
	if(this->Fid<other.Fid) {
		return true;
	}
	
	return false;
}


Student.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
#ifndef STUDENT_H_
#define STUDENT_H_

#include <string>
using namespace std;

class Student {


	int Fid;
	string Fname;
	string Fschool;

public:
	/*
	 * Default ctor
	 */
	Student();



	/*
	 * Overloaded ctor
	 */
	Student(int id, string name, string school);




	/*
	 * Returns a string representation of a student object
	 * like "Caroline Greene,10537229,SMC"
	 */
	string toString();



	/*
	 * Compares two students by ID for equality
	 */
	bool operator == (const Student &other) const;



	/*
	 * Compares two students by ID for ordering
	 */
	bool operator < (const Student& other) const;

	virtual ~Student();
};

#endif /* STUDENT_H_ */ 



closed account (48T7M4Gy)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#ifndef STUDENT_H_
#define STUDENT_H_

#include <string>

using namespace std;

class Student
{
 private:
    int Fid;
    string Fname;
    string Fschool;

public:
    Student();
    Student(int id, string name, string school);
    ~Student();
    string toString();
    friend bool operator== ( const Student&, const Student& );
};
#endif 


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
#include "Student.h"
#include <iostream>
#include <fstream>
#include <sstream>
#include <algorithm>
#include <ctime>
using namespace std;

Student::Student()
{
}

Student::Student (int id, string name, string school)
{
    Fid = id;
    Fname = name;
    Fschool = school;
}

Student::~Student()
{
}

string Student::toString()
{

    string str;
    ostringstream convert;		//Converting the ID number to string
    convert << Fid;				//
    str=convert.str();			//
    string toString;
    return toString.append(Fname).append(",").append(str).append(",").append(Fschool);//Returning added strings
}

bool operator == ( const Student &student1, const Student &student2)
{
     if (student1.Fid == student2.Fid)
        return true;
     else
        return false;
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
#include "Student.h"

using namespace std;

int main()
{
    Student a(123, "XYZ Smith", "CPP Secondary");
    Student b(456, "ABC Jones", "C++ Primary");
    Student c(123, "LMN Green", "ABC University");

    cout << (a==b) << endl;
    cout << (b==c) << endl;
    cout << (a==c) << endl;

    return 0;
}



Try this - it works. I'd forgotten about 'friend'

compiler highlights it and says "too many parameters for this operator function"
That's because kemort's function is not a member function.
Implementing binary operators as global functions requires two parameters: the left and right operands.
Implementing them as member functions requires only the right operand to be explicit: the one on the left is the object on which the operation is invoked, and is implicitly passed as a pointer with the name "this".
The friend declaration is needed because a global function can't access the private member Fid.

When you break on the error, can you see the stack trace? See if you can post it.
Last edited on
I just changed this line
bool found = binary_search(group2, group2 + len2, group1[i]);
to
bool found = binary_search(group2, group2 + len2, group1);
and that access violation errors went away.

Now I get this one

1>------ Build started: Project: tester1, Configuration: Debug Win32 ------
1>  tester1.cpp
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\algorithm(2987): error C2679: binary '<' 
: no operator found which takes a right-hand operand of type 'Student' (or there is no acceptable conversion)
1>          could be 'built-in C++ operator<(Student *, Student *)'
1>          while trying to match the argument list '(Student *const , Student)'
1>          c:\users\afb\documents\visual studio 2012\projects\tester1\tester1\tester1.cpp(163) 
: see reference to function template instantiation 'bool std::binary_search<Student[],Student[]>(_FwdIt,_FwdIt,const _Ty &)' 
being compiled
1>          with
1>          [
1>              _FwdIt=Student [],
1>              _Ty=Student []
1>          ]
It's very cryptic, but it should be saying that the compiler doesn't know how to do "Student < Student*", because you're passing an array as the value to search which is of type Student*.
It was correct in the previous form. You want to pass a value to search for.
I think your Student definition including the operators overloaded does not cause the error.
Instead I found several problems in your main.cpp. Try fixing them and see if the error is still here.

In
readStudentsFromFile(string filename, int num),


static Student* readArray = new Student [num]; //An array of student object that will contain the read objects
1. why do you declare readArray as static?
If you call the function with num = 10 in the first time, then you have the same size (and same array!) in the second, thrid, ... call, no matter what is passed to num.

2. Memory can never be freed if the file is not opened, which causes the function return NULL.

3. You just need the for loop if you are certain of the number of records being reading.
If you want to check if each line is extracted successfully, you can write:
1
2
3
4
5
6
7
8
for(int i=0;i<num;i++) {
  if (getline(studentsStream, line)) {
    // ... read the line
  }
  else {
    // ... throw an exception, or do whatever you want
  }
}


4. If you are uncertain of the number of records, do not use the param num. And because you do not know the size, you probably should use a vector<Student> (even if the size is known beforehand, vector is easier to manage than allocating memory manually).

In
1
2
findCommonStudents1(Student group1[], int len1, Student group2[],
		int len2, int numCommon)
,

5. How can you know the number of common students?

6. Same question for findCommonStudents2

In short, vector is your friend.
Nikko YL
1.I changed the static, you are right about that. Thank you for that. In fact now I do not get errors while building the code. For some reason compiler did not complain anything about that array and it kept complaining about the < operator. Now it works fine except writing the records to the files. But I think that is due to this little part in writeStudentsToFile function

1
2
3
4
for(int i=0;i<num;i++) {
		string str=students[i].toString();
		output << str<<"\n"<<endl;
	}//End of for loop 


I get this while debugging this piece of code.
+ output {_Filebuffer={_Set_eback=0xcccccccc <Error reading characters of string.> _Set_egptr=0xcccccccc <Error reading characters of string.> ...} } std::basic_ofstream<char,std::char_traits<char> >


2.I opened the file
1
2
ifstream studentsStream;
	studentsStream.open(filename.c_str());

This is suppose to open the file right?

3.
That num is defined when function is called in the main so there is no problem with that. Same for common students, it is passed to the function. They are all defined ints. Number of records are certain and passed to the functions. So those numbers do not change, and they are known.


Also I do know that vectors would be 10x easier, but my professor insists we do not use them yet. He will actually cut points for using vectors in this project.


Topic archived. No new replies allowed.