Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

Understand the Application Sort Flexibility (Student class) In week 8 , we saw a

ID: 3676803 • Letter: U

Question

Understand the Application

Sort Flexibility (Student class)

In week 8, we saw an example of a Student class that provided a compareTwoStudents() method. We needed to define such a method because our sort algorithm (which was in the StudentArrayUtilities (SAU) class) had to have a basis for comparing two Student objects, the foundation of SAUs sorting algorithm. Since a Student is a compound data type, not a double or a string, there was no pre-defined less-than, <, operation available, so we created our own compareTwoStudents(), which was based on the spelling of the last name. You can review those notes to see its definition.

We want to make the sort more flexible in this assignment. Sometimes we want to sort on last name, as we did in the lectures, but other times we may choose to sort on the first name (useful for informal communication) or total points (useful for analyzing statistics). We could go into the compareTwoStudents() method and change its definition to work on first name or total points, but all that does is replace the inflexibility of last name with the inflexibility of some other criteria. So here's the plan: we will provide a static Student class method called setSortKey() which will establish a new sort criteria. A client will invoke it whenever it wants to switch to a new basis for comparison. The client will pass a parameter to setSortKey() telling it which one of the three Student fields it wants future sort algorithms to use.

No Output (SAU class)

Another change we'll make affects the output modality. Rather than displaying the array directly in the SAU class, we want to make the class "U.I. neutral." So we will replace SAU's printArray() method with a toString() method, and let the client choose how to use that. In our example main() we will be sending the string array to the console.

Median (SAU class)

We'll add one more method to our SAU class: double getMedianDestructive( Student[] someArray ). This method will return the median of the totalPoints values in an array. Look up median. It is defined as the "middle-value" and is easily computed, but you first have to sort the array in order to find it. Fortunately, you already have the sort method.

Client

Our client will declare three Student arrays to make sure our median works: one array that has an odd number of students (15), one that has an even number of students (16) and one that has a single student.

We'll test the sortKey and sort algorithm only on the even numbered array, and then we will test our median computation on all four arrays.

The Program Spec

These changes should not be complicated as long as you read carefully and follow directions. New and modified members/methods are all very short, so stay focused and apply what you learned back in week 8.

Additions to the Student Class

We will add the following members to the class in the modules.

Public static int consts:

SORT_BY_FIRST = 88

SORT_BY_LAST = 98

SORT_BY_POINTS = 108

These are the three sort keys that will be used by the client and the class, alike, to keep track of, or set, the sort key.   If the client wants to establish a new sort key, it will pass one of these tokens (say Student::SORT_BY_FIRST) to the setter described next.    I have intentionally made the literal values non-contiguous so you would not rely on their particular values in your logic.   You should be able to change the values without breaking your program (but you don't have to change them; use the three values above).

Private static int:

sortKey - this will always have one of the three constants above as its value. Make sure it initially has SORT_BY_LAST in it, but after the client changes it, it could be any of the above constants.

You should supply the following simple public static methods:

boolean setSortKey( int key ) -- a mutator for the member sortKey.

int getSortKey() -- an accessor for sortKey.

Modification to the Student Class

compareTwoStudents( ... ) -- same signatures as in the modules, but now this method has to look at the sortKey and compare the two Students based on the currently activce sortKey. A switch statement with three different expressions is all you need, and each expression will be very similar to the one already in the modules (in fact one will be identical). As you saw in the modules, it needs to return an int, which is positive, if the first student is greater than the second, negative if less than, and zero if they are the same, based on the current value of sortKey, of course.

Change to the StudentArrayUtilities Class

Replace printArray() with toString(). Generate the same kind of string, but instead of sending it to the screen, return it to the client.

Add a static method double getMedianDestructive(Student array[], int arraySize) - This computes and returns the median of the total scores of all the students in the array The details are simple, but you have to take them each carefully:

Dispose of the case of a one-element array. A one-element array returns its one and only Student's totalPoints. (This case can actually be skipped if you handle the next cases correctly, but it doesn't hurt to do it separately, here.)

Even-numbered arrays >= 2 elements: find the two middle elements and return their average of their total points.

Odd-numbered arrays >= 3 elements: return the total points of the exact middle element.

Special Note: This method has to do the following. It must sort the array according to totalScore in order to get the medians, and that's easy since we already have the sort method. Then it has to find the middle-student's score (e.g., if the array is size 21, the middle element is the score in array[10], after the sort). But, before doing the sort, it also has to change the sortKey of the Student class to SORT_BY_POINTS. One detail, that you may not have though of, is that, at the very start of the method, it needs to save the client's sort key. Then, before returning, restore the client's sort key. This method doesn't know what that sort key might be, but there is an accessor getSortKey() that will answer that question.

This method has the word "Destructive" in its name to remind the client that it may (and usually will) modify the order of the array, since it is going to sort the array by total points in the process of computing themedian. However, it will not destroy or modify the cleint's sortKey when the method returns to client (see previous bullet).

