Freeing memory of dynamic struct array - c

its me again :D
I have the following structs:
typedef struct
{
int day, month, year;
}date;
typedef struct
{
char name[15];
date birth;
int courses;
int *grades;
}student;
Thats how I allocated memory to each array:
printf("What is the number of students?\n");
scanf("%d", &size); //asking for size from user and creating 'size' number of structs
for (i = 0; i < size; i++) {
pData[i] = malloc(sizeof(student) * size);
}
........ //initializing char and birth
for (i = 0; i < size; i++) {
printf("\nPlease enter number of courses of student #%d:\n", i+1);
scanf("%d", &pData[i]->courses); //allocating memory for array of grades for each student (i)
pData[i]->grades = (int*)malloc(sizeof(int)*pData[i]->courses);
}
for (j = 0; j < size; j++) {
for (i = 0; i < pData[j]->courses; i++) {
printf("\nPlease enter grades of student #%d in course #%d\n", j+1, i+1);
scanf("%d", &pData[j]->grades[i]);
} //entering grades of each student
Now I am having troubles freeing the memory... Ive tried many ways but the program ends with an error everytime..
I've tried this method:
for (i = 0; i < size; i++) {
free(pData[i].grades);
}
free(pData);
pData = NULL;
Yet I still get errors...
EDIT: Thats how I declared on veriable pData:
student* pData = NULL;
Thats the function that initialize the array:
int initialize(student**);
Thats how I send the pData to the function:
size = initialize(&pData); //the function is suppose to return the size of the array.

You're not allocating space for pData properly. You do that once and assign it to *pData, not pData[i]. You have a pointer to a pointer, not an array of pointers.
printf("What is the number of students?\n");
scanf("%d", &size); //asking for size from user and creating 'size' number of structs
*pData = malloc(sizeof(student) * size);
You then need to reference it properly when reading data.
for (i = 0; i < size; i++) {
printf("\nPlease enter number of courses of student #%d:\n", i+1);
scanf("%d", &(*pData)[i].courses); //allocating memory for array of grades for each student (i)
(*pData)[i].grades = (int*)malloc(sizeof(int)*(*pData)[i].courses);
}
for (j = 0; j < size; j++) {
for (i = 0; i < (*pData)[j].courses; i++) {
printf("\nPlease enter grades of student #%d in course #%d\n", j+1, i+1);
scanf("%d", &(*pData)[j].grades[i]);
}
}
EDIT:
To further explain the syntax of how pData is being used, here are the datatype of each part of the relevant expressions.
pData: student **
*pData: student *
(*pData)[i]: student

Related

how can i solve segmentation error in terminal message?

I wrote a simple program to take names and numbers from the user and store it in an array, then compare between each cell until it reach the maximum grade then it displays it. The problem is that when it run it shows a message (segmentation fault (Core dump)). I really don't know what my mistake is.
#include <stdio.h>
int main() {
int n;
printf("Enter the number of students: ");
scanf("%d", & n);
char name[n];
float score[n];
for (int i = 0; i < n; i++) {
printf("\nEnter the name of Student: ");
scanf("%s", & name[i]);
printf("\nEnter the score: ");
scanf("%f", & score[i]);
}
float max;
int index;
max = score[0];
index = 0;
for (int i = 1; i < n; i++) {
if (max < score[i]) {
max = score[i];
index = i;
}
}
printf("\nHighest mark scored is %f by student %s", name[index], score[index]);
}
1- you use user input to define the size of an array (wrong)
-- array in c has static size so you must define it's size before the code reach the compiling stage(use dynamic memory allocation instead)
2- scanf("%s", & name[I]); you want to save array of char and save the address at the name variable but name it self not a pointer to save address it's just of char type (wrong)
-- you need pointer to save the address of every name so it's array of pointer and a pointer to allocate the address of the array to it so it's a pointer to poiner and define max size of word if you define size the user input exceed it will produce an error
3- finally you exchanged the %f,%s in printf
#include <stdlib.h>
#include <stdio.h>
#define SIZE_OF_WORD 10
int main() {
int n;
printf("Enter the number of students: ");
scanf("%d", & n);
char **name=(char**)malloc((sizeof(char*)*n));
for (int i = 0; i < n; i++) {
name[i]=(char*)malloc((sizeof(char)*SIZE_OF_WORD));
}
float *score=(float*)malloc((sizeof(float)*n));
for (int i = 0; i < n; i++) {
printf("\nEnter the name of Student: ");
scanf("%s", name[i]);
printf("\nEnter the score: ");
scanf("%f", & score[i]);
}
float max;
int index;
max = score[0];
index = 0;
for (int i = 1; i < n; i++) {
if (max < score[i]) {
max = score[i];
index = i;
}
}
printf("\nHighest mark scored is %s by student %.0f\n", name[index],score[index]);
}

Inputting errors in structure pointer code

#include <stdio.h>
typedef struct book
{
int bid;
char bname[50];
} bok;
typedef struct student
{
int roll;
char sec;
char name[50];
bok *issue;
} stud;
int main()
{
int n;
printf("enter no. of students\n");
scanf("%d", &n);
stud s[n];
printf("enter names,section and roll no. of %d students\n", n);
for (int i = 0; i < n; i++)
{
scanf("%s", &s[i].name);
scanf("%c", &s[i].sec);
scanf("%d", &s[i].roll);
}
int m, temp;
printf("enter no. of books\n");
scanf("%d", &m);
bok s1[m];
printf("enter book id and book names of %d books\n", m);
for (int i = 0; i < m; i++)
{
scanf("%d\n", &s1[i].bid);
scanf("%s\n", &s1[i].bname);
}
printf("assign book id to students.\n");
for (int i = 0; i < n; i++)
{
printf("assign id for roll %d\n", s[i].roll);
scanf("%d\n", s[i].issue);
}
int info;
printf("enter roll no. of student to get his/her information and book assigned to him\n ");
scanf("%d\n", &info);
for (int i = 0; i < n; i++)
{
if (s[i].sec == info)
printf("name:%s \nsection:%c \nbook assigned:%s\n", s[i].name, s[i].sec, *s[i].issue);
}
}
my code is not showing any compilation error but it does not give required output.my question is Create 2 two structure array Student and Book by the name S and B. And link the students with their respective books.
Print the books issued by a particular student.
Do not forget the brackets in order to assign user's input to the corresponding struct member:
for (int i = 0; i < n; i++)
{
scanf("%s", &(s[i].name));
scanf("%c", &(s[i].sec));
scanf("%d", &(s[i].roll));
}
and here you need to assign the input to bid, you cannot set an integer for book:
scanf("%d\n", &(s[i]->issue.bid));
or you wil get a segfault.

Array of structures not storing data as expected

I wrote the following code which is supposed to read an input, n = number of people, then create an array of structs the size of n, then read the info of each person and finally print all the info in order.
#include <stdio.h>
int main() {
int n;
scanf("%d", &n);
struct person {
char name[51];
int age;
};
struct person list[n];
int i;
for(i = 0; i < n; i++) {
scanf("%s", list[n].name);
scanf("%d", &list[n].age);
}
for(i = 0; i < n; i++) {
printf("Name: %s - Age: %d\n", list[i].name, list[i].age);
}
return 0;
}
So I compiled it using GCC on Ubuntu, executed and provided the following inputs:
1
Lucia
60
But instead of getting Name: Lucia - Age: 60 on the terminal, I'm getting Name: �rI�� - Age: 32766 which I believe is random trash in the computer's memory. I'm using the same treatment of arrays of structs I see in some web pages and in my college's material, so why doesn't it store the data properly?
Since you used i in your for loop, you should end up calling it as well in your scanfs not n. Change it to:
for(int i = 0; i < n; i++) {
scanf("%s", list[i].name);
scanf("%d", &list[i].age);
}
and this should do the trick!

Sort by using Structure's arrays

So I want to sort the list so that i can give them their position according to their grades but it's not working.
It is Showing error like : incompatible types when assigning to type char from type struct info.
p.s : I am trying to do this sorting using Structures.
#include <stdio.h>
#define SIZE 3
struct info {
char name[20];
int number;
double grade;
};
int main(void) {
struct info list[SIZE];
int i, j;
char temp;
int avg;
for (i = 0; i < SIZE; i++) {
printf("Enter your name : ");
scanf("%s", list[i].name);
printf("Enter your number : ");
scanf("%d", & list[i].number);
printf("Enter your grade : ");
scanf("%lf", & list[i].grade);
}
for (i = 0; i < SIZE; i++) {
printf("Name : %s Student Number : %d Grade : %f", list[i].name,
list[i].number, list[i].grade);
printf("\n");
}
for (i = 0; i < SIZE; i++) {
for (j = i + 1; j < SIZE; j++) {
if (list[j].grade > list[i].grade) {
temp = list[j];
list[j] = list[i];
list[i] = temp;
}
}
}
for (i = 0; i < SIZE; i++) {
printf("%d st Position : Name : %s Student Number : %d Grade : %f ",i,
list[i].name, list[i].number, list[i].grade);
printf("\n");
}
avg = 0;
for (i = 0; i < SIZE; i++)
avg += list[i].grade;
avg = avg / 3;
printf("Average is %d", avg);
getch();
return 0;
}
errors are in the following code:
for(i=0;i<SIZE;i++) {
for(j=i+1;j<SIZE;j++) {
if(list[j].grade>list[i].grade) {
temp=list[j];
list[j]=list[i];
list[i]=temp;
}
}
}
You assign a type char with name temp and try to assign a struct to it. Instead create a struct temp and then sort your array of structs.
#include <stdio.h>
#define SIZE 3
struct info { // use typedef struct info instead
char name[20];
int number;
double grade;
};
int main(void) {
struct info list[SIZE]; // allows you to write info list[size]
int i, j; // do not initialize loop variables outside of their loops unless you need to(makes it easier to read the loop statements/spot mistakes)
char temp; // you need to use a type info, not char e.g. info temp
I can not compile it myself at the moment, so please let us know in the comments if you have any further questions.

Why my program won't show each element with printf();?

I made a very tiny program which actually allows you to create N families with X members and when I try to display "ALL" members from all families I can't, it will only display last family members. Why and how to fix it?
.....................................................................................................................................................................
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
struct family {
int size;
struct person *member;
char address[256];
};
struct person {
int age;
char name[30];
};
int main(){
struct family *member;
struct person *ptr;
int j,k;
int i,n;
printf("\nEnter family count: ");
scanf("%d",&j);
for(k=0;k<j;k++){
member=(struct family*)malloc(j*sizeof(struct family));
printf("Enter family member count: ");
scanf("%d",&n);
ptr=(struct person*)malloc(n*sizeof(struct person));
for(i=0;i<n;++i){
printf("\nEnter person and the age:\n");
scanf("%s%d",&(ptr+i)->name, &(ptr+i)->age);
}
}
printf("\nDisplaying Infromation:\n");
for(i=0;i<n;++i)
printf("%s\t%d\t\n",(ptr+i)->name,(ptr+i)->age);
_getch();
return 0;
}
These lines:
for(k=0;k<j;k++){
member=(struct family*)malloc(j*sizeof(struct family));
make sure that only the last member is retained when the loop ends.
This line
ptr=(struct person*)malloc(n*sizeof(struct person));
makes sure that only the last ptr is retained when the loop ends.
What you need is something like:
int main(){
struct family *family_array = NULL;
int j,k;
int i,n;
printf("\nEnter family count: ");
scanf("%d",&j);
// Allocate memory for j families.
family_array = malloc(j*sizeof(struct family));
// Read the data for each family.
for(k=0;k<j;k++){
printf("Enter family member count: ");
scanf("%d",&n);
// Make sure to store the size of the family.
family_array[k].size = n;
// Allocate memory for the members of the family.
family_array[k].member = malloc(n*sizeof(struct person));
// Read the data for each member of the family.
for(i=0;i<n;++i){
printf("\nEnter person and the age:\n");
scanf("%s%d",family_array[k].member[i].name, &(family_array[k].member[i].age));
}
}
printf("\nDisplaying Infromation:\n");
for(k=0;k<j;k++)
{
n = family_array[k].size;
for(i=0;i<n;++i)
{
printf("%s\t%d\t\n", family_array[k].member[i].name, family_array[k].member[i].age);
}
}
// Make sure to deallocate the memory.
for(k=0;k<j;k++)
{
free(family_array[k].member);
}
free(family_array);
_getch();
return 0;
}
PS It will be good to add error checking code any time you use scanf. It's not a good practice to assume that the user always provides good input.
I fixed your code, the problems I found were
The first allocation, for the struct family *member is wrong, because it should be performed before the loop
member=(struct family*)malloc(j*sizeof(struct family));
for (k = 0 ; k < j ; k++) ...
You never use the allocated struct family *member; it should be used to store the members of the family, that's why I renamed it to family, so you have a member size in that struct, that's where scanf for the member count should store the value
printf("Enter family member count: ");
scanf("%d", &member[k].size);
now the value is stored at the size member so the next loop should go like
for (j = 0 ; j < member[k].size ; j++)
and the malloc, before the loop should be
member[k].member = malloc(member[k].size * sizeof(struct person));
Your scanf for the name is wrong, you should not take the address of the array
scanf("%s%d",&(ptr+i)->name, &(ptr+i)->age); -> scanf("%s%d",(ptr+i)->name, &(ptr+i)->age);
but according to the previously mentioned issues you should do it this way
scanf("%s%d", member[k].memberj].name, &member[k].member[j].age);
after all this is fixed you can output the data iterating over all member elements and all member->member elements.
Here is the fixed code
struct family
{
int size;
struct person *member;
char address[256];
};
struct person
{
int age;
char name[30];
};
int main()
{
struct family *family;
int familyCount, i, j;
printf("\nEnter family count: ");
scanf("%d", &familyCount);
family = malloc(familyCount * sizeof(*family));
for (i = 0 ; i < familyCount ; i++)
{
printf("Enter family member count: ");
scanf("%d", &family[i].size);
family[i].member = malloc(family[i].size * sizeof(*(family[i].member)));
for (j = 0 ; j < family[i].size ; ++j)
{
printf("\nEnter person and the age:\n");
scanf("%s%d", family[i].member[j].name, &family[i].member[j].age);
}
}
for (i = 0 ; i < familyCount ; ++i)
{
printf("Family %d:\n", 1 + i);
for (j = 0 ; j < family[i].size ; ++j)
printf("\tmember %d: %s, %d\n", 1 + j, family[i].member[j].name, family[i].member[j].age);
}
return 0;
}

Resources