I'm not used to programm (Since i'm a newcomer) so I'd like to get some help with this project... I'm trying to make a maker/reader programm using binary files, structs and pointers but my programm crashes every time this and his process
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct Recipe{
char name[30];
char difficulty[30];
double calories;
};
void generate_file(FILE *in){
fopen("recipe.bin", "wb");
if(in == NULL){
fprintf(stderr, "\nErro, o arquivo não pode ser aberto\n");
exit(1);
}
struct Recipe *recipe = malloc(sizeof(struct Recipe));
printf("Digite o nome da receita: ");
gets(recipe->name);
printf("Digite o nivel de dificuldade da receita: ");
gets(recipe->difficulty);
printf("Digite o número de calorias: ");
scanf("%d", &recipe->calories);
fwrite(&recipe, sizeof(struct Recipe), 1, in);
if(fwrite != 0){
printf("Arquivo salvo com sucesso!");
}else{
printf("Falha no salvamento de dados");
exit(1);
}
fclose(in);
exit(0);
}
int main(int argc, char* argv[]){
FILE *in;
generate_file(in);
}
CodePudding user response:
The program crashes because you pass uninitialized or wrong pointers to certain functions.
From top to bottom:
Change the declaration of generate_file so that it takes a filename and returns an integer, like this:
int generate_file(const char *filename)
Assign the result from fopen to in, like this:
FILE *in = fopen(filename, "wb");
Replace exit with return:
return 1;
Initialize the structure after creation with zeros, for easier troubleshooting:
memset(recipe, 0, sizeof(struct Recipe));
Replace %d when scanning calories with %lf:
scanf("%lf", &recipe->calories);
Do not dereference the recipe (replace &recipe with recipe) when calling fwrite - it already is a pointer. Assign result of fwrite function into a variable and then test the variable instead of the function pointer when checking how many items were written:
size_t written = fwrite(&recipe, sizeof(struct Recipe), 1, in);
if (written != 0) {
Again, replace exit with return and use a different value then before, so that you can distinguish the cause of the problem later:
return 2;
In main(), change the argument to the name of the file and use the result from called function:
int result = generate_file("recipe.bin");
return result;
Here is the complete code:
int generate_file(const char *filename) {
FILE* in = fopen(filename, "wb");
if(in == NULL) {
fprintf(stderr, "\nErro, o arquivo não pode ser aberto\n");
return 1;
}
struct Recipe *recipe = malloc(sizeof(struct Recipe));
memset(recipe, 0, sizeof(struct Recipe));
printf("Digite o nome da receita: ");
gets(recipe->name);
printf("Digite o nivel de dificuldade da receita: ");
gets(recipe->difficulty);
printf("Digite o número de calorias: ");
scanf("%lf", &recipe->calories);
size_t written = fwrite(recipe, sizeof(struct Recipe), 1, in);
if(written != 0){
printf("Arquivo salvo com sucesso!");
}else{
printf("Falha no salvamento de dados");
return 2;
}
fclose(in);
return 0;
}
int main(int argc, char* argv[]) {
int result = generate_file("recipe.bin");
return result;
}
CodePudding user response:
I guess you want to use in
as your file? You don't assign the return value of fopen
to in
. in
points to nothing, so using I/O functions such as fwrite
on it will cause some errors.
in = fopen("recipe.bin", "wb");
Also, fwrite
expects a pointer, not a pointer to a pointer, since recipe
is already a pointer, you don't need to &
. fwrite(const void *ptr..)
Side note: You should never use gets
, it is not a safe function as it might cause an overflow. Use fgets
instead.