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.
#include <iostream>
#include <string> // For utilizing strings
usingnamespace 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 = newint[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;
}
It works for me if I change for (intvariable_name = 0; variable_name<=limit; variable_name++)
to for (intvariable_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.
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.
#include <iostream>
#include <string> // For utilizing strings
usingnamespace 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 = newint[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';
elseif (average > 80 && average <= 90)
letterGrade = 'B';
elseif (average > 70 && average <= 80)
letterGrade = 'C';
elseif (average > 60 && average <= 70)
letterGrade = 'D';
elseif (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;
}
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 = newint[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?
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.