1

The functions are getInputN(), calculateMean() & displayData().

So to be really clear, these are the requirements.

  • getInputN function: Should accept the number of the value, N as an integer as argument and ask the user to enter the value of N number. Then, return the sum of the value as a double.
  • calculateMean function: Should accept the number of the value, N and sum of the value as arguments. Then return the mean as a double.
  • displayData function: Should accept the mean as argument. Then, display them in the appropriate message on screen. No return value required for this function.

If I run the code, it will display Average = inf

p/s: I'm really sorry for the confusing question at first. I'm really new to this website and this is my very first question. It took me some times to figure out things to ask properly in this platform. I hope you guys understand and once again, sorry for the inconvenience. Thank you for the helps too :)

Here is my code:

#include <iostream>
using namespace std;

int getInputN(int n);
float calculateMean (int n, float sum);
float displayData(double mean);

int i,n;
float sum = 0.0, num[50];
double mean;

int main()
{
    getInputN(n);
    calculateMean (n, sum);
    displayData(mean);

    return 0;
}

int getInputN(int n)
{
    int i;
    float num[50];

    //User enter the number of value
    cout << "Enter the numbers of data: ";
    cin >> n;
    
    //if user input more than 50 numbers
    while (n > 50 || n <= 0)
    {
        cout << "Invalid! Enter the number in range of (1 to 50)." << endl;
        cout << "Enter the number of data: ";
        cin >> n;
    }

    for(i = 0; i < n; ++i)
    {
        cout << i + 1 << ". Enter number: ";
        cin >> num[i];
        sum += num[i];
    }

    return n;
}

    //function to calculate the mean
    float calculateMean (int n, float sum)
    {
    
        mean = sum/n;
    
        return mean;
    }

    //function to display the mean
    float displayData (double mean)
    {
        cout << "Average = " << mean;
    }
fabian
  • 80,457
  • 12
  • 86
  • 114
daisy98
  • 11
  • 3
  • What are the errors? – drescherjm Jun 11 '21 at 14:35
  • 4
    It's never too soon to stop using global variables. – molbdnilo Jun 11 '21 at 14:35
  • 1
    The parameter `int n` in `getInputN` shadows the global `int n`. So `getInputN` doesn't update the global variable, it just returns a value. So when you call `calculateMean(n, sum)` using the global `n` as an argument, it doesn't have any valid value. Your functions have return types, you should be using them in your calling code. – Nathan Pierson Jun 11 '21 at 14:38
  • And calculateMean divides a sum (which you never added anything to, so it's zero) by a number n which you never initialized at all. It seems a lot like you don't really understand how to use return values at all yet. – Useless Jun 11 '21 at 14:39
  • The output that I got is Average = inf. The answer supposed to get the mean of the input numbers. I think the arguments and return value are all messed up lol – daisy98 Jun 11 '21 at 14:40
  • Actually, question: Is this even defined behavior? The uninitialized global `n` is being passed to `getInputN` by value. Even though `getInputN` doesn't attempt to read the value of its parameter, does this still form UB? – Nathan Pierson Jun 11 '21 at 14:40
  • @Useless Doesn't `getInputN` actually update `sum`? There's no shadowing for _that_ global variable. – Nathan Pierson Jun 11 '21 at 14:41
  • Oh, you're right - I didn't notice it was updating the only global it _didn't_ have any business touching (given it _should_ update `n` and `num` but doesn't) – Useless Jun 11 '21 at 14:43
  • Can you give a little more detail on exactly what your lecturer expects `getInputN` to do? What is its argument(s) supposed to be? What is its return value supposed to be? What, if anything, is it supposed to do to global variables? There's a ton of different ways you could rewrite `getInputN` and `main` based on the answers to that, and "it accepts arguments" is not sufficient to narrow it down at all. – Nathan Pierson Jun 11 '21 at 15:02

3 Answers3

1

The argument int n in the function getInputN is shadowing (hiding) the global variable n. This prevents the global variable from being updated and sum is divided by zero (the default value of gloval variable without explicit initialization).

