Solution to Programming Assignment 4

Solution to Programming Assignment 4


////
//
// This program computes statistics for student scores stored in a grades file.
// The file contains header information describing the graded items for a
// class.  The information for each graded item consists of its label, (e.g.,
// "midtm", "final") and the percentage of the total score for that item.
// Following the header information are individual student records containing
// student name, short four-digit id, and raw scores for each graded item.
//
// The program begins execution by prompting for the name of the grades file
// from the terminal.  If the file opens successfully, the program computes the
// statistical information and outputs it to the terminal.  The output is in
// the form of a table with the following labeled columns: student name,
// student id, scores for each graded item, and weighted total score.  The
// weighted total is the sum of each score multiplied by its percentage.  Each
// row in the table contains the information for one student.
//
// At the end of the output table are two rows of computed statistics for each
// scores column, as well as for the total column.  The first statistics row
// has the means of the scores, the second row has the standard deviations.
//
// Further details of program operation, including precise input and output
// formats, are available in the program specification at
//
//   http://www.csc.calpoly.edu/~gfisher/classes/101/assignments/program4.html
//
//
// Author: Gene Fisher (gfisher@calpoly.edu)
// Created: 22apr99
// Modified: 11may99
//
////

#include <iostream.h>
#include <iomanip.h>
#include <fstream.h>
#include <math.h>


////
//
// Function OpenGradesFile prompts the user for a file name from the terminal
// and opens a file of that name.  The opened file is returned in the reference
// parameter grades_file.
//
////
void OpenGradesFile(
    ifstream& grades_file       // Opened file
);

////
//
// Function ProcessHeaderInfo reads the header information from the given
// grades file.  It returns the number of items in the grades file, the number
// of items graded so far, and the percentage value for the graded items.
// These returns are through the reference parameters.  ProcessHeaderInfo uses
// three subfunctions to perform its computation: InputAndInitCounters,
// ProcessItemInfo, and OutputRestOfColumnHeading.  Further processing details
// are described in the declarations of these functions below.
//
////
void ProcessHeaderInfo(
    ifstream& grades_file,      // Input file
    int& num_items,             // Number of graded items
    int& num_graded,            // Number of items graded so far
    int& percent1,              // Percentage of 1st graded item
    int& percent2,              //     "      "  2nd    "    "
    int& percent3,              //     "      "  3rd    "    "
    int& percent4,              //     "      "  4th    "    "
    int& percent5               //     "      "  5th    "    "
);

////
//
// Function InputAndInitCounters reads the first two numbers from the given
// grades file, which are the number of graded items and the number of items
// graded so far.  These values are returned in the num_items and num_graded
// reference parameters.  The item_counter reference parameter is initialized
// to the value of num_items.  This counter is used subsequently by later
// functions to control file processing.
//
////
void InputAndInitCounters(
    ifstream& grades_file,      // Input file
    int& num_items,             // Number of graded items
    int& num_graded,            // Number of items graded so far
    int& item_counter           // Counter for reading item info
);

////
//
// Function ProcessItemInfo reads a label and percentage value from the given
// grades file.  If there is further item information to read, the grades_file
// read marker is assumed to be at the beginning of a line containing the
// information.  The item_counter parameter is used to determine if more
// information needs to be read.  Specifically, if it is non-zero, the
// information is read otherwise it is not.  The input label is output
// immediately to the terminal.  The input percentage value is returned in the
// percent reference parameter.  The item_counter reference parameter is
// decremented by one if information was read.
//
////
void ProcessItemInfo(
    ifstream& grades_file,      // Input file
    int& item_counter,          // Counter for reading item info
    int& percent                // Percentage of the processed graded item
);

////
//
// Function OutputRestOfColumnHeading inputs and discards the "======" heading
// separator from the given grades file.  It outputs to the terminal the
// "TOTAL" column heading and a line containing enough equals signs to extend
// from column 1 to to just below the "L" in the TOTAL column label.  The
// num_items input is used to compute the proper number of equals signs to
// output.
//
////
void OutputRestOfColumnHeading(
    ifstream& grades_file,      // Input file
    int num_items               // Number of graded items
);

