Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
265 views
in Technique[技术] by (71.8m points)

pointers - c Dynamic allocation of struct array

I have an assignment of dynamic allocation for an array of structs. I'm having trouble to understand/explain why I need pointer to pointer and not like with regular array only pointer, Maybe someone can explain? The code as following i added the whole code including main function.

struct Date {
    int year;
    int month;
    int day;
};

struct Student {
    char name[100];
    float grades;
    float points;
    int id;
    struct Date birth_date;
};

struct Student** get_student_data(int* number_of_student)
{
    printf("how many students in your class? ");
    scanf("%d", number_of_student);

    struct Student** student_pointers_array = malloc(sizeof(struct Student*) * *number_of_student);
    if (student_pointers_array == NULL)
        return;
    struct Student* student_array = malloc(sizeof(struct Student) * *number_of_student);
    if (student_array == NULL)
        return;
    for (int i = 0; i < *number_of_student; i++)
    {
        printf("Enter Name
");scanf(" %[^
]s", &student_array[i].name);
        printf("Enter Grades
");scanf("%f", &student_array[i].grades);
        printf("Enter Points
");scanf("%f", &student_array[i].points);
        printf("Enter ID
");scanf("%d", &student_array[i].id);
        printf("Enter year
");scanf("%d", &student_array[i].birth_date.year);
        printf("Enter month
");scanf("%d", &student_array[i].birth_date.month);
        printf("Enter day
");scanf("%d", &student_array[i].birth_date.day);
        student_pointers_array[i] = &student_array[i];
    }

    return student_pointers_array;
}
void print_student_data(struct Student** student_data, int number_of_student)
{
    for (int i = 0; i < number_of_student; i++)
    {
        printf("name: %s
", student_data[i]->name);
        printf("average: %f
", student_data[i]->grades);
        printf("academic points: %f
", student_data[i]->points);
        printf("ID: %d
", student_data[i]->id);
        printf("birth year: %d
", student_data[i]->birth_date.year);
        printf("birth month: %d
", student_data[i]->birth_date.month);
        printf("birth day: %d
", student_data[i]->birth_date.day);
    }
}

void main()
{
    int number_of_student = 0;
    struct Student** student_data = get_student_data(&number_of_student);
if (student_data == NULL)
        return;
    print_student_data(student_data, number_of_student);
    free(student_data);
}


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You don't need to use struct Student ** — you can use a single level of pointers, like this:

#include <stdio.h>
#include <stdlib.h>

struct Date
{
    int year;
    int month;
    int day;
};

struct Student
{
    char name[100];
    float grades;
    float points;
    int id;
    struct Date birth_date;
};

static
struct Student *get_student_data(int *number_of_student)
{
    printf("how many students in your class? ");
    scanf("%d", number_of_student);

    struct Student *student_array = malloc(sizeof(struct Student) * *number_of_student);
    if (student_array == NULL)
        return NULL;
    for (int i = 0; i < *number_of_student; i++)
    {
        printf("Enter Name
");
        scanf(" %[^
]s", student_array[i].name);
        printf("Enter Grades
");
        scanf("%f", &student_array[i].grades);
        printf("Enter Points
");
        scanf("%f", &student_array[i].points);
        printf("Enter ID
");
        scanf("%d", &student_array[i].id);
        printf("Enter year
");
        scanf("%d", &student_array[i].birth_date.year);
        printf("Enter month
");
        scanf("%d", &student_array[i].birth_date.month);
        printf("Enter day
");
        scanf("%d", &student_array[i].birth_date.day);
    }

    return student_array;
}

static
void print_student_data(struct Student* student_data, int number_of_student)
{
    for (int i = 0; i < number_of_student; i++)
    {
        printf("name: %s
", student_data[i].name);
        printf("average: %f
", student_data[i].grades);
        printf("academic points: %f
", student_data[i].points);
        printf("ID: %d
", student_data[i].id);
        printf("birth year: %d
", student_data[i].birth_date.year);
        printf("birth month: %d
", student_data[i].birth_date.month);
        printf("birth day: %d
", student_data[i].birth_date.day);
    }
}

int main(void)
{
    int number_of_student = 0;
    struct Student* student_data = get_student_data(&number_of_student);
    if (student_data != NULL)
    {
        print_student_data(student_data, number_of_student);
        free(student_data);
    }
    return 0;
}

This simplifies the memory release, too. The code in the question leaks the array of structures (it only frees the array of pointers).


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...