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.
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
Related
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\n");scanf(" %[^\n]s", &student_array[i].name);
printf("Enter Grades\n");scanf("%f", &student_array[i].grades);
printf("Enter Points\n");scanf("%f", &student_array[i].points);
printf("Enter ID\n");scanf("%d", &student_array[i].id);
printf("Enter year\n");scanf("%d", &student_array[i].birth_date.year);
printf("Enter month\n");scanf("%d", &student_array[i].birth_date.month);
printf("Enter day\n");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\n", student_data[i]->name);
printf("average: %f\n", student_data[i]->grades);
printf("academic points: %f\n", student_data[i]->points);
printf("ID: %d\n", student_data[i]->id);
printf("birth year: %d\n", student_data[i]->birth_date.year);
printf("birth month: %d\n", student_data[i]->birth_date.month);
printf("birth day: %d\n", 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);
}
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\n");
scanf(" %[^\n]s", student_array[i].name);
printf("Enter Grades\n");
scanf("%f", &student_array[i].grades);
printf("Enter Points\n");
scanf("%f", &student_array[i].points);
printf("Enter ID\n");
scanf("%d", &student_array[i].id);
printf("Enter year\n");
scanf("%d", &student_array[i].birth_date.year);
printf("Enter month\n");
scanf("%d", &student_array[i].birth_date.month);
printf("Enter day\n");
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\n", student_data[i].name);
printf("average: %f\n", student_data[i].grades);
printf("academic points: %f\n", student_data[i].points);
printf("ID: %d\n", student_data[i].id);
printf("birth year: %d\n", student_data[i].birth_date.year);
printf("birth month: %d\n", student_data[i].birth_date.month);
printf("birth day: %d\n", 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).
I am trying to return a structure variable from the function, i created a function getInformation to get the data but i got an error said "Invalid operands to binary + (have 'struct student' and 'int')", What does it mean? and how can i fix it?
int main(){
struct student *s1;
int n;
printf("Enter how many data: ");
scanf("%d", &n);
s1 =(struct student *) malloc(n *sizeof(struct student));
if ( s1 == NULL)
{
printf("memory not available");
return 1; // exit(1); stlib.h
}
for(int i = 0; i < n; i++ )
{
printf("\nEnter details of student %d\n\n", i+1);
*s1 = getInformation();
}
}
struct student getInformation(struct student *s1,int i)
{
struct student s;
scanf("%d", (s+i)->age);
printf("Enter marks: ");
scanf("%f", (s+i)->marks);
return s;
}
Here is my structure
struct student {
int age;
float marks;
};
Reason for error :scanf("%d",(s+i)->age);. Here, s is not a pointer to structure. So, adding i gives you error, because both s and i are of different types ( s is of type struct student but i is of type int).
#include <stdio.h>
#include<stdlib.h>
struct student
{
int age;
float marks;
};
struct student getInformation(struct student *s1);
int main()
{
struct student *s1;
int n;
printf("Enter how many data: ");
scanf("%d", &n);
s1 = malloc(n * sizeof(struct student));
if (s1 == NULL)
{
printf("memory not available");
return 1; // exit(1); stlib.h
}
for (int i = 0; i < n; i++)
{
printf("\nEnter details of student %d\n\n", i + 1);
*(s1+i) = getInformation(s1+i); //Changed the function call
}
for(int i=0;i<n;i++)
{
printf("%d ",s1[i].age);
printf("%f ",s1[i].marks);
}
}
struct student getInformation(struct student *s1)
{
scanf("%d", &(s1->age));
printf("Enter marks: ");
scanf("%f", &(s1->marks));
return *s1;
}
The output is :
Enter how many data: 3
Enter details of student 1
23
Enter marks: 67
Enter details of student 2
34
Enter marks: 99
Enter details of student 3
24
Enter marks: 56
23 67.000000 34 99.000000 24 56.000000
I am learning structure and function and I'm trying to pass a pointer to structure as an argument. My code is to input student name,age and marks. This is my program
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
struct student {
char name[15];
int age;
double marks;
};
void display();
int main(){
struct student *s1;
s1 =(struct student *) malloc(sizeof(struct student));
for(int i=0; i<2; i++)
{
printf("\nEnter details of student %d\n\n", i+1);
printf("Enter name: ");
scanf("%s", s1->name);
printf("Enter age: ");
scanf("%d", &s1->age);
printf("Enter marks: ");
scanf("%f", &s1->marks);
}
display(&s1);
}
void display(struct student *s1){
printf("\nName\tAge\tMarks\n");
for(int i = 0; i<2;i++ )
{
printf("Name: %s",s1->name);
printf("\nAge: %d",s1->age);
printf("\nMarks: %.2lf",s1->marks);
}
}
the code runs but it gave a wrong outputs and garbage value. What did i do wrong?
There are several syntax error. I have included documentation in the code below.
Also, you are overwriting the content of s1 everytime when you are prompting user to input. Test it with two different data for example (name: "alex", age: 19, mark: 100.0 and name: "jason", age: 22, mark: 100.0) your program will output only the later.
To solve this, I would suggest you to allocate your student pointer before looping so that you have two distinct memory for each student and you wont overwrite them in this case.
Basically, each student struct is treated as an array and instead of s1->name you will dereference them as s1[i].name
display function declaration
void display(struct student *s1);
main function
int main()
{
int i;
struct student *s1;
s1 =(struct student *) malloc(sizeof(struct student) * 2); /* 2 = number of students */
for(i=0; i<2; i++)
{
printf("\nEnter details of student %d\n\n", i+1);
printf("Enter name: ");
scanf("%s", s1[i].name);
printf("Enter age: ");
scanf("%d", &s1[i].age);
printf("Enter marks: ");
scanf("%lf", &s1[i].marks); /* Instead of %f, it should be %lf */
}
display(s1); /* Instead of &, it should be s1 */
/* Free heap memory */
for(i=0; i<2; i++)
{
free(s1);
s1 = NULL;
}
return 0;
}
Display function, you need some modification in your display function as well
void display(struct student *s1)
{
int i;
printf("\nName\tAge\tMarks\n");
for(i = 0; i<2;i++ )
{
printf("%s\t",s1[i].name);
printf("%d\t",s1[i].age);
printf("%.2f\t",s1[i].marks); /* Instead of %.2lf, it should be %.2f */
printf("\n");
}
}
Struct for student
struct student
{
char name[15];
int age;
double marks;
};
I must create a program focusing on the use of structures.
The program will ask the user to enter the number of students for whom he will later add specific information (name, surname, average grade).
For some reason, when I start the the program, I enter the number of students i want, after that I enter the info of the first student and then the program terminates.
Here's what I've tried.
#include <stdio.h>
#include <stdlib.h>
struct student
{
char *name;
char *surname;
float *average;
};
void inputs(struct student *a, int size);
int main()
{
int size;
printf("Enter the number of students: ");
scanf("%d", &size);
struct student *data;
data = (struct student *)malloc(size*sizeof(struct student));
if(data==NULL) {
printf("Cannot allocate memory. The program will now terminate.");
return -1;
}
inputs (data, size);
return 0;
}
void inputs(struct student *a, int size)
{
int j=0;
int i;
for(i=0; i<size; i++) {
printf("Enter the name of the student number %d: ", j+1);
scanf("%s", a->name);
printf("Enter the surname of the student number %d: ", j+1);
scanf("%s", a->surname);
printf("Enter the average grade of the student number %d: ", j+1);
scanf("%f", a->average);
j++;
a++;
}
}
This code works:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct student
{
char name[30];
char surname[30];
float average;
};
void inputs(struct student *a, int size);
int main()
{
int size;
int i=0; // we need i
char string[100];
printf("Enter the number of students: ");
// scanf can be tricky lets use fgets
fgets( string , 99 , stdin );
size= atoi(string);
struct student **data; // array of struct
// get memory for the pointers to pointer
data=(struct student **) calloc( size , sizeof(char *));
// now each struct need space
for( i=0 ; i<size ; i++)
{
data[i] = malloc(sizeof(struct student));
if(data[i]==NULL) {
printf("Cannot allocate memory. The program will now terminate.");
return -1;
}// end if
}// end for loop
// input each student
for( i=0 ; i<size ; i++)
inputs (data[i], i );
return 0;
}
void inputs(struct student *a, int num)
{
int j=0;
char string[100];
// scanf can be tricky lets use fgets
printf("Enter the name of the student number %d: ", num+1);
fgets(a->name, 29, stdin);
printf("Enter the surname of the student number %d: ", num+1);
fgets( a->surname , 29, stdin);
printf("Enter the average grade of the student number %d: ", num+1);
fgets( string , 99, stdin);
a->average=atof(string);
}
I have been trying to allocate memory to the pointer variable but it keeps giving me errors or segmentation fault. How do i properly initialize the pointer variable to the course struct?
typedef struct {
char courseId[7];
char courseName[10];
} Course;
struct Student{
char firstName[10];
char lastName[10];
int studentId;
Course *course;
};
int main() {
int numStudents;
printf("How many students do you wish to register?: ");
scanf("%d", &numStudents);
struct Student *student[numStudents];
student[numStudents] = malloc(sizeof(*student[numStudents]));
student[numStudents]->course = malloc(sizeof*(numStudents * Course));
for (int i = 0; i < numStudents; i++) {
printf("Enter student #%d First Name: ", i+1);
scanf("%s", student[i]->firstName);
printf("Enter student Last Name: ");
scanf("%s", student[i]->lastName);
printf("Enter Student ID: ");
scanf("%d", &student[i]->studentId);
printf("Enter Course ID: ");
//student[i]->course = malloc(sizeof(*(student[i]->course)));
scanf("%s", student[i]->course->courseId);
printf("Enter Cousrse Name: ");
//student[i]->course = malloc(sizeof(*(student[i]->course)));
scanf("%s", student[i]->course->courseName);
}
for (int i = 0; i < numStudents; i++) {
printf("Student Name: %s %s\n", student[i]->firstName, student[i]->lastName);
printf("Student ID: %d\n", student[i]->studentId);
printf("Course Code: %s\n", student[i]->course->courseId );
printf("Course name: %s\n", student[i]->course->courseName);
free(student[i]->course);
}
You almost had it, there was a few corrections that needed to be made.
Course object in Student doesn't need to be a pointer. The array of Student structures need to be dynamically allocated then free'd later on. -> is used as a dereference operator but in your case [] is already dereferencing so you would use . instead of -> and when you allocate memory for the array of structures it needs to be the size of the structure multiplied by the number of structures. malloc(sizeof(struct Student)*numStudents);
typedef struct {
char courseId[7];
char courseName[10];
} Course;
struct Student{
char firstName[10];
char lastName[10];
int studentId;
Course course;
};
int main() {
int numStudents;
printf("How many students do you wish to register?: ");
scanf("%d", &numStudents);
struct Student* students = malloc(sizeof(struct Student)*numStudents);
for (int i = 0; i < numStudents; i++) {
printf("Enter student #%d First Name: ", i+1);
scanf("%s", students[i].firstName);
printf("Enter student Last Name: ");
scanf("%s", students[i].lastName);
printf("Enter Student ID: ");
scanf("%d", &students[i].studentId);
printf("Enter Course ID: ");
scanf("%s", students[i].course.courseId);
printf("Enter Cousrse Name: ");
scanf("%s", students[i].course.courseName);
}
for (int i = 0; i < numStudents; i++) {
printf("Student Name: %s %s\n", students[i].firstName, students[i].lastName);
printf("Student ID: %d\n", students[i].studentId);
printf("Course Code: %s\n", students[i].course.courseId );
printf("Course name: %s\n", students[i].course.courseName);
}
free(students);
return 0;
}
I tried to make minimal changes to your code.