Class of students tracker (Homework Help)

Hello,
I am currently working on some programming homework for my grade 12 class and I am stuck on this question for a couple of days now. If someone can please check my code so far and give me some help on what to do next that would be much aprriciated.
This is the question
Write a program that manages a class of students and keeps track of their marks. Create a menu that has the following options:
1) Open a class from a file
2) Add a new student
3) Change existing student
4) Delete a student
5) Print a class list (include the class average)
6) Save the class to a file
7) Quit
Create a structure for students that includes: name, ID, number of courses and those courses. Each
course is a structure that included course name and associated mark. The class of students will be a
vector of student structures.

Also option #5 doesn't work. I get a weird error message on the debug window. If you can check it out that would be very helpful. Thanks in Advance.
My Code:
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
  #include <iostream>
#include <fstream>
#include <vector>

using namespace std;


struct course
{
    string coursename;
    int markachieved;
};

struct Student
{
    string name;
    int ID;
    int numberCourses;
    vector <course> coursetrack;

};

vector <Student> studentstructures;

int main()
{
    while (true)
    {
        int input,numberCourses=0,markachieved=0,ID=0;
        string name,coursename;
        cout<<"Welcome to the class tracker!"<<endl;
        cout<<"Choose an option."<<endl;
        cout<<"1) Open a class from a file"<<endl;
        cout<<"2) Add a new student"<<endl;
        cout<<"3) Change existing student"<<endl;
        cout<<"4) Delete a student"<<endl;
        cout<<"5) Print a class list (includes the class average)"<<endl;
        cout<<"6) Save the class to a file"<<endl;
        cout<<"7) Quit"<<endl;
        cin>>input;
        cin.ignore();
        if(input==1)
        {
            ifstream InFile("Class.txt"); // just a text file

        }
        if (input==2)
        {
            Student a;
            //course b;
            string temp="";
            // cin.ignore();
            cout<<"Input the name of the student."<<endl;
            getline(cin, a.name);
            //cin>>name;
            cout<<"Input the ID of the student."<<endl;
            cin>>a.ID;
            cout<<"Input the number of courses the student is taking."<<endl;
            cin>>a.numberCourses;
            //cin>>numberCourses;
            a.coursetrack.resize(a.numberCourses);
            cout<<"Size: "<<a.coursetrack.size()<<endl;
            for(int i=0; i<a.numberCourses; i++)
            {
                cout<<"Course name?"<<endl;
                cin>>a.coursetrack[i].coursename;
                cout<<"Mark Achieved?"<<endl;
                cin>>a.coursetrack[i].markachieved;
            }
            cout<<a.name<<","<<a.ID<<","<<a.numberCourses<<",";
            for(int i=0; i<a.numberCourses; i++)
            {
                cout<<a.coursetrack[i].coursename<<","<<a.coursetrack[i].markachieved;
            }
            studentstructures.push_back(a);

        }

        if (input==5)
        {
            cout<<"Name  | ID | Courses | Marks "<<endl;
            cout<<"____________________________"<<endl;
            for (int i=0; i<studentstructures.size(); i++)
            {
               cout<<studentstructures.at(i).name<<"    "<<studentstructures.at(i).ID<<"    ";
               for(int l=0; l<studentstructures.at(l).numberCourses; l++)
            {
                cout<<studentstructures.at(l).coursetrack[l].coursename<<endl;
            }
            }



        }
        if(input==7)
        {
            cout<<"Thank you for using the class tracker"<<endl;
            cout<<"Have a good day"<<endl;
            break;
        }
    }
    return 0;
}
Hey man, if you have learned about functions you should consider splitting this code between some of them.
1. For example this should go inside 1 function that's responsible to get correct options input from the user
1
2
3
4
5
6
7
8
9
10
11
        cout<<"Welcome to the class tracker!"<<endl;
        cout<<"Choose an option."<<endl;
        cout<<"1) Open a class from a file"<<endl;
        cout<<"2) Add a new student"<<endl;
        cout<<"3) Change existing student"<<endl;
        cout<<"4) Delete a student"<<endl;
        cout<<"5) Print a class list (includes the class average)"<<endl;
        cout<<"6) Save the class to a file"<<endl;
        cout<<"7) Quit"<<endl;
        cin>>input;
        cin.ignore();