If you want to pass data using gloval variables, the arguments should be removed because one of that (n as descrived above) is harmful and other are redundant.

Also the function displayData is declared to return float but didn't execute any return statement. This invokes undefined behavior. I fixed this by changing its return type to void.

#include <iostream>
using namespace std;

int getInputN();
float calculateMean ();
void displayData();

int i,n;
float sum = 0.0, num[50];
double mean;

int main()
{
    getInputN();
    calculateMean ();
    displayData();

    return 0;
}

int getInputN()
{
    int i;
    float num[50];

    //User enter the number of value
    cout << "Enter the numbers of data: ";
    cin >> n;
    
    //if user input more than 50 numbers
    while (n > 50 || n <= 0)
    {
        cout << "Invalid! Enter the number in range of (1 to 50)." << endl;
        cout << "Enter the number of data: ";
        cin >> n;
    }

    for(i = 0; i < n; ++i)
    {
        cout << i + 1 << ". Enter number: ";
        cin >> num[i];
        sum += num[i];
    }

    return n;
}

//function to calculate the mean
float calculateMean ()
{

    mean = sum/n;

    return mean;
}

//function to display the mean
void displayData ()
{
    cout << "Average = " << mean;
}

This fix will make the code work, but there should be better design without usage of global variables. References is useful to have functions modify things given as arguments and std::vector is useful to return "arrays".

MikeCAT
  • 73,922
  • 11
  • 45
  • 70
  • Oh ok I see... Actually in the question, my lecturer said the three functions getInput(N), calculateMean() & displayData accept arguments. So, how is that being implemented in the code? Btw, thank you so much for the answer! Appreciate it a lot. – daisy98 Jun 11 '21 at 14:53
0

The variable n in int getInputN(int n) is used in the function instead of the global n declared. As such, using global n (which is uninitialized till that point initialized to 0) to calculate mean = sum/n will lead to a undefined behavior divide by 0 error, resulting in inf.

More info :

Also, the function float displayData (double mean) doesn't return any value, causing another undefined behavior.

More info :

Modified code :

#include <iostream>
using namespace std;

void getInputN();
void calculateMean();
void displayData();

int i,n;
float sum = 0.0, num[50];
double mean;

int main()
{
    getInputN();
    calculateMean();
    displayData();

    return 0;
}

void getInputN()
{
    int i;
    float num[50];

    //User enter the number of value
    cout << "Enter the numbers of data: ";
    cin >> n;

    //if user input more than 50 numbers
    while (n > 50 || n <= 0)
    {
        cout << "Invalid! Enter the number in range of (1 to 50)." << endl;
        cout << "Enter the number of data: ";
        cin >> n;
    }

    for(i = 0; i < n; ++i)
    {
        cout << i + 1 << ". Enter number: ";
        cin >> num[i];
        sum += num[i];
    }
}

//function to calculate the mean
void calculateMean ()
{
    mean = sum/n;
}

//function to display the mean
void displayData ()
{
    cout << "Average = " << mean;
}

Result :

Enter the numbers of data: 3
1. Enter number: 1
2. Enter number: 3
3. Enter number: 6
Average = 3.33333

Furthermore, if you don't use the numbers for anything else, declaring a float num[50]; is quite pointless. Also, noted that using global variable and using namespace std; is not recommended.

#include <iostream>

const int maxn = 50;
const int minn = 1;

int main()
{
    int n; std::cout << "Enter N : "; std::cin >> n;
    while (n < minn || n > maxn) {std::cout << "Invalid. Re-enter N : "; std::cin >> n;}

    double sum = 0; int tmp;
    for (int i = 0; i < n; i++) { std::cout << "Enter number " << i+1 << " : "; std::cin >> tmp; sum += tmp;}

    std::cout << "Average : " << sum/n;
}

Result :

