Sorting class array in ascending order - c++

Quite new to programming and in need of some help, I'm looking to sort an class array in ascending order based on age, but I can only get the code to work in descending order. I may be overlooking something small since I've worked on this far too long so I'd appreciate any help!
#include <iostream>
#include <string>
using namespace std;
class Person
{
public:
string name;
int age;
Person(string name = "empty", int age = 0)
{
setName(name);
setAge(age);
}
void setName(string x) {
name = x;
}
string getName() {
return name;
}
void setAge(int y) {
age = y;
}
int getAge() {
return age;
}
void displayinfo()
{
cout << "Name: " << name; cout << " Age: " << age << endl;
}
};
void swap(Person &p, Person &q)
{
Person temp;
temp.name = p.name;
temp.age = p.age;
p.name = q.name;
p.age = q.age;
q.name = temp.name;
q.age = temp.age;
}
int main()
{
int userValue;
Person po("Jessica", 24);
Person po2("Robert", 49);
Person po3("Maria", 47);
Person po4("John", 19);
Person family[4] = {po,po2,po3,po4};
int sort(family[4].getAge());
{
for(int i = 0; i < 3; i++)
if (family[i].getAge() < family[i+1].getAge())
{
swap(family[i], family[i+1]);
}
}
for(int i = 0; i < 4; i++)
family[i].displayinfo();
}

