Sructs and Classes

Write a program that stores information about students. There should be a Date structure that has values for a month, day and year. The Student class should have member variables to hold a student's last name, first name, major, and date of birth (which is a Date structure object).
The program should allow the user to enter and retrieve values for all member variables of both Date and Student objects.
Also, the program should allow the user to find out which of two Student objects is older, using an overloaded operator that compares two Student objects. ( if(Student1 > Student2) )

We are learning to add classes as .h files and the general layout for a .h file is this one

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// student.h

#ifndef STUDENT_H
#define STUDENT_H

class Fraction
{
	public:
		Student();

		// I dont know what to put here?
	private:
               string lastname;
               string firstname;
               string major;
               string dob;
		
};


#endif


how to i make a function that will let me enter the the data for the variables?

Last edited on
You need to make setters (mutator functions) which allow you to set the variables to a certain value, and getters (accessor functions) that allow you to get the values as needed.

Your constructor should initialize the variables appropriately, and 'dob' should be of type Data.
You can do it with constructors.

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
#include <iostream>

class Student {
public:
    Student(const std::string &lastname, const std::string &firstname, const std::string &major,
            const std::string &dob) {
        this->lastname = lastname;
        this->firstname = firstname;
        this->major = major;
        this->dob = dob;
    }

    const std::string &get_lastname() const {
        return lastname;
    }

    const std::string &get_firstname() const {
        return firstname;
    }

    void printFullName() {
        std::string s = "Name: " + get_firstname () + " " + get_lastname ();
        std::cout << s << std::endl;
    }

private:
    std::string lastname;
    std::string firstname;
    std::string major;
    std::string dob;

};
using namespace std;

