2

I keep getting this error when I try to pass this array of structures into the function AthleticContest():

cannot convert 'person' to 'person*'

Can someone please tell me what I am doing wrong? Am I passing the wrong thing into the function?

struct person
{
    int athletic;
    int smarts;
    int spirit;
    int contestVal;
};

int AthleticContest(person subjects[])
{
     cout << "Athletic Contest!!!" << endl << endl;
     for (int hh = 0; hh < 3; hh++)
     {
         int result = subjects[hh].athletic;
         subjects[hh].contestVal = result;
         cout << "Contestant # " << (hh+1) << ") " << subjects[hh].contestVal  << endl;
     }
     int winner;
     int tempWin = -1;
     for (int hh = 0; hh < 3; hh++)
     {
        if (subjects[hh].contestVal > tempWin)
        {
            tempWin = subjects[hh].contestVal;
            winner = hh;
        }
        else if (subjects[hh].contestVal == tempWin)
        {
            if (randomInt() > 4)
                winner = hh;
        }
    }
    cout << "Winner is Contestant # " << (winner+1)   << endl;

    return winner;
}

int main()
{
    person subject[10];

    subject[0].athletic = 5;
    subject[0].smarts   = 3;
    subject[0].spirit   = 1;
    subject[1].athletic = 1;
    subject[1].smarts   = 3;
    subject[0].spirit   = 5;
    subject[1].athletic = 3;
    subject[1].smarts   = 5;
    subject[0].spirit   = 1;

    AthleticContest(subject[2]);
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
CuriousGuy
  • 47
  • 4
  • This would be much simpler if you just used `std::array` or `std::vector` rather than C-style arrays. – Jesper Juhl Aug 25 '18 at 18:02
  • What are you trying to achieve? You declare an array of size **ten**, but your `AthleticCode` function only uses the first **three** elements of your array, and your main function only initializes the first **two** elements of your array. See the problem? It's not possible to advise unless you make it clear what you want. – john Aug 25 '18 at 18:29
  • @CuriousGuy If any answer helped you any then you can vote/accept so others could find it too. This is how the website is maintained – Geezer Aug 26 '18 at 04:30
  • @CuriousGuy See here: https://stackoverflow.com/help/someone-answers – Geezer Aug 26 '18 at 09:41

2 Answers2

5

The error

When you call your function in main():

    AthleticContest(subject[2]);

you pass as argument a single person, which is the third element of your array (the element with index 2). So the compiler understands that you try to pass this object of type person.

But your function's parameter is declared to be of type array of undetermined size (i.e. person[]). C++ treats such array arguments as if they were a pointer (to their first element), so like person*.

This is why you get this error message: these types are incompatible

The solution

To get rid of this error, a solution would be to pass a pointer to a subject, for example:

    AthleticContest(&subject[2]);  // passes the pointer to the third element
    // or 
    AthleticContest(subject);  // passes the pointer to the first element of the original array

However, be very careful, because your function has a very risky design: you expect the argument to be a pointer to an array of at least 3 consecutive elements. So if you call it with &subject[8], it would try to access subject[10] which would be out of bounds. If you'd call with &subject[2] it would work with garbege information, since you have initalized only the first two elements, and not the 3rd, 4th and 6th.

A better solution

It is not clear, why you do the constest just with 3 elements. A better option would be the caller to say how many contestant shall be used (the caller know the size of the array).

In main():

    AthleticContest(subject, 2);  // 2 is the number of contestants in array

Your function would be defined as:

int AthleticContest(person subjects[], int participants)
{
     cout << "Athletic Contest!!!" << endl << endl;
     for (int hh = 0; hh < participants; hh++)
     ... 
     for (int hh = 0; hh < participants; hh++)
     ...
}

A much better solution

You'd better go for std::vector instead of C++ arrays. They can behave like arrays:

    vector<person> subject(2);  // create a vector of 2 items
    subject[0].athletic = 5;
    ...

But they are much more convenient because they can have a dynamic size and grow as you add new participants:

    person hbolt = {4, 2, 1, 0}; 
    subject.emplace_back (hbolt);   // one more participant
    AthleticContest(subject);

Your function could get the vector by reference or by value. Let's take by reference, since you intend to modify its content and could possibly want this modified data after the return:

int AthleticContest(vector<person> &subjects)
{
    ...
}

The big advantage, is that you can always know the size of the vector:

for (int hh = 0; hh < subjects.size(); hh++)
...

Here is an online demo.

Of course, if you don't want to take all the participants in the vector, you'd have to think about your function's argument(s): would you prefer a second argument n and always take the n first elements of the vector ? Or would you prefer n participants but start at an arbitrary offset ? In both case, you'd be wise to check that your indexing never goes out of bounds.

Christophe
  • 68,716
  • 7
  • 72
  • 138
0

One thing you need to change to compile: You're passing a reference to a single element of the array instead of the array itself.

One more thing you might want to check is to change your signature for AthleticContest() so it'll be the right one in C++ to receive fixed-sized array or person as a parameter.

When fixed to compile, and you're code looks like this:

#include <iostream>

using namespace std;

struct person
{
    int athletic;
    int smarts;
    int spirit;
    int contestVal;
};

template <std::size_t size>
int AthleticContest(person (&subjects)[size])
{
    cout << "Athletic Contest!!!" << endl << endl;
     for (int hh = 0; hh < 3; hh++)
     {
         int result = subjects[hh].athletic;
         subjects[hh].contestVal = result;
         cout << "Contestant # " << (hh+1) << ") " << subjects[hh].contestVal  << endl;
     }
     int winner;
     int tempWin = -1;
     for (int hh = 0; hh < 3; hh++)
     {
        if (subjects[hh].contestVal > tempWin)
            {
             tempWin = subjects[hh].contestVal;
             winner = hh;
            }
            else if (subjects[hh].contestVal == tempWin)
            {
             if (5 > 4)
             winner = hh;
            }
      }
        cout << "Winner is Contestant # " << (winner+1)   << endl;

    return winner;
}

int main()
{
    person subject[10];

    subject[0].athletic = 5;
    subject[0].smarts   = 3;
    subject[0].spirit   = 1;
    subject[1].athletic = 1;
    subject[1].smarts   = 3;
    subject[0].spirit   = 5;
    subject[1].athletic = 3;
    subject[1].smarts   = 5;
    subject[0].spirit   = 1;

    AthleticContest(subject);
}
Geezer
  • 5,600
  • 18
  • 31
  • It's pretty clear that's not what the OP is asking for. He wants to slice his array of size 10 and only pass the first two elements. – john Aug 25 '18 at 18:25
  • @john terribly sorry, didn't get that. where is it showing that this is what he's asking? – Geezer Aug 25 '18 at 18:28
  • Actually what I want to do is pass the array of the structure to the function. – CuriousGuy Aug 25 '18 at 18:31
  • Well I'll admit it's not totally clear, but his function (and also your version of it) is only accesses the first three elements of his array. – john Aug 25 '18 at 18:32
  • @CuriousGuy OK friend then I believe this answer gives you the solution. Let me know how it plays out : ) – Geezer Aug 25 '18 at 18:33
  • @john it's hardly *my function* as you're calling it -- I just serve the OP's code and answer his issue. His function, and now it does what he intended and compiles. – Geezer Aug 25 '18 at 18:35
  • @CuriousGuy Well if you wanted to pass the whole array what made you put `[2]` in `AthleticContest(subject[2]);`. Serious question, trying to understand. – john Aug 25 '18 at 18:35
  • @CuriousGuy Don't feel stupid! Small mistakes like this are nothing. Keep on coding! Glad to help. – Geezer Aug 25 '18 at 18:36
  • Thanks for the assist. – CuriousGuy Aug 25 '18 at 18:39
  • @CuriousGuy I have to apologize as the text before just editing wasn't fully accurate. I believe now it is so feel free to let me know what you think – Geezer Aug 25 '18 at 18:48