Reputation: 186
I try to take the name and the code of students from a file and save it to a structure. The file look like this
6, student1
2, student2
9, student3
and here is my attempt. Can you tell me what is wrong in this code?
#include <stdio.h>
#include <stdlib.h>
#define N 20
struct Students {
char studentName[N];
int code;
};
void student() {
FILE *f = fopen("file.txt", "r");
struct Students *ptr;
int i;
ptr = malloc(sizeof(struct Students));
if (ptr == NULL){
printf("memory cannot be allocated");
exit(1);
}
if (f == NULL) {
printf("can't open the file");
exit(1);
}
i=0;
while (feof(f)) {
fscanf(f, "%d, %s\n", &(ptr+i)->code, &(ptr+i)->studentName);
ptr = realloc(ptr, sizeof(struct Students) * i);
i++;
}
}
int main() {
student();
return 0;
}
Upvotes: 1
Views: 87
Reputation: 303
i debugged your code, there was few problems that we will see them:
#include <stdio.h>
#include <stdlib.h>
#define N 20
struct Student { // 1- changed name from Students to Student
char name[N];
int code;
};
struct Student* student() {
FILE *f = fopen("file.txt", "r");
if (f == NULL) {
printf("can't open the file");
exit(1);
}
struct Student *ptr = NULL; // 2- initialize pointer with null
int i;
for(i=0; !feof(f); i++) { // 3- replace while with for and changed condition to !foef(f)
ptr = realloc(ptr, sizeof(struct Student) * (i+1)); // 4- allocate with size (i+1) because i is always size-1 and less than we need.
fscanf(f, "%d, %s\n", &ptr[i].code, ptr[i].name); // 5- changed syntax of accessing fields of structs
}
return ptr; // 6- return pointer to free it later and prevent memory leak
}
int main() {
struct Student* ptr = student();
// use it and free it
return 0;
}
explain:
studentCode
to code
because it is obvious that this code belongs to Student.for
for better code readability, and more importantly, our condition should be !feof(f)
because we want to read until the file ends.i
variable always contains last size, if we want to expand array, we should allocate memory with a size of i+1
..
operator instead of getting address and use ->
.last note: allocating 20 bytes for a char string isn't always safe and getting input with sscanf
could cause memory problems, you should consider using fgets
or getline
, because they are safe.
good luck.
Upvotes: 2
Reputation: 167
in the first reallocation allocated size is calculated by multiplying with i = 0, thus allocating size of 0. Also, studenName is already an address as it is an array, so the '&' before this variable is not needed.
It can be better written, but sticking with the original code a better version is:
i = 0;
while (!feof(f)) {
fscanf(f, "%d, %s\n", &(ptr+i)->code, (ptr+i)->studentName);
++i;
ptr = realloc(ptr, sizeof(struct Students) * (i+1));
}
Final point which is worth to note: performance-wise, realloc is a costly action. Consider allocating more than 1 allocation unit per loop cycle. Memory here is not nearly as expensive
Upvotes: 1