int main() {
    Student s1 ("Foo", "Bar", "CS", "01/01/01");
    s1.printFullName ();
    return 0;
Name: Bar Foo

Process finished with exit code 0
Last edited on
So I tried to modify your example into the way that we are learning to do so in the course (it is online so it is hard to really know if we have to do it exactly how we are doing it in the book or if we can take shortcuts). Anyways, we need three files. For this problem we would need a main.cpp, a Student.h, and a Student.cpp.

Here is what I did for each file

main.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>

using namespace std;

#include "Student.h"

int main()
{
    Student s1 ("Appleseed", "John", "CS", "05/23/1990");

    s1.printFullName();

    return 0;
}


For 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
#ifndef STUDENT_H
#define STUDENT_H

class Student
{
    public:
        Student();
        Student(const std::string, const std::string, const std::string, const std::string);
        const std::string &getSurname() const;
        const std::string &getName() const;
        void printFullName();
        virtual ~Student();

    protected:

    private:
        std::string name;
        std::string surname;
        std::string major;
        std::string dob;
};

#endif // STUDENT_H 


And finally for 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
#include "Student.h"

Student::Student()
{
    //ctor
}

Student::Student(const std::string &surname, const std::string &name, const std::string &major, const std::string &dob)
{
    this->surname = surname;
    this->name = name;
    this->major = major;
    this->dob = dob;
}
const std::string Student::&getSurname()
{
    return surname;
}

const std::string Student::&getName()
{
    return name;
}

void Student::printFullName()
{
    std::string s = "Student Name: " + getName() + " " + getSurname();
    std::cout << s << endl;
}

Student::~Student()
{
    //dtor
}


I get these errors

Student.h:8:28: error: 'string' in namespace 'std' does not name a type

To use std::string, you need #include <string>
I added #include <string> in my main.cpp but I still get an error saying that in line 8 of Student.h 'string' in namespace 'std' does not name a type. Is there anywhere else I should add it? Thanks!
std::string is used in both Student.cpp and in Student.h
The best approach is to put that #include in Student.h
One more thing..

1
2
3
4
    void printFullName() {
        std::string s = "Name: " + get_firstname () + " " + get_lastname ();
        std::cout << s << std::endl;
    }


could be re-written by just calling your variables. using this->
I went a bit overboard with that, using get_... would make more sense from main.
could be re-written by just calling your variables. using this->

No need to use this->
Within the class, the member variables are available directly.

Do declare the function as const.
void Student::printFullName() const
{
//    std::string s = "Student Name: " + getName() + " " + getSurname();
    std::string s = "Student Name: " + name + " " + surname;
    std::cout << s << std::endl;
}
@Chervil Thank you, for pointing these errors out.
Thank you everyone for you help! I modified the code to look a bit more familiar to me. Now I tried to do the comparing the dates of birth to see who is older if I declare two student objects.

here is what I did

for 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
#include <string>

using namespace std;

class Student
{
    public:
        Student();
        //Student(const string, const string, const string, const string);
        void setName(string);
        void setSurname(string);
        void setMajor(string);
        void setMonth(int);
        void setDay(int);
        void setYear(int);
        const string getSurname() const;
        const string getName() const;
        const string getMajor() const;
        int getMonth();
        int getDay();
        int getYear();
        //void printFullName();

        bool operator > (Student);
        bool operator < (Student);
        virtual ~Student();

    protected:

    private:
        string name;
        string surname;
        string major;
        int month;
        int day;
        int year;
};

#endif // STUDENT_H 


for 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
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
#include "Student.h"
#include <iostream>

using namespace std;

Student::Student()
{
    //ctor
}

/*Student::Student(const string surname, const string name, const string major, const string dob)
{
    this->surname = surname;
    this->name = name;
    this->major = major;
    this->dob = dob;
}*/

void Student::setName(string nm)
{
    name = nm;
}

void Student::setSurname(string sn)
{
    surname = sn;
}

void Student::setMajor(string mjr)
{
    major = mjr;
}

void Student::setMonth(int m)
{
    month = m;
}

void Student::setDay(int d)
{
    day = d;
}

void Student::setYear(int y)
{
    year = y;
}

const string Student::getSurname() const
{
    return surname;
}

const string Student::getName() const
{
    return name;
}

const string Student::getMajor() const
{
    return major;
}

int Student::getMonth()
{
    return month;
}

int Student::getDay()
{
    return day;
}

int Student::getYear()
{
    return year;
}

bool Student::operator > (Student stud1)
{
    if (year < stud1.year)
        return true;
    else if (year == stud1.year && month < stud1.month)
        return true;
    else if (year == stud1.year && month == stud1.month && day < stud1.day)
        return true;
    else if (year == stud1.year && month == stud1.month && day == stud1.day)
        return false;
}

bool Student::operator < (Student stud2)
{
    if (year > stud2.year)
        return false;
    else if (year == stud2.year && month > stud2.month)
        return false;
    else if (year == stud2.year && month == stud2.month && day > stud2.day)
        return false;
    else if (year == stud2.year && month == stud2.month && day == stud2.day)
        return false;
}
/*void Student::printFullName()
{
    string s = "Student Name: " + getName() + " " + getSurname();
    cout << s << endl;
}*/

Student::~Student()
{
    //dtor
}


for main.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
#include <iostream>

using namespace std;

#include "Student.h"

struct Date
{
    int month, day, year;
};

int main()
{
    Date d1, d2;

    d1.month = 5;
    d1.day = 9;
    d1.year = 1995;

    d2.month = 5;
    d2.day = 9;
    d2.year = 1994;

    Student s1, s2;

    s1.setName("john");
    s1.setSurname("appleseed");
    s1.setMajor("CS");
    s1.setMonth(d1.month);
    s1.setDay(d1.day);
    s1.setYear(d1.year);

    s2.setName("carl");
    s2.setSurname("appleseed");
    s2.setMajor("CS");
    s2.setMonth(d2.month);
    s2.setDay(d2.day);
    s2.setYear(d2.year);


    cout << "name: " << s1.getName() << endl;
    cout << "surname: " << s1.getSurname() << endl;
    cout << "date of birth: " << s1.getMonth() << "/" << s1.getDay() << "/" << s1.getYear() << endl;
    cout << "major: " << s1.getMajor() << endl;
    cout << endl;
    cout << "name: " << s2.getName() << endl;
    cout << "surname: " << s2.getSurname() << endl;
    cout << "date of birth: " << s2.getMonth() << "/" << s2.getDay() << "/" << s2.getYear() << endl;
    cout << "major: " << s2.getMajor() << endl;
    cout << endl;

    if (s1 > s2)
        cout << s1.getName() << " " << s1.getSurname() << " is older." << endl;
    else if (s1 < s2)
        cout << s2.getName() << " " << s2.getSurname() << " is older." << endl;
    else
        cout << "Both individuals are the same age" << endl;

    //Student s1 ("Appleseed", "John", "CS", "05/23/1990");

    //s1.printFullName();
    //cout << "Major: " << s1.getMajor() << endl;
    //cout << "Date of Birth: " << s1.getDOB() << endl;

    return 0;
}


I have a runtime error because for some reason my comparison only displays the true value if the dates are the same (it says that they are the same age) but if I switch the dates around I get the wrong result. Could you guys help me figure out what I am doing wrong, is it my overloaded operators?
Line 52 and 54, switch the comparison signs to the opposite of how you have them.

The older one is the 'lesser one' (i.e. born earlier), younger one is 'greater one'.
Hi,

I think you should still have the constructor, rather than using set functions to do the same thing. The point of constructors is to initialise all the member variables. I am not saying set functions are a bad thing, they may still be needed if something needs to change after the object has been created. At the moment you don't have that situation. Often one can combine several related functions into one: as in changing the names.

All the get functions should be marked const: they don't change (or should not be allowed to change a member variable). You have that for some of them, not all.

There was nothing wrong with the printFullName() function: I would rather have one function to call, instead of several. If Name was a class, then this could be generalised: printFullName() would still work no matter how many names there were. you could do the same with the Date.

The parameters of the constructor which are strings or any other type of class should be passed by reference, and a member initialization list should be used. Also, do yourself a favour: make the parameters different to the member variable names.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <string>

#include "Student.hpp"
#include "Date.hpp"

Student::Student(const std::string& surnameArg,
                const std::string& firstnameArg, 
                const std::string& majorArg, 
                const Date& dobArg)

                :  // colon introduces member initializer list

                surname(surnameArg),  // direct intialization
                firstname(firstnameArg),
                major(majorArg) ,
                dob(dobArg)
{
// do validation here
}


Consider making Name a class in it's own right. It could have a std::vector<std::string> FullName That way, one can have multiple middle names, and deal with the Family name scenarios - some cultures write the Family name first :+)

The Date class could have an enum of the months. Scott Meyers even mentions having a class for every month !! The idea being to make the class hard to use wrongly: given the various date formats around the world. 10/03/2016 could be 10th of March or Oct 3 depending on the locale.

Good Luck !!

Edit:

it is online so it is hard to really know if we have to do it exactly how we are doing it in the book or if we can take shortcuts


I would try to get away with as many language features or best practises as possible, or at least ask what is allowed.
Last edited on
Thank you! I am still quite new to this language so there are many things that I still need to learn. I feel that even when I do "learn" it I will still not know everything. I will mess around with what you said and see what happens!
Topic archived. No new replies allowed.