////
//
// Function ProcessStudentInfo reads the lines of student grade information
// from the given grades file.  As the information is read, the raw score
// values and weighted totals are output to the terminal.  The num_items and
// num_graded input parameters are used to control how many items are processed
// for each student.  The percent inputs are used to compute the weighted
// total score for each student.
//
// The sum and sum_sq reference parameters are used to return the sums and sums
// of squares for all students for each graded item as well as for the weighted
// totals.  ProcessStudentInfo uses three subfunctions to perform its
// computation: InitStatsVars, ProcessStudentNameAndId, and
// ProcessStudentScores.  Further processing details are described in the
// declarations of these functions below.
//
////
void ProcessStudentInfo(
    ifstream& grades_file,      // Input file
    int num_items,              // Number of graded items
    int num_graded,             // Number of items graded so far
    int& num_students,          // Total number of students

    int percent1, int percent2, int percent3, int percent4, int percent5,
                                // Percentages for each graded item

    float& sum1, float& sum2, float& sum3, float& sum4, float& sum5,
        float& sum_total,
                                // Column sums for each item plus TOTAL

    float& sum_sq1, float& sum_sq2, float& sum_sq3, float& sum_sq4,
        float& sum_sq5, float& sum_sq_total
                                // Sum of squares for each item plus TOTAL
);

////
//
// Function InitStatsVars initializes all of the given reference parameters to
// zero, in preparation for the computations performed in the
// ProcessStudentScores function.
//
////
void InitStatsVars(
    int& num_students,          // Total number of students
    float& sum1, float& sum2, float& sum3, float& sum4, float& sum5,
        float& sum_total,
                                // Column sums for each item plus TOTAL

    float& sum_sq1, float& sum_sq2, float& sum_sq3, float& sum_sq4,
        float& sum_sq5, float& sum_sq_total
                                // Sum of squares for each item plus TOTAL
);

////
//
// Function ProcessStudentNameAndId outputs the student name and id to the
// terminal, with proper spacing.  The name is received as an input parameter,
// having been read in the calling function.  (The calling function reads the
// name in order to easily detect the end-of-file condition on the input
// file).  The student id is read from the given input file.
//
////
void ProcessStudentNameAndId(
    ifstream& grades_file,      // Input file
    char* name                  // Student name
);

////
//
// Function ProcessStudentScores is the central processing function of the
// entire program.  It is called once for each graded item.  The grades_file
// input parameter is the file from which scores are read.  The item_counter
// and graded_counter inputs control how items are processed.  Specifically, if
// the graded counter is non-zero, then a score is read, processed, and output
// to the terminal.  If the graded counter is zero, but the item counter is
// non-zero, then a score is read, discarded, and blanks are written to the
// terminal where the score would go.  If both counters are zero, no processing
// is performed.  If processing is performed, the counters are decremented by
// one, for use in the next call to this function.
//
// Score processing consists of computing three sums: the weighted score sum
// for the TOTAL column, the running sum for the graded item being processed,
// and the running sum of squares for the item.  The percent input parameter is
// used to compute the weighted sum.  The three sum values are returned in
// reference parameters.
//
////
void ProcessStudentScores(
    ifstream& grades_file,      // Input file
    int& item_counter,          // Counter for reading item info
    int& graded_counter,        // Counter for outputting non-empty item scores
    int percent,                // Percent for this graded item
    float& weighted_score_sum,  // Sum of weighted (i.e., percentaged) scores
    float& sum,                 // Running sum for this graded item
    float& sum_sq               // Running sum of squares for this graded item
);

////
//
// Function ProcessTotalScore outputs the given weighed score sum to the
// terminal, if num_graded is non-zero.  The weighed sum is added to the given
// sum_total and sum_sq_total reference parameters.  These parameters hold the
// running sum and sum of squares for the TOTAL column.
//
////
void ProcessTotalScore(
    int num_graded,             // Number of graded items
    float weighted_score_sum,   // Sum of weighted scores
    float& sum_total,           // Running sum of weighted sums
    float& sum_sq_total         // Running sum of squares of weighted sums
);

