Use the pointer to a structure array

I just started learning pointer. I wanted to call the selection sort function to sort a structure array by the test scores, but the function call had an error: invalid conversion from 'int' to 'Student*'. I am not even sure the rest of my codes are correct because I just try and error to write the codes. Thanks a lot!
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
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
//Student structure holds the student's name and score
struct Student			
{
string name;
int testScore;
    Student()
    {
         name="unknown";
	 testScore=0;
     }
};
//Function prototypes:
void selectionSort(Student [], int); 
double calAverage(double, int);
int main()
{
    Student *student=NULL;      //To dynamically allocate an array
    int	numTests=0;		//To hold the number of tests
    double total=0.0;	        //Accumulator
	
	
    //Get the number of the tests
    cout << "How many test scores do you wish to process? ";
    cin >> numTests;
    cout << endl;
	
//Dynamically allocate an array large enough to hold that many test scores
    student= new Student[numTests];	//Allocate memory
	
//Get the scores for each test
    cout << "Enter the information below.\n";
    for(int count=0; count<numTests; count++)
    {
	cout << "Test " << count+1 << ": " << endl;
	cout << "Name: " ;
	getline(cin, (student+count)->name);	
	cout << endl;
	cout << "Score: ";
	cin >> (student+count)->testScore;		
	while(((student+count)->testScore) < 0)	//Input validation
	{
	    cout << "Invalid input. Please enter a positive number: ";
	    cin >> (student+count)->testScore;	
	} 
    }
	cout << endl;
//Sort the array
    selectionSort(student->testScore, numTests);
	
//Calculate the total scores
    for (int count=0; count<numTests; count++)
    {
	total+=(student+count)->testScore;	
    }
//Display the sorted list and average	
    cout << "The test scores in ascending order are: " << endl;
    for(int x=0; x<numTests; x++)
    {
	cout << (student+x)->testScore<< " ";	
    }
    cout << endl << endl;
    cout << setprecision(2) << fixed << showpoint;
    cout << "The average of these " << numTests << " tests is ";
    cout << calAverage(total, numTests);	//Calculate the average
//Free dynamically allocated memory
    delete [] student;
    student=NULL;
    return 0;
}
void selectionSort(Student array[], int size)
{
    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;
    }
}
double calAverage(double total, int size)
{
    return total/size;
}
Do you want the selectionSort function to be able to sort an array of Students based on different criteria and that is why you are trying to pass the testScore as argument to the functions? Well, in that case it becomes a bit more complicated and you might want to use templates or function pointers to be be able to pass in a comparison function, but since you have just started with pointers I'm guessing this is a bit too advanced right now.

If you just want the selectionSort function to always sort by testScore you need to change the code to use testScore as the value, instead of the Sutdent object (which is not even an int).

