STL sort() function and accumulate() function

Try to sort the student' scores data by student's name, after that, try to use accumulate() to find the average of the score

I read the data from a csv file and sortage them in a vector. However, no matter where i PLACE my sort() function, it won't work.
meanwhile, the accumulate() is not working since I am trying to make two different types of data equal.

I can't really clear explain my issues now(I am confused about the stl), but what I want to attain has stated above. Can anyone help me to figure out the way to solve the problem?

thank you!

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
  #include<iostream>
#include<string>
#include<vector>
#include <fstream> 
#include <algorithm>
#include <functional>
#include <numeric>

using namespace std;
# pragma warning (disable:4996)

// score_data class
class score_data
{
private:
	string Lastname;
	string Firstname;
	int First_Score;
	int Second_Score;
	int Third_Score;
	int Fourth_Score;
	int Fifth_Score;
	int Sixth_Score;
	int Seventh_Score;
	int Eighth_Score;
	int Ninth_Score;
	int Tenth_Score;

public:

	//constructors
	score_data()
	{
		Lastname = "";
		Firstname = "";
		First_Score = 0;
		Second_Score = 0;
		Third_Score = 0;
		Fourth_Score = 0;
		Fifth_Score = 0;
		Sixth_Score = 0;
		Seventh_Score = 0;
		Eighth_Score = 0;
		Ninth_Score = 0;
		Tenth_Score = 0;
	}

	score_data(string lastname, string firstname, int first_score, int second_score, int third_score, int fourth_score, int fifth_score, int sixth_score, int seventh_score, int eighth_score, int ninth_score, int tenth_score)
	{
		this->Lastname = lastname;
		this->Firstname = firstname;
		this->First_Score = first_score;
		this->Second_Score = second_score;
		this->Third_Score = third_score;
		this->Fourth_Score = fourth_score;
		this->Fifth_Score = fifth_score;
		this->Sixth_Score = sixth_score;
		this->Seventh_Score = seventh_score;
		this->Eighth_Score = eighth_score;
		this->Ninth_Score = ninth_score;
		this->Tenth_Score = tenth_score;
	}

	operator double() { return (double)First_Score; }

	//accessor
	string getLastname()
	{
		return Lastname;
	}

	void display() { cout << Lastname << "  " << Firstname << "  " << First_Score << endl; }

	//destructor
	~score_data(){}

	friend score_data operator + (const score_data& sd_1)
	{
		return score_data(sd_1.Lastname, sd_1.Firstname, sd_1.First_Score + sd_1.Second_Score + sd_1.Third_Score + sd_1.Fourth_Score + sd_1.Fifth_Score + sd_1.Sixth_Score + sd_1.Seventh_Score + sd_1.Eighth_Score + sd_1.Ninth_Score + sd_1.Tenth_Score, 0, 0, 0, 0, 0, 0, 0, 0, 0);
	}
};


template <typename T>
class score_data_container
{
private:
	vector<T*> Score_DataVector;
public:
	score_data_container() {}

	void InsertData(T* score)
	{
		Score_DataVector.push_back(score);
		double average_score = accumulate(Score_DataVector.begin(), Score_DataVector.end(), 0.0, plus<score_data>())/3;
		cout << average_score << endl;
	}

	bool rule(const score_data fir, const score_data sec)
	{
		if (fir.Lastname > sec.Lastname)
		{
			return true;
		}
		else
		{
			return false;
		}
	}

	sort(Score_DataVector.begin(), Score_DataVector.end(), rule); // not work

	void show()
	{
		int a = 3;
		int b = 0;
		
		do
		{
			//Score_DataVector[b]->display();
			b++;
		} while (b < a);
	}

	~score_data_container()
	{
		vector<T*>().swap(Score_DataVector);
	}
};

