Solution to the statistics package program
/**
NOTE 0: This is an approximation of the assignment.
NOTE 1: I put all the array functions in this file
to make it easier to see all the code used in this assignment. However,
I have added the array functions to the array file.
NOTE 2: I calculated the location of the mode rather than the value of the
mode so that I could more easily output "there is no mode" when there was
no mode.
NOTE 3: It is much easier to find the median and mode if the array is sorted,
therefore, if the array was not sorted, I sorted it. The only subprograms
that rely on the sorted array are the ones for median and mode. I am
surprized that the sample output in Foster does not reflect the sorting.
If you wanted to maintain the original input order, you would need to have
an array to hold the data in the original order and another one to hold the
sorted array. Can't see than maintaining the original order in this case
is worth the extra memory or work.
NOTE 4: The function brendas_bubble() is a variation of bubble sort that is
much more efficient than the traditional bubble sort. Check it out.
NOTE 5: I added in the output for number of elements as shown in Foster as
part of the show data selection.
NOTE 6: I added a "press return to continue message" just to show you an
example of one way of accomplishing this. Not very elegant but not an
awful example.
**/
/********************************************************
* *
* Brenda Sonderegger Sept. 28, 1997 *
* *
* CS210 - Assignment 4 *
* *
* Purpose: Use 1-d arrays *
* *
* Description: Create a menu driven statistics program *
* that allows the user to choose to enter data, *
* display data, display the high and low datum, *
* display the mean, the mode, and the varience *
* and standard deviation. *
********************************************************/
#include <stdio.h>
#include <math.h>
#include <ctype.h>
#include <stdlib.h>
#include "myio_c.h"
#define MAX 20
#define TRUE 1
#define FALSE 0
#define EPSILON 0.001
/* syntactic sugar */
#define ADD_DATA 1
#define WRITE 2
#define HI_LOW 3
#define MEAN 4
#define MEDIAN 5
#define MODE 6
#define VAR_STD 7
#define QUIT 8
void print_menu(void);
void fill_1d_float(float [], int, int, int *);
void write_1d_float(float [], int, int);
void brendas_bubble(float [], int, int);
float calc_mean(float [], int, int);
float calc_median(float [], int, int);
float calc_variance(float [], int, int, float);
int calc_mode_location(float [], int, int);
float calc_high(float [], int, int);
float calc_low(float [], int, int);
void main(void)
{
char junk;
int choice, actual_high = -1, sorted = 0, mode_location = -1;
float data[MAX];
float high, low, mean, median, variance, standard_dev;
high = low = mean = median = variance = standard_dev = -1.0;
do
{
print_menu();
printf("\nEnter your choice now ");
get_int_bound(&choice, 1, 8);
if ((choice != 8) && (choice != 1) && (actual_high < 0 ))
printf("\nNo data - you must enter data first.\n");
else
{
switch(choice)
{
case ADD_DATA:
fill_1d_float(data, actual_high + 1, MAX-1, &actual_high);
high = low = mean = variance = standard_dev = -1;
mode_location = -1;
sorted = 0;
break;
case WRITE: printf("\nNumber of elements: %d\n", actual_high + 1);
write_1d_float(data, 0, actual_high);
printf("\n\n");
break;
case HI_LOW:
if (sorted == 0)
{
low = calc_low(data, 0, actual_high);
high = calc_high(data, 0, actual_high);
}
else
{
low = data[0];
high = data[actual_high];
}
printf("\nHigh = %f, low = %f\n\n", high, low);
break;
case MEAN: mean = calc_mean(data, 0, actual_high);
printf("\nmean = %f\n\n", mean);
break;
case MEDIAN:
if (sorted == 0)
{
brendas_bubble(data, 0, actual_high);
sorted = 1;
}
median = calc_median(data, 0, actual_high);
printf("\nmedian = %f\n\n", median);
break;
case MODE:
if (sorted == 0)
{
brendas_bubble(data, 0, actual_high);
sorted = 1;
}
mode_location = calc_mode_location(data, 0, actual_high);
if (mode_location >= 0)
printf("\nmode = %f\n\n", data[mode_location]);
else
printf("\nThere is no mode\n\n");
break;
case VAR_STD:
if (mean < 0)
mean = calc_mean(data, 0, actual_high);
variance = calc_variance(data, 0, actual_high, mean);
standard_dev = sqrt(variance);
printf("\nvariance = %f\nstandard deviation = %f\n\n",
variance, standard_dev);
break;
case QUIT: printf("\nThanks for using the program \n");
}
}
if (choice != 8)
{
printf("\nPress carriage return to continue ");
scanf("%c", &junk);
/** for safety, it would probably be a good idea to check to see
if junk has a carriage return in it and if not, then clean the
input stream
**/
}
}
while (choice != 8);
}
void print_menu(void)
{
printf("\n\nStatistics Menu\n");
printf("\n1 - Enter data");
printf("\n2 - Display data");
printf("\n3 - Calculate and display high value and low value");
printf("\n4 - Calculate and display mean value ");
printf("\n5 - Calculate and display median value");
printf("\n6 - Calculate and display smallest mode ");
printf("\n7 - Calculate and display the varience and standard diviation");
printf("\n8 - quit");
}
/********fill_1d_float() is somewhat different than fill_1d_int_part() in
that I did not send a stopping value. In this case, I choose to use a
print statement and a local value to control the end of input. Both
methods are completely legitimate. Which you use depends on personal
preference, the problem to be solved, and other considerations. No 1
fill procedure will be correct for every array based problem.
************/
void fill_1d_float(float array[], int low, int high, int *actual)
{
int index = low, done = FALSE;
float temp;
if (index <= high)
{
printf("\nEnter a -1.0 to indicate end of input.\n");
do
{
printf("\nEnter item #%d ", index + 1);
get_float_low(&temp, -1.0);
if (temp < 0.0)
{
done = TRUE;
*actual = index - 1;
}
else
{
array[index] = temp;
index++;
if (index > high)
{
printf("\nEnd of input - array full.\n");
*actual = index - 1;
}
}
}
while ((index <= high) && (done != TRUE));
}
else
printf("\nArray is full - no more data can be entered.\n");
}
void write_1d_float(float array[], int low, int high)
{
int i;
for (i = low; i <= high; i++)
printf("%f ", array[i]);
}
float calc_high(float array[], int low, int high)
{
int i;
float biggest = array[low];
for (i = low + 1; i <= high; i++)
{
if (array[i] > biggest)
biggest = array[i];
}
return (biggest);
}
float calc_low(float array[], int low, int high)
{
int i;
float small = array[low];
for (i = low + 1; i <= high; i++)
{
if (array[i] < small)
small = array[i];
}
return (small);
}
float calc_mean(float array[], int low, int high)
{
int i, num_elements = high - low + 1;
float sum = 0.0;
for (i = low; i <= high; i++)
{
sum = sum + array[i];
}
if (num_elements != 0)
return (sum/num_elements);
else
return (0.0);
}
float calc_median(float array[], int low, int high)
{
float median;
int num_elements = high - low + 1;
int middle = num_elements/2 + low;
if (num_elements%2 == 1)
median = array[middle];
else
median = (array[middle] + array[middle - 1])/2.0;
return (median);
}
float calc_variance(float array[], int low, int high, float mean)
{
float sum_squares = 0.0, value;
int i, num_elements = high - low + 1;
for (i = low; i <= high; i++)
{
value = mean - array[i];
sum_squares = sum_squares + value * value;
}
if (num_elements > 0)
return (sum_squares / num_elements);
else
return (0.0);
}
int calc_mode_location(float array[], int low, int high)
{
float mode = array[low];
int i, location = low, temp_locate = low, count = 0, temp_count = 1;
for (i = low + 1; i <= high; i++)
{
if (fabs(array[i] - mode) < EPSILON)
{
temp_count++;
}
else
{
if (temp_count > count)
{
count = temp_count;
location = i - 1;
}
mode = array[i];
temp_count = 1;
}
}
if (count > 1)
return location;
else
return low - 1;
}
void brendas_bubble(float array[], int low, int high)
{
int i = low, j, sorted = FALSE;
int count = 1;
float temp;
while ((sorted == FALSE) && (i <= high))
{
sorted = TRUE;
for (j = low; j <= high - count; j++)
{
if (array[j] > array[j+1])
{
/** could call swap() instead of doing the swap here **/
temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
sorted = FALSE;
}
}
i++;
count++;
}
}