Tuesday, March 14, 2017

Programming Challenge 9.4 - Test Scores #2

/* Test Scores #2 - This program dynamically allocates an array large
   enough to hold a user-defined number of test scores. Once all scores
   are entered, the array is passed to a function that sorts them in
   ascending order.

   Another function is called that calculates the average score. The
   p rogram displays the sorted list of scores and averages with
   appropriate headings. Pointer notation is used rather than array
   notation whenever possible.

   Input Validation: No negative numbers for test scores is accepted.
  
   This is a modification of Programming Challenge 2. It allows the user
   to enter name-score pairs. For each student taking a test, the user
   types the student's name followed by the student's integer test scores.
  
   The sorting function is modified so it takes an array holding the
   student names and an array holding the student test scores. When the
   sorted list of scores is displayed, each student's name is displayed
   along with his or her score. In stepping through the arrays, pointers
   are used rather than array subscripts. */

#include "Utility.h"

/* Function prototypes */
void mainMenu();
void displayIntro();
void displayMenuItems();
void getTestScores(int *, string *, const int);
void sortScores(int *, string *, const int);
double calcAverage(int *, const int);
void displayResults(const int *, const string *,
                    const double, const int);

int main()
{
   mainMenu();

   pauseSystem();
   return 0;
}

/* **********************************************************
   Definition: mainMenu

   Allows the user to select from the following items:

      * View Introduction
      * Enter Test-Scores
      * View Score-Data
      * Quit

   It takes care of calling the necessary functions, passing
   and receiving results, and freeing up the memory when the
   user decides to quit the program.
   ********************************************************** */

void mainMenu()
{
   /* Dynamically allocated arrays */
   int *testScores = nullptr;
   string *studentNames = nullptr;

   const int DISPLAY_INTRODUCTION = 1,
             GET_TEST_SCORES = 2,
             VIEW_RESULTS = 3,
             QUIT = 4;

   int menuItem = 0,
       numScores = 0;

   double averageScore = 0.0;

   do
   {
      displayMenuItems();
      cin >> menuItem;

      /* Validate input */
      while (menuItem < DISPLAY_INTRODUCTION || menuItem > QUIT)
      {
         cout << "\n\tInvalid menu item selected!\n"
              << "\tYour choice: ";
         cin >> menuItem;
      }

      switch (menuItem)
      {
         case DISPLAY_INTRODUCTION:
         {
            displayIntro();
         }
         break;

         case GET_TEST_SCORES:
         {
            /* Get the number of scores (at least three) */
            cout << "\n\tHow many test-scores do you wish to enter? ";
            cin >> numScores;

            cout << "\n";

            /* Dynamically allocates two arrays to hold the number of
               test scores and the student names */
            testScores = new int[numScores];
            studentNames = new string[numScores];

            /* Gets the number of scores entered by the user */
            getTestScores(testScores, studentNames, numScores);

            /* Sorts the scores and student names with an ascending-order
               selection sort algorithm */
            sortScores(testScores, studentNames, numScores);

            /* Calculates the average score and returns the result */
            averageScore = calcAverage(testScores, numScores);
         }
         break;

         case VIEW_RESULTS:
         {
            /* Displays the data after sorting the scores and
               calculating the average */
            displayResults(testScores, studentNames, averageScore, numScores);
         }
         break;

         case QUIT:
         {
            cout << "\n\tDoing a little housekeeping ... ";

            /* Free up memory */
            delete[] testScores;
            delete[] studentNames;
            testScores = nullptr;
            studentNames = nullptr;

            cout << "\n\ttestScores cleared: " << testScores
                 << "\n\tstudentNames cleared: " << studentNames
                 << "\n\tPress enter to close this window!\n";
         }
         break;
      }
   } while (menuItem != QUIT); 
}

/* **********************************************************
   Definition: displayMenuItems

   This function displays the menu items the user can select
   between.
   ********************************************************** */

void displayMenuItems()
{
   cout << "\n\n\t\tAVERAGE TEST SCORE CALCULATOR\n\n"
        << "\t1. View Introduction\n"
        << "\t2. Enter Test-Scores\n"
        << "\t3. View Score-Data\n"
        << "\t4. Quit\n\n"
        << "\tYour choice: ";
}