Enter N : 3
Enter number 1 : 25
Enter number 2 : 97
Enter number 3 : 111
Average : 77.6667
silverfox
  • 1,568
  • 10
  • 27
  • 1
    The *global* `n` has *static storage duration*, so it is *zero-initialized* by default. ([N3337](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf) 8.5 Initializers 9) `mean = sum/n` invokes *undefined behavior* because it is division by zero. (N3337 5.6 Multiplicative operators) – MikeCAT Jun 11 '21 at 14:52
  • @MikeCAT my mistake, I'm going to modified it now. – silverfox Jun 11 '21 at 14:53
  • Oh ok I see... Actually in the question, my lecturer said the three functions getInput(N), calculateMean() & displayData accept arguments. So, how is that being implemented in the code? Btw, thank you so much for the answer! Appreciate it a lot. – daisy98 Jun 11 '21 at 14:54
  • @daisy98 If you have additional requirements for what the functions' signatures should be and how they should work, please edit the actual question to include them. Otherwise people will have to guess what the intended behavior of the functions is. – Nathan Pierson Jun 11 '21 at 14:55
  • @daisy98 "Actually in the question, my lecturer said the three functions getInput(N), calculateMean() & displayData accept arguments." But what for? Well I mean as `sum`, `mean` and `n` are global variables anyway and can be read by any function so `float calculateMean (int n, float sum)` and `float displayData (double mean)` will work the same, `int getInputN(int n)` leads to some problem. So what are you using those arguments **for**? If you has other requirements, edit your question to include them, else, including unnecessary arguments can lead to confusion. – silverfox Jun 11 '21 at 15:00
0

Knowing how the functions are behaved, we can write implementations that work nicely and don't use any global variables at all.

#include <iostream>

double getInputN(int n);
double calculateMean(int n, double sum);
void displayData(double mean);

int main()
{   
    //User enter the number of value
    int numEntries;
    std::cout << "Enter the numbers of data: ";
    std::cin >> numEntries;

    //if user input more than 50 numbers
    while (numEntries > 50 || numEntries <= 0)
    {
        std::cout << "Invalid! Enter the number in range of (1 to 50)." << std::endl;
        std::cout << "Enter the number of data: ";
        std::cin >> numEntries;
    }

    // Get user input
    double sum = getInputN(numEntries);

    double mean = calculateMean(numEntries, sum);

    displayData(mean);

    return 0;
}

double getInputN(int n)
{
    double sum = 0.;

    for (int i = 0; i < n; ++i)
    {
        double userInput;
        std::cout << i + 1 << ". Enter number: ";
        std::cin >> userInput;
        sum += userInput;
    }

    return sum;
}

//function to calculate the mean
double calculateMean(int n, double sum)
{

    double mean = sum / n;

    return mean;
}

//function to display the mean
void displayData(double mean)
{
    std::cout << "Average = " << mean;
}

Let's go into some more detail on each of the changes.

First, I've changed the signatures of all of your functions. getInputN is supposed to return a double, not an int. calculateMean is supposed to accept and return a double, not a float. And displayData isn't required to return anything, it doesn't make sense for it to return anything, and therefore I've made its return type void.

Second, note that I've moved the code for figuring out how many entries to enter from getInputN into main. The reason for this is that the sole argument to getInputN is "how many inputs should we get?", so we need to know its value before we call getInputN.

Third, note how I've used the return values from each function in the calling code. In main, when I write double sum = getInputN(numEntries);, that declares a variable sum and stores the return value of getInputN(numEntries) to sum. When you just write getInputN(n);, the return value from getInputN is discarded. By storing it in a variable in main, I can then pass its value to another function, like in the next line where I've written double mean = calculateMean(numEntries, sum);.

Fourth, note how the requirements of the question are such that I no longer use any kind of array whatsoever. getInputN doesn't bother tracking each individual entry, because all we care about is the final sum at the end.

Nathan Pierson
  • 5,461
  • 1
  • 12
  • 30
  • @daisy98 That sounds like an issue with your environment. Maybe [this question](https://stackoverflow.com/questions/22921297/codeblocks-c-build-permission-denied-collect2-exe) will help? – Nathan Pierson Jun 11 '21 at 15:36
  • Oh I got it! The error came from me, sorry. Thank you so much for helping me from the start :) Really appreciate it! – daisy98 Jun 11 '21 at 15:41