Structs are great when organizing information in your program. The only issue is that when your program ends, the data you store in those sweet sweet structs also disappears. Because we use files in order to achieve data persistence, we can use file operations to save structs for later use. Pretty neat!
Fwrite
This function accepts $4$ arguments:
- A pointer to the data to be written e.g. &total, post_data
- The size of the data to be written e.g. sizeof(int), sizeof(Post)
- The number of values of the data to be written e.g. 1 integer, 5 posts
- The pointer to the file to be written to e.g. file
It returns the number of values that were successfully written to the file
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
char author[100];
char content[1000];
} Post;
bool write_data(char *filename, Post *data, int total);
Post *read_data(char *filename, int *total);
int main() {
Post *newsfeed;
newsfeed = malloc(sizeof(Post) * 2);
strcpy(newsfeed[0].author, "John Doe");
strcpy(newsfeed[0].content, "Hello world!");
strcpy(newsfeed[1].author, "Mary Sue");
strcpy(newsfeed[1].content, "How are you??");
if (write_data("newsfeed.bin", newsfeed, 2)) {
printf("Write data OK.\n");
} else {
printf("Error writing to file.\n");
}
free(newsfeed);
int total = 0;
Post *file_data = read_data("newsfeed.bin", &total);
if (file_data == NULL) {
printf("Error reading from file.\n");
return 1;
}
printf("\nData read OK.\n\n");
for (int i = 0; i < total; i++) {
printf("Post %d: '%s'\n- %s\n\n", i + 1, file_data[i].content,
file_data[i].author);
}
return 0;
}
bool write_data(char *filename, Post *post_data, int total) {
FILE *file = fopen(filename, "wb");
if (file == NULL) {
return false;
}
if (fwrite(&total, sizeof(int), 1, file) != 1) {
return false;
}
if (fwrite(post_data, sizeof(Post), total, file) != total) {
return false;
}
if (fclose(file) != EOF) {
return false;
}
return true;
}
Post *read_data(char *filename, int *total) {
FILE *file = fopen(filename, "rb");
if (file == NULL) {
return NULL;
}
if (fread(total, sizeof(int), 1, file) != 1) {
return NULL;
}
Post *post_data = malloc(sizeof(Post) * (*total));
if (fread(post_data, sizeof(Post), *total, file) != *total) {
free(post_data);
return NULL;
}
if (fclose(file) == EOF) {
free(post_data);
return NULL;
}
return post_data;
}
structs-to-file.c Copy