dynamically allocating an array of strucures

I am having problems with dynamically allocating an array of structures. I have to write a program that ask for how many students a teacher has and then create an array of structures to fit that request. My complier compiles but when I run the prgm I get a runtime error and the prgm freezes.


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<limits>
#include<iostream>
#include<cmath>
#include<cstdlib>
#include<string>
#include<vector>
#include<ctime>
#include<iomanip>
#include <algorithm>
#include<fstream>
#include<conio.h>
using namespace std;

bool inputGood = false;         //global variable used to validate input;

int numberStudents(int);        //prototype for function that gets the number of students from user
int numberTests(int);        //prototype for function that gets the number of tests from user



//a strucure to be used as a data type to hold a student's info
struct StudentInfo
    {
        string name;            //member to hold name of a student
        string idNumber;        //member to hold students id number
        int *testScores;        //pointer member to hold students test grades
        double averageOfTests;  //member to hold the average of the students test grades
        char courseGrade;       //member to hold the letter grade for the student
    };

int main()
{
    int numStudents;       //variable to hold the number of students input by user
    int numTests;          //variable to hold the number of tests

    numStudents = numberStudents(numStudents);
    numTests = numberTests(numTests);

    StudentInfo *student[numStudents];
    student[numStudents] = new StudentInfo;

    for(int i = 0; i < numStudents; i++)
    {
        cout << "What is student number " << (i+1) << "'s name";
        cin.ignore();
        getline(cin, student[i]->name);
    }

    //delete [] student;
    return 0;
}

//function to get the number of students
int numberStudents(int numberOfStudents)
{
    do
    {
        cout << "How many students do you have to enter information on? ";
        inputGood = std::cin >> numberOfStudents;

        if(numberOfStudents <= 0 || !inputGood)
        {
            cout << "Invalid Entry!" << endl;
            cin.clear();
            while( cin.get() != '\n' );
        }

    }while(numberOfStudents <= 0 || !inputGood);

    system("cls");
    return numberOfStudents;
}

//function to get the number of tests for each student
int numberTests(int numberOfTests)
{
    do
    {
        cout << "How many tests does each student have? ";
        inputGood = std::cin >> numberOfTests;

        if(numberOfTests <= 0 || !inputGood)
        {
            cout << "Invalid Entry!" << endl;
            cin.clear();
            while( cin.get() != '\n' );
        }

    }while(numberOfTests <= 0 || !inputGood);

    system("cls");
    return numberOfTests;
}

  
1
2
    StudentInfo *student[numStudents];
    student[numStudents] = new StudentInfo;


Should be StudentInfo *student = new StudentInfo[numStudents]

Also you should remove the commented out delete so it actually deletes and does not leave a memory leak.

[edit]forgot code tag
Last edited on
Thanks a lot giblet that along with using the dot operator instead of the -> deference operator to a pointer fixed my problems
39
40
StudentInfo *student[numStudents];
student[numStudents] = new StudentInfo;

Line 40 there doesn't do what you might think it does.
Rather than initializing each item in the student array with a new StudentInfo structure, it gives the array element at index numStudents (which is out-of-bounds) a new StudentInfo.

It's kinda like this:
1
2
int array[5];
array[5] = 4; // Assigning a value to an out-of-bounds element 


So you'll need to use a loop.

