Sorting Arrays with String and Integer

I'm trying to add last names into my array that sorts the exam scores (I built it first without the names and it worked) but, I'm receiving errors, and a little lost because I realized I had to add a structure. I'm getting "uninitialized local variable" and have no idea where I'm going wrong.

Thanks to all that read 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
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
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;


void showArray (double array[], int size, string name)
{
	for (int count = 0; count < size; count++)
		cout << array[count] << " ";
		cout << endl;
}

void selectionSort (double array[], int size, string name)
{
	int startScan, minIndex, minValue;
	for (startScan = 0; startScan < (size-1); startScan++)
	{
		minIndex = startScan;
		minValue = array[startScan];
		for (int index = startScan+1; index < size; index++)
		{
			if (array[index] < minValue)
			{
				minValue = array[index];
				minIndex = index;
			}
		}
		array[minIndex] = array[startScan];
		array[startScan] = minValue;
	}
	showArray(array, size, name);
}
struct Student
{
	string name;
	double testScores;
};

int main()
{
	Student * studentarray;
	Student** arrPtr;
	string *name = 0;
	double *testScores,
		    total = 0,
		    average;
	int numberOfScores;
	cout << "How many test scores will you enter?\n";
	cin >> numberOfScores;
	studentarray = new Student [numberOfScores];
	for (int count=0; count < numberOfScores; count++)
	{
		arrPtr[count]=&studentarray[count];
	}

	cout << "Enter the test scores below.\n";
	for (int count = 0; count < numberOfScores; count++)
	{
		cout << "Score " << (count + 1 ) << ":  ";
		cin >> (*(studentarray + count)).testScores; 
		while ((*(studentarray + count)).testScores <= 0.00)
		{
			cout << "The score cannot be negative.\n";
			cin >> (*(studentarray + count)).testScores;
		}
		cout << "Last Name " << (count + 1 ) << ":  ";
		cin >> (*(studentarray + count)).name;
	}
	for (int count = 0; count < numberOfScores; count++)
	{
		total += (*(studentarray + count)).testScores; 
		
	}

	average = total/numberOfScores;
	cout << "The scores in order from lowest to highest is:\n";
	selectionSort(testScores, numberOfScores, *name);
	cout << setprecision(2) << fixed <<showpoint;
	cout << "The average of all the scores is:\n" << average << endl;
	delete [] arrPtr;
	arrPtr = 0;
	cout << endl;
	return 0;
}
It looks like this is half-way between two versions of the code. In main() there are four separate pointers:
1
2
3
4
	Student * studentarray;
	Student** arrPtr;
	string *name = 0;
	double *testScores,

I think, because your Student class contains both name and testScores, you just need a single pointer
 
Student * studentarray;
and possibly for purposes of sorting, the array of pointers,
 
Student** arrPtr;

The other two pointers aren't needed and should be removed.

In the current version of the code, arrPtr is not initialised, so it will cause an error when used at line 54. You should have something like this:
1
2
    studentarray = new Student [numberOfScores];
    arrPtr       = new Student* [numberOfScores];
Remember to delete [] each of these at the end.

This code will work, but it looks clumsy and hard to read:
 
    cin >> (*(studentarray + count)).testScores;
Instead, use this:
 
    cin >> studentarray[count].testScores;
That change should be made througout the code, where necessary.

Since I assume you will be using the array of pointers, some of the other code will change too. Example - though you may need to adjust the formatting of the output:
1
2
3
4
5
6
void showArray (Student *array[], int size)
{
    for (int count = 0; count < size; count++)
        cout << setw(20) << left  << array[count]->name
             << setw(5)  << right << array[count]->testScores << endl;
}

The selectionSort() function has roughly the right structure, but will need to be modified so that instead of swapping the testScores, it instead swaps the pointers. There should also be a temporary variable which is necessary when exchanging two variables.
example:
1
2
3
4
// swap x and y;
    int temp = x;
    x = y;
    y = temp;

You will be doing the same thing but with pointers - if that is the approach you are planning to take with this project..
Last edited on
Thanks you SO MUCH, I'm getting closer, but I still get a few errors that I can't test my sort 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
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

#include <iostream>
#include <iomanip>
#include <string>
using namespace std;


void showArray (double array[], int size, string name)
{
	for (int count = 0; count < size; count++)
		 cout << setw(20) << left  << arrPtr[count].name;
         cout << setw(5)  << right << studentarray[count].testScores << endl;
}

