Search code examples
cstructmallocmembers

members of struct keeps printing when not called


I am now learning malloc and nested structs. I have one problem however. When I print out a member of a struct I also get other variables from another nested struct. The code below is what I have.

structs.h

struct course_info{
 char *name[20];
 int *course_id;
 int *count;
};

struct student_info{
  char *last[20];
  char *first[20];
  int *student_id;
  int count;
};

typedef struct gradebook_info{
 struct course_info course;
 struct student_info student;
}gradebook;

main.c

gradebook *info=NULL;
info=(gradebook *)malloc(sizeof(gradebook));

init(info);

in func.c

void init(gradebook *info)
{
    int i;

    info->course.course_id=(int *)malloc(sizeof(int));
    info->student.student_id=(int *)malloc(sizeof(int));

    for(i=0; i<20; i++)
        {
            info->course.name[i]=(char*)malloc(sizeof(char)*20);
            info->student.last[i]=(char*)malloc(sizeof(char)*20);
            info->student.first[i]=(char*)malloc(sizeof(char)*20);
        }

    info->course.count=0;
    info->student.count=0;

}
void addCourse(gradebook *info)
{
    int i, loop=0;

    printf("Enter Number of Courses: ");
    scanf("%d", &loop);

    for(i=0; i<loop; i++)
        {
            printf("Enter Course ID: ");
            scanf("%d", &info->course.course_id[info->course.count]);

            info->course.count++;
        }

}
void addStudent(gradebook *info)
{
    int i, loop=0;

    printf("Enter Number of Students: ");
    scanf("%d", &loop);

    for(i=0; i<loop; i++)
        {
            printf("Enter Student ID: ");
            scanf("%d", &info->student.student_id[info->student.count]);

            info->student.count++;
        }
}
void printCourse(gradebook *info)
{
    int i;

    if(info->course.count==0)
        printf("No Courses in Databse.\n");
    else
        {
            printf("Course ID\tCourse Name\n");

            for(i=0; i<info->course.count; i++)
                printf("%d\t\t%s\n", info->course.course_id[i], info->course.name[i]);
        }

}
void printStudent(gradebook *info)
{
    int i;

    if(info->student.count==0)
        printf("No Students in Database.\n");
    else
        {
            printf("Student ID\tLast Name\tFirst Name\n");

            for(i=0; i<info->student.count; i++)
                printf("%d\t\t%s\t\t%s\n", info->student.student_id[i], info-  >student.last[i], info->student.first[i]);
        }
}

When I add values to courses and students and call the print function for courses. Not only do I print all the members of the courses but also the members of students. I don't understand what is causing the memory leak and how to prevent it. Any help is appreciated.


Solution

  • As a suggestion, I'd use a structure setup like the following:

    typedef struct student_info{
        char last[20];
        char first[20];
        int student_id;
    } student;
    
    typedef struct course_info{
        char name[20];
        int course_id;
        int student_count;
        student* students;
    } course;
    
    typedef struct gradebook_info{
        int course_count;
        course* courses;
    }gradebook;
    

    A gradebook is composed of a number of courses. Each course holds its students.

    The program would look something like this:

    void createStudents(course *info)
    {
        int i;
    
        printf("Enter Number of Students in Course %d: ", info->course_id);
        scanf("%d", &info->student_count);
        info->students = malloc(sizeof(student)* info->student_count);
    
        for (i = 0; i<info->student_count; i++)
        {
            printf("Enter Student ID: ");
            scanf("%d", &info->students[i].student_id);
    
            // make sure printf doesn't run past end of name
            info->students[i].first[0] = '\0';
            info->students[i].last[0] = '\0';
    
        }
    }
    
    void createCourses(gradebook *info)
    {
        int i;
    
        printf("Enter Number of Courses: ");
        scanf("%d", &info->course_count);
    
        info->courses = malloc(sizeof(course)* info->course_count);
    
        for (i = 0; i < info->course_count; i++)
        {
            printf("Enter Course ID: ");
    
            scanf("%d", &info->courses[i].course_id);
            createStudents(&info->courses[i]);
    
            // make sure printf doesn't run past end of name
            info->courses[i].name[0] = '\0'; 
        }
    }
    
    
    void init(gradebook *info)
    {
        info->course_count = 0;
        createCourses(info);
    }
    
    void clear(gradebook *info)
    {
        int i;
        for (i = 0; i < info->course_count; i++)
        {
            free(info->courses[i].students);
        }
    
        free(info->courses);
    }
    
    void printStudents(course *info)
    {
        int i;
    
        if (info->student_count == 0)
            printf("No Students in Database.\n");
        else
        {
            printf("Student ID\tLast Name\tFirst Name\n");
    
            for (i = 0; i<info->student_count; i++)
                printf("%d\t\t%s\t\t%s\n", info->students[i].student_id, info->students[i].last, info->students[i].first);
        }
    }
    
    void printCourses(gradebook *info)
    {
        int i;
    
        if (info->course_count == 0)
            printf("No Courses in Database.\n");
        else
        {
            printf("Course ID\tCourse Name\n");
    
            for (i = 0; i < info->course_count; i++)
            {
                printf("%d\t\t%s\n", info->courses[i].course_id, info->courses[i].name);
                printStudents(&info->courses[i]);
            }
        }
    
    }
    
    int main()
    {
        gradebook *info = 0;
        info = (gradebook *)malloc(sizeof(gradebook));
    
        init(info);
        printCourses(info);
        clear(info);
        return 0;
    }
    

    and this is sample input/output:

    Enter Number of Courses: 2
    Enter Course ID: 1
    Enter Number of Students in Course 1: 2
    Enter Student ID: 100
    Enter Student ID: 101
    Enter Course ID: 2
    Enter Number of Students in Course 2: 3
    Enter Student ID: 123
    Enter Student ID: 456
    Enter Student ID: 789
    Course ID       Course Name
    1
    Student ID      Last Name       First Name
    100
    101
    2
    Student ID      Last Name       First Name
    123
    456
    789