int sort(family[4].getAge()); is not a function declaration (and you can't implement a function inside of another function). It is actually a variable declaration. It is declaring a variable int sort that is initialized with the value from family[4].getAge() (which is undefined behavior since index 4 is out of bounds of your family[] array).
So, you are declaring an unused sort variable, and then you enter your for(int i = 0; i < 3; i++) loop, which DOES NOT perform a full sort of the array. For what you are attempting, use the standard std::sort() algorithm instead, eg:
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
class Person
{
public:
string name;
int age;
Person(string name = "empty", int age = 0)
{
setName(name);
setAge(age);
}
void setName(string x) {
name = x;
}
string getName() const {
return name;
}
void setAge(int y) {
age = y;
}
int getAge() const {
return age;
}
void displayinfo() const
{
cout << "Name: " << name; cout << " Age: " << age << endl;
}
};
int main()
{
Person po1("Jessica", 24);
Person po2("Robert", 49);
Person po3("Maria", 47);
Person po4("John", 19);
Person family[4] = {po1, po2, po3, po4};
std::sort(family, family + 4,
[](const Person &p1, const Person &p2) {
return p1.getAge() < p2.getAge();
}
);
for(int i = 0; i < 4; i++) {
family[i].displayinfo();
}
return 0;
}
Live Demo
Note that your family[] array holds copies of the Person objects that you initialize it with. To avoid the overhead of those copies, you can sort pointers instead, eg:
int main()
{
Person po1("Jessica", 24);
Person po2("Robert", 49);
Person po3("Maria", 47);
Person po4("John", 19);
Person* family[4] = {&po1, &po2, &po3, &po4};
std::sort(family, family + 4,
[](const Person *p1, const Person *p2) {
return p1->getAge() < p2->getAge();
}
);
for(int i = 0; i < 4; i++) {
family[i]->displayinfo();
}
return 0;
}
Live Demo
Or, you can get rid of the individual p0... objects altogether and initialize the array directly instead, eg:
int main()
{
Person family[4]{
{"Jessica", 24},
{"Robert", 49},
{"Maria", 47},
{"John", 19}
};
std::sort(family, family + 4,
[](const Person &p1, const Person &p2) {
return p1.getAge() < p2.getAge();
}
);
for(int i = 0; i < 4; i++) {
family[i].displayinfo();
}
return 0;
}
Live Demo

Related

Access violation executing in classes with inheritance/ c++

I have a base class Participant and I need to sort object in array of participant by quantity of their prizes or diplomas. The virtual function get_data return this number. But whileI try to sort, i've got error Access violation executing in row with comparing 2 numbers.
if (p[j].Get_Data() < p[i].Get_Data()) {
This is my full code:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Participant {
protected:
string name;
string surname;
vector <string> type;
int age;
public:
Participant() : name(""), surname(""), type(), age(0)
{}
Participant(string name, string surname, vector <string> type, int age) {
this->name = name;
this->surname = surname;
this->type = type;
this->age = age;
};
Participant(const Participant& other) : name(other.name), surname(other.surname), type(other.type), age(other.age)
{
}
Participant& operator=(const Participant& other)
{
name = other.name;
surname = other.surname;
type = other.type;
age = other.age;
return *this;
}
virtual int Get_Data() {
return 0;
}
friend void Sort(Participant* p);
};
class Diploma : public Participant {
protected:
vector<int> places;
vector <string> type_d;
public:
Diploma() : places(), type_d{}
{}
Diploma(string name, string surname, vector <string> type, int age, vector<int> places, vector <string> type_d);
int Get_Data() override {
cout << "diplom prize" << endl;
cout << type_d.size() << endl;
return type_d.size();
}
};
class Prize : public Participant {
protected:
vector <int> places;
vector<string> prize;
public:
Prize(string name, string surname, vector <string> type, int age, vector<int> places, vector<string> prize);
int Get_Data() override{
cout << "Cont prize" << endl;
cout << prize.size() << endl;
return prize.size();
}
};
Prize::Prize(string name, string surname, vector <string> type, int age, vector<int> places, vector<string> prize) {
this->name = name;
this->surname = surname;
this->type = type;
this->age = age;
this->places = places;
this->prize = prize;
}
Diploma::Diploma(string name, string surname, vector <string> type, int age, vector<int> places, vector <string> type_d){
this->name = name;
this->surname = surname;
this->type = type;
this->age = age;
this->places = places;
this->type_d = type_d;
}
void Sort(Participant* p) {
Participant temp;
for (int i = 0; i < 3; i++) {
for (int j = i + 1; j < 3; j++)
{
if (p[j].Get_Data() < p[i].Get_Data()) {
temp = p[i];
p[i] = p[j];
p[j] = temp;
}
}
}
}
int main() {
Participant* pa[3];
pa[0] = new Diploma("Alex", "Smith", { "Geo","Math" }, 17, { 1,6 }, { "first"});
pa[1] = new Prize("Helen", "Blink", { "IT","Math" }, 18, { 2,2 }, {"Golden medal", "medal"});
pa[2] = new Prize("Brandon", "Brown", { "IT","Math" }, 18, { 2,2 }, { "Golden medal", "medal","gold"});
Sort(*pa);
for (int i = 0; i < 3; i++) {
pa[i]->Get_Data();
cout << endl;
}
}
The issue here is that when you are passing *pa, only the first element is accessible. If you run it in debug mode you will be able to see that inside sort function, p[1] is not a valid object. Basically, only p[0] is passed to the function. You should pass the reference to the array i.e. **pa to the sort function
void Sort(Participant **p)
{
Participant *temp;
for (int i = 0; i < 3; i++)
{
for (int j = i + 1; j < 3; j++)
{
if (p[j]->Get_Data() < p[i]->Get_Data())
{
temp = p[i];
p[i] = p[j];
p[j] = temp;
}
}
}
}
int main()
{
Participant *pa[3];
pa[0] = new Diploma("Alex", "Smith", {"Geo", "Math"}, 17, {1, 6}, {"first"});
pa[1] = new Prize("Helen", "Blink", {"IT", "Math"}, 18, {2, 2}, {"Golden medal", "medal"});
pa[2] = new Prize("Brandon", "Brown", {"IT", "Math"}, 18, {2, 2}, {"Golden medal", "medal", "gold"});
Sort(pa);
for (int i = 0; i < 3; i++)
{
pa[i]->Get_Data();
cout << endl;
}
}

C++, pointers, exception thrown: read access violation. this was 0xFFFFFFFFFFFFFF5F

I am working on a school project that is all about pointers. I have been setting variables that string just fine but when I arrived at an int it throws
Exception thrown: read access violation. this was 0xFFFFFFFFFFFFFF5F
I am not sure what this particular variable age is a problem and the rest were fine.
I tried to set int age = 0; to initialize it somehow but no success. Here is the screenshot and the files if that helps narrow down the issue.
Student.cpp
#pragma once
#include <string>
#include <iostream>
#include "student.h"
#include "degree.h"
using namespace std;
// Accessors
string Student::getStudent_ID()
{
return Student_ID;
}
string Student::getFirst_Name()
{
return First_Name;
}
string Student::getLast_Name()
{
return Last_Name;
}
string Student::getEmail_Address()
{
return Email_Address;
}
int Student::getAge()
{
return age;
}
int* Student::getNumber_Days()
{
return Number_Days;
}
DegreeProgram Student::getDegreeProgram()
{
return degreeProgram;
}
//Mutators
void Student::setStudent_ID(string student_ID)
{
this->Student_ID = Student_ID;
}
void Student::setFirst_Name(string first_Name)
{
this->First_Name = First_Name;
}
void Student::setLast_Name(string last_Name)
{
this->Last_Name = Last_Name;
}
void Student::setEmail_Address(string email_Address)
{
this->Email_Address = Email_Address;
}
void Student::setAge(int age)
{
this->age = age;
}
void Student::setNumber_Days(int* Number_Days)
{
this->Number_Days[0] = Number_Days[0];
this->Number_Days[1] = Number_Days[1];
this->Number_Days[2] = Number_Days[2];
}
void Student::setDegreeProgram(DegreeProgram degreeProgram)
{
this->degreeProgram = degreeProgram;
}
//Constructor - essentually the same as a group of setters
Student::Student(string Student_ID, string First_Name, string Last_Name, string Email_Address, int age, int Number_Days[], DegreeProgram degreeProgram)
{
this->Student_ID = Student_ID;
this->First_Name = First_Name;
this->Last_Name = Last_Name;
this->Email_Address = Email_Address;
this->age = age;
this->Number_Days[0] = Number_Days[0];
this->Number_Days[1] = Number_Days[1];
this->Number_Days[2] = Number_Days[2];
this->degreeProgram = degreeProgram;
}
void Student::print()
{
cout << Student_ID << "\t" << First_Name << "\t" << Last_Name << "\t" << age << "\t" << Number_Days[0] << "\t" << Number_Days[1] << "\t" << Number_Days[2] << "\t" << degreeProgram << endl;
}
the Student.h file
#pragma once
#include <string>
#include <iostream>
#include "degree.h"
using namespace std;
class Student
{
private:
string Student_ID;
string First_Name;
string Last_Name;
string Email_Address;
int age;
int* Number_Days = 0;
DegreeProgram degreeProgram;
public:
//initialize need help
// accessors
Student(string Student_ID, string First_Name, string Last_Name, string Email_Address, int age, int Number_Days[], DegreeProgram degreeProgram);
string getStudent_ID();
string getFirst_Name();
string getLast_Name();
string getEmail_Address();
int getAge();
int* getNumber_Days();
DegreeProgram getDegreeProgram();
// mutators
void setStudent_ID(string);
void setFirst_Name(string);
void setLast_Name(string);
void setEmail_Address(string);
void setAge(int);
void setNumber_Days(int Number_Days[]);
void setDegreeProgram(DegreeProgram degreeProgram);
void print();
~Student();
};
Roster.cpp
#pragma once
#include <string>
#include <iostream>
#include <stdlib.h>
#include "student.h"
#include "degree.h"
#include "roster.h"
using namespace std;
//Student* classRosterArray[5];
//void add(string Student_ID, string First_Name, string Last_Name, string Email_Address, int Age, int Number_Days[], DegreeProgram degreeProgram);
//Student* classRosterArray[5]; //string studentData() = 0;
const string studentData[] =
{ "A1,John,Smith,John1989#gm ail.com,20,30,35,40,SECURITY",
"A2,Suzan,Erickson,Erickson_1990#gmailcom,19,50,30,40,NETWORK",
"A3,Jack,Napoli,The_lawyer99yahoo.com,19,20,40,33,SOFTWARE",
"A4,Erin,Black,Erin.black#comcast.net,22,50,58,40,SECURITY",
"A5,Rebekah,Johnson,rjoh804#wgu.edu,27,35,56,65,SOFTWARE" };
//2.E Looping through StudentData and parsing it
//Student* classRosterArray[];
void Roster::add(string Student_ID, string First_Name, string Last_Name, string Email_Address, int age, int Number_Days1, int Number_Days2, int Number_Days3, DegreeProgram degreeProgram)
//void Roster::parsingStudentData()
{
for (int i = 0; i < 5; i++)
{
//string studentData[];
int rhs = studentData[i].find(",");
classRosterArray[i]->setStudent_ID(studentData[i].substr(0, rhs));
int lhs = rhs + 1;
rhs = studentData[i].find(",", lhs);
classRosterArray[i]->setFirst_Name(studentData[i].substr(lhs, rhs - lhs));
lhs = rhs + 1;
rhs = studentData[i].find(",", lhs);
classRosterArray[i]->setLast_Name(studentData[i].substr(lhs, rhs - lhs));
lhs = rhs + 1;
rhs = studentData[i].find(",", lhs);
classRosterArray[i]->setEmail_Address(studentData[i].substr(lhs, rhs - lhs));
lhs = rhs + 1;
rhs = studentData[i].find(",", lhs);
classRosterArray[i]->setAge(stoi(studentData[i].substr(lhs, rhs - lhs))); // Made the string an int with "stoi"// help
//int NumberDays[Student::Number_Days];
lhs = rhs + 1;
rhs = studentData[i].find(",", lhs);
int NumberDays1 = stoi(studentData[i].substr(lhs, rhs - lhs));
lhs = rhs + 1;
rhs = studentData[i].find(",", lhs);
int NumberDays2 = stoi(studentData[i].substr(lhs, rhs - lhs));
lhs = rhs + 1;
rhs = studentData[i].find(",", lhs);
int NumberDays3 = stoi(studentData[i].substr(lhs, rhs - lhs));
int NumberDays[3] = { NumberDays1, NumberDays2, NumberDays3 };
classRosterArray[i]->setNumber_Days(NumberDays);
//Enum type
lhs = rhs + 1;
rhs = studentData[i].find(",", lhs);
//TO FINISH, THIS NEEDs TO BE REFINED, WE do not have the word in between defined"studentData[i].substr(lhs, rhs - lhs)" done
if (studentData[i] == "SECURITY")
classRosterArray[i]->setDegreeProgram(SECURITY);
else if (studentData[i] == "SOFTWARE")
classRosterArray[i]->setDegreeProgram(SOFTWARE);
else
classRosterArray[i]->setDegreeProgram(NETWORK);
}
//void Roster::add();
}
void Roster::remove(string Student_ID)
{
for (int i = 0; i < 5; i = i + 1)
{
if (Student_ID == classRosterArray[i]->getStudent_ID())
{
classRosterArray[i] = nullptr;
}
else
{
cout << "Error:Student not found" << endl;
}
}
}
void Roster::printAll()
{
for (int i = 0; i < 5; i = i + 1)
{
this->classRosterArray[i]->print();
//cout << Student_ID << /t << First_Name << /t << Last_Name << /t << Age << /t << Number_Days[] <<
}
}
void Roster::printAverageDaysInCourse(string Student_ID)
{
for (int i = 0; i < 5; i = i + 1)
{
//this->classRosterArray[i]->getNumber_Days();
//int* Number_Days[] = classRosterArray[i]->getNumber_Days();
int AvgDays = (classRosterArray[i]->getNumber_Days()[0] + classRosterArray[i]->getNumber_Days()[1] + classRosterArray[i]->getNumber_Days()[2]) / 3;
cout << Student_ID << ": " << AvgDays << endl;
}
}
void Roster::printInvalidEmails()
{
for (int i = 0; i < 5; i = i + 1)
{
string Email_Check = classRosterArray[i]->getEmail_Address();
string StudentID = classRosterArray[i]->getStudent_ID();
if (Email_Check.find("#") == string::npos or Email_Check.find(".") == string::npos or Email_Check.find(" ") != string::npos)
{
cout << StudentID << ": Invalid Email" << endl;
}
}
}
void Roster::printByDegreeProgram(DegreeProgram degreeProgram)
{
for (int i = 0; i < 5; i = i + 1)
{
if (classRosterArray[i]->getDegreeProgram() == degreeProgram)
{
classRosterArray[i]->print();
}
}
}
Roster.h
#pragma once
#include <string>
#include <iostream>
#include "student.h"
#include "degree.h"
using namespace std;
class Roster
{
Student* classRosterArray[5]; // = { 0,0,0 }; // Array holding Student data table information
void inicializeArray()
{
classRosterArray[0] = 0; // elements of the array initialized to 0
classRosterArray[1] = 0;
classRosterArray[2] = 0;
classRosterArray[3] = 0;
classRosterArray[4] = 0;
}
void parsingStudentData();
//classRosterArray=(Student1, Student2, )
// classRosterArray[2] = 37; // sets Student3 to 37 // to access the variables in classRosterArray
//Roster* classRosterArray[] = { "Student_ID", "First_Name", "Last_Name", "Email_Address", " Age", " Number_Days[]", "DegreeProgram"};
public:
void add(string Student_ID, string First_Name, string Last_Name, string Email_Address, int Age, int Number_Days1, int Number_Days2, int Number_Days3, DegreeProgram degreeProgram);
void remove(string Student_ID);
void printAll();
void printAverageDaysInCourse(string Student_ID);
void printInvalidEmails();
void printByDegreeProgram(DegreeProgram degreeProgram);
};

Reserve dynamic memory with the new operator

I'm learning new operator and I have the next question:
I want to reserve new memory when I add a new subject and if I do this way I lose all the previus content of array.
So, how can I do this if i have to reserve memory each time that i want to add a new subject? Or in other words, how i reserve memory without lose the previus?
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <string>
using namespace std;
class Subject {
public:
Subject() { m_name = "";
m_hours = 0;
}
string getName() { return m_name; }
int getHours() { return m_hours; }
void setName(string name) { m_name = name; }
void setHours(int hours) { m_hours = hours; }
private:
string m_name;
int m_hours;
};
class Person {
private:
string m_name;
int m_age;
Subject *m_subjects;
int m_nSubjects;
public:
Person() {
m_name = "";
m_age = 0;
m_nSubjects = 0;
}
~Person() {
}
string getName() { return m_name; }
int getAge() { return m_age; }
void setName(string name) {
m_name = name;
}
void setAge(int age) {
m_age = age;
}
void addSubject(string name, int hour);
void showSubjects();
};
void Person::addSubject(string name, int hours) {
m_subjects = new Subject[m_nSubjects+1]; *the problem is here, all the previus content is lost*
m_subjects[m_nSubjects].setName(name);
m_subjects[m_nSubjects].setHours(hours);
m_nSubjects++;
}
void Person::showSubjects() {
for (int i = 0; i < m_nSubjects; i++) {
cout << m_subjects[i].getName();
cout << "\n";
cout << m_subjects[i].getHours();
}
}
int main() {
int nSubjects;
string name;
int hours;
Person person1;
person1.setName("Name 1");
person1.setAge(30);
cout << "Subjects to add: ";
cin >> nSubjects;
for (int i = 0; i < nSubjects; i++) {
cout << "Name of subject: " << "\n" << endl;
cin >> name;
cout << "Hours: " << "\n" << endl;
cin >> hours;
person1.addSubject(name, hours);
}
person1.showSubjects();
system("pause");
return 0;
}
I hope you can understand me.
You need to copy the existing data to the new array before you then replace the previous array (which you are leaking, BTW), eg:
void Person::addSubject(string name, int hours) {
Subject *new_subjects = new Subject[m_nSubjects+1];
for(int i = 0; i < m_nSubjects; ++i) {
new_subjects[i] = m_subjects[i];
}
new_subjects[m_nSubjects].setName(name);
new_subjects[m_nSubjects].setHours(hours);
delete[] m_subjects;
m_subjects = new_subjects;
m_nSubjects++;
}
You also need to free the current array in your Person destructor to avoid leaking as well:
~Person() {
delete[] m_subjects;
}
And you also need to add a copy constructor and a copy assignment operator to Person as well, to avoid future problems with multiple Person objects sharing the same array in memory if you assign one Person to another:
Person(const Person &src) {
m_name = src.m_name;
m_age = src.m_age;
m_nSubjects = src.m_nSubjects;
m_subjects = new Subject[m_nSubjects];
for (int i = 0; i < m_nSubjects; ++i) {
m_subjects[i] = src.m_subjects[i];
}
}
Person& operator=(const Person &rhs) {
if (&rhs != this) {
Person copy(rhs);
std::swap(m_name, copy.m_name);
std::swap(m_age, copy.m_age);
std::swap(m_nSubjects, copy.m_nSubjects);
std::swap(m_subjects, copy.m_subjects);
}
return *this;
}
And, if you are using C++11 or later, you should (optionally) also add a move constructor and move assignment operator to Person, too:
Person(Person &&src) {
m_name = std::move(src.m_name);
m_age = src.m_age; src.m_age = 0;
m_nSubjects = src.m_nSubjects; src.m_nSubjects = 0;
m_subjects = src.m_subjects; src.m_subjects = nullptr;
}
Person& operator=(Person &&rhs) {
Person movedTo(std::move(rhs));
std::swap(m_name, movedTo.m_name);
std::swap(m_age, movedTo.m_age);
std::swap(m_nSubjects, movedTo.m_nSubjects);
std::swap(m_subjects, movedTo.m_subjects);
return *this;
}
See the Rule of 3/5/0 for more details.
A better solution is to use std::vector instead, let the compiler handle all of these details for you:
#include <iostream>
#include <string>
#include <vector>
#include <limits>
class Subject {
public:
Subject() {
m_name = "";
m_hours = 0;
}
Subject(std::string name, int hours) {
m_name = name;
m_hours = hours;
}
std::string getName() const { return m_name; }
int getHours() const { return m_hours; }
void setName(std::string name) { m_name = name; }
void setHours(int hours) { m_hours = hours; }
private:
std::string m_name;
int m_hours;
};
class Person {
private:
std::string m_name;
int m_age;
std::vector<Subject> m_subjects;
public:
Person() {
m_name = "";
m_age = 0;
}
std::string getName() const { return m_name; }
int getAge() const { return m_age; }
void setName(std::string name) { m_name = name; }
void setAge(int age) { m_age = age; }
void addSubject(std::string name, int hour);
void showSubjects() const;
};
void Person::addSubject(string name, int hours) {
m_subjects.push_back(Subject(name, hours));
}
void Person::showSubjects() const {
for (std::size_t i = 0; i < m_nSubjects.size(); ++i) {
cout << m_subjects[i].getName();
cout << "\n";
cout << m_subjects[i].getHours();
}
}
int main() {
int nSubjects;
std::string name;
int hours;
Person person1;
person1.setName("Name 1");
person1.setAge(30);
std::cout << "Subjects to add: ";
std::cin >> nSubjects;
for (int i = 0; i < nSubjects; i++) {
std::cout << "Name of subject: ";
std::getline(std::cin, name);
std::cout << "Hours: ;
std::cin >> hours;
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
person1.addSubject(name, hours);
}
person1.showSubjects();
std::system("pause");
return 0;
}

Array of derived class stored in parent class

I don't think I quite understand how to store an array of a derived class in its parent class.
I keep getting errors
Error C3646 'list': unknown override specifier
Error C2065 'list': undeclared identifier
Here is the code I have
#include <iostream>
#include <string>
using namespace std;
class GameScores
{
public:
GameEntry list[9];
void inputList(GameEntry x);
void sortList();
void removeList(int r);
void printList();
GameScores();
};
class GameEntry :public GameScores
{
public:
GameEntry(const string& n = "", int s = 0, const string d = "1/1/99");
string getName() const;
int getScore() const;
string getDate() const;
string setName(string n);
int setScore(int s);
string setDate(string d);
private:
string name;
int score;
string date;
};
GameScores::GameScores()
{
GameEntry list[9];
}
void GameScores::inputList(GameEntry x)
{
for (int i = 0; i < 10; i++)
if (x.getScore() >= list[i].getScore())
{
list[i + 1] = list[i];
list[i] = x;
}
}
void GameScores::sortList()
{
GameEntry swap;
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10 - 1; j++)
{
if (list[j].getScore() > list[j].getScore() + 1)
{
swap = list[j];
list[j] = list[j + 1];
list[j + 1] = swap;
}
}
}
}
void GameScores::removeList(int r)
{
for (int i = r; i < 10; i++)
list[i - 1] = list[i];
list[9].setScore(0);
list[9].setName(" ");
list[9].setDate(" ");
}
void GameScores::printList()
{
cout << "Top Scores" << endl;
for (int i = 0; i < 10; i++)
cout << list[i].getScore() << " " << list[i].getName() << " " << list[i].getDate() << endl;
}
GameEntry::GameEntry(const string& n, int s, const string d) // constructor
: name(n), score(s), date(d) { }
// accessors
string GameEntry::getName() const { return name; }
int GameEntry::getScore() const { return score; }
string GameEntry::getDate() const { return date; }
string GameEntry::setName(string n)
{
name = n;
}
int GameEntry::setScore(int s)
{
score = s;
}
;
string GameEntry::setDate(string d)
{
date = d;
}
int main()
{
GameEntry p1("John", 90, "9/9/98"), p2("Jane", 95, 8/21/98), p3("Bob", 60, "7/11/99"), p4("Jo", 92, "6/4/97");
GameScores topScores;
topScores.inputList(p1);
topScores.inputList(p2);
topScores.inputList(p3);
topScores.inputList(p4);
topScores.printList();
return 0;
}
This design is very questionable. What purpose is being served by making the second class inherit the first? It looks like you'd end up with each member of the array containing an additional array with all its siblings. Don't you want only one array? You need to rethink this from an earlier point.
If you really have a reason for a parent class to contain an array of the child class, maybe you should define an interface (abstract base class) that both classes implement.
To use GameEntry as a type in your GameScores class , you must forward-declare the class like so :
class GameEntry;
class GameScores
{
public:
GameEntry list[9];
void inputList(GameEntry x);
void sortList();
void removeList(int r);
void printList();
GameScores();
};