////
//
// Function ProcessStatistics computes and outputs the mean and standard
// deviation statistics to the terminal.  The num_items and num_graded input
// parameters are used to control how many statistics columns are computed.
// The num_students, sum, and sum of squares inputs are used in the mean and
// standard deviation formulae.  ProcessStatistics uses two subfunctions to
// perform its computation: ComputeAndOutputMeans and ComputeAndOutputStdDevs.
// Further processing details are described in the declarations of these
// functions below.
//
////
void ProcessStatistics(
    int num_items,              // Number of graded items
    int num_graded,             // Number of items graded so far
    int num_students,           // Total number of students

    float sum1, float sum2, float sum3, float sum4, float sum5,
        float sum_total,
                                // Column sums for each item plus TOTAL

    float sum_sq1, float sum_sq2, float sum_sq3, float sum_sq4, float sum_sq5,
        float sum_sq_total
                                // Sum of squares for each item plus TOTAL
);


////
//
// Function ComputeAndOutputMeans computes all of the means and outputs them to
// the terminal, with the appropriate heading and spacing.  This is an
// intermediate managerial function.  Parameter usage is as explained in the
// parent function ProcessStatistics.  The real work is done in the subfunction
// ComputeAndOuputOneMean, q.v.
//
////
void ComputeAndOutputMeans(
    int num_items,              // Number of graded items
    int num_graded,             // Number of items graded so far
    int num_students,           // Total number of students

    float sum1, float sum2, float sum3, float sum4, float sum5,
        float sum_total
                                // Column sums for each item plus TOTAL
);

////
//
// Function ComputeAndOutputStdDevs computes all of the standard deviations and
// outputs them to the terminal, with the appropriate heading and spacing.
// This is an intermediate managerial function.  Parameter usage is as
// explained in the parent function ProcessStatistics.  The real work is done
// in the subfunction ComputeAndOuputOneStdDev, q.v.
//
////
void ComputeAndOutputStdDevs(
    int num_items,              // Number of graded items
    int num_graded,             // Number of items graded so far
    int num_students,           // Total number of students

    float sum1, float sum2, float sum3, float sum4, float sum5,
        float sum_total,
                                // Column sums for each item plus TOTAL

    float sum_sq1, float sum_sq2, float sum_sq3, float sum_sq4, float sum_sq5,
        float sum_sq_total
                                // Sum of squares for each item plus TOTAL
);

////
//
// Function ComputeAndOutputOneMean computes and outputs the mean for one
// graded item.  The num_students and sum input parameters are used in the
// normal formula for the arithmetic mean, which is:
//
//     mean = sum / num_students
//
// The item_counter and graded_counter reference parameters are used to control
// processing in precisely the same manner as they are used in function
// ProcessStudentScores, q.v.
//
////
void ComputeAndOutputOneMean(
    int num_students,           // Total number of students
    float sum,                  // Sum for column being computed
    int& item_counter,          // Counter for reading item info
    int& graded_counter         // Counter for outputting non-empty item scores
);

////
//
// Function ComputeAndOutputOneStdDev computes and outputs the standard
// deviation for one graded item.  The num_students, sum, and sum_sq input
// parameters are used in a computationally-oriented version of the standard
// deviation formula, which is:
//
//     sqrt((sum_sq - pow(sum, 2) / num_students) / (num_students - 1))
//
// This version of the std dev formula is advantageous here because it does not
// involve the mean, and thereby avoids the need to save the mean values and
// send them into this function.
//
// The item_counter and graded_counter reference parameters are used to control
// processing in precisely the same manner as they are used in function
// ProcessStudentScores, q.v.
//
////
void ComputeAndOutputOneStdDev(
    int num_students,           // Total number of students
    float sum,                  // Sum for column being computed
    float sum_sq,               // Sum of squares for column being computed
    int& item_counter,          // Counter for reading item info
    int& graded_counter         // Counter for outputting non-empty item scores
);


