简体   繁体   中英

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?

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! :(

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);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM