Reputation: 169
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
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
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