//Function that reads input from file.
bool readinput(score_data_container<score_data> *container, ifstream &infile)
{
	infile.open("Scores.csv");

	if (infile)
	{
		string line;
		string Lastname;
		string Firstname;
		int First_Score;
		int Second_Score;
		int Third_Score;
		int Fourth_Score;
		int Fifth_Score;
		int Sixth_Score;
		int Seventh_Score;
		int Eighth_Score;
		int Ninth_Score;
		int Tenth_Score;

		while (getline(infile, line))
		{
			char *c_line = new char[line.length() + 1];
			strcpy(c_line, line.c_str());
			string str(c_line);

			char *lastname = strtok(c_line, ",");
			char *firstname = strtok(NULL, ",");
			char *first_score = strtok(NULL, ",");
			char *second_score = strtok(NULL, ",");
			char *third_score = strtok(NULL, ",");
			char *fourth_score = strtok(NULL, ",");
			char *fifth_score = strtok(NULL, ",");
			char *sixth_score = strtok(NULL, ",");
			char *seventh_score = strtok(NULL, ",");
			char *eighth_score = strtok(NULL, ",");
			char *ninth_score = strtok(NULL, ",");
			char *tenth_score = strtok(NULL, ",");

			Lastname.assign(lastname);
			Firstname.assign(firstname);
			First_Score = atoi(first_score);
			Second_Score = atoi(second_score);
			Third_Score = atoi(third_score);
			Fourth_Score = atoi(fourth_score);
			Fifth_Score = atoi(fifth_score);
			Sixth_Score = atoi(sixth_score);
			Seventh_Score = atoi(seventh_score);
			Eighth_Score = atoi(eighth_score);
			Ninth_Score = atoi(ninth_score);
			Tenth_Score = atoi(tenth_score);

			score_data *Score_Data = new score_data(Lastname, Firstname, First_Score, Second_Score, Third_Score, Fourth_Score, Fifth_Score, Sixth_Score, Seventh_Score, Eighth_Score, Ninth_Score, Tenth_Score);
			container->InsertData(Score_Data);
		}
	}
	else
		return false;
}

int main()
{
	ifstream infile;
	score_data_container<score_data> *container = new score_data_container < score_data > ;
	if (!readinput(container, infile))
	{
		cout << "Error opening the file!";
		return -1;
	}

	container->show();
	return 0;
}
score_data_container<score_data> *container = new score_data_container < score_data > ;
Why do you want it to be a pointer?
You have a memory leak and no reason to use pointers so just put it on the stack:
1
2
3
score_data_container<score_data> container;
// ...
	container.show();


And then pass it as reference to the readinput function:
bool readinput(score_data_container<score_data>& container, ifstream &infile)

 
	vector<T*> Score_DataVector;

Why do you have a vector of pointers?
Again, pointers are a bad choise here, just use elements on the stack.
vector<T> Score_DataVector;

And why do you pass infile by reference, you don't need it outside the function anymore.
1
2
3
4
5
6
bool readinput(score_data_container<score_data>& container)
{ 
    ifstream infile;

    // rest
}


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
		while (getline(infile, line))
		{
			char *c_line = new char[line.length() + 1];
			strcpy(c_line, line.c_str());
			string str(c_line);

			char *lastname = strtok(c_line, ",");
			char *firstname = strtok(NULL, ",");
			char *first_score = strtok(NULL, ",");
			char *second_score = strtok(NULL, ",");
			char *third_score = strtok(NULL, ",");
			char *fourth_score = strtok(NULL, ",");
			char *fifth_score = strtok(NULL, ",");
			char *sixth_score = strtok(NULL, ",");
			char *seventh_score = strtok(NULL, ",");
			char *eighth_score = strtok(NULL, ",");
			char *ninth_score = strtok(NULL, ",");
			char *tenth_score = strtok(NULL, ",");

			Lastname.assign(lastname);
			Firstname.assign(firstname);
			First_Score = atoi(first_score);
			Second_Score = atoi(second_score);
			Third_Score = atoi(third_score);
			Fourth_Score = atoi(fourth_score);
			Fifth_Score = atoi(fifth_score);
			Sixth_Score = atoi(sixth_score);
			Seventh_Score = atoi(seventh_score);
			Eighth_Score = atoi(eighth_score);
			Ninth_Score = atoi(ninth_score);
			Tenth_Score = atoi(tenth_score);

			score_data *Score_Data = new score_data(Lastname, Firstname, First_Score, Second_Score, Third_Score, Fourth_Score, Fifth_Score, Sixth_Score, Seventh_Score, Eighth_Score, Ninth_Score, Tenth_Score);
			container->InsertData(Score_Data);
		}

Stop mixing C and C++ like that.

Stop using char*, use std::string instead.
You'll get nuts with that many pointers
score_data *Score_Data; // Why a pointer?

use stringstream instead of strtok and atoi
you should also just store the scores in score_data in an array so you can assign them in a loop

1
2
3
4
5
6
7
8
9
10
11
12

	int First_Score;
	int Second_Score;
	int Third_Score;
	int Fourth_Score;
	int Fifth_Score;
	int Sixth_Score;
	int Seventh_Score;
	int Eighth_Score;
	int Ninth_Score;
	int Tenth_Score;
std::array<int, 10> scores; // need #include <array> at the beginning 



Ok, back to the problem:
no matter where i PLACE my sort() function, it won't work.
How should the STL sort function know what element is bigger?
You need to declare an operator< to use STL sort.

