mbistato
mbistato

Reputation: 169

How to make a function return a pointer to array struct

I'm working on a function in C that should return a pointer to an array struct. The struct is

struct corr{
  char nome[128];
  char cognome[128];
  char password[10];
  float importo;
};
typedef struct corr correntista;

The function that return a pointer to this struct is

correntista *max_prelievo(FILE *fcorrentisti, FILE *fprelievi){
    correntista *corr_max[2];
    corr_max[0] = (correntista *)malloc(sizeof(correntista));
    corr_max[1] = (correntista *)malloc(sizeof(correntista));
    /*.........*/
    return *corr_max;
}

In the main program I want to print the returned value in the following way:

*c_max = max_prelievo(fc, fp);
printf("Correntista con max prelievi:\n");
printf("Nome: %s\n", c_max[0]->nome);
printf("Cognome: %s\n", c_max[0]->cognome);
printf("Max prelievo: %f\n\n", c_max[0]->importo);

printf("Correntista con max versamenti:\n");
printf("Nome: %s\n", c_max[1]->nome);
printf("Cognome: %s\n", c_max[1]->cognome);
printf("Max versamento: %f\n", c_max[1]->importo);

but only the first struct c_max[0] has the expected value. c_max[1] has garbage values. What should I change in my program?

Upvotes: 1

Views: 108

Answers (2)

autistic
autistic

Reputation: 15642

There are several solutions, but they all require an overhaul of how your function is to operate. Perhaps the best solution is to consider how scanf works; It returns no objects, instead it operates solely on objects that are pointed to by parameters passed to it. Hence:

void max_prelievo(correntista *corr_max, FILE *fcorrentisti, FILE *fprelievi){
    /* NOTE: You should make a habit of separating your allocation from this logic;
     *       it makes debugging and testing so much easier... */

    corr_max[0] = (correntista) { .nome = "Michael",
                                  .cognome = "Anderson",
                                  .importo = 42.0 };

    corr_max[1] = (correntista) { .nome = "Undefined",
                                  .cognome = "Behaviour",
                                  .importo = -1.0 };


    /*.........*/
}

int main(void) {
    correntistia c_max[2] = { 0 };
    FILE *f1 = fopen(...), *f2 = fopen(...);

    max_prelievo(c_max, f1, f2);

    printf("Correntista con max prelievi:\n");
    printf("Nome: %s\n", c_max[0].nome);
    printf("Cognome: %s\n", c_max[0].cognome);
    printf("Max prelievo: %f\n\n", c_max[0].importo);

    printf("Correntista con max versamenti:\n");
    printf("Nome: %s\n", c_max[1].nome);
    printf("Cognome: %s\n", c_max[1].cognome);
    printf("Max versamento: %f\n", c_max[1].importo);
}

What scanf does return is a single integer, indicating success. Perhaps, if you are to use return values in the future, you could resort to using a similar pattern? Look at the bright side: There's no malloc or free here and no chance you could leak any memory; the code is as simple as it could possibly get.


Alternatively, as horrific as it seems, if you must resort to using such a pattern then less calls to malloc will serve you well. Consider something like this:

correntista *max_prelievo(FILE *fcorrentisti, FILE *fprelievi) {
    correntista *corr_max = malloc(2 * sizeof *corr_max);

    corr_max[0] = (correntista) { .nome = "Michael",
                                  .cognome = "Anderson",
                                  .importo = 42.0 };

    corr_max[1] = (correntista) { .nome = "Undefined",
                                  .cognome = "Behaviour",
                                  .importo = -1.0 };

    /*.........*/

    return corr_max;
}

The main entry point will be almost identical to the example I gave earlier... except for one thing: Don't forget to free that memory! :(

Upvotes: 2

Gopi
Gopi

Reputation: 19874

Remember what you have is array of pointers so when you exit the function the array is out of scope. Have a pointer to pointer for this purpose as shown below.

correntista **max_prelievo(FILE *fcorrentisti, FILE *fprelievi){
    correntista **corr_max = malloc(sizeof(correntista *) * 2);
    corr_max[0] = malloc(sizeof(correntista));
    corr_max[1] = malloc(sizeof(correntista));
    /*.........*/
    return corr_max;
}

The call should be

correntista **c_max = max_prelievo(fc, fp);

Upvotes: 1

Related Questions