1
2
3
4
5
...
if(array[index].testScore < minValue)
{
	minValue = array[index].testScore;
	...

And when you call the function you just pass the student array pointer.

 
selectionSort(student, numTests);
Last edited on
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
#include <iostream>
#include <string>
// #include <vector>

struct student
{
    std::string name ;
    int score = 0 ;
};

// student_info: pointer to the first student in the array to be sorted
// num_students: number of students
void selection_sort( student student_info[], int num_students )
{
    if( num_students < 2 ) return ; // nothing to be done

    // get the index of the student with the lowest score
    int pos_lowest = 0 ;
    for( int i = 1 ; i < num_students ; ++i )
        if( student_info[i].score < student_info[pos_lowest].score ) pos_lowest = i ;

    // bring the student with the lowest score to the front of the sequence
    student temp = student_info[0] ;
    student_info[0] = student_info[pos_lowest] ;
    student_info[pos_lowest] = temp ;

    // leave the student at the front of the sequence (one with the lowest score)
    // as it is and sort the remaining num_students-1 students in the array
    // student_info: pointer to first student in the array
    // student_info+1: pointer to second student in the array
    selection_sort( student_info+1, num_students-1 ) ;
}

int get_test_score()
{
    int score ;
    std::cout << "score? " ;

    const int MAX_TEXT_SCORE = 100 ;
    // if the user entered a valid score, return it
    if( std::cin >> score && score > 0 && score <= MAX_TEXT_SCORE ) return score ;

    std::cout << "please enter a non-negative number not more than "
              << MAX_TEXT_SCORE << '\n' ;

    // recover from really bad (non-numeric) input: eg 'abcd'
    // you may ignore these two lines for now
    std::cin.clear() ;
    std::cin.ignore( 1000, '\n' ) ;

    return get_test_score() ;
}

int main()
{
    // avoid dynamic memory allocation
    // consider using std::vector https://cal-linux.com/tutorials/vectors.html
    const int MAX_NUM_STUDENTS = 1024 ;
    student student_info[MAX_NUM_STUDENTS] ;

    int num_students ;
    std::cout << "how many students? " ;
    std::cin >> num_students ;
    if( num_students > MAX_NUM_STUDENTS ) num_students = MAX_NUM_STUDENTS ;

    for( int i = 0 ; i< num_students ; ++i )
    {
        std::cout << "name? " ;
        std::cin >> student_info[i].name ; // we assume that the name does not contain spaces

        student_info[i].score = get_test_score() ;
    }

    // implicit conversion from array to pointer to the first element of an array.
    // https://en.cppreference.com/w/cpp/language/array#Array-to-pointer_decay
    selection_sort( student_info, num_students ) ;

    // print the sorted list
    for( int i = 0 ; i < num_students ; ++i )
        std::cout << student_info[i].name << "  -  " << student_info[i].score << '\n' ;
}
To Perter87:
Thank you for your help. I amended my codes as you suggested. Now it runs, but I can't enter the students' name. The running case is shown below:
------------------------------------------------------------------------
How many students do you wish to process? 5

Enter the information below
Student 1
Name:
Score: 86
Student 2
Name:
Score: -9
Invalid input. Please enter a positive number: 98
Student 3
Name:
Score: 73
Student 4
Name:
Score: 62
Student 5
Name:
Score: 86

The test scores in ascending order are:
Name: Test score: 62
Name: Test score: 73
Name: Test score: 86
Name: Test score: 86
Name: Test score: 98

The average of these 5 students' test scores is 81.00
--------------------------------------------------------------------------
I also amended my codes to ask for the number of students instead of the tests. I hope to the names and the test scores can be matched. Is there anyhting wrong with the getline? Why can't I enter the names? Thank you!

To JLBorges:
Thank you for your time and codes. I have to practice the pointers, that's why I have to dynamically allocate the array. Your codes work perfectly. Thank you!
Now it runs, but I can't enter the students' name.

The problem is that >> doesn't consume the newline character that comes after the value. If getline comes after, it will find the newline character right away, giving you an empty string, without waiting for more input.

Either use something like
 
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
after you have used the >> operator in order to discard the rest of the line so that if getline follows it will start reading on the next line instead of what's left of the old one.

Or always use std::ws before using getline in order to discard all whitespaces (including newlines) before reading the line.
 
std::getline(std::cin >> std::ws, line);
This is probably easier but doesn't work if you care about whitespace characters at the beginning of the line (which I don't think you do in this case).
Last edited on
To Peter87
Thank you! I just added "cin.ignore()", and it worked. The only problem was that I couldn't control the formatting of the output, but my instructor was okay with it. I also amended my selection sort function to sort the whole structure by the test scores. Here is the new code:
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
struct Student
{
string name;
int testScore;
Student()
{
name="unknown";
testScore=0;
}
};
void selectionSort(Student [], int);
double calAverage(double, int);
int main()
{
Student *student=NULL;
int numStud=0;
double total=0.0;

cout << "How many students do you wish to process? ";
cin >> numStud;
cout << endl;

student= new Student[numStud];

cout << "Enter the information below\n";
for(int count=0; count<numStud; count++)
{
cout << endl;
cout << "Student " << count+1 << endl;
cout << "Name: " ;
cin.ignore();
getline(cin, (student+count)->name);
cout << endl;
cout << "Score: ";
cin >> (student+count)->testScore;
while(((student+count)->testScore) < 0)
{
cout << "Invalid input. Please enter a positive number: ";
cin >> (student+count)->testScore;
}
}
cout << endl;

selectionSort(student, numStud);

for (int count=0; count<numStud; count++)
{
total+=(student+count)->testScore;
}

cout << "The test scores in ascending order are: " << endl;
for(int x=0; x<numStud; x++)
{
cout << "Name: " << left << setw(20) <<(student+x)->name << "Test score: " << (student+x)->testScore<< endl;
}
cout << endl;
cout << setprecision(2) << fixed << showpoint;
cout << "The average of these " << numStud << " students' test scores is ";
cout << calAverage(total, numStud);

delete [] student;
student=NULL;
return 0;
}
void selectionSort(Student array[], int size)
{
int startScan, minIndex;
Student minValue;
for(startScan=0; startScan<(size-1); startScan++)
{
minIndex=startScan;
minValue=array[startScan];
for(int index=startScan+1; index<size; index++)
{
if(array[index].testScore<minValue.testScore)
{
minValue=array[index];
minIndex=index;
}
}
array[minIndex]=array[startScan];
array[startScan]=minValue;
}
}
double calAverage(double total, int size)
{
return total/size;
}
Topic archived. No new replies allowed.