Pointers/Dynamic Arrays Issue

I'm currently delving into my first venture with pointers and dynamic arrays, and I am creating a gradebook program for my class, and it requires the use of dynamic arrays/pointers for the bulk of the input storage, and that's one area where I've kinda gone off the rails. So far in my program, what keeps happening is that when it attempts to gather the scores for calculating the average, it always asks for one more test score than specified, which throws off the average calculation. No matter how many different ways I attempt to rewrite my inputScores function, it always goes over by one or throws an error.

Here's a description of the program required I've included in my notes.

Description: The purpose of this program is to utilize a structure to store data give by the program specifications. The program should keep a list of test scores for a group of students, ask the user how many students there are, and dynamically allocate an array of structures using the input given. Each structure's Tests member will point to a dynamically allocated array that will hold the test scores for a student. The program will then ask the user for the ID number and all the test scores for each student. The Average member will hold the calculated average test score. A grading scale given in the program specification that ranges from A to F will be stored in the Grade member structure. Once all information has been given, a table will be displayed on screen each student's name, ID number, average test score, and course grade.

Program specifications require that all data for each student must be entered, and negative integers cannot be accepted.

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
#include <iostream>
#include <string>		// For utilizing strings
using namespace std;

// Declare structure(s)
struct GradeBook{
	string name;		// Name of student
	int idnum;			// Student ID number
	int* tests;			// Pointer to an array of test scores
	double average;		// Average of test scores
	char grade;			// Grade for the course
};

// Function Prototype(s)
int inputStudents();				// Asks user for number of students
int inputTests();					// Asks user for number of test scores
string inputName();					// Asks uer for each student's name
int inputID();						// Asks user for each student's ID number
int *inputScores(int);				// Asks user for the test scores for each student
double calcAverage(int*, int);		// Calculates the average test score for each student
char calcGrade(double);				// Calculates the letter grade for each student based on their average
void display(GradeBook*, int);		// Displays each student's name, ID#, average test score, and course grade

int main(){

	// Create a dynamic array of the GradeBook structure. Array size is based upon user input given in
	// the inputStudents function. 
	GradeBook *studentList; 
	int size = inputStudents(); 
	studentList = new GradeBook[size];

	// Check for possible memory allocation errors. If error is found, end program. 
	if (studentList == NULL){
		cout << "Memory Allocation Error!";
		system("pause");
		return 0;
	}

	// Create a variablearray to hold the number of test scores for each student.
	int numOfTests = inputTests();

	for (int count = 0; count <= size; count++){
		studentList[count].name = inputName();
		studentList[count].idnum = inputID();
		studentList[count].tests = inputScores(numOfTests);
		studentList[count].average = calcAverage(studentList[count].tests, numOfTests); 
		studentList[count].grade = calcGrade(studentList[count].average); 
	}

	display(studentList, size); 

	delete [] studentList; 

	system ("pause");
	return 0;
}

int inputStudents(){

	int students; 
	cout << "How many students are there?" << endl;
	cin >> students; 

	return students; 
}

int inputTests(){

	int tests; 
	cout << "How many tests will there be?" << endl;
	cin >> tests;

	return tests;
}

string inputName(){

	string name; 
	cout << "Enter the student's name: ";
	cin >> name;

	return name; 

}

int inputID(){

	int idNum;
	cout << "Enter the student's ID Number ";
	cin >> idNum;

	return idNum;

}

int *inputScores(int numOfTests){

	int *scores; 
	scores = new int[numOfTests]; 

	cout << "Enter the test scores for the student. Press ENTER after each score." << endl;

	for (int count = 0; count <= numOfTests; count++){
		cout << "Score " << (count + 1) << ": "; 
		cin >> scores[count];
	}

	return scores; 
}

