-
Binary file
Hello
I am working on binary files management and I've done an excercise but don't know if it correct or not. I have tried to do 1 Here is the excercise:
Suppose you have a binary file called books.dat that contains informationabout unknown number of books of the following type:
struct Book
char title[140];
char category[50];
int edition;
int publish_year;
double price;
You are required to write a program that reads the contends of the fileand writes the books into 3 new binary files with the following conditions:
1. The books that have the category “Software Engineering” and are published after 2005 are written into the first file,
2. The books that have the category “Software Engineering” and are published before 2005 are written into the second file,
3. The rest of the books (the books that do not fulfil the conditions in 1or 2) must be written into the third file.
Here is the code:
insert
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Book
{
char title[140];
char category[50];
int edition;
int publish_year;
double price;
};
int main()
{
struct Book book;
FILE *myfile = fopen("./my-data.dat", "rb");
if (myfile == NULL) {
printf("Could not open the file!\n");
return 1;
}
while ( fread(&book, sizeof(struct Book), 1, myfile) )
{
if(book.category == "Software Engineering" && book.publish_year > 2005)
{
FILE *file1 = fopen("./data.dat", "wb");
if (myfile == NULL) {
printf("Could not open the file!\n");
return 1;
}
fwrite(&book, sizeof(struct Book), 1, file1);
fclose(file1);
}
}
fclose(myfile);
return 0;
-
You should open the second file before the loop and close it after the loop. Or you could open in append mode, but I'd prefer to open once instead of each time you need to write.
-
Code:
book.category == "Software Engineering"
This doesn't not work. To compare strings you need to use strcmp.
Your compiler should warn you.
gcc -Wall -Wextra "binary.c" -std=c99 -o file_demo.exe
binary.c: In function 'main':
binary.c:28:26: warning: comparison with string literal results in unspecified behavior [-Waddress]
if(book.category == "Software Engineering" && book.publish_year > 2005)
-
Is it better now?
insert
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Book
{
char title[140];
char category[50];
int edition;
int publish_year;
double price;
};
int main()
{
struct Book book;
FILE *myfile = fopen("./my-data.dat", "rb");
if (myfile == NULL) {
printf("Could not open the file!\n");
return 1;
}
FILE *file1 = fopen("./file1.dat", "wb");
FILE *file2 = fopen("./file2.dat", "wb");
FILE *file3 = fopen("./file3.dat", "wb");
if (file1 == NULL && file2 == NULL && file3 == NULL) {
printf("Could not open the file!\n");
return 1;
}
while (fread(&book, sizeof(struct Book), 1, myfile))
{
if(strcmp(book.category, "Software Engineering") == 0 && book.publish_year > 2005)
{
fwrite(&book, sizeof(struct Book), 1, file1);
}
else if(strcmp(book.category, "Software Engineering") == 0 && book.publish_year < 2005)
{
fwrite(&book, sizeof(struct Book), 1, file2);
}
else
fwrite(&book, sizeof(struct Book), 1, file3);
}
fclose(file1);
fclose(file2);
fclose(file3);
fclose(myfile);
-
Looks better now, but one problem remains.
Code:
if (file1 == NULL && file2 == NULL && file3 == NULL) {
Shouldn't the conditions be || since if one file can't be opened there is no point to continue.
-
You are assuming:
1- Struct members alignment/padding will be the same for any architecture (false);
2- All architetures use the same endianmess (false);
3- All architectures use IEEE 754 format (false).
-
I guess the op wants to run it only on his machine so this assumptions are justified.
-
I guess it is better to use ||
Is the code correct overall? Anything else to be considered?
-
As far as I see it seems ok, but I am not an expert.
-
Consider the case where file1 != NULL, file2 == NULL and file3 != NULL (failed to open file2 only)...
Code:
if ( file1 == NULL && file2 == NULL && file3 == NULL )
Will evaluate to:
Since (0 and X) is always 0 (and && is a sequence point), this will be evaluated to FALSE (0).
-
Ok, but if I use || then the code will be executed even if only one of the files suceed, right?
example:
insert
Code:
if ( file1 == NULL || file2 == NULL || file3 == NULL )
-
Only if one of the pointers is NULL. Or, putting the other way: If any of the fopen() fails.