C++ - incrementing integer variable does not work

Oct 15, 2020 at 9:19am
So I'm creating a program that implements several classes representing a school, and its students and courses. I'm running into an issue in School.cc where the addTaken() finds the student object with the given student number and the course object with the given course code, and then creates a new Taken object with the found student and course objects and adds it to the back of the Taken collection which is studentCoursePairs[].

The problem is the variable numTaken never increments despite having the '++'. It seems to always stay at 0. If numTaken is 0, the loop immediately stops (as 0 < 0 is false) and numTaken is never incremented for this reason. I was wondering if anyone knows how to fix this?

Since numTaken is always 0 it won't let me print anything in the Taken collection out.

School.cc

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
#include <iostream>
#include <iomanip>
using namespace std;
#include <string.h> 

#include "School.h"

School::School(string s1) : name(s1){ 
    numTaken = 0;
}

void School::addTaken(string number, int code, string grade){
    Student* s = nullptr;
    Course* c = nullptr;
    if((studentsCollection->find(number, &s)) && (coursesCollection->find(code, &c))){
        Taken* taken = new Taken(s, c, grade);
        studentCoursePairs[numTaken] = taken;            
        ++numTaken;
    }
}

void School::printTaken(){
    cout << name << " === TAKEN: "<< endl;
    for(int i = 0; i < numTaken; ++i){
        studentCoursePairs[i]->print(); //seg fault
    }   
}


Last edited on Oct 15, 2020 at 11:27pm
Oct 15, 2020 at 10:01am
In addTaken(), why the for loop?
Oct 15, 2020 at 10:02am
despite having the '++'

Only if it ever runs that section.

I should stop using pointers with explicit dynamic allocation (which is going to lead to memory leak sooner or later) and just use vectors.
Last edited on Oct 15, 2020 at 10:04am
Oct 15, 2020 at 10:03am
Sorry, I accidentally copied an old version that caused a seg fault. I updated it to remove the for loop - so now the seg fault is gone but numTaken just doesn't increment for some reason. I think it's because of the fact that find() in the other two classes is a boolean function and stops running when it returns but I don't know how to get around this.

When I print numTaken in the School's print function, it's always 0 no matter where I increment it in addTaken(). And because it stays at 0, nothing ever prints.
Last edited on Oct 15, 2020 at 10:04am
Oct 15, 2020 at 10:14am
You do not use numTaken anywhere. The print function should look like:
1
2
3
4
5
6
void School::printTaken(){
    cout << name << " === TAKEN: "<< endl;
    for(int i = 0; i < numTaken; ++i){ // Note: numTaken instead of sizeof...
        studentCoursePairs[i]->print(); //it shouldn't seg fault unless numTaken > MAX_STUDENTS
    }   
}
Last edited on Oct 15, 2020 at 10:14am
Oct 15, 2020 at 10:18am
What type is studentCoursePairs? Shouldn't the loop be dependent upon numTaken?

1
2
3
4
5
6
void School::printTaken(){
    cout << name << " === TAKEN: "<< endl;
    for(int i = 0; i < sizeof(studentCoursePairs)/sizeof(studentCoursePairs[0]); ++i){
        studentCoursePairs[i]->print(); //seg fault
    }   
}


Consider:

1
2
3
4
5
6
void School::printTaken(){
    cout << name << " === TAKEN: "<< endl;
    for(int i = 0; i < numTaken; ++i){
        studentCoursePairs[i]->print();
    }   
}


