Reading and printing using class, enum class, default constructors and setters/getters

I'm getting loads of errors in printing. I'm also unsure how to use setters/getters. Could someone help?
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
  #include <iostream>
#include <fstream>
#include <vector>
#include <string>
using namespace std;

enum class gender {
    Male, Female
};

class Student {
private:
    string fname, lname, id, cname;
    int Icount;
    gender g;
public:
    Student() { fname = "None"; lname = "None"; id = "None"; cname = "None"; Icount = 0; g = gender::Female; }
    Student(string _fname, string _lname, string _id, string _cname, int _Icount, gender _g) {
        fname = _fname;
        lname = _lname;
        id = _id;
        cname = _cname;
        Icount = _Icount;
        g = _g;
    }
    void setfname(string _fname) { fname = _fname; } string getfname(string fname) {
        return fname;
    }
    void setlname(string _lname) { fname = _lname; } string getlname(string lname) {
        return fname;
    } void setlname(string _id) { fname = _id; } string getlname(string id) {
        return id;
    } void setcname(string _cname) { fname = _cname; } string getlname(string cname) {
        return cname;
    }
    void setIcount(int _Icount) { Icount = _Icount; } int getIcount(int Icount) {
        return Icount;
    }
    void setg(gender _g) { g = _g; } gender getg(gender g) {
        return g;
    }

};

vector<Student> readStudents(string filename) {
    int size;
    string temp;
    vector <Student> students;
    ifstream f;
    f.open("input.txt");
    if (f.fail()) {
        cout << "Failed to open file"; exit(1);
    }
    f >> size; getline(f, temp); getline(f, temp);
    for (int i = 0; i < size; i++) {
        int c; string _fname, _lname, _id, _cname; gender _g; int _Icount;
        f >> _id >> c >> _fname >> _lname >> _cname >> _Icount;
        _g = gender::Female; if (c == 0)_g = gender::Male; else _g = gender::Female;
        Student student(_id, c, _fname, _lname, _cname, _Icount);
        students.push_back(student);
    }
    return students;
}
void printStudents(const vector<Student> stds)
{
    cout << "ID [" << stds. << "] First Name [" << stds._fname << "] Last Name [" << stds.
        lname << "] Gender [" << stds.g << "] Course [" << stds.
        cname << "] Attendance [" << stds.Icount << "]\n";

}




vector<Student> getFemales(const vector<Student>& stds) {

    cout << "The Female Students are:\n";
    int i = 0;
    string s;
    while (stds[i].g == 1)
    {
        cout << "ID [" << stds[i].
            id << "] First Name [" << stds[i].fname << "] Last Name [" << stds[i].
            lname << "] Gender [" << stds[i].g << "] Course [" << stds[i].
            cname << "] Attendance [" << stds[i].Icount << "]\n";
        i++;
    }
    return stds;
}

}

vector<Student> getLowAttendance(const vector<Student>& stds) {
    cout << "The Students with Low Attendance are: \n";
    int i = 0;
    while (stds[i].Icount < 20)
    {
        cout << "ID [" << stds[i].
            id << "] First Name [" << stds[i].fname << "] Last Name [" << stds[i].
            lname << "] Gender [" << stds[i].g << "] Course [" << stds[i].
            cname << "] Attendance [" << stds[i].Icount << "]\n";
        i++;
    }
    return stds;

}

int main()
{

    vector <Student> stds_vect;
    stds_vect = readStudents();
    for (int i = 0; i<size.stds_vect() i++) {
        printStudents(stds_vect[i]);
        getFemales[i](stds_vect);
        getLowAttendance[i](stds_vect);
    }


    return 0;
}
Last edited on
Make sure each function has a unique name.

The getters should not have parameters.

When you call a function (or constructor) make sure the arguments are passed in the correct order and have the correct types so that they match the parameters of the function definition.

Instead of trying to access the values of the Student objects directly you should use the getters (that's what they're for).

And read the error messages. They are often helpful. If you get a long list of errors start with the first one, fix it, recompile and repeat. Don't start from the bottom because later errors are sometimes caused indirectly by earlier errors.
Last edited on
Instead of trying to access the values of the Student objects directly you should use the getters (that's what they're for).


Could you show how I could do that? I understand I have to do that but I'm not sure how.
I mean instead of stds[i].fname you do stds[i].getfname().
Last edited on
Oh okay. Lmao stupid me. Thank you so much! I'll try and check if it works.
@Peter87 should the parentheses be empty?
The problem is that the definition of the getfname function itself should not have a parameter. Currently, you're just returning the passed-in string.
You meant to do
1
2
3
    string getfname() {
        return fname;
    }


So, yes, the parentheses should be empty, but you need to change your function.

Also, putting two functions on the same line is hard to read. There's no benefit to that.
Last edited on
Getters usually don't pass a parameter when called, they return a value.

So, yes, the parentheses should be empty. IF that is how your class declared/defined the getter's signature.
Ha, jinx!
Normally a getter should be declared as const:
std::string getFName() const { return fname; }

