I created a struct of student
inside the function using malloc
and populated it with data. I want to return the address of the array of struct back to main
and print it line by line, but with my implementation, it is not printing. I debugged my code and indeed, it is able to return the address of my array to main
. I don't know why it's not printing though. Any thoughts?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct student Student;
struct student
{
char name[100];
int age;
char sex;
};
Student **getstudents(int n)
{
Student **t = malloc(sizeof *t * n); // memory for the array of pointers
for (int i = 0; i < n; i++) // memory for each individual pointer
{
t[i] = malloc(sizeof **t);
}
/* Data is inputted by user with form <student> <sex> <age>, then get mapped to the struct *t */
return t; /* Pointer to an array of pointers */
}
int main()
{
Student **students;
int n;
scanf("%d\n", &n);
students = getstudents(n);
for (int i = 0; i < n; i++)
{
printf("Name: %s, Sex: %s, Age: %d\n", students[i]->name, students[i]->sex, students[i]->age);
}
for (int i = 0; i < n; i++)
{
free(students[i]);
}
free(students);
return 0;
}
I am only allowed to modify the code in `Student **getstudents(int n)`.
In the line:
Student *t = (char*)malloc(sizeof(Student)*n);
You are allocating memory for one pointer, if you want to return a pointer to pointer, you need to allocate memory accordingly:
Student **t = malloc(sizeof *t * n); // memory for the array of pointers
for(int i = 0; i < n; i++){ // memory for each individual pointer
t[i] = malloc(sizeof **t);
}
To later free the pointers you also need to free each individual pointer previously allocated:
for(int i = 0; i < n; i++){ // memory for each individual pointer
free(students[i]);
}
free(students);
Note that the specifier for a single character is %c
, the printf will need to be corrected:
printf("Name: %s, Sex: %c, Age: %d\n", students[i]->name, students[i]->sex, students[i]->age);
// ^^
Another thing I would change is in strncpy
instead of null terminating the string later I would let the function do it:
// one more byte and strncpy terminates the string for you
strncpy(t[i]->name, data[0], strlen(data[0]) + 1);
// ^^^^
// already corrected for the new pointer
Having corrected the issues here is a possible alternative you can use to parse all the elements in the struct with sscanf
from entry
in one go, if you want to:
Student **getstudents(int n)
{
Student **t = malloc(sizeof *t * n); // memory for the array of pointers
if (t == NULL)
{
perror("malloc");
exit(EXIT_FAILURE);
}
for (int i = 0; i < n; i++) // memory for each individual pointer
{
t[i] = malloc(sizeof **t);
if (t[i] == NULL)
{
perror("malloc");
exit(EXIT_FAILURE);
}
}
for (int i = 0; i < n; i++)
{
char entry[100];
if (fgets(entry, sizeof entry, stdin))
{
if (sscanf(entry, "%25s %c %d", t[i]->name, &t[i]->sex, &t[i]->age) != 3)
{
// deal with bad input
}
}
}
return t;
}