Thread: Binary file

  1. #1
    Registered User
    Join Date
    Feb 2021
    Posts
    19

    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;

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    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.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User
    Join Date
    Sep 2020
    Posts
    150
    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)

  4. #4
    Registered User
    Join Date
    Feb 2021
    Posts
    19
    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);

  5. #5
    Registered User
    Join Date
    Sep 2020
    Posts
    150
    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.

  6. #6
    Registered User
    Join Date
    Feb 2019
    Posts
    1,078
    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).

  7. #7
    Registered User
    Join Date
    Sep 2020
    Posts
    150
    I guess the op wants to run it only on his machine so this assumptions are justified.

  8. #8
    Registered User
    Join Date
    Feb 2021
    Posts
    19
    I guess it is better to use ||
    Is the code correct overall? Anything else to be considered?

  9. #9
    Registered User
    Join Date
    Sep 2020
    Posts
    150
    As far as I see it seems ok, but I am not an expert.

  10. #10
    Registered User
    Join Date
    Feb 2019
    Posts
    1,078
    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:
    Code:
     if ( 0 && 1 && 0 )
    Since (0 and X) is always 0 (and && is a sequence point), this will be evaluated to FALSE (0).

  11. #11
    Registered User
    Join Date
    Feb 2021
    Posts
    19
    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 )

  12. #12
    Registered User
    Join Date
    Feb 2019
    Posts
    1,078
    Only if one of the pointers is NULL. Or, putting the other way: If any of the fopen() fails.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 4
    Last Post: 11-21-2017, 10:48 AM
  2. Replies: 4
    Last Post: 12-07-2013, 04:33 PM
  3. Replies: 6
    Last Post: 12-06-2013, 11:39 PM
  4. Replies: 3
    Last Post: 11-28-2012, 09:16 AM
  5. Replies: 12
    Last Post: 06-18-2012, 08:23 AM

Tags for this Thread