Hi,
I'm a beginning C++ student and have an assignment to dynamically create an array of a struct to store students' first names, last names, and test grade scores, and then pass it via pointer to a function that will sort the grades and names in ascending order. I wrote a function that finds the lowest numeric grade score of the pointer array of struct, puts it in the first (0) index position, and then puts the numeric value that was in the first (0) index position in the index position that was formerly occupied by the newly found lowest value. Then, it starts at the next highest index position and finds the next lowest value, etc, and swaps it. The issue that I'm having is that I can get the numeric scores sorted properly and moved in the function, but I can't get the first and last names in the array to change position, except somewhat unpredictably. Sometimes, one of the names will overwrite another name and be listed twice in the final output. I have them declared as a string data type and ideally would like them to do the same thing that I have the numeric values doing, but can't seem to achieve it. I've tried using char and strcpy but that's not working, either. I'm sure there's an easier way to do what I'm doing but the assignment is worded very specifically. I'm not sure if it's a simple logic error in the nested loop or perhaps I need to use a different syntax or method to change the index positions of the strings, since I'm using pointers? Maybe a constructor for struct?
This is my first post on any C++ forum, so please excuse any transgressions I may have made in code etiquette, posting, etc! I read all the faqs first and tried to follow them as much as possible, so my apologies if I shouldn't have posted the whole code- I just wanted to give a clear idea of the problem! I'd really appreciate any help...
Thanks in advance!
Evan
/* Test Scores #2 programming challenge */
#include <iostream>
#include <iomanip>
#include <string>
#include <cstring>
using namespace std;
struct TestData //create TestData structure to hold students' first name, last name, and grade score
{
string studentFirstName;
string studentLastName;
float studentGrade;
};
typedef struct TestData StructDataType; //create a data type StructDataType to be able pass the entire
//structure back and forth by pointers
StructDataType *getScores(int ); //function prototype to dynamically create a pointer array of struct with data
//type of StructDataType to be able to input mixed string/int values into the array,
//then pass it back into int main by using pointers
void structSort(StructDataType *, int); //function prototype to sort the pointer array of struct by integer grade score,
//then pass it back by pointer into int main
float findAverage(StructDataType *, int); //function prototype to find the average integer grade test score, passes again
//by use of pointers to and from findAverage function
void printScores(StructDataType *, int); //outputs resorted pointer array of struct
int main()
{
int numScores;
cout << "How many test scores would you like to enter? ";
cin >> numScores;
StructDataType *test1Scores = getScores(numScores); /*sets pointer array of data type StructDataType equal to results
of calling function getScores, which dynamically creates an
array and asks user to enter in required data */
structSort(test1Scores, numScores); //calls function to perform selection sort by integer test score
float averageScore = findAverage(test1Scores, numScores); /*sets float integer averageScore equal to results of function call
findAverage, which passes test1Scores array to function that finds
average of all test scores*/
printScores(test1Scores, numScores); //function call to output resorted list to screen
cout << "\nAverage test score in your array is: " << setprecision(3) << averageScore << endl << endl;
cout << endl;
system("pause");
return 0;
}
StructDataType *getScores(int numScores)
{
const int numChars = 20;
StructDataType *test1Scores;
while (numScores < 2)
{
cout << "Test score array can't be less than 2!\n" << "\nPlease enter a number " <<
"2 or greater for test score array: "; //validate entries to be greater than 1 for array size
cin >> numScores;
}
test1Scores = new StructDataType[numScores];
for (int index = 0; index < numScores; index++) //for loop for user to enter input up to however many records are to be created
{
cout << "\nEnter student # " << index + 1 << " first name: ";
cin >> test1Scores[index].studentFirstName; //enter first name for record in test1Scores array of struct
cout << "Enter student # " << index + 1 << " last name: ";
cin >> test1Scores[index].studentLastName; //enter last name for record in test1Scores array of struct
cout << "Enter student # " << index + 1 << " test score: ";
cin >> test1Scores[index].studentGrade; //enter grade score record in test1Scores array of struct
while (test1Scores[index].studentGrade < 0 || test1Scores[index].studentGrade > 100) /*validate numeric test grade score entries
to be greater than 0 and less than 101 */
{
cout << "Test score value can't be less than 0 or over 100!\n" << "\nPlease enter a value " <<
"greater than -1 and less than 100 for test score " << index + 1 << ": ";
cin >> test1Scores[index].studentGrade;
}
}
return test1Scores;
}
void structSort(StructDataType *test1Scores, int numScores) /*function to perform selection sort based value of studentGrade, which is
the float data variable to hold numeric test score */
{
string tempFirstName, tempLastName;
int startScan, minIndex;
float minValue;
for (startScan = 0; startScan < numScores - 1; startScan++) //nested loops to find lowest value of studentGrade
{
minIndex = startScan;
minValue = (test1Scores + startScan)->studentGrade;
for (int index = startScan + 1; index < numScores; index++)
{
if ((test1Scores + index)->studentGrade < minValue)
{
minValue = (test1Scores + index)->studentGrade;
minIndex = index;
}
}
/*this is the issue! these statements are supposed to swap the numeric value of the lowest value of studentGrade found in the
pointer struct array with the first position of the array's index, and also swap the first and last names of the new lowest
score with the first and last names that were in index position 0. i.e., if the lowest test grade score was at index position
4, put it at position 0 along with the first and last names that were at that position, and put the old value of position 0 at
position 4, along with the first and last names that were at position 0. This is working with the numeric values perfectly
but for some reason it's not working with with the string values for the students' first and last names. I tried switching to
char data type within the intial struct declaration and using strcpy and passing the array by reference (see below comments) but
that's not working, either! */
(test1Scores + minIndex)->studentFirstName = (test1Scores + startScan)->studentFirstName;
(test1Scores + minIndex)->studentLastName = (test1Scores + startScan)->studentLastName;
(test1Scores + minIndex)->studentGrade = (test1Scores + startScan)->studentGrade;
(test1Scores + startScan)->studentGrade = minValue;
//strcpy(&test1Scores[startScan].studentFirstName, &test1Scores[minValue].studentFirstName);
//strcpy(&test1Scores[startScan].studentLastName, &test1Scores[minValue].studentLastName);
}
}
float findAverage(StructDataType *test1Scores, int numScores)
{
float total = 0, average;
for (int index = 0; index < numScores; index ++)
{
total += (test1Scores+index)->studentGrade;
}
average = total / numScores;
return average;
}
void printScores(StructDataType *test1Scores, int numScores)
{
for (int index = 0; index < numScores; index++)
{
cout << "\n" << (test1Scores+index)->studentLastName << ", "
<< (test1Scores+index)->studentFirstName << ": " << (test1Scores+index)->studentGrade;
}
cout << endl;
}