after that, try to use accumulate() to find the average of the score

The average of which score?
Of each student, or of each score?
How should accumulate know what value you want to accumulate in score_data?

Is it correct that each score_data has 10 different scores?
And to be honest I don't understand the meaning of score_data, do you want to store information about a student or about a score? What is the purpose of that class? Were there more than 1 Test and so each student has 10 scores for 10 different tests?
Last edited on
I may better post the requirement here

Purpose: Use STL Containers and Algorithms

Using the Scores.csv file:

1. Design a class to hold the score data. To hold the 10 scores, use a vector instead of an array.

2. Convert each line of text in the data file into an instance of the class designed in step #1 and place the class instance into a vector.

3. After reading the data file, sort the data using one of the STL sorting algorithms by student name.

4. After sorting the vector, for each member of the vector, use the STL accumulate algorithm to determine the average score for each student.

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
#include<iostream>
#include<string>
#include<vector>
#include <fstream> 
#include <algorithm>
#include <functional>
#include <numeric>

using namespace std;
# pragma warning (disable:4996)

// score_data class
class score_data
{
private:
	string Lastname;
	string Firstname;
	vector<int>Scores;

public:

	//constructors
	score_data()
	{
		Lastname = "";
		Firstname = "";
		vector<int>Scores(10);
	}

	score_data(string lastname, string firstname, int score_receive[])
	{
		this->Lastname = lastname;
		this->Firstname = firstname;
		
		for (int i = 0; i<10; i++)
		{
			Scores.push_back(score_receive[i]);
		}
	}

	//accessors
	string getLastname(){ return Lastname; }
	string getFirstname(){ return Firstname; }
	int getScores()
	{ 
		for (int i = 0; i < 10; i++)
			return Scores[i];
	}

	////function for calculating the sum of ten scores by using accumulate()
	//void Sum_of_Ten_score()
	//{
	//	for (int i = 0; i < 10; i++)
	//	{
	//		Scores[i];
	//		int sum = accumulate(Scores.begin(), Scores.end(), 0, Plus_all_Scores());
	//		cout << sum << endl;
	//	}

	//}

	void display() { cout << Lastname << "  " << Firstname << "  " << Scores[0] << endl; }

	//destructor
	~score_data()
	{
		vector<int>().swap(Scores);
	}

};

//class for overloading operator() for accumulate() (acts as a rule)
class Plus_all_Scores
{
public:
	int operator()(int s1, score_data& s2)
	{
		return (s1 + s2.getScores());
	}
};

// rule for sorting
const bool rule(score_data fir, score_data sec)
{
	if (fir.getLastname() < sec.getLastname())
	{
		return true;
	}
	else if ((fir.getLastname() == sec.getLastname()) && (fir.getFirstname() < sec.getFirstname()))
	{
		return true;
	}
	else
	{
		return false; //use sort()
	}
}

//container class
template <typename T>
class score_data_container
{
private:
	vector<T> Score_DataVector;

public:
	score_data_container() {}

	//function for inserting data
	void InsertData(T &score)
	{
		Score_DataVector.push_back(score);
	}

	//sort the score_data by rule(alphabetically)
	void Sort()
	{
		sort(Score_DataVector.begin(), Score_DataVector.end(), rule);
	}

	//function for calculating the average of ten scores by using accumulate()
	void Average()
	{
		for (int i = 0; i < 10; i++)
		{
			score_data b = Score_DataVector[i];
int sum = accumulate(Score_DataVector.begin(), Score_DataVector.end(), 0,  Plus_all_Scores());
			cout << sum << endl;
		}
	}

	void show()
	{
		int a = 3;
		int b = 0;

		do
		{
			Score_DataVector[b].display();
			b++;
		} while (b < a);
	}

	~score_data_container()
	{
		vector<T>().swap(Score_DataVector);
	}
};