double calcAverage(int *testScores, int numOfTests){

	int total = 0;  
	double average;

	for (int count = 0; count <= numOfTests; count++){
		total += testScores[count];
	}

	average = total/numOfTests;
	return average;

}
for (int count = 0; count <= numOfTests; count++){

Shouldn't this be just < instead of <=?
When I do that, my scores variable ends up with some crazy values stored in it.
Can you give an example of the output you're getting?

Also, can you post your display function?
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
char calcGrade(double average){

	char letterGrade; 

	if		(average > 90 && average <= 100)
		letterGrade = 'A';
	else if (average > 80 && average <= 90)
		letterGrade = 'B';
	else if (average > 70 && average <= 80)
		letterGrade = 'C'; 
	else if (average > 60 && average <= 70)
		letterGrade = 'D';
	else if (average >= 0 && average <= 60)
		letterGrade = 'F'; 
	else{  
		cout << "Logic error." << endl;
		system("pause");
		exit(EXIT_FAILURE); 
	}

	return letterGrade;
}

void display(GradeBook *studentList, int size){

	for (int count = 0; count <= size; count++)
		cout << studentList[count].name << " " << studentList[count].idnum << " " 
		<< studentList[count].average << " " << studentList[count].grade << endl; 

	return; 
}


That's the rest of the code... Obviously my program stops because of the final else statement in calcAverage.

What I end up with is an insane negative value in my scores variable.
Last edited on
It works for me if I change
for (int variable_name = 0; variable_name <= limit; variable_name++)
to
for (int variable_name = 0; variable_name < limit; variable_name++)
everywhere (so that would be lines 42, 103, and 116 of your first code, and also line 26 of your second code).

Most likely, what's happening is that you're going out-of-bounds in your arrays, so then you end up averaging in some extra junk value (which is probably some random negative value), which drops your whole average to some insane negative value.

Also, I think you have a memory leak since although you delete[] studentList;, you never delete[] the scores for each student.
Last edited on
Works fine for me... I think long double main was right. You just need to replace each of the four <= with <. An array only goes from 0 to n-1, not from 0 to n.

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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#include <iostream>
#include <string>		// For utilizing strings
using namespace std;

// Declare structure(s)
struct GradeBook{
	string name;		// Name of student
	int idnum;			// Student ID number
	int* tests;			// Pointer to an array of test scores
	double average;		// Average of test scores
	char grade;			// Grade for the course
};

// Function Prototype(s)
int inputStudents();				// Asks user for number of students
int inputTests();					// Asks user for number of test scores
string inputName();					// Asks uer for each student's name
int inputID();						// Asks user for each student's ID number
int *inputScores(int);				// Asks user for the test scores for each student
double calcAverage(int*, int);		// Calculates the average test score for each student
char calcGrade(double);				// Calculates the letter grade for each student based on their average
void display(GradeBook*, int);		// Displays each student's name, ID#, average test score, and course grade

int main(){

	// Create a dynamic array of the GradeBook structure. Array size is based upon user input given in
	// the inputStudents function. 
	GradeBook *studentList; 
	int size = inputStudents(); 
	studentList = new GradeBook[size];

	// Check for possible memory allocation errors. If error is found, end program. 
	if (studentList == NULL){
		cout << "Memory Allocation Error!";
		// system("pause");
		return 0;
	}

	// Create a variablearray to hold the number of test scores for each student.
	int numOfTests = inputTests();

	for (int count = 0; count < size; count++){
		studentList[count].name = inputName();
		studentList[count].idnum = inputID();
		studentList[count].tests = inputScores(numOfTests);
		studentList[count].average = calcAverage(studentList[count].tests, numOfTests); 
		studentList[count].grade = calcGrade(studentList[count].average); 
	}

	display(studentList, size); 

	delete [] studentList; 

	// system ("pause");
	return 0;
}

int inputStudents(){

	int students; 
	cout << "How many students are there?" << endl;
	cin >> students; 

	return students; 
}

int inputTests(){

	int tests; 
	cout << "How many tests will there be?" << endl;
	cin >> tests;

	return tests;
}

string inputName(){

	string name; 
	cout << "Enter the student's name: ";
	cin >> name;

	return name; 

}

int inputID(){

	int idNum;
	cout << "Enter the student's ID Number ";
	cin >> idNum;

	return idNum;

}

int *inputScores(int numOfTests){

	int *scores; 
	scores = new int[numOfTests]; 

	cout << "Enter the test scores for the student. Press ENTER after each score." << endl;

	for (int count = 0; count < numOfTests; count++){
		cout << "Score " << (count + 1) << ": "; 
		cin >> scores[count];
	}

	return scores; 
}

double calcAverage(int *testScores, int numOfTests){

	int total = 0;  
	double average;

	for (int count = 0; count < numOfTests; count++){
		total += testScores[count];
	}
	
	average = total/numOfTests;
	return average;

}

char calcGrade(double average){

	char letterGrade; 

	if		(average > 90 && average <= 100)
		letterGrade = 'A';
	else if (average > 80 && average <= 90)
		letterGrade = 'B';
	else if (average > 70 && average <= 80)
		letterGrade = 'C'; 
	else if (average > 60 && average <= 70)
		letterGrade = 'D';
	else if (average >= 0 && average <= 60)
		letterGrade = 'F'; 
	else{  
		cout << "Logic error." << endl;
		// system("pause");
		exit(EXIT_FAILURE); 
	}

	return letterGrade;
}

void display(GradeBook *studentList, int size){

	for (int count = 0; count < size; count++)
		cout << studentList[count].name << " " << studentList[count].idnum << " " 
		<< studentList[count].average << " " << studentList[count].grade << endl; 

	return; 
}
Last edited on
Thank you, that worked. The issue I have now is what long double main pointed out with the memory leak. How would I go about fixing that? I need to keep...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int *inputScores(int numOfTests){

	int *scores; 
	scores = new int[numOfTests]; 

	cout << "Enter the test scores for the student. Press ENTER after each score." << endl;

	for (int count = 0; count < numOfTests; count++){
		cout << "Score " << (count + 1) << ": "; 
		cin >> scores[count];
	}

	return scores; 
}


But I don't see a way to delete it outside of its function. The only solution I can think of is to declare *scores in main and pass it to the function, but it would seem there would be a more direct work around to this. Any solution?
Last edited on
inputScores() is returning the pointer to the calling code, so you're able to delete it in the calling code, or in any other code to which you pass that pointer.
Topic archived. No new replies allowed.