Objects and Pointers

this program requires the creation of class objects that are used to store student information, grades, and find the average. It is pretty basic, and I understand most of it, however, there is one part that I can not wrap my head around. The assignment asks for pointers to the test scores and I can not find a solution to this, or at least understand anything remotely similar. I am still a bit rusty on pointers and I have been trying to go back to try to understand them better. I would like to figure this out on my own, but unfortunately, I feel like I am not getting anywhere. Here is what I have so far:

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

using namespace std;

class StudentInfo
{
public:
    void setId (int);
    void setAverage (double);
    void setName (string);
    void setScore(double );

    int getId ( ) const;
    double getAverage ( ) const;
    string getName ( ) const;

    double calcAverage ( );

private:
    int id;

    double average,
           scores;

    string name;

};

void StudentInfo::setId       (int ID)              {id = ID;}
void StudentInfo::setName     (string student_name) {name = student_name;}
void StudentInfo::setScore    (double score)        {scores = score;}

int StudentInfo::getId        ( ) const             {return id;     }
double StudentInfo::getAverage( ) const             {return average;}
string StudentInfo::getName   ( ) const             {return name;   }

double StudentInfo::calcAverage( ) {}  // need to do


int main()
{
    const int SIZE = 15;

    int id;

    double score;

    string name;

    ifstream fin;
    fin.open ("students.txt");
    if(!fin)
        cout << "***failed to open***" << endl;

    ifstream test_fin;
    test_fin.open ("test_scores.txt");
    if(!fin)
        cout << "***failed to open***" << endl;

    StudentInfo students[SIZE];

    for (int count = 0; count < SIZE; count++)
    {
        fin >> id >> name;
            students[count].setId(id);
            students[count].setName(name);
        test_fin >> score;
            students[count].setScore(score);
    }


    return 0;
}


Here is what the assignment calls for:

Create arrays of class objects for 15+ student records including student ID’s, student names, pointers point to each of student’s test scores, and the average of each student’s test scores.

The part I am having the most trouble on:

"pointers point to each of student’s test scores"

I would be more than grateful for any hints or other examples, thank you!
Last edited on
1
2
3
4
private:
    ...
    double average,
           scores;

pointers point to each of student’s test scores

If you need to calculate the average of (a bunch of) scores, it implies you need to store more than one score, therefore you can’t use a simple double scores; to put them into memory, can you? In one double you can store one value; what you need is a sequence of doubles.

To store a sequence of values in memory, in C++ you could take advantage of std::vectors, but it seems your teacher wants you to use (the old-fashioned) pointers.

If you don’t know how to use pointers to store a sequence of values, that’s another kettle of fish - in that case, please specify what you need help about.

@KeaganM are you sure you wrote down the instructions correctly?

You wrote:
Create arrays of class objects for 15+ student records including student IDs, student names, pointers point to each of student’s test scores, and the average of each student’s test scores.


Some things I marked in bold might just be grammatical errors, but might also change the project specs completely. I expected something more exact, with types, like this:

- Create a class TestScore to store a string test subject and double test grade
- Create a class StudentInfo to store a string name, a string ID, TestScore pointers, and a double test average
- make an array of 15+ StudentInfo s


something like that would leave very little doubt
Last edited on
These are the full instructions:

CS2308 Project 5
Programming Project 5 : Class specification (.h). Class implementation (.cpp).

References: Program 13-3 with header file for class declaration 
and member function definition for class implementation. You may 
need to refer to program 13-2. Please also ref to Prog 13-14 and header file 
in section 13.10 for array of class objects.Input Output file refers to Program 12-1,12-2, 12-3, and 12-4

Create arrays of class objects for 15+ student records including student ID’s, student names, pointers point to each of student’s test scores, and the average of each student’s test scores. 


a.	The student records must be in a file for input including students ID’s, and student names. The file path in the desktop can be located by file property, for example: 
  
  “C:\\Users\\yourUsersName\\Desktop\\filename.txt”

b.	The 10 testScores of each student may be initialized in the program body or stored in a second file for input.

c.	After inputting the file into arrays of class objects, calculate the average score of each student. The call function for average must be a member function of the student class.
 
d.	Print out student ID’s, student names, average scores and the associated 10 testScores of each student.

e.	Your class declaration should include student records as member data of the class. Your function definition should include the average function and other functions as you 
desire as member functions of the class.

f.	Must use class specification (.h) and class implementation (.cpp). There will be no credit if specification file and implementation file are not used.


Also I think I may be asking how to use pointers for a sequence of values in the context of a class.
Last edited on
Well the trouble with a design involving pointers is that you need to decide who owns the data (the caller? the Student class? the TestScore class?)

At least you seem to have some freedom in the file format. What I have here is not quite per the spec, as I bunched it into one imitated "file". Average is calculated at the time of parsing and not in a standalone function, and I threw in a subject to go with the test score. Might give you some ideas of how to store pointers to a TestScore class.

Your spec mentions exactly how many tests (10), but not how many students. In my custom file format I started off with a single line to show this number.

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

using namespace std;

class TestScore
{
public:
    TestScore() : subject_("Unknown"), score_(0.0)
    {        
    }