Eh, or see giblit's post.
(That code isn't even valid anyways since arrays on the stack have to have a constant size.)
Last edited on
In C++, std::vector<> is the canonical dynamically allocated array.
http://www.mochima.com/tutorials/vectors.html

You have #include <vector> , so use it.

int numberStudents(int numberOfStudents) and int numberTests(int numberOfTests) are identical, but for the prompt. The code can be factored into a single function, with the prompt as a parameter.

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
#include<limits>
#include<iostream>
#include<cmath>
#include<cstdlib>
#include<string>
#include<vector>
#include<ctime>
#include<iomanip>
#include <algorithm>
#include<fstream>
//#include<conio.h>
using namespace std;

//bool inputGood = false;         //global variable used to validate input;

// int numberStudents(int);        //prototype for function that gets the number of students from user
// int numberTests(int);        //prototype for function that gets the number of tests from user
int get_positive_number( std::string prompt ) ;

//a strucure to be used as a data type to hold a student's info
struct StudentInfo
    {
        string name;            //member to hold name of a student
        string idNumber;        //member to hold students id number
        //int *testScores;        //pointer member to hold students test grades
        vector<int> testScores ;
        double averageOfTests;  //member to hold the average of the students test grades
        char courseGrade;       //member to hold the letter grade for the student
    };

int main()
{
    // int numStudents;       //variable to hold the number of students input by user
    // int numTests;          //variable to hold the number of tests

    const int numStudents = get_positive_number( "number of students? " );
    const int numTests = get_positive_number( "number of tests? " );

    // StudentInfo *student[numStudents];
    // student[numStudents] = new StudentInfo;
    vector<StudentInfo> student(numStudents) ;

    for(int i = 0; i < numStudents; i++)
    {
        cout << "What is student number " << (i+1) << "'s name? ";
        cin.ignore();
        //getline(cin, student[i]->name);
        getline(cin, student[i].name);

        student[i].testScores.resize(numTests) ;

        // ...
    }

    //delete [] student;
    // return 0;
}

int get_positive_number( std::string prompt )
{
    bool inputGood = false ;
    int value ;
    do
    {
        cout << prompt ;
        inputGood = std::cin >> value ;

        if( value <= 0 || !inputGood )
        {
            cout << "Invalid Entry!" << endl;
            cin.clear();
            while( cin.get() != '\n' );
        }

    }while( value <= 0 || !inputGood );

    // system("cls");
    return value ; // numberOfStudents;
}

I have made the suggested fixes that JLBorges suggested. But now I am having problems inputting data into the dynamically allocated array within the structure I have tried using the -> dereference operator and still no luck.
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

#include<limits>
#include<iostream>
#include<cmath>
#include<cstdlib>
#include<string>
#include<vector>
#include<ctime>
#include<iomanip>
#include <algorithm>
#include<fstream>
#include<conio.h>
using namespace std;

bool inputGood = false;         //global variable used to validate input;

//protype to retrieve a positive number
int poitiveNumber(string);


//a strucure to be used as a data type to hold a student's info
struct StudentInfo
    {
        string name;            //member to hold name of a student
        string idNumber;        //member to hold students id number
        int *testScores;        //pointer member to hold students test grades
        double averageOfTests;  //member to hold the average of the students test grades
        char courseGrade;       //member to hold the letter grade for the student
    };

int main()
{
     //variable to hold the number of students input by user
    const int numStudents = poitiveNumber("Number of students? ");

    //variable to hold the number of tests
    const int numTests = poitiveNumber("Number of tests? ");

    int i;                 //variable to use to iterate the first for loop

    StudentInfo *student = new StudentInfo[numStudents];

    for(i = 0; i < numStudents; i++)
    {
        cout << "What is student number " << (i+1) << "'s name? ";
        cin.ignore();
        getline(cin, student[i].name);

        cout << "What is " << student[i].name << "'s id number? ";
        cin >> student[i].idNumber;

        for(int x = 0; x < numTests; x++)
        {
            cout << "What is " << student[i].name << "'s number "
                 << (x+1) << " test score";
            cin >> student[i].testScores[x];
        }

    }

    delete [] student;
    return 0;
}

//function to get a positive number
int poitiveNumber(string prompt)
{
    int pNum;
    do
    {
        cout << prompt;
        inputGood = std::cin >> pNum;

        if(pNum <= 0 || !inputGood)
        {
            cout << "Invalid Entry!" << endl;
            cin.clear();
            while( cin.get() != '\n' );
        }

    }while(pNum <= 0 || !inputGood);

    system("cls");
    return pNum;
}

You forgot to allocate memory for the test scores. You are trying to assign a value to the pointer. Before line 52 you should put

student[i]->testScores = new int[numTests];

or if you can use vectors like JLBorges mentioned use them they are much better than using arrays like that. Since you forgot to allocate and deallocate both times :P

http://www.cplusplus.com/doc/tutorial/dynamic/

[edit]Also why do you have all these includes you aren't even using half of them. Are they just everything you learned?

1
2
3
4
5
6
7
8
9
10
11
#include<limits>
#include<iostream>
#include<cmath>
#include<cstdlib>
#include<string>
#include<vector>
#include<ctime>
#include<iomanip>
#include <algorithm>
#include<fstream>
#include<conio.h> 
Last edited on
Thanks giblet. I would prefer vectors I believe they are easier to deal with and have many other prebuilt in functions that I could use. Im only stuck with following the prompt of my book. I did what you mentioned except that I had to utilize the dot(.) operator other than the dereference operator(->) other than that it seems to work so far. I will be finishing this prgm today before I go to sleep I hope. I having only been coding for 6 months now so I still have much to learn.

The reason why I have all the libraries is they are in my basic_program_model I use when I build prgms. I eliminate the ones I don't use when im done coding the prgm
Last edited on
Side note: conio.h is non-standard and should never be used ever:
https://en.wikipedia.org/wiki/Conio.h
Thanks for that info L B
Topic archived. No new replies allowed.