////
//
// Function main calls subfunctions OpenGradesFile, ProcessHeaderInfo,
// ProcessStudentInfo, and ProcessStatistics to do their things.  Main declares
// variables that are used as input and output parameters among its
// subfunctions.
//
////
int main() {

    int num_items;              // Total number of graded items
    int num_graded;             // Number of items graded so far
    ifstream grades_file;       // Input file
    int num_students;           // Count of number of students

    int percent1, percent2, percent3, percent4, percent5;
                                // Percentages for each graded item

    float sum1, sum2, sum3, sum4, sum5, sum_total;
                                // Column sums for each item plus TOTAL
    float sum_sq1, sum_sq2, sum_sq3, sum_sq4, sum_sq5,
          sum_sq_total;
                                // Sum of squares for each item plus TOTAL

    //
    // Set up floating point output format always to print decimal point and
    // not to use scientific notation.
    //
    cout.setf(ios::fixed, ios::floatfield);
    cout.setf(ios::showpoint);

    //
    // Open the grades file.
    //
    OpenGradesFile(grades_file);

    //
    // If a grades file was found, proceed with the work, otherwise do
    // nothing.
    //
    if (grades_file) {

        //
        // Process all of the header info, up to and including the "======".
        //
        ProcessHeaderInfo(grades_file, num_items, num_graded,
            percent1, percent2, percent3, percent4, percent5);

        //
        // Process all of the student grade info in the remainder of the file.
        //
        ProcessStudentInfo(
            grades_file, num_items, num_graded, num_students,
            percent1, percent2, percent3, percent4, percent5,
            sum1, sum2, sum3, sum4, sum5, sum_total,
            sum_sq1, sum_sq2, sum_sq3, sum_sq4, sum_sq5, sum_sq_total);

        //
        // Compute and output the statistics.
        //
        ProcessStatistics(num_items, num_graded, num_students,
            sum1, sum2, sum3, sum4, sum5, sum_total,
            sum_sq1, sum_sq2, sum_sq3, sum_sq4, sum_sq5, sum_sq_total);
    }

    cout << endl;

    return 0;
}


void OpenGradesFile(ifstream& grades_file) {

    char file_name[50];         // File name input

    //
    // Prompt for and input the name of the grades file.
    //
    cout << "Input the name of the grades file: ";
    cin >> file_name;
    cout << endl;

    //
    // Open the grades file, issuing an error message if it cannot be opened.
    //
    grades_file.open(file_name);
    if (! grades_file) {
        cout << "Given grades file not found or could not be opened.";
    }
}

void ProcessHeaderInfo(ifstream& grades_file, int& num_items, int& num_graded,
        int& percent1, int& percent2, int& percent3, int& percent4,
            int& percent5) {

    int item_counter;           // Counter for reading item info.

    //
    // Input the number of items and number graded and initialize an item
    // counter to the number of items.
    //
    InputAndInitCounters(grades_file, num_items, num_graded, item_counter);

    //
    // Output the beginning of the column-heading line, formatted per the
    // specs.
    //
    cout << "Name                      "
         << "  Id   ";

    //
    // Process the info for the first item by reading it in off the file and
    // outputting the column heading with the first label.  Decrement the item
    // counter so the subsequent processing of items will stop when there are
    // no more.
    //
    ProcessItemInfo(grades_file, item_counter, percent1);
    ProcessItemInfo(grades_file, item_counter, percent2);
    ProcessItemInfo(grades_file, item_counter, percent3);
    ProcessItemInfo(grades_file, item_counter, percent4);
    ProcessItemInfo(grades_file, item_counter, percent5);

    //
    // Output the rest of the column heading, which consists of the TOTAL label
    // and the line of equals signs.
    //
    OutputRestOfColumnHeading(grades_file, num_items);
}

void InputAndInitCounters(ifstream& grades_file, int& num_items,
        int& num_graded, int& item_counter) {

    //
    // Read in sum number of items and number of items graded so far.
    //
    grades_file >> num_items;
    grades_file >> num_graded;

    //
    // Initialize an item counter to read header info for each item.
    //
    item_counter = num_items;
}

