user2969508
user2969508

Reputation: 11

Functions and arrays

The question is

Design the grade processing program to use functions and an array. Let user enter number of grades (set the maximum to 50). Store grades in an array. Create a separate function for each calculation (total of 3 functions): 1) average grade, 2) maximum grade, 3) number of grades above the average. Display all results.

I think I got the main part, but I'm having trouble with how to write the functions, the functions are outputting one for some reason, and I'm having trouble writing the max function or how to start it.

#include <iostream>
using namespace std;

double average(double x[], int n);
double maximum(double x[], int n);
int nAboveAvg(double x[], int n);

int main()
{
    double grades[50];
    int ngrades;

    cout<<"How many grades? (max = 50)";
    cin>>ngrades;

//create for loop to get grades from user
    for(int i = 0; i<ngrades; i++)
    {
         cout<<"Enter grade ";
         cin>> grades[i];
    }

      //call the functions
   double avg = average(grades, ngrades);
   double max = maximum(grades, ngrades);
   int nAbove = nAboveAvg(grades, ngrades);
   //display results

   cout<<"Average = "<<avg<<endl;
   cout<<"# above average = "<<nAbove<<endl;


}

double average(double x[], int npts) //define the functon to recieve the array
{
    double sum = 0;
    for(int k = 0; k<npts; k++)
    {
       sum = sum +x[k];
    }
    return sum / npts;
}
double maximum(double x[], int npts)
{
   double max = 0;
   for(int i = 0; i<npts; i++)
   {
      if(max == npts)
      {
          return max;
      }
      if(max < npts)
      {
          return npts;
      }
   }
}
int nAboveAvg(double x[], int npts)
{
    int nAboveAvg = 0;
    for(int i = 0; i<npts;i++)
    {
        if(x[i] > npts)
        {
            nAboveAvg++;
        }
    }
    return nAboveAvg;
}

Upvotes: 0

Views: 579

Answers (2)

Dan Mašek
Dan Mašek

Reputation: 19041

Incorrect Printing

//call the functions
double avg = average(grades, ngrades);
double max = maximum(grades, ngrades);
int nAbove = nAboveAvg(grades, ngrades);

Notice that you define variables named avg and nAbove.

//display results
cout<<"Average = "<<average<<endl;
cout<<"# above average = "<<nAboveAvg<<endl;

But then you use average and nAboveAvg (the functions) when you attempt to print the results.

The correct version here would be:

cout << "Average = " << avg << endl;
cout << "# above average = " << nAbove << endl;

Compiler Warnings

When I try to compile this, the compiler emits a number of warnings. e.g.

main.cpp: In function 'int main()':
main.cpp:29:24: warning: the address of 'double average(double*, int)' will always evaluate as 'true' [-Waddress]

    cout<<"Average = "<<average<<endl;

or

main.cpp:24:11: warning: unused variable 'avg' [-Wunused-variable]

    double avg = average(grades, ngrades);

It is a good idea not to ignore those warnings.


Count Above Average

        if(x[i] > npts)
        {
            nAboveAvg++;
        }

You compare the value at position i with number of input values. However, you should be comparing value at position i with the average of all the values. Hence

int nAboveAvg(double x[], int npts)
{
    int count = 0;
    double avg = average(x, npts);

    for (int i(0); i < npts; ++i) {
        if (x[i] > avg) {
            ++count;
        }
    }
    return count;
}

Refactoring

You may now notice that in our program we end up calculating the average value twice. We can fix this by making our function more general -- instead of counting number of values above average, let's count the number of values above arbitrary target passed as a parameter.

int count_above(double x[], int npts, double target)
{
    int count = 0;
    for (int i(0); i < npts; ++i) {
        if (x[i] > target) {
            ++count;
        }
    }
    return count;
}

Now we can write

//call the functions
double avg = average(grades, ngrades);
double max = maximum(grades, ngrades);
int nAbove = count_above(grades, ngrades, avg);

Maximum Value

Let's think about the algorithm, and start from simplest case -- only one value in the array. In this scenario the first value is also the maximum.

double max = x[0];

Knowing that, let's consider how to find the maximum when there are 2 values in the input array. We already know the maximum of all the values before the second value. Therefore

if (x[1] > max) {
    max = x[1];
}

Next step, input array with 3 values. Again, we already know the maximum of all the values before the third value. Therefore

if (x[2] > max) {
    max = x[2];
}

We can see a pattern repeating here, which we can wrap in a loop.

double maximum(double x[], int npts)
{
    if (npts <= 0) {
        exit(-1); // Error...
    }

    double max = x[0];

    for (int i(1); i < npts; ++i) {
        if (x[i] > max) {
            max = x[i];
        }
    }
    return max;
}

Validating Input

You don't have any validation of the input passed to your functions, yet there are some obvious cases that need to be accounted for.

  • In all of your functions, what should happen when the npts is negative?
  • What's the average value of a 0 elements?
  • What's the maximum value of 0 elements?

A very simple way to handle those cases would be to return some special value as a result. You then have to check the results for this value every time you call the function. In many cases it may be hard to select an appropriate value for this.

Another possibility that would be accepted at a beginner level, would be simply printing some error message to console, and exiting the program. For example

if (npts <= 0) {
    cerr << "Too few values in input array." << endl;
    exit(-1); // Error...
}

The proper C++ approach would be to throw an exception, for example std::invalid_argument. For example

#include <stdexcept>

// ....

if (npts <= 0) {
    throw std::invalid_argument("Too few values in input array.);
}

Upvotes: 2

Bill Dhimitri
Bill Dhimitri

Reputation: 204

The "average" function looks good. In the last 2 lines in main, I think you want to output avg instead of average (because average is the name of the function, not the name of the variable that holds the computed value). Similarly, output nAbove instead of nAboveAvg.

The maximum function looks like an empty implementation. I don't think that will compile because it needs to (at least) return a double value.

In the nAboveAvg function, "x[i] > npts" seems like the wrong test. I think you want to compare x[i] to avg (you will want to pass avg into this function as an argument.

Upvotes: 0

Related Questions