Doing that tells the compiler (and anyone reading the code) the getter should not change the class member data.

If the method body DOES change the member data
1
2
3
4
5
std::string getFName() const
{
   fname = "Hi! " + fname;
   return fname;
}

The compiler will complain and whinge and error out.
what's a better way of getting for enum gender:females and low attendance using the void print function from class?
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
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
using namespace std;

enum class gender {
    Male, Female
};

class Student {
private:
    string fname, lname, id, cname;
    int Icount;
    gender g;
public:
    Student() { fname = "None"; lname = "None"; id = "None"; cname = "None"; Icount = 0; g = gender::Female; }
    Student(string _id, gender _g, string _fname, string _lname, string _cname, int _Icount,) {
        fname = _fname;
        lname = _lname;
        id = _id;
        cname = _cname;
        Icount = _Icount;
        g = _g;
    }
    void setfname(string _fname) { fname = _fname; } string getfname() {
        return fname;
    }
    void setlname(string _lname) { fname = _lname; } string getlname() {
        return lname;
    } void setid(string _id) { fname = _id; } string getid() {
        return id;
    } void setcname(string _cname) { fname = _cname; } string getcname() {
        return cname;
    }
    void setIcount(int _Icount) { Icount = _Icount; } int getIcount() {
        return Icount;
    }
    void setg(gender _g) { g = _g; } gender getg() {
        return g;
    }
    void print() {
        int c;
        if (c == 1) cout << "Female"; else cout << "Male";
        cout << "ID [" << id << "] First Name [" << fname << "] Last Name [" << lname << "] Gender [" << c << "] Course [" << cname << "] Attendance [" << Icount << "]\n";
    }
};

vector<Student> readStudents(string filename) {
    int size;
    string temp;
    vector <Student> students;
    ifstream f;
    f.open("input.txt");
    if (f.fail()) {
        cout << "Failed to open file"; exit(1);
    }
    f >> size; getline(f, temp); getline(f, temp);
    for (int i = 0; i < size; i++) {
        int c; string _fname, _lname, _id, _cname; gender _g; int _Icount;
        f >> _id >> c >> _fname >> _lname >> _cname >> _Icount;
        _g = gender::Female; if (c == 0)_g = gender::Male; else _g = gender::Female;
        Student student(_id, c, _fname, _lname, _cname, _Icount);
        students.push_back(student);
    }
    return students;
}
void printStudents(const vector<Student> stds)
{
    Student students;
    students.print();

}




vector<Student> getFemales(const vector<Student>& stds) {

    cout << "The Female Students are:\n";
    int i = 0, c;
    string s;
    for (int i = 0; i < stds.size(); i++) {
        if (stds[i].g == 1)
        {
            
        }
    }
}

}

vector<Student> getLowAttendance(const vector<Student>& stds) {
    cout << "The Students with Low Attendance are: \n";
    int i = 0;
    while (stds[i].Icount < 20)
    {
       
        i++;
    }
    return stds;

}

int main()
{

    vector <Student> stds_vect;
    stds_vect = readStudents();
    for (int i = 0; i < size.stds_vect() i++) {
        printStudents(stds_vect[i]);
        getFemales[i](stds_vect);
        getLowAttendance[i](stds_vect);
    }


    return 0;
}
_Icount;
I know this isn't an answer your question, but please note that technically this name is illegal. Variables that start with [underscore + capital letter] or [2x underscore] are reserved for internal use in all contexts.

_________________

But anyway,

1
2
        int c;
        if (c == 1) cout << "Female"; else cout << "Male";

The value of c here is junk. It's an uninitialized local variable.

You should separate out each statement into its own line. Your code is hard to read.

______________________

1
2
3
4
5
6
void printStudents(const vector<Student> stds)
{
    Student students;
    students.print();

}
This is creating a new Student variable and calling print on it. It is not using the passed in 'stds' vector of Student.
Last edited on
Your code is hard to read.

Sorry for that. Its just more convenient for me so I stick to it.

The value of c here is junk. It's an uninitialized local variable.

How else can I output the gender according to you?
I've done this same (very similar) program before recently...

Without data (please post a sample of the file data whenever a program reads a file!), I haven't checked but something like this:

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
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
using namespace std;

enum class gender { Male, Female };

class Student {
private:
	string fname {"None"}, lname {"None"}, id {"None"}, cname {"None"};
	int Icount {};
	gender g {gender::Female};

public:
	Student() {}
	Student(const string& _fname, const string& _lname, const string& _id, const string& _cname, int _Icount, gender _g) :
		fname(_fname), lname(_lname), id(_id), cname(_cname), Icount(_Icount), g(_g) { }

	void setfname(const string& _fname) { fname = _fname; }
	string getfname() const { return fname; }
	void setlname(const string& _lname) { lname = _lname; }
	string getlname() const {return lname; }
	void setid(const string& _id) { id = _id; }
	string getid() const { return id; }
	void setcname(const string& _cname) { cname = _cname; }
	string getcname() const { return cname; }
	void setIcount(int _Icount) { Icount = _Icount; }
	int getIcount() const { return Icount; }
	void setg(gender _g) { g = _g; }
	gender getg() const { return g; }
};