void ProcessItemInfo(ifstream& grades_file, int& item_counter, int& percent) {

    char label[6];              // Label for each graded item

    //
    // If the item counter is not yet 0, read in the next label and percent
    // pair.  Output the label immediately, and store the percent in the
    // percent reference parameter.
    //
    if (item_counter > 0) {
        grades_file >> label;
        cout << " " << setw(5) << label << " ";
        grades_file >> percent;
    }
    //
    // If item counter has reached zero, do no reading and set the percent to
    // zero.
    //
    else {
        percent = 0;
    }

    //
    // Decrement the item counter for next time around.  Note that it's a
    // reference parameter.
    //
    item_counter--;
}

void OutputRestOfColumnHeading(ifstream& grades_file, int num_items) {

    char ignore[7];             // String to ignore "======" separator
    int equal_sign_counter;     // Counter for '=' chars in heading separator

    //
    // Read in and ignore "======" separator line.
    //
    grades_file >> ignore;

    //
    // Output the TOTAL column heading, followed by a newline.
    //
    cout << "  TOTAL"
         << endl;

    //
    // Output the appropriate-length "======= ... " separator line.
    //
    equal_sign_counter = 25 + 7 + num_items * 7 + 8;
    while (equal_sign_counter > 0) {
        cout << "=";
        equal_sign_counter--;
    }
    cout << endl;
}

void ProcessStudentInfo(ifstream& grades_file,
        int num_items, int num_graded, int& num_students,
        int percent1, int percent2, int percent3, int percent4, int percent5,
        float& sum1, float& sum2, float& sum3, float& sum4, float& sum5,
            float& sum_total,
        float& sum_sq1, float& sum_sq2, float& sum_sq3, float& sum_sq4,
            float& sum_sq5, float& sum_sq_total) {

    int item_counter;           // Counter for reading item info
    int graded_counter;         // Counter for outputting non-empty item scores
    char name[25];              // Student name input
    float weighted_score_sum;   // Sum of weighted (i.e., percentaged) scores

    //
    // Initialize the statistics variables.
    //
    InitStatsVars(num_students, sum1, sum2, sum3, sum4, sum5, sum_total,
        sum_sq1, sum_sq2, sum_sq3, sum_sq4, sum_sq5, sum_sq_total);

    //
    // Read first student name.
    //
    grades_file >> name;

    //
    // Continue reading and outputting student info until end of file.
    //
    while (grades_file) {

        //
        // Increment the number of students by 1.
        //
        num_students++;

        //
        // Process the already read-in name and the yet to be read-in id.
        //
        ProcessStudentNameAndId(grades_file, name);

        //
        // Initialize item counter, graded item counter, and weighted sum
        // for this student.
        //
        item_counter = num_items;
        graded_counter = num_graded;
        weighted_score_sum = 0;

        //
        // Process the scores for each student, doing all necessary computation
        // and output for each set of student data.
        //
        ProcessStudentScores(grades_file, item_counter, graded_counter,
            percent1, weighted_score_sum, sum1, sum_sq1);
        ProcessStudentScores(grades_file, item_counter, graded_counter,
            percent2, weighted_score_sum, sum2, sum_sq2);
        ProcessStudentScores(grades_file, item_counter, graded_counter,
            percent3, weighted_score_sum, sum3, sum_sq3);
        ProcessStudentScores(grades_file, item_counter, graded_counter,
            percent4, weighted_score_sum, sum4, sum_sq4);
        ProcessStudentScores(grades_file, item_counter, graded_counter,
            percent5, weighted_score_sum, sum5, sum_sq5);

        //
        // Process the total score for this student.
        //
        ProcessTotalScore(num_graded, weighted_score_sum, sum_total,
            sum_sq_total);

        //
        // Input the next student name.
        //
        grades_file >> name;

    }
}

void InitStatsVars(int& num_students,
        float& sum1, float& sum2, float& sum3, float& sum4, float& sum5,
            float& sum_total,
        float& sum_sq1, float& sum_sq2, float& sum_sq3, float& sum_sq4,
            float& sum_sq5, float& sum_sq_total) {

    //
    // Initialize the number of students to 0.
    //
    num_students = 0;

    //
    // Initialize column sum and squares sum for each item.
    //
    sum1 = sum2 = sum3 = sum4 = sum5 = sum_total = 0;
    sum_sq1 = sum_sq2 = sum_sq3 = sum_sq4 = sum_sq5 =
        sum_sq_total = 0;
}

