Writing an array of structs to a binary file in C
Solution 1
struct Person* people;
This allocates just a pointer to struct, but you don't have any allocated space for actual struct contents. Either use malloc
similarly to your write program, or try something like:
struct Person people;
fread(&people, sizeof(people), 1, data);
Solution 2
You need to allocate memory for the person first. Change: struct Person* people;
into struct Person* people = malloc(sizeof(struct Person));
. And don't forget to free your memory at the end: free(people);
.
Solution 3
You either need to malloc
memory into the pointer variable people
before you do the fread
, or (easier) just read directly into a local variable:
struct Person people;
fread(&people, sizeof(struct Person) * 1/* Just read one person */, 1, data);
Solution 4
You need to allocate space for the data you are reading in:
people = malloc(sizeof(*people)*numPeople);
John Jacquay
Updated on December 09, 2020Comments
-
John Jacquay over 3 years
I have an array of structs I would like to write to a binary file. I have a write.c program and a read.c program. The write.c program seems to be working properly but when I run the read.c program I get a segmentation fault. I'm new to C so It would be great if someone could look over my code for any obvious errors. I promise it's not too long :)
write.c:
#include <stdlib.h> #include <stdio.h> struct Person { char f_name[256]; char l_name[256]; int age; }; int main(int argc, char* argv[]) { struct Person* people; int people_count; printf("How many people would you like to create: "); scanf("%i", &people_count); people = malloc(sizeof(struct Person) * people_count); int n; for (n = 0; n < people_count; n++) { printf("Person %i's First Name: ", n); scanf("%s", people[n].f_name); printf("Person %i's Last Name: ", n); scanf("%s", people[n].l_name); printf("Person %i's Age: ", n); scanf("%i", &people[n].age); } FILE* data; if ( (data = fopen("data.bin", "wb")) == NULL ) { printf("Error opening file\n"); return 1; } fwrite(people, sizeof(struct Person) * people_count, 1, data); fclose(data); return 0; }
read.c:
#include <stdlib.h> #include <stdio.h> struct Person { char f_name[256]; char l_name[256]; int age; }; int main(int argc, char* argv[]) { FILE* data; if ((data = fopen("data.bin", "rb")) == NULL) { printf("Error opening file\n"); return 1; } struct Person* people; fread(people, sizeof(struct Person) * 1/* Just read one person */, 1, data); printf("%s\n", people[0].f_name); fclose(data); return 0; }
Thanks for the help!
-
Steve Townsend over 13 yearsThis seems more extensible once OP decides to read > 1 element. Could loop on a single local variable instead.
-
John Jacquay over 13 yearsCan you explain when the (struct Person*) means before the malloc(sizeof(struct Person))? Is that a cast?
-
Przemek Kryger over 13 years@jjacquay712 Yes it is. I just like to not relay too much on default compiler options.
-
Karl Knechtel over 13 yearsPlease do not cast the result from
malloc
. It is standard and well-defined C behaviour, and idiomatic C to leave it out. You are guaranteed to get an implicit cast. If you do cast, the compiler is no longer able to diagnose the error if you forget to#include <stdlib.h>
. -
Przemek Kryger over 13 years@Karl Knechtel Thanks, for pointing this out. Edited and removed casting.