The main()

Our client will declare four Student arrays: using direct initialization, as in the modules: no user input. The array sizes should be 15, 16 and 1. The second array can be the same as the first with one extra Student tagged onto the end. Each array should be initialized in no particular order: unsorted in all fields.

Using the largest, even numbered, array:

display the array immediately before calling a sort method.

sort the array using the default (initial) sort key and display.

change the sort key to first name, sort and display.

change the sort key to total score, sort and display.

setSortKey() to first name, call the getMedian() method and display the median score. Then call and, getSortKey() to make sure that the getMedian() method preserved the client's sortKey value of first name that was just set prior to the getMedian() call.

Using each of the two other arrays:

get the median of each array and display. No other testing needed in this part.

Here's a sample output, but you must not use my arrays. Make your own as per the spec above.

Explanation / Answer

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

class Student
{
private:
string lastName;
string firstName;
int totalPoints;
public:
static const string DEFAULT_NAME;
static const int DEFAULT_POINTS = 0;
static const int MAX_POINTS = 1000;
public:
Student( string lst = DEFAULT_NAME, string fst = DEFAULT_NAME, long pts = DEFAULT_POINTS);
{
return lastName;
}
string getFirstName()
{
return firstName;
}
int getTotalPoints()
{
return totalPoints;
}
bool setLastName(string last);
bool setFirstName(string first);
bool setPoints(int pts);
static int compareTwoStudents( Student firstStud, Student secondStud );
string toString();
private:
static bool validString( string testStr );
static bool validPoints( int testPoints );
};


class StudentArrayUtilities
{
public:
static void printArray(string title, Student data[], int arraySize);
static void arraySort(Student array[], int arraySize);
private:
static bool floatLargestToTop(Student data[], int top);
static void mySwap(Student &a, Student &b);
};

const string Student::DEFAULT_NAME = "Abhishek";
int main()
{
Student myClass[] = { Student("s","fr", 95), Student("b","ja",123), Student("j","ca", 195),
Student("r","abe",148), Student("j","t", 108), Student("p","friend",225), Student("l","fred", 44),
Student("s","pa",452), Student("c","ro", 295), Student("c","john",321) };
int arraySize = sizeof(myClass) / sizeof(myClass[0]);
StudentArrayUtilities::printArray("Before: ", myClass, arraySize);
StudentArrayUtilities::arraySort(myClass, arraySize);
StudentArrayUtilities::printArray("After: ", myClass, arraySize);
}


Student::Student( string last, string first, long points)
{
if ( !setLastName(last))
lastName = DEFAULT_NAME;
if ( !setFirstName(first))
firstName = DEFAULT_NAME;
if ( !setPoints(points))
totalPoints = DEFAULT_POINTS;
}
bool Student::setLastName(string last)
{
if ( !validString(last))
return false;
lastName = last;
return true;
}
bool Student::setFirstName(string first)
{
if ( !validString(first))
return false;
firstName = first;
return true;
}
bool Student::setPoints(int pts)
{
if ( !validPoints(pts))
return false;
totalPoints = pts;
return true;
}


int Student::compareTwoStudents(Student firstStud, Student secondStud)
{
int result;
result = firstStud.lastName.compare(secondStud.lastName);
return result;
}
string Student::toString()
{
string resultString;
ostringstream cnvrtFirst, cnvrtLast, cnvrtPoints;
cnvrtFirst << firstName;
cnvrtLast << lastName;
cnvrtPoints << totalPoints;
resultString = " "+ cnvrtLast.str() + ", " + cnvrtFirst.str() + " points: " + cnvrtPoints.str() + " ";
return resultString;
}

bool Student::validString(string testStr)
{
if (testStr.length() > 0 && isalpha(testStr[0]))
return true;
return false;
}
bool Student::validPoints(int testPoints)
{
if (testPoints >= 0 && testPoints <= MAX_POINTS)
return true;
return false;
}


void StudentArrayUtilities::printArray(string title, Student data[], int arraySize)
{
string output = ""; cout << title << endl;
for (int k = 0; k < arraySize; k++)
output += " "+ data[k].toString();
cout << output << endl;
}
void StudentArrayUtilities::arraySort(Student array[], int arraySize)
{
for (int k = 0; k < arraySize; k++)


if (!floatLargestToTop(array, arraySize-1-k))
return;
}


bool StudentArrayUtilities::floatLargestToTop(Student data[], int top)
{
bool changed = false;
for (int k =0; k < top; k++)
if (Student::compareTwoStudents(data[k], data[k+1]) > 0)
{
mySwap(data[k], data[k+1]);
changed = true;
}
return changed;
}
void StudentArrayUtilities::mySwap(Student &a, Student &b)
{
Student temp("", "", 0);
temp = a;
a = b;
b = temp;
}