void ProcessStudentNameAndId(ifstream& grades_file, char* name) {

    char id[5];                 // Student id as a string.  Note that it's not
                                // an int, so we don't ignore leading zeros.
    int blank_counter;          // Counter for padding name output with blanks

    //
    // Output the student name, padded on the right by spaces up to
    // column 26.
    //
    cout << name;
    blank_counter = 25 - strlen(name);
    while (blank_counter > 0) {
        cout << ' ';
        blank_counter--;
    }

    //
    // Input and output the student id, in a 6-char-wide column.
    //
    grades_file >> id;
    cout << setw(6) << id << " ";
}

void ProcessStudentScores(ifstream& grades_file, int& item_counter,
        int& graded_counter, int percent, float& weighted_score_sum,
        float& sum, float& sum_sq) {

    int score;                  // Graded item score input

    //
    // If the item counter is not yet expired, input a score.
    //
    if (item_counter > 0) {
        grades_file >> score;
    }

    //
    // If the graded item counter has not expired, output the score and
    // perform the running computations.
    //
    if (graded_counter > 0) {
        //
        // Output the score.
        //
        cout << " " << setw(5) << score << " ";

        //
        // Add in the weighted score to the weighted sum.
        //
        weighted_score_sum =
            weighted_score_sum + score * 0.01 * percent;

        //
        // Add in the score for the column sum of this item, as well
        // as squares sum.
        //
        sum = sum + score;
        sum_sq = sum_sq + pow(score, 2);
    }

    //
    // If the graded item counter has expired, but the item counter has
    // not, output seven blanks of space for the ungraded item and do
    // no running computation
    //
    else if (item_counter > 0) {
        cout << "       ";
    }

    //
    // Unconditionally decrement the item and graded item counters.
    //
    item_counter--;
    graded_counter--;
}

void ProcessTotalScore(int num_graded,  float weighted_score_sum,
        float& sum_total, float& sum_sq_total) {

    //
    // Output the weighted total for the current student, as long as num_graded
    // is non-zero.
    //
    if (num_graded > 0) {
        cout << "  " << setw(6) << setprecision(2)
             << weighted_score_sum;
    }

    //
    // Add in the weighted sum for this student to the running weighted sum, as
    // well as sum of squares.
    //
    sum_total = sum_total + weighted_score_sum;
    sum_sq_total = sum_sq_total + pow(weighted_score_sum, 2);

    //
    // Output a newline at end of one student's info.
    //
    cout << endl;
}

void ProcessStatistics(int num_items, int num_graded, int num_students,
        float sum1, float sum2, float sum3, float sum4, float sum5,
            float sum_total,
        float sum_sq1, float sum_sq2, float sum_sq3, float sum_sq4,
            float sum_sq5, float sum_sq_total) {

    //
    // Output the stats heading.
    //
    cout << endl << "STATISTICS:"<< endl;

    //
    // Compute and output the means stats row.
    //
    ComputeAndOutputMeans(num_items, num_graded, num_students,
        sum1, sum2, sum3, sum4, sum5, sum_total);

    //
    // Compute and output the standard deviation stats row.
    //
    ComputeAndOutputStdDevs(num_items, num_graded, num_students,
        sum1, sum2, sum3, sum4, sum5, sum_total,
            sum_sq1, sum_sq2, sum_sq3, sum_sq4, sum_sq5, sum_sq_total);
}