void selectionSort (double array[], int size, string name)
{
	int startScan, minIndex, minValue;
	for (startScan = 0; startScan < (size-1); startScan++)
	{
		minIndex = startScan;
		minValue = array[startScan];
		for (int index = startScan+1; index < size; index++)
		{
			if (array[index] < minValue)
			{
				minValue = array[index];
				minIndex = index;
			}
		}
		array[minIndex] = array[startScan];
		array[startScan] = minValue;
	}
	showArray(array, size, name);
}
struct Student
{
	string name;
	double testScores;
};

int main()
{
	Student * studentarray;
	Student** arrPtr;
	double  total = 0,
		    average;
	int numberOfScores;
	cout << "How many test scores will you enter?\n";
	cin >> numberOfScores;
	studentarray = new Student [numberOfScores];
	arrPtr = new Student* [numberOfScores];
	for (int count=0; count < numberOfScores; count++)
	{
		arrPtr[count]=&studentarray[count];
	}
	cout << "Enter the test scores below.\n";
	for (int count = 0; count < numberOfScores; count++)
	{
		cout << "Score " << (count + 1 ) << ":  ";
		cin >> studentarray[count].testScores; 
		while (studentarray[count].testScores <= 0.00)
		{
			cout << "The score cannot be negative.\n";
			cin >> studentarray[count].testScores;
		}
		cout << "Last Name " << (count + 1 ) << ":  ";
		cin >> studentarray[count].name;
	}
	for (int count = 0; count < numberOfScores; count++)
	{
		total += studentarray[count].testScores; 
	}
	average = total/numberOfScores;
	cout << "The scores in order from lowest to highest is:\n";
	selectionSort(studentarray, numberOfScores, string name);
	cout << setprecision(2) << fixed <<showpoint;
	cout << "The average of all the scores is:\n" << average << endl;
	delete [] arrPtr;
	arrPtr = 0;
	delete [] studentarray;
	studentarray = 0;
	cout << endl;
	return 0;
}
Well, this seems a bit closer, but it's still a bit muddled in places. Before looking at the sort function (sorting as a topic can cause problems as the logic can be tricky), let's look at something a bit simpler. That is, the showArray() function. I think when you get this one working, the sort will also be easier.

The code posted above does not compile, it has many inconsistencies.

Let's look at the function showArray(). Its purpose is to print the contents of the array of Student objects.
Well then, let's start with the function header.
void showArray (double array[], int size, string name)
Well, the first parameter should be an array of Students. But instead it is declared as an array of doubles. The second parameter, size is good and makes sense. But what about the third parameter, string name. That should not be there at all. The name of each student is already to be found contained within the Student object.
So, change the function header like this:
 
void showArray (Student array[], int size)

In order to get this to compile, the structure Student must be declared before it, so move that struct so it is above the function, like this:
1
2
3
4
5
6
7
8
struct Student
{
    string name;
    double testScores;
};