/* **********************************************************
   Definition: displayIntroduction

   This function introduces the program and how it works to
   the user.
   ********************************************************** */

void displayIntro()
{
   cout << "\n\n\t\tAVERAGE TEST SCORE CALCULATOR\n\n"
        << "\tThis program allows you to enter a number of scores to\n"
        << "\tbe averaged, along with the student names who have taken\n"
        << "\ta test in your class.\n\n"
        << "\tAfter you have entered all of your student's names and\n"
        << "\tscores, the scores and student names are sorted in ascending\n"
        << "\torder, based on their scores. The class average will then be\n"
        << "\tcalculated.\n\n"
        << "\tOnce finished, you can view the results by choosing item '3'\n"
        << "\tfrom the main menu.\n\n";
}

/* **********************************************************
   Definition: getTestScores

   This function accepts testScores and numScores, containing
   the number of elements to be stored in the array, as its
   arguments. It gets the scores and student names to be
   stored in testScore and studentNames.
   ********************************************************** */

void getTestScores(int *testScores, string *studentNames, const int numScores)
{
      for (int index = 0; index < numScores; index++)
      {
         cout << "\n\tStudent Name: ";
         cin >> *(studentNames + index);

         cout << "\tScore #" << (index + 1) << ": ";
         cin >> *(testScores + index);

         /* Validate Input */
         while ((*(testScores + index) <= 0) ||
                (*(testScores + index) > 100.0))
         {
            cout << "\n\t\tYou entered an invalid score!\n\n";
            cout << "\tScore #" << (index + 1) << ": ";
            cin >> *(testScores + index);
         }
      }
      cout << "\n";
}

/* **********************************************************
   Definition: sortScores

   This function accepts testScores, studentNames, and
   numScores, containing the number of elements stored
   in the array, as arguments. An ascending-order selection
   sort is performed on the elements stored in both arrays.
   ********************************************************** */

void sortScores(int *testScores, string *studentNames, const int numScores)
{
   int startScan = 0,
       minIndex = 0,
       minElem = 0,
       index = 0;

   string tempNames = " ";
 
   for (startScan = 0; startScan < (numScores - 1); startScan++)
   {
      minIndex = startScan;
      minElem = *(testScores + startScan);
      tempNames = *(studentNames + startScan);

      for (index = startScan + 1; index < numScores; index++)
      {
         if (*(testScores + index) < minElem)
         {
            minElem = *(testScores + index);
            tempNames = *(studentNames + index);
            minIndex = index;
         }
      }

      *(testScores + minIndex) = *(testScores + startScan);
      *(studentNames + minIndex) = *(studentNames + startScan);
      *(testScores + startScan) = minElem;
      *(studentNames + startScan) = tempNames;
   }
}

/* **********************************************************
   Definition: calcAverage

   This function accepts testScores and numScores as its
   argument. It steps through the array to total the scores,
   then calculates and returns the average.
   ********************************************************** */

double calcAverage(int *testScores, const int numScores)
{
   double total = 0.0,
          average = 0.0;

   for (int count = 0; count < numScores; count++)
   {
      total += *(testScores + count);
   }

   /* Calculates and returns the average */
   return average = total / numScores;
}

/* **********************************************************
   Definition: displayResults

   This function accepts testScores, studentNames,
   averageScore and numScores as its argument. It displays
   the student name along with his or her score in sorted
   order, and the class average reached on the test.
   ********************************************************** */

void displayResults(const int *testScores, const string *studentNames,
                    const double averageScore, const int numScores)
{
   int index = 0;

   cout << fixed << showpoint << setprecision(2);

   cout << "\n\n\tTHE SCORES IN SORTED ORDER\n";

   cout << "\n\tSTUDENT NAME: " << "\t\t" << "SCORE\n"
        << "\t-------------" << "\t\t" << "-----\n";

   for (index = 0; index < numScores; index++)
   {
      cout << "\t" << setw(9) << left << *(studentNames + index)
         << setw(20) << right << *(testScores + index)
          << " \n" ;
   }
   cout << "\t-------------\n"
        << "\tCLASS AVERAGE:\t" << setw(13) << right
        << averageScore << "\n";
}

Example Output:





No comments:

Post a Comment