void ComputeAndOutputMeans(int num_items, int num_graded, int num_students,
        float sum1, float sum2, float sum3, float sum4, float sum5,
            float sum_total) {

    int graded_counter;         // Counter for outputting non-empty item scores
    int item_counter;           // Counter for reading item info

    //
    // Output the mean row heading.
    //
    cout << setprecision(2) << ("  Mean                           ");

    //
    // Initialize the graded item counter and the item counter.
    //
    graded_counter = num_graded;
    item_counter = num_items;

    //
    // Compute and output the mean for each graded column.
    //
    ComputeAndOutputOneMean(num_students, sum1, item_counter, graded_counter);
    ComputeAndOutputOneMean(num_students, sum2, item_counter, graded_counter);
    ComputeAndOutputOneMean(num_students, sum3, item_counter, graded_counter);
    ComputeAndOutputOneMean(num_students, sum4, item_counter, graded_counter);
    ComputeAndOutputOneMean(num_students, sum5, item_counter, graded_counter);

    //
    // Output one extra space in front of mean for TOTAL column, and set graded
    // counter to num_graded to force output if appropriate.
    //
    cout << " ";
    graded_counter = num_graded;

    ComputeAndOutputOneMean(num_students, sum_total,
        item_counter, graded_counter);

    //
    // Output a newline at the end of the mean output.
    //
    cout << endl;
}

void ComputeAndOutputStdDevs(int num_items, int num_graded, int num_students,
        float sum1, float sum2, float sum3, float sum4, float sum5,
            float sum_total,
        float sum_sq1, float sum_sq2, float sum_sq3, float sum_sq4,
            float sum_sq5, float sum_sq_total) {

    int graded_counter;         // Counter for outputting non-empty item scores
    int item_counter;           // Counter for reading item info

    //
    // Output the std dev row heading.
    //
    cout << setprecision(2) << ("  Standard deviation             ");

    //
    // Initialize the graded item and item counters.
    //
    graded_counter = num_graded;
    item_counter = num_items;

    //
    // Compute and output the std dev for each graded column.
    //
    ComputeAndOutputOneStdDev(num_students, sum1, sum_sq1,
        item_counter, graded_counter);
    ComputeAndOutputOneStdDev(num_students, sum2, sum_sq2,
        item_counter, graded_counter);
    ComputeAndOutputOneStdDev(num_students, sum3, sum_sq3,
        item_counter, graded_counter);
    ComputeAndOutputOneStdDev(num_students, sum4, sum_sq4,
        item_counter, graded_counter);
    ComputeAndOutputOneStdDev(num_students, sum5, sum_sq5,
        item_counter, graded_counter);

    //
    // Output one extra space in front of std dev for TOTAL column, and set
    // graded counter to num_graded to force output if appropriate.
    //
    cout << " ";
    graded_counter = num_graded;

    ComputeAndOutputOneStdDev(num_students, sum_total, sum_sq_total,
        item_counter, graded_counter);

    //
    // Output a newline at the end of the std dev output.
    //
    cout << endl;
}

void ComputeAndOutputOneMean(int num_students, float sum, int& item_counter,
        int& graded_counter) {

    float mean;                 // Mean for column being computed

    //
    // If the graded counter has not expired, compute and output the mean.
    //
    if (graded_counter > 0) {
        mean = sum / num_students;
        cout << " " << setw(5) << mean << " ";
    }

    //
    // If the graded item counter has expired, but the item counter has
    // not, output seven blanks of space for the ungraded item and do no
    // running computation
    //
    else if (item_counter > 0) {
        cout << "       ";
    }

    //
    // Unconditionally decrement the graded item and item counters.
    //
    graded_counter--;
    item_counter--;
}

void ComputeAndOutputOneStdDev(int num_students, float sum, float sum_sq,
         int& item_counter, int& graded_counter) {

    //
    // If the graded counter has not expired, output the std dev.
    //
    if (graded_counter > 0) {
        cout << " " << setw(5)
             << sqrt((sum_sq - pow(sum, 2) / num_students) /
                    (num_students - 1))
             << " ";
    }

    //
    // If the graded item counter has expired, but the item counter has
    // not, output seven blanks of space for the ungraded item and do no
    // running computation
    //
    else if (item_counter > 0) {
        cout << "       ";
    }

    //
    // Unconditionally decrement the graded item counter.
    //
    graded_counter--;
    item_counter--;
}


index | lectures | labs | handouts | assignments | solutions | grades | help