2. Open a class from a file
Looks like you have to open a file and read all the class members from it to some container representing a class (looks like in your case its vector <Student> studentstructures;). Its a good choice but you shouldn't be using it as a global variable :
http://stackoverflow.com/questions/484635/are-global-variables-bad

Also what if you want data about 2 classes to be at your fingertips at the same time to make comparisons or anything else. Now you have only 1 global variable where you can write into and read from. Consider making a function taking a string argument representing a filename and as return type choose vector <Student> representing class with its members. (vector<Student> read_class_from_file(const string& filename))

When you are going to read class members from file and write them back to file you must overload operator>> and operator<< for Student because now there is no reading happening, you are just opening the file.

About #5
1
2
3
4
5
6
7
8
9
10
11
          cout<<"Name  | ID | Courses | Marks "<<endl;
            cout<<"____________________________"<<endl;
            for (int i=0; i<studentstructures.size(); i++)
            {
                   cout<<studentstructures.at(i).name<<"    "<<studentstructures.at(i).ID<<"    ";
                   
                   for(int l=0; l<studentstructures.at(l).numberCourses; l++)
                   {
                       cout<<studentstructures.at(l).coursetrack[l].coursename<<endl;
                   }
            }


It compiles but you can easily get runtime exception thrown because of studentstructures.at(l)
and that's good because otherwise you would have undefined behavior.

Outer loop works fine but now when you go to inner loop your condition is
not dependent on outer loop at all l<studentstructures.at(l).numberCourses; that should be i from your outer loop. Think about what would happen to this condition when inner loop executes it body and increments l. The current studentstructures[i] from outer loop is not connected to inner loops studentstructures[l] in any way.

Same goes for your l in cout<<studentstructures.at(l).coursetrack[l].coursename<<endl;

Also for inner loops condition use
studentstructures.at(i).coursetrack.size() rather than numberCourses because vector itself knows better its own size than any other variable

To make it easier in C++11 you can write that inner loop like this
1
2
for(const auto& c : studentstructures.at(i).coursetrack)
        cout<<c<<endl;


You should be using different character than l for inner loop because i and l are as confusing to look at as O and 0 next to each other and its only matter of time when typing errors as yours happens.

Consider making #5 a function as well with signature something like this void print_class_vector(const vector<Student>& class_vec)
Last edited on
Okay I have gotten #5 to work. It is currently looking 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
if (input==5)
        {
            cout<<"Name      |  ID  |         Course and Mark "<<endl;
            cout<<"_______________________________________________"<<endl;
            for (int i=0; i<studentstructures.size(); i++)
            {
                cout<<studentstructures.at(i).name<<"         "<<studentstructures.at(i).ID<<"        ";
                for(int q=0; q<studentstructures.at(i).coursetrack.size(); q++)
                {
                    //cout<<"Num: "<<studentstructures.at(i).coursetrack.size()<<endl;
                    cout<<studentstructures.at(i).coursetrack[q].coursename<<",";
                    cout<<studentstructures.at(i).coursetrack[q].markachieved<<",";
                }
                for(int a=0; a<studentstructures.at(i).coursetrack.size();a++)
                {
                    average +=(studentstructures.at(i).coursetrack[a].markachieved);
                    //cout<<"Average is: "<<average<<endl;
                    n++;
                }

                cout<<""<<endl;
        //avgfinal=(average[0]+average[1])/2;
            }
            average=average/n;
                cout<<"n is:" <<n<<endl;
            cout<<"The average of the class is: "<<average<<endl;
        }
            if(input==7)
            {
                cout<<"Thank you for using the class tracker"<<endl;
                cout<<"Have a good day"<<endl;
                break;
            }
        }


Now I have options #2 and #5 completed would I need to save the class to a file (option #6) and then continue working on the other options?
Bump any ideas please?
Topic archived. No new replies allowed.