Class with Pointer and Dynamic Arrays

I'm currently writing a program that will help a college keep track of which students are in what clubs. This code will be pasted into existing code that works, as provided by my professor.
Could someone please look my code over, and help me work through my mistakes? I included comments to explain what everything should do.
Also, please note this is an assignment and I cannot change anything about the class. I'm also a beginner, so keep it simple, please. Your help will be extremely appreciated beyond all measure.
class Club
{
public:
Club();
Club(Club &c);
Club(string cname);
void addMember(string name);
void removeMember(string name);
string getClubName() const;
string setClubName(const string& nameOfClub);
void loadClub();
bool isMember(string& name) const;
string getAllMembers() const;
friend Club mergeClubs(Club& c1, Club& c2);
~Club();
private:
string *members;
int numMembers;
string clubName;
};
Club::Club()
{
clubName = "";
numMembers = 0;
}
Club::Club(Club &c)
{
numMembers = c.numMembers;
members = new string [numMembers];
for (int i = 0; i < numMembers; i++)
{
members[i] = c.members[i];
}
//copy constructor
//watch out for memory leaks
}
Club::Club(string cname)
{
clubName = cname;
//cname should be saved as the club's name in the clubName variable
}
void Club::addMember(string name)
{
string *m;
m = new string [numMembers];
string *members = m;
for (int i = 0; i < numMembers; i++)
{
for (int j = 0; j < name.length(); i++)
{
m[i] = name[j];
}
}
delete [] m;
//adds new member to the club
//records their name in the members variable
//may need a dynamic array to make this work, watch for memory leaks!
}
void Club::removeMember(string name)
{
string *m;
m = new string [numMembers];
string *members = m;
for (int i = 0; i < numMembers; i++)
{
if ( m[i] == name)
{
m[i] = "";
}
}
delete [] m;
//deletes the person from the array in members
//will do nothing if the person is not in the array to begin with
//may require dynamic array to make this work- watch for memory leaks!
//if the person's name appears more than once, just delete the first instance
}
string Club::getClubName() const
{
return clubName;
//getter of clubName
}
string Club::setClubName(const string& nameOfClub)
{
return clubName = nameOfClub;
//setter of clubName
}
void Club::loadClub()
{
//should print "tell me the name of the next member of the club"
//reads into the variable name
//uses addMember() to add that person to the club
//the input should include up to the line break as the name, so it should take in "jane doe" as an entry
//keeps asking for more names until the user enters a blank entry
string name;
do
{
cout << "Tell me the name of the next member of the club, ";
cout << "or submit a blank entry to stopent ering names." << endl;
getline(cin, name, '\n');
addMember(name);
} while (name != "");
}
bool Club::isMember(string& name) const
{
/*for (int i = 0; i < numMembers; i++)
{
for (int j = 0; j < name.length(); j++)
{
if (members[i] == name)
{
return true;
}
else
{
return false;
}
}
}*/
for (int i = 0; i < numMembers; i++)
{
if (members[i] == name)
{
return true;
}
return false;
}
//returns true if the person is a member of the club, false otherwise
}
string Club::getAllMembers() const
{
for (int i = 0; i < numMembers; i++)
{
return members[i];
cout << ", ";
}
cout << endl;
//returns a string of all the names of the members of the club
//commas and spaces separating every entry of the list
//should not be a comma following the last name in the list
}
Club mergeClubs(Club& c1, Club& c2)
{
//creates a new club from 2 existing clubs
//combined club name should be Club 1/Club 2
Club temp;
temp.clubName = c1.clubName + "/" + c2.clubName;
return temp;
}
Club::~Club()
{
delete [] members;
//destructor
//watch out for memory leaks
}
For some reason I cannot fathom I have (mostly) corrected this program for you. There are still some nasty things like passing copies of strings into const functions but fixing these would be mere optimisations. At least this program is logically correct.
#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
#include <sstream>
using namespace std;
class Club
{
public:
Club();
Club(const Club &c);
Club(string cname);
void addMember(string name);
void removeMember(string name);
string getClubName() const;
string setClubName(const string& nameOfClub);
void loadClub();
bool isMember(const string& name) const;
string getAllMembers() const;
friend Club mergeClubs(Club& c1, Club& c2);
~Club();
private:
vector<string> members;
string clubName;
};
Club::Club()
: members()
, clubName()
{
}
Club::Club(const Club &c)
: members(c.members)
, clubName(c.clubName)
{
}
Club::Club(string cname)
: members()
, clubName(cname)
{
}
void Club::addMember(string name)
{
members.push_back(name);
}
void Club::removeMember(string name)
{
members.erase(remove(members.begin(), members.end(), name), members.end());
}
string Club::getClubName() const
{
return clubName;
//getter of clubName
}
string Club::setClubName(const string& nameOfClub)
{
return clubName = nameOfClub;
//setter of clubName
}
void Club::loadClub()
{
//should print "tell me the name of the next member of the club"
//reads into the variable name
//uses addMember() to add that person to the club
//the input should include up to the line break as the name, so it should take in "jane doe" as an entry
//keeps asking for more names until the user enters a blank entry
string name;
do
{
cout << "Tell me the name of the next member of the club, ";
cout << "or submit a blank entry to stopent ering names." << endl;
getline(cin, name, '\n');
addMember(name);
} while (name != "");
}
bool Club::isMember(const string& name) const
{
return find(members.begin(), members.end(), name) != members.end();
}
string Club::getAllMembers() const
{
stringstream result;
vector<string>::const_iterator b = members.begin(), e = members.end();
for (bool comma = false ; b != e; ++b, comma = true)
{
if (comma) {
result << ", ";
}
result << *b;
}
return result.str();
}
Club mergeClubs(Club& c1, Club& c2)
{
Club temp(c1.clubName + "/" + c2.clubName);
struct memberAdd {
Club& _club;
memberAdd(Club& club) : _club(club) {}
void operator()(const string& member) {
_club.addMember(member);
}
};
for_each(c1.members.begin(), c1.members.end(), memberAdd(temp));
for_each(c2.members.begin(), c2.members.end(), memberAdd(temp));
return temp;
}
Club::~Club()
{
//destructor
//watch out for memory leaks
}
int main()
{
Club boys("red");
boys.addMember("Ben");
boys.addMember("Paul");
Club girls("blue");
girls.addMember("Lucy");
girls.addMember("Hermione");
Club unisex = mergeClubs(boys, girls);
cout << unisex.getClubName() << " has the following members: " << unisex.getAllMembers() << endl;
}
Some initial comments:
The copy constructor should take a const Club& like this:
Club(const Club& club)
members and numMembers are anachronistic. Use a std::vector for members and drop the numMembers altogether (std::vector has a size() method).
Club::Club does not initialise members or numMembers. This will result in a possible crash in the destrutor. This would be solved if you replaced them with a vector.
the logic in addMember does not make sense.
nor in removeMember
isMember should take a const string& and you would be well advised to write it in terms of std::find() (#include <algorithm>)
I could go on...