//Function that reads input from file.
bool readinput(score_data_container<score_data> &container, ifstream &infile)
{
	infile.open("Scores.csv");

	if (infile)
	{
		string line;
		string Lastname;
		string Firstname;
		int First_Score;
		int Second_Score;
		int Third_Score;
		int Fourth_Score;
		int Fifth_Score;
		int Sixth_Score;
		int Seventh_Score;
		int Eighth_Score;
		int Ninth_Score;
		int Tenth_Score;

		while (getline(infile, line))
		{
			char *c_line = new char[line.length() + 1];
			strcpy(c_line, line.c_str());
			string str(c_line);

			char *lastname = strtok(c_line, ",");
			char *firstname = strtok(NULL, ",");
			char *first_score = strtok(NULL, ",");
			char *second_score = strtok(NULL, ",");
			char *third_score = strtok(NULL, ",");
			char *fourth_score = strtok(NULL, ",");
			char *fifth_score = strtok(NULL, ",");
			char *sixth_score = strtok(NULL, ",");
			char *seventh_score = strtok(NULL, ",");
			char *eighth_score = strtok(NULL, ",");
			char *ninth_score = strtok(NULL, ",");
			char *tenth_score = strtok(NULL, ",");

			Lastname.assign(lastname);
			Firstname.assign(firstname);
			First_Score = atoi(first_score);
			Second_Score = atoi(second_score);
			Third_Score = atoi(third_score);
			Fourth_Score = atoi(fourth_score);
			Fifth_Score = atoi(fifth_score);
			Sixth_Score = atoi(sixth_score);
			Seventh_Score = atoi(seventh_score);
			Eighth_Score = atoi(eighth_score);
			Ninth_Score = atoi(ninth_score);
			Tenth_Score = atoi(tenth_score);

			int temparray[10] = { First_Score, Second_Score, Third_Score, Fourth_Score, Fifth_Score, Sixth_Score, Seventh_Score, Eighth_Score, Ninth_Score, Tenth_Score };

			score_data &Score_Data_1 = score_data(Lastname, Firstname, temparray);
      		container.InsertData(Score_Data_1);
		}
	}
	else
		return false;
}

int main()
{
	ifstream infile;
	score_data_container<score_data>container;
	if (!readinput(container, infile))
	{
		cout << "Error opening the file!";
		return -1;
	}

	container.Sort();
	container.Average();
	container.show();

	return 0;
}



I think I am a little bit clear now. the only problem is that I can't just add the score for each person
Last edited on
Ok, finally I made it!!!!
Yeah maybe you made it but it's an ugly mixture of C and C++ features and you have a memory-leak.
You never delete this:
char *c_line = new char[line.length() + 1];

Here's a pure C++ example of what you want to do.
I made the data in Student (which is your score_data) public because I'm lazy, of course it's better to keep it private to encapsulate the data.

I just made the class Student and overloaded operator>> and operator<<

I don't know the exact data format of your File so I made it like this:
lname, fname, score1, score2[, scores...]
for example: Maier, Hans, 12, 13, 14, 15, 16

Thats the table of content:
Maier, Hans, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21
Someone, Else, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
Holzer, Hugo, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31

the students are sorted by lastname and then by firstname

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
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <algorithm>

class Student {
public:
    std::string fname;
    std::string lname;
    std::vector<int> scores;
    
    float average() {
        return (float)sum() / scores.size();
    }
    int sum() {
        return std::accumulate(scores.begin(), scores.end(), 0);
    }
};
// allow to read a student from a stream
std::istream& operator>>(std::istream& is, Student& s)
{
    s.scores.clear();
    std::string temp;
    std::getline(is, temp);
    std::stringstream ss(temp);
    
    std::getline(ss, s.lname, ',');
    ss.ignore(1); // ignore the space before the first-name
    std::getline(ss, s.fname, ',');
    
    int data;
    while(ss >> data) {
        s.scores.push_back(data);
        ss.ignore(256, ','); // skip the ',' between the numbers so the stream is allways in a good state
    }
    return is;
}
// allow to stream a student
std::ostream& operator<<(std::ostream& os, const Student& s)
{
    os << s.lname << ' ' << s.fname << ' ';
    for(int i = 0; i < s.scores.size(); ++i)
        os << s.scores[i] << ' ';
    os << '\n';
    return os;
}
// allow to compare students
bool operator<(const Student& s1, const Student& s2)
{ 
    std::string name1 = s1.lname + s1.fname;
    std::string name2 = s2.lname + s2.fname;

    return name1 < name2;
}

int main()
{
    std::stringstream input("Maier, Hans, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21\nSomeone, Else, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31\nHolzer, Hugo, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31");
    std::vector<Student> students;
    Student dummy;    
    while(input >> dummy) {
        students.push_back(dummy);
    }
    for(int i = 0; i < students.size(); ++i) {
        std::cout << students[i] << "average: " << students[i].average() << std::endl;
    }
    
    // calculate the overall average
    int value = 0;
    for(int i = 0; i < students.size(); ++i)
        value += students[i].average();
    if(students.size() != 0)
        value /= (float)students.size();
    std::cout << "overall average: " << value << std::endl;
}
Last edited on
Thanks for your advises.
I am totally a newer for C++ :)
Topic archived. No new replies allowed.