void showArray (Student array[], int size)
{


Now when it comes to displaying the array contents, you just need to access the member variables, like this: array[count].name and array[count].testScores

Armed with this understanding, you should now be able to get the showArray() function working. When that is done, you can apply exactly the same ideas to the selectionSort() function.
Last edited on
THANK YOU CHERVIL. You have been the most helpful person! I think I'm at a point of frustration that I'm missing the obvious.

I rewrote the sort function. It's still giving me errors.

If anyone wants to help one more time I would truly appreciate it. Tutorials can only help so much.

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
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;

struct Student
{
	string name;
	double testScores;
};


void showArray (Student array[], int size)
{
	for (int count = 0; count < size; count++)
		 cout << setw(10) << left  << array[count].name << array[count].testScores << endl;
}

void swap (int *num1, int *num2)
{
	int temp = *num1;
	*num1 = *num2;
	*num2 = temp;
}
void selectionSort (Student array[], int size)

{
	for (int i = 0; i < size-1; ++i)
		for (int j = 0; i+1; j < size; ++j)
			if (i < j)
			{
				swap(&array[i], &array[j]);          //error here!!
			}
	showArray(array, size);
}

int main()
{
	Student * studentarray;
	Student** arrPtr;
	double  total = 0,
		    average;
	int numberOfScores;
	cout << "How many test scores will you enter?\n";
	cin >> numberOfScores;
	studentarray = new Student [numberOfScores];
	arrPtr = new Student* [numberOfScores];
	for (int count=0; count < numberOfScores; count++)
	{
		arrPtr[count]=&studentarray[count];
	}
	cout << "Enter the test scores below.\n";
	for (int count = 0; count < numberOfScores; count++)
	{
		cout << "Score " << (count + 1 ) << ":  ";
		cin >> studentarray[count].testScores; 
		while (studentarray[count].testScores <= 0.00)
		{
			cout << "The score cannot be negative.\n";
			cin >> studentarray[count].testScores;
		}
		cout << "Last Name " << (count + 1 ) << ":  ";
		cin >> studentarray[count].name;
	}
	for (int count = 0; count < numberOfScores; count++)
	{
		total += studentarray[count].testScores; 
	}
	average = total/numberOfScores;
	cout << "The scores in order from lowest to highest is:\n";
	selectionSort(studentarray, numberOfScores);
	cout << setprecision(2) << fixed <<showpoint;
	cout << "The average of all the scores is:\n" << average << endl;
	delete [] arrPtr;
	arrPtr = 0;
	delete [] studentarray;
	studentarray = 0;
	cout << endl;
	return 0;
}
Last edited on
1.) In your showArray() function, your for() loop isn't using any braces. As a result, only the single line following the for loop will be looped. Because of that, the counter 'count' falls out of scope once the loop ends, and the second line which should print each students test scores cannot compile.
Fix this by putting the things that need to be looped in between braces {}.

2.) In selectionSort(), what's the point of the random i+1?

3.) In selectionSort(), you need to compare the students testScores variable. Right now you're trying to compare the raw student objects, which you cannot do because you
don't have an overloaded operator for your Student struct.

4.) In selectionSort(), If you're trying to swap students, then your swap() function won't do, because it accepts int* arguments.
Last edited on
#1 Good catch

#2 typo that has been fixed
for (int j = i+1; j < size; ++j)

#3 Any suggestions because I don't understand how to change from raw objects to the variable.

#4 I changed to doubles.

THANKS!


Now, this is the only line that is giving me troubles.

swap(&array[i], &array[j]);

Please help.

THANKS!!
Last edited on
Changing to doubles doesn't solve anything. If you want to swap students, then you need to be able to pass students to the swap function.

Any suggestions because I don't understand how to change from raw objects to the variable.


Well, I meant, you should be accessing the students testScore members.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void swap(Student* student1, Student* student2) {
	Student temp = *student1;
	*student1 = *student2;
	*student2 = temp;
}

void selectionSort(Student students[], unsigned short size) {
	for(unsigned short i=0; i<size-1; ++i) {
		for(unsigned short j=0; j<size; ++j) {
			if(students[i].testScores > students[j].testScores) {
				swap(&students[i], &students[j]);
			}
		}
	}
	showArray(students, size);
}
Hmm, it looks as though the selection sort algorithm has magically transmuted itself into a bubble sort algorithm. If that's the method you intend, its ok, though the name of the sort routine should be modified accordingly.

Take a look at the selection sort algorithm here, taken directly from (the sometimes unreliable) Wikipedia:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    for (int i = 0; i < n-1; i++) 
    {
        int minIndex = i;

        for (int j = i+1; j < n; j++) 
        {
            if (a[j] < a[minIndex]) {
                minIndex = j;
            }
        }
     
        if ( minIndex != i ) {
            swap(a[i], a[minIndex]);
        }
    }

Just remember that instead of directly comparing the array elements on line 7,
a[index], you need to compare the testScores, students[index].testScores

In the swap function, I'd recommend passing by reference rather than as a pointer. Either way will work, but the code is cleaner and easier to read with references.
1
2
3
4
5
6
void swap(Student & student1, Student & student2) 
{
    Student temp = student1;
    student1     = student2;
    student2     = temp;
}


One more comment, as a matter of style, I would remove the call to showArray() from inside the sort function, and instead call it as required directly from main(). Doing it that way makes the sort function more readily re-useable in another project.

THANK YOU XISMN!!! I finally see what everyone was trying to say.

I did change one line to this to get it to work.

for(unsigned short j=i+1; j<size; ++j

Again, CHERVIL thank you so much for your time!! I changed to bubble sort because I wasn't understanding passing using a pointer. So I thought I would simplify with bubble???

I appreciate you both so much!!!

:)

Topic archived. No new replies allowed.