How to return struct array from function

Been browsing various forums, can't find anything that would explain on how could I return struct array from function.

Basically I need to sort out the results sheep[].coeff and sheep[].name from biggest to smallest and if numbers are the same alphabetically by name. And I need to make a separate function for that and as I said I can't figure out how to return the values from function matchingCoeff.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
  #include <iostream>
#include <fstream>

using namespace std;

struct genes{ // structure to save subjects data
    string name;
    char DNR[20];
    int coeff=0;
};

void matchingCoeff(struct genes sheep[], int n, int m ,int e){ // function to calculate genes matching coefficient
    for (int i=0; i<n; i++){
        if (i!=e-1){ // skipping the sheep to which others are being compared to
            for (int j=0; j<m; j++){
                if (sheep[e-1].DNR[j]==sheep[i].DNR[j]){ // comparing DNR fragments
                    sheep[i].coeff++; // adding 1 if DNR fragments match
                }
            }
        }
    }
    
    rez << sheep[e-1].name << endl; // print the sheep to which others are being compared to
    for (int i=0; i<n; i++){
        if (i!=e-1){ // skipping the sheep to which others are being compared to again
            rez << sheep[i].name << " " << sheep[i].coeff<< endl; // printing out results
        }
    }


}

int main()
{
    genes sheep[20]; // struct variable for sheep
    ifstream duom ("U2.txt"); // input to file
    ofstream rez ("U2rez.txt"); // output to file
    int n; // amount of sheeps
    int m; // length of DNR fragment
    int e; // sheep to which others are being compared to
    duom >> n; 
    duom >> m; 
    duom >> e; 
    for (int i=0; i<n; i++){ // reading data from file
        duom>>sheep[i].name;
        for (int j=0; j<m; j++){
            duom>>sheep[i].DNR[j];
        }
    }

    matchingCoefi(sheep, n, m, e);

    duom.close();
    rez.close();
    return 0;
}
C++ does not "pass array parameter by value" as in "make a local copy".
Only the address of the first element is passed to function.
As result, the function does modify the array of the caller:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// arrays example
#include <iostream>

void modify( int* arr )
{
  if ( arr ) arr[0] += 42;
}

int main ()
{
  int data [] {16, 2, 77, 40, 12071};
  modify( data );
  std::cout << data[0] << '\n';  // prints 58
}

Therefore, there is no need to "return an array".
wuwy wrote:
how could I return struct array from function

When a C-style array is passed as an argument to a function, it decays to a pointer:
https://en.cppreference.com/w/cpp/language/array#Array-to-pointer_decay

So I don’t think there’s any differences between
1
2
3
void myfunction ( int myarr[] );
           and
void myfunction ( int* myarr );


In both cases you probably want to pass the array size as an additional parameter.

Even if you don’t need to return a C-style array that has been modified by a function, you can do it: just return a pointer of the desired type:

1
2
3
4
double* myfunction ( double myarr[] )
{
    return myarr;
}


Just remember what you get is another pointer to the same memory area.
Here’s an example - I couldn’t test it because you didn’t provide any example of your data, but I hope it works.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include <iostream>
#include <fstream>


// Structure to save subjects data:
struct genes {
    std::string name;
    char dnr[20]; // if you can use std::strings, why do you use C-style arrays?
    int coeff {};
};


genes* matchingCoeff(genes* sheep, int size, int dnr_len, int sample);


int main()
{
    constexpr int Max_Sheeps { 20 };    // let's avoid magic numbers
    genes sheep[Max_Sheeps];

    std::ifstream duom ("U2.txt");
    // TODO: check if 'duom' has been correctly opened

    int sheep_num;              // amount of sheeps
    duom >> sheep_num;

    int dnr_length;              // length of DNR fragment
    duom >> dnr_length;

    int specimen;                // sheep to which others are being compared to
    duom >> specimen;

    // Reading data from file:
    for (int i = 0; i < sheep_num; ++i) {
        duom >> sheep[i].name;
        for (int j = 0; j < dnr_length; ++j) {
            duom >> sheep[i].dnr[j];
        }
    }

    genes* sheeps2 { matchingCoeff (sheep, sheep_num, dnr_length, specimen) };
    for (int i {}; i < sheep_num; ++i) {
        std::cout << sheeps2[i].name << ' ' << sheeps2[i].coeff << '\n';
    }

    duom.close();
    return 0;
}


// Function to calculate genes matching coefficient:
genes* matchingCoeff(genes* sheep, int size, int dnr_len, int sample)
{
    // Calculate coefficients:
    for (int i = 0; i < size; ++i) {

        // Skip the sheep to which others are being compared to:
        if (i == sample - 1 ) { continue; }

        for (int j = 0; j < dnr_len; ++j) {
            if (sheep[sample - 1].dnr[j] == sheep[i].dnr[j]) {
                ++sheep[i].coeff;
            }
        }
    }

    // Printing out results:
    std::ofstream rez ("U2rez.txt"); // output to file
    // TODO: check if 'rez' has been correctly opened

    // Print the sheep to which others are being compared to
    rez << sheep[sample - 1].name << '\n';

    // Print all the others:
    for (int i = 0; i < size; ++i) {

        // Skip the sheep to which others are being compared to again:
        if (i == sample - 1 ) { continue; }

        rez << sheep[i].name << ' ' << sheep[i].coeff << '\n';
    }

    return sheep;
}

When a C-style array is passed as an argument to a function, it decays to a pointer:

In both cases you probably want to pass the array size as an additional parameter.

Even if you don’t need to return a C-style array that has been modified by a function, you can do it: just return a pointer of the desired type:

Honestly I didn't learn pointers, kinda hoped that I could skip them. But I guess I will have to take a look today.

I will try out your program, but I won't be able to use it as its a little bit too advanced for what I do. But thanks anyway.
If you want to pass arrays around the same way you do with other objects you can use std::array (or std::vector if the number of elements can vary).

https://en.cppreference.com/w/cpp/container/array
https://en.cppreference.com/w/cpp/container/vector
With object parameters one has by value and by reference (&):
1
2
3
4
5
void func( genes[] sheep, int size );    // will access caller's array
void func( std::vector<genes>& sheep ); // will access caller's vector
void func( const genes[] sheep, int size );    // will access caller's array read-only
void func( const std::vector<genes>& sheep ); // will access caller's vector read-only
void func( std::vector<genes> sheep );  // gets a deep copy 
Topic archived. No new replies allowed.