    TestScore(string subject, double score ) : 
        subject_(subject),
        score_(score)
    {        
    }

    double Score() const { return score_; }

    friend ostream& operator<<(ostream& os, const TestScore& t)
    {
        os << setw(15) << t.subject_ << t.score_;
        return os;
    }
    friend istream& operator>>(istream& is, TestScore& t)
    {
        is >> t.subject_ >> t.score_;
        return is;
    }

private:
    string subject_;
    double score_;
};

class StudentInfo
{
public:
    StudentInfo() : name_("NoName"), id_("00000"), tests_size_(0)
    {        
    }

    StudentInfo(string name, string id, int tests_size) : 
        name_(name),
        id_(id),
        tests_size_(tests_size)
    {
    }

    ~StudentInfo()
    {
        if (tests_)
            delete [] tests_;
    }

    void ParseTests(istream& is)
    {
        if (tests_)
            delete [] tests_;
        
        tests_ = new TestScore[tests_size_];
        double sum = 0.0;
        for (int i=0; i<tests_size_; ++i)
        {
            is >> tests_[i];
            sum += tests_[i].Score();
        }
        average_ = sum/tests_size_;
    }

    unsigned TestsSize() const { return tests_size_; }

    friend ostream& operator<<(ostream& os, const StudentInfo& s)
    {
        os << setw(10) << left << s.id_ << s.name_; 
        os << "\nTest Scores(" << s.tests_size_ << "):\n";
        for (int i=0; i<s.tests_size_; ++i)
            os << "  " << s.tests_[i] << '\n'; 
        os << "Test Average: " << s.average_ << '\n';       
        return os;
    }
    friend istream& operator>>(istream& is, StudentInfo& s)
    {
        is >> s.id_ >> s.name_ >> s.tests_size_;
        return is;
    }

private:
    string name_;
    string id_;
    TestScore* tests_;
    unsigned tests_size_;
    double average_;
};


int main() 
{
    // Format as follows:
    //  - one line for number of students
    //  - for each student: ID Name Number_of_Tests
    //  - for each test: Subject Score    
    const char* student_data = R"LITERAL(2
S00001 Sally 3
Geometry 95.4
Physics 87.3
English 89
S12345 John 4
Trig 97.2
English 82.5
Gym 85.0
History 79.6
)LITERAL";

    cout << fixed << setprecision(1);
    istringstream iss(student_data);  // Imitate file stream

    int number_students;
    iss >> number_students;

    StudentInfo* students = new StudentInfo[number_students];
    for (int i=0; i<number_students; ++i)
    {
        iss >> students[i];
        students[i].ParseTests(iss);
    }
    
    // Show all students previously read in
    for (int i=0; i<number_students; ++i)
        cout << students[i] << '\n';
    
    delete [] students;

    return 0;
}


running at https://repl.it/@icy_1/HospitableWryConsulting

S00001    Sally
Test Scores(3):
  Geometry       95.4
  Physics        87.3
  English        89.0
Test Average: 90.6

S12345    John
Test Scores(4):
  Trig           97.2
  English        82.5
  Gym            85.0
  History        79.6
Test Average: 86.1
Last edited on
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

#include <iostream>
#include <fstream>

using namespace std;

class StudentInfo
{
public:
    void setId (int);
    void setAverage (double);
    void setName (string);
    void setScore(double );

    int getId ( ) const;
    double getAverage ( ) const;
    string getName ( ) const;
    double getScore ( ) const;

    double calcAverage (int );

    void createScoreArray (int size);

private:
    int id,
        num_scores;

    double score;

    string name;

};

void StudentInfo::setId           (int ID)                      {id = ID;}
void StudentInfo::setName     (string student_name) {name = student_name;}
void StudentInfo::setScore     (double test)               {score = test;  }

int StudentInfo::getId             ( ) const             {return id;        }
string StudentInfo::getName   ( ) const             {return name;   }
double StudentInfo::getScore  ( ) const             {return score;   }

double StudentInfo::calcAverage(int total) {return total/10;}

int main()
{
    const int SIZE = 6;
    int id,
        total = 0;
    double average = 0,
           score;

    string name;

    StudentInfo students[SIZE];
    StudentInfo *testptr = nullptr;

    testptr = new StudentInfo;

    ifstream fin;
    fin.open ("students.txt");
    if(!fin)
        cout << "***failed to open***" << endl;

    ifstream test_fin;
    test_fin.open ("test_scores.txt");
    if(!fin)
        cout << "***failed to open***" << endl;


    for (int student_num = 0; student_num < SIZE; student_num++)
    {
        fin >> id >> name;
            students[student_num].setId(id);
            students[student_num].setName(name);

            cout << students[student_num].getId() << " "
                   << students[student_num].getName() << " ";

         for (int test_num = 0; test_num < 10; test_num++)
         {
             test_fin >> score;
             testptr->setScore(score);
             total += testptr->getScore();
            
             cout << testptr->getScore() << " ";

         }

        average = students[student_num].calcAverage(total);

        cout << average << endl;

        total = 0;
    }

   return 0;
}



This is my second attempt to tackle the problem, based on some of the response. It outputs what it needs to but I wanted to see what everyone else thought about it.
Last edited on
Topic archived. No new replies allowed.