If
Last edited on Oct 15, 2020 at 10:18am
Oct 15, 2020 at 10:18am
Fixed! Unfortunately still dealing with the issue that numTaken is always 0 :(
Oct 15, 2020 at 10:28am
studentCoursePairs is a Taken object. Each Taken object represents the fact that a specific student has taken a specific course, and it will store the grade that the student earned in that course.

Even if I added 'numTaken' in the for loop instead, if I add a print statement above the for loop that prints out the value of numTaken it's 0 for some reason. It never gets incremented in addTaken(). I was told my find functions in StudentCollection and CourseCollection always return on the first iteration of the loop which is probably why but I don't know how to get past this as both my find functions must be boolean.
Last edited on Oct 15, 2020 at 10:30am
Oct 15, 2020 at 10:50am
In studentCollection, when is size incremented? In coursesCollection, when is numCourses incremented? In the .find(), are these numbers as expected?

Is the data in studentCollection and coursesCollection OK - verified with a print?

What debugging of this code have you done? The debugger should be your best friend when trying to find out what's happening and why it's not working as expected.

Oct 15, 2020 at 10:53am
I updated the code to include the add function in StudentCollection. There's also an add function in CoursesCollection which is basically the exact same thing but checks for the course code instead of student number. Size is incremented in the add function in these classes.

All add() does in these functions is add the Student/Course object to their collection in ascending order by their alphabetical name/course code. There are different print functions to print all students in the school and all courses in the school.

The size integer in these functions are unrelated to numTaken. I'm worried about getting numTaken to increment for when I print courses taken by a specific student.
Last edited on Oct 15, 2020 at 10:56am
Oct 15, 2020 at 10:56am
In StudentCollection is size changed? Or in CoursesCollection numCourses?

numTaken is only taken/incremented when both find functions return true.
Oct 15, 2020 at 10:58am
size is incremented in the add function in StudentCollection. This number basically represents the number of total Student objects in the school. CoursesCollection also has a variable size and an identical add function that represents the total number of different courses offered at the school.

numTaken is separate and only belongs to the School class. It represents the total number of courses taken by a specific student. So basically the number of Taken objects in the array which is determined by addTaken()
Last edited on Oct 15, 2020 at 11:02am
Oct 15, 2020 at 11:09am
numTaken is separate and only belongs to the School class. It represents the total number of courses taken by a specific student. So basically the number of Taken objects in the array which is determined by addTaken()
Yes, but due to this line:

if((studentsCollection->find(number, &s)) && (coursesCollection->find(code, &c))){

numTaken depends on StudentCollection and CoursesCollection. So you need to check whether their data is correctly set.
Oct 15, 2020 at 1:36pm
@OP FWIW, I reckon you data model and naming could do with a 're-spray' along the following lines. I see you ignored <vector>'s for C-style arrays - a teaching constraint maybe? <maps> would be even better ...

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

class Student
{
public:
    std::string name;
    int ID;
    Student(){};
    Student( std::string n, int id){ name = n; ID = id; }
};

class Course
{
public:
    std::string name;
    int course_no;
    Course(){};
    Course( std::string n, int c){ name = n; course_no = c; }
};

class Enrolment
{
public:
    Student student;
    Course course;
    int grade{0};
    Enrolment(){};
    Enrolment(Student s, Course c){ student = s; course = c; }
};

class School
{
public:
    std::string name;
    
    int no_students{0};
    int no_courses{0};
    int no_enrolments{0};
    
    Student* roll = new Student[5];
    Course* curriculum = new Course[20];
    Enrolment* report = new Enrolment[100];
    
    void addStudent(Student s){roll[no_students] = s; no_students++;}
    void addCourse(Course c){curriculum[no_courses] = c; no_courses++;}
    void addEnrolment(Enrolment e){report[no_enrolments] = e; no_enrolments++;}
    
    void display_students()
    {
        for(int i = 0; i < no_students; i++)
        std::cout << roll[i].ID << '\t' << roll[i].name << '\n';
    }
    
    void display_courses()
    {
        for(int i = 0; i < no_courses; i++)
        std::cout << curriculum[i].course_no << '\t' << curriculum[i].name << '\n';
    }
    
    void display_enrolments()
    {
        for(int i = 0; i < no_enrolments; i++)
        std::cout
        << i << '\t' << report[i].student.name << " -> "
        << report[i].course.name << '\t' << "Grade: " << report[i].grade << '\n';
    }
    
    void setGrade(int i, int g)
    {
        report[i].grade = g;
    }
};

int main()
{
    School eton; eton.name = "Eton";
    
    Student s1("Mary",11), s2("Bob",22), s3("Jack",44);
    eton.addStudent(s1); eton.addStudent(s2);  eton.addStudent(s3);
    eton.display_students();
    
    Course c1("Woodwork", 23); Course c2("English", 541);
    eton.addCourse(c1); eton.addCourse(c2);
    eton.display_courses();
    
    Enrolment e1(s1,c2), e2(s1,c1), e3(s2,c2), e4(s3,c2);
    eton.addEnrolment(e1); eton.addEnrolment(e2); eton.addEnrolment(e3); eton.addEnrolment(e4);
    eton.display_enrolments();
    
    eton.setGrade(1,96);
    eton.setGrade(2,87);
    eton.display_enrolments();
    
    return 0;
}


11	Mary
22	Bob
44	Jack
23	Woodwork
541	English
0	Mary -> English	Grade: 0
1	Mary -> Woodwork	Grade: 0
2	Bob -> English	Grade: 0
3	Jack -> English	Grade: 0
0	Mary -> English	Grade: 0
1	Mary -> Woodwork	Grade: 96
2	Bob -> English	Grade: 87
3	Jack -> English	Grade: 0
Program ended with exit code: 0
Topic archived. No new replies allowed.