vector<Student> readStudents(const string& filename) {
	size_t size {};
	string temp;
	vector <Student> students;
	ifstream f {filename};

	if (!f) {
		cout << "Failed to open file";
		exit(1);
	}

	f >> size;
	getline(f, temp);
	getline(f, temp);

	for (size_t i {}; i < size; ++i) {
		int c {}, _Icount {};
		string _fname, _lname, _id, _cname;

		f >> _id >> c >> _fname >> _lname >> _cname >> _Icount;

		students.emplace_back(_fname, _lname, _id, _cname, _Icount, c == 0 ? gender::Male : gender::Female);
	}

	return students;
}

void printStud(const Student& s) {
	cout << "ID [" << s.getid() << "] First Name [" << s.getfname() << "] Last Name [" << s.getlname()
		<< "] Gender [" << (int)s.getg() << "] Course [" << s.getcname()
		<< "] Attendance [" << s.getIcount() << "]\n";
}

void printStudents(const vector<Student>& stds) {
	for (const auto& s : stds)
		printStud(s);
}

vector<Student> getFemales(const vector<Student>& stds) {
	vector<Student> fem;

	for (const auto& s : stds)
		if (s.getg() == gender::Female)
			fem.push_back(s);

	return fem;
}

vector<Student> getLowAttendance(const vector<Student>& stds) {
	vector<Student> low;

	for (const auto& s : stds)
		if (s.getIcount() < 20)
			low.push_back(s);

	return low;
}

int main() {
	const auto vect {readStudents("students.txt")};
	const auto fem {getFemales(vect)};
	const auto low {getLowAttendance(vect)};

	std::cout << "The students are:\n";
	printStudents(vect);

	std::cout << "The female students are:\n";
	printStudents(fem);

	std::cout << "The low attendances are:\n";
	printStudents(low);
}

Last edited on
s.getg()

There's an error. It says:
the object has type qualifiers which are incompatible with the member function "Student::getg" object type is: const Student
It compiles OK with VS2022. Which compiler are you using? Which usage of .getg() is causing the error?

L63 usage (with cast) is just a temp kludge to get the display. You'd replace this with say an access into an array to get a string of the gender.

Also, as requested, please post some sample data.
Last edited on
I'm using VS2019.
Which usage of .getg() is causing the error?
: for getFemales' and getLowAttendance's if functions.

This is the input.txt:

8
ID Gender (enum 0:m, 1:f) First Name LName Course Attendance
1 0 Mohammad Saleh CMP220 30
2 1 Sara Ali CMP220 28
5 0 Charles Dickens CMP220 25
4 1 Jain Austin CMP220 23
19 1 Ahlam Mosteghanemi CMP220 15
21 0 Mario Puzo CMP220 21
88 1 Marie Curie CMP220 30
1930 0 John Steinbeck CMP220 19
Last edited on
The code from seeplus Feb 22, 2022 at 8:52pm compiles on my VS2019. Did you change any projects settings ?
Given that data file, the output from my code above gives:


The students are:
ID [1] First Name [Mohammad] Last Name [Saleh] Gender [0] Course [CMP220] Attendance [30]
ID [2] First Name [Sara] Last Name [Ali] Gender [1] Course [CMP220] Attendance [28]
ID [5] First Name [Charles] Last Name [Dickens] Gender [0] Course [CMP220] Attendance [25]
ID [4] First Name [Jain] Last Name [Austin] Gender [1] Course [CMP220] Attendance [23]
ID [19] First Name [Ahlam] Last Name [Mosteghanemi] Gender [1] Course [CMP220] Attendance [15]
ID [21] First Name [Mario] Last Name [Puzo] Gender [0] Course [CMP220] Attendance [21]
ID [88] First Name [Marie] Last Name [Curie] Gender [1] Course [CMP220] Attendance [30]
ID [1930] First Name [John] Last Name [Steinbeck] Gender [0] Course [CMP220] Attendance [19]
The female students are:
ID [2] First Name [Sara] Last Name [Ali] Gender [1] Course [CMP220] Attendance [28]
ID [4] First Name [Jain] Last Name [Austin] Gender [1] Course [CMP220] Attendance [23]
ID [19] First Name [Ahlam] Last Name [Mosteghanemi] Gender [1] Course [CMP220] Attendance [15]
ID [88] First Name [Marie] Last Name [Curie] Gender [1] Course [CMP220] Attendance [30]
The low attendances are:
ID [19] First Name [Ahlam] Last Name [Mosteghanemi] Gender [1] Course [CMP220] Attendance [15]
ID [1930] First Name [John] Last Name [Steinbeck] Gender [0] Course [CMP220] Attendance [19]


As required. A couple of extra \n would help the display, but that a minor display.
Topic archived. No new replies allowed.