I create a dynamic int
array and I read from a file numbers and passing them in the array using malloc
and realloc
, when the while in the function is finished the printing is correct but when I go back to the main
after the function readNames
the printf
prints addresses instead of the values.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void readNames(FILE *, int *, char **, int *);
void readNames(FILE *fpN, int *numbers, char **names, int *total){
char sentence[512];
while (fgets(sentence, sizeof(sentence), fpN)){
char *token = strtok(sentence, " "); //grab the number
numbers[*total] = atoi(token); //add it to the array
token = strtok(NULL, " \n");
//names[*total] = malloc(strlen(token) 1);
//strcpy(names[*total], token);
(*total) ;
// printf("TOTAL:%d",*total);
numbers = (int*)realloc(numbers,*(total 1)*sizeof(int)); //allocate more space for the int array
//names = (char**)(realloc(names, (*total 1)*sizeof(char*)));
//printf("%d", sizeof(names));
//allocate more space for the string array
}
printf("%d ", (*(numbers 2)));
printf("%d ", (numbers[1]));
printf("%d ", (numbers[2]));
}
int main(int argc, char **argv){
FILE *fpN = NULL;
FILE *fpG = NULL;
if(argc!=3){
printf("Wrong arguments");
exit(0);
}
if ((fpN = fopen(argv[1], "r")) == NULL)
{ // check if the file exists
printf("File not found!");
exit(0);
}
if ((fpG = fopen(argv[2], "r")) == NULL)
{ // check if the file exists
printf("File not found!");
exit(0);
}
int total = 0;
int *numbers = (int*)malloc(sizeof(int)); //array will initially have 1 element
char **names = (char**)malloc(sizeof(char*));
readNames(fpN, numbers, names, &total);
printf("%d ", (numbers[0]));
printf("Enter");
printf("%d ", (numbers[1]));
printf("%d ", (numbers[2]));
printf("Enter");
// char sentence[512];
// int diagram[total][total];
// memset(diagram, 0 , sizeof(diagram));
// while (fgets(sentence, sizeof(sentence), fpG)){
// char *token = strtok(sentence, " ->\n:\n");
// int row = atoi(token);
// while(token = strtok(NULL, " ->\n:\n")){
// int col = atoi(token);
// diagram[row][col] = atoi(strtok(NULL, " ->\n:\n"));
// }
// }
}
CodePudding user response:
You are passing your pointers "by value", that means a copy of the current value is passed to the function. Whatever you do to that copy inside your function, will be lost once you return from the function.
Furthermore the allocated memory you passed, may be invalid after calling realloc
.
Instead of passing your pointers, you must pass the addresses of your pointer variables:
(Also note a fixed typo in the size used for realloc
).
void readNames(FILE *fpN, int **numbers, char ***names, int *total){
char *my_numbers = *numbers;
char **my_names = *names;
char sentence[512];
while (fgets(sentence, sizeof(sentence), fpN)) {
char *token = strtok(sentence, " "); //grab the number
my_numbers[*total] = atoi(token); //add it to the array
token = strtok(NULL, " \n");
//my_names[*total] = malloc(strlen(token) 1);
//strcpy(my_names[*total], token);
(*total) ;
// printf("TOTAL:%d",*total);
my_numbers = realloc(my_numbers, (*total 1)*sizeof(int)); //allocate more space for the int array
//my_names = realloc(my_names, (*total 1)*sizeof(char*));
//printf("%zu", sizeof(my_names)); // << this will only print size of a pointer.
//allocate more space for the string array
}
// Copy local pointers back to caller's variables
*numbers = my_numbers;
*names = my_names;
printf("%d ", (*(numbers 2)));
printf("%d ", (numbers[1]));
printf("%d ", (numbers[2]));
}
Then update your caller:
int total = 0;
int *numbers = malloc(sizeof(int)); //array will initially have 1 element
char **names = malloc(sizeof(char*));
readNames(fpN, &numbers, &names, &total);
You could improve that code a bit more:
- You allocate memory for next element in advance. That means you have 1 unused element allocated. You could initialize your pointers to
NULL
and onlyrealloc
when you found a new line to parse. - Unless you have a specific need to handle the 2 arrays you pass, separately, it would be better to create a struct for both values and pass only one pointer to an array of these structs.
With these 2 changes your code would look like this:
struct element {
int number;
char *name;
};
void readNames(FILE *fpN, struct elemen **elements, int *total){
struct element *my_elements = *elements;
char sentence[512];
while (fgets(sentence, sizeof(sentence), fpN)) {
my_elements= realloc(my_elements, (*total 1) *sizeof(*my_elements)); //allocate space for the new entry
char *token = strtok(sentence, " "); //grab the number
my_elements[*total].number = atoi(token); //add it to the array
token = strtok(NULL, " \n");
//my_elements[*total].name = malloc(strlen(token) 1);
//strcpy(my_elements[*total].name, token);
(*total) ;
// printf("TOTAL:%d",*total);
}
// Copy local pointer back to caller's variable
*elements= my_elements;
printf("%d ", my_elements[1].number);
printf("%d ", my_elements[2].number);
}
and the caller:
int total = 0;
struct element *elements = NULL; // Allcation will be done later
readNames(fpN, &elements, &total);