0

For my class I am supposed to create a program that asks for 5 test scores and to average the 4 highest scores using functions. I wrote this program with some help and I am a little confused. How does void calcAverage know to input score1-score5 in the parameters into test1-test5? Does it know based on the information I put into int findLowest? Thanks!

#include <iostream>
#include <cmath>
#include <iomanip>

using namespace std;

void getscore(int &testcore);
void calcAverage (double, double, double, double, double);
int findLowest (double, double, double, double, double);


int main()

{
    int score1, score2, score3, score4, score5;

    cout << fixed << setprecision(2);

    getscore(score1);
    getscore(score2);
    getscore(score3);
    getscore(score4);
    getscore(score5);



    calcAverage(score1, score2, score3, score4, score5);



    return 0;
}

void getscore(int &testscore){
    cout << "Enter test score:" << endl;
    cin >> testscore;

    while(testscore<1||testscore > 100){
        cout << "Invalid. Enter a number between 1-100" << endl;
        cin >> testscore;
    }

}

void calcAverage(double test1, double test2, double test3, double test4, double test5){

    double scores_added, average;

    scores_added = test1 + test2 + test3 + test4 + test5;


    average = (scores_added-findLowest(test1, test2, test3, test4, test5))/4.0;
    cout << "The average of the 4 highest scores is " << average << endl;



}

int findLowest(double score1, double score2, double score3, double score4, double score5){

    if(score1<score2 && score1<score3 && score1<score4 && score1<score5){
        return score1;
    }else if(score2<score1 && score2<score3 && score2<score4 && score2<score5){
        return score2;
    }else if(score3<score1 && score3<score2 && score3<score4 && score2<score5){
        return score3;
    }else if(score4<score1 && score4<score2 && score4<score3 && score4<score5){
        return score4;
    }else if(score5<score1 && score5<score2 && score5<score3 && score5<score4){
        return score5;
    }
}
Ilya
  • 1
  • 1
    Recommendation: Replace the 5 variables with one five-element array (container class like `std::vector` if you're allowed to use them). Most of your problems will go away. – user4581301 Mar 03 '21 at 17:57
  • 1
    Put into array. Sort the array. Use the four highest values in sorted array to calculate your "average". – Some programmer dude Mar 03 '21 at 17:58
  • And `calcAverage` doesn't do any "input score1-score5 in the parameters into test1-test5". This "input" is done when you call the function from your `main` function. – Some programmer dude Mar 03 '21 at 18:00
  • 2
    You're asking why the parameters passed to the function call, and the parameter list inside the called function, have different names. I feel this is firmly in the [read a good book](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) category. However, you could also play around with some simpler code to develop your intuition about the basics of calling functions. – Useless Mar 03 '21 at 18:04
  • Have you learned about arrays or even vectors yet? Or are you just learning about basic types and using them as parameters. Where are you on your C++ walk? Think about learning Calculus, we can tell you how to integrate e to the x, but if you are on learning the delta process at the beginning of differential calculus, and asking how to determine the derivate of 5x +2, most of our answers probably won't help. – franji1 Mar 03 '21 at 19:26

2 Answers2

0

Because getscore(score1); passes score1 (example) by reference, which means it passes the address to score1, then the function getscore reads the score from the user and places it into where testscore points to (in this case to score1). When you call calcAverage it is passing those arguments by value meaning calcAverage has its own copies locally from that point.

If you're asking how does score1 become test1, that is just the naming, in this case for calcAverage it is the first argument and it calls it test1 but could have been anything else. On the input side you're passing in score1 as the first argument but you could have also put a number there, basically the 2 things don't need to use the same name.

Notice that you are passing type int to a function that expects type double. You probably get compiler warnings for that.

user4581301
  • 33,082
  • 7
  • 33
  • 54
pgibbons
  • 309
  • 2
  • 5
  • *which means it passes the address to score1* A common implementation detail, but not necessarily what will happen. The compiler may generate code that merely reaches outside of the normally visible scope and directly modifies `score1`. – user4581301 Mar 03 '21 at 18:56
  • user4581301 right, when you pass by address, the original value will be the one that will be modified. – pgibbons Mar 03 '21 at 20:46
0

To answer what I think is your main question, you just need to read your main function line by line.

First you declare five score variables. Then you set std::cout's precision for printing. Your next five lines get the test scores. So, the five variables you declared now hold the test scores.

Then you call your calc_average(), passing it the five scores. The function has the scores because you gave them to it. This is a fairly common thing that I see a lot of beginners struggle with. Variables hold data. If you give a variable to a function, you are giving that data to the function. (More or less, and there are nuances in how you can give the data). If something isn't clicking, you might have to just treat those statements as axiomatic, meaning they simply must be accepted as true. It eventually clicks.

=== OPTIONAL ===
As you continue to learn, you'll find easier ways to do things. Here's one possible example:

#include <algorithm>   // std::sort
#include <functional>  // std::greater
#include <iostream>
#include <numeric>  // std::accumulate
#include <vector>

#include <random>  // Generating test scores

template <typename Container>
void print(const Container& container, std::ostream& sout = std::cout) {
  for (const auto& i : container) {
    sout << i << ' ';
  }
  sout << '\n';
}

int main() {
  constexpr int numScores = 5;
  constexpr int topN = 4;

  if (topN > numScores) {
    std::cerr << "Top N scores value larger than total scores\n";
    return 1;
  }

  std::vector<int> scores;

  // Just to generate random values instead of relying on std::cin
  std::mt19937 prng(std::random_device{}());
  std::uniform_int_distribution<int> testDist(1, 100);
  for (int i = 0; i < numScores; ++i) {
    scores.push_back(testDist(prng));
  }

  print(scores);
  std::sort(scores.begin(), scores.end(), std::greater<int>());
  print(scores);
  double average = std::accumulate(
      scores.begin(), scores.begin() + topN, 0.0, [](double avg, int num) {
        return avg += (static_cast<double>(num) / static_cast<double>(topN));
      });

  std::cout << average << '\n';
}
sweenish
  • 4,793
  • 3
  • 12
  • 23