Thread: writing an array of struct to a binary file

  1. #1
    Registered User
    Join Date
    Oct 2014
    Posts
    74

    writing an array of struct to a binary file

    im trying to write an array of struct to a binary the array of struct is filled with data from a text file .

    the program gives no errors or warnings but does not write anything at all to the binary file here is the main
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    
    struct matches 
    {
        char teamA[20] ;
        char teamB[20];
        int scoreA ; 
        int scoreB;
    };
    
    
    
    
    void table(void) ; 
    void matchesofateam(void) ; 
    void HighestNoOfGoals(void) ;
    void enternew(void) ;
    
    
    
    
    int main(void)
    {
        FILE *PtrToTxt ; 
        FILE *PtrToBinary ; 
        
        char clubA[20] ;
        char clubB[20] ;
        int clubAscore ;
        int clubBscore ; 
        int i = 0 ; 
            
        struct matches matchresults[200] ; 
        
        
        //****open text file and check for error****//
        PtrToTxt = fopen( "matches.txt" , "r" ) ; 
        
        if(PtrToTxt == NULL)
        {
            printf("Error opening the text file 'Matches'. \n " ) ;
            exit(1); 
        }//****end if****//
        
        //****create binary file and check for errors****//
        PtrToBinary = fopen( "matchesbin.bin" , "w+b" ) ; 
        
        if(PtrToBinary == NULL)
        {
            printf("Error creating the binary file 'matchesbin'. \n " ) ;
            exit(1); 
        }//****end if****//
        
        //***Read the text file in format using FSCANF want write to BinaryFile using Fwrite****//
        
        while(fscanf(PtrToTxt , "%[^,] , %[^,] , %i , %i" , clubA , clubB , &clubAscore, &clubBscore)!= EOF)
        {
            strcpy(matchresults[i].teamA, clubA ) ; 
            strcpy(matchresults[i].teamB, clubB ) ; 
            matchresults[i].scoreA = clubAscore  ;
            matchresults[i].scoreB = clubBscore  ;
            
            printf("%s %s %d %d \n" , matchresults[i].teamA , matchresults[i].teamB , matchresults[i].scoreA,matchresults[i].scoreB ) ;
            
            i++ ; 
        }
        
         fwrite(matchresults, 1 ,1*sizeof( matchresults ) ,PtrToBinary ) ;
        
        
        fclose( PtrToBinary ) ;
        fclose( PtrToTx t) ; 
        
        return 0 ; 
        
    }//****************************End Of Main****************************//
    any help would be much appreciated

  2. #2
    Registered User
    Join Date
    May 2014
    Posts
    121
    Check the return value from fwrite and see if you get any errors.

  3. #3
    Registered User
    Join Date
    Oct 2014
    Posts
    74
    9600 is the return from fwrite ?

  4. #4
    Registered User
    Join Date
    Oct 2014
    Posts
    74
    it seems to be working now.

  5. #5
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    EDIT: Guess it took me too long to write this, I see you got it working :P. Still, much of this is worth considering.

    In the future, please provide more complete information, such as the input file you are using that is causing problems. Also, please post code that is not full of strange characters like \240 and \302. Here's what I got when I first compiled
    Code:
    $ make foo
    gcc -Wall -ggdb3 -pedantic -std=gnu99 -O0 -o foo foo.c -lm -lpthread -lrt
    foo.c:4:1: error: stray ‘\302’ in program
    foo.c:4:1: error: stray ‘\240’ in program
    foo.c:5:1: error: stray ‘\302’ in program
    How do you know it doesn't write anything to the binary file? It seemed to work just fine for me:
    Code:
    $ cat matches.txt 
    aaa,bbb,1,2
    bbb,ccc,2,3
    ccc,ddd,3,4
    ddd,eee,4,5
    eee,aaa,5,1
    
    
    $ hexdump -C matchesbin.bin                                                                   
    00000000  61 61 61 00 00 00 00 00  00 00 00 00 00 00 00 00  |aaa.............|
    00000010  00 00 00 00 62 62 62 00  00 00 00 00 00 00 00 00  |....bbb.........|
    00000020  00 00 00 00 00 00 00 00  01 00 00 00 02 00 00 00  |................|
    00000030  0a 62 62 62 00 00 00 00  00 00 00 00 00 00 00 00  |.bbb............|
    00000040  00 00 00 00 63 63 63 00  00 00 00 00 00 00 00 00  |....ccc.........|
    00000050  00 00 00 00 00 00 00 00  02 00 00 00 03 00 00 00  |................|
    00000060  0a 63 63 63 00 00 00 00  00 00 00 00 00 00 00 00  |.ccc............|
    00000070  00 00 00 00 64 64 64 00  00 00 00 00 00 00 00 00  |....ddd.........|
    00000080  00 00 00 00 00 00 00 00  03 00 00 00 04 00 00 00  |................|
    00000090  0a 64 64 64 00 00 00 00  00 00 00 00 00 00 00 00  |.ddd............|
    000000a0  00 00 00 00 65 65 65 00  00 00 00 00 00 00 00 00  |....eee.........|
    000000b0  00 00 00 00 00 00 00 00  04 00 00 00 05 00 00 00  |................|
    000000c0  0a 65 65 65 00 00 00 00  00 00 00 00 00 00 00 00  |.eee............|
    000000d0  00 00 00 00 61 61 61 00  00 00 00 00 00 00 00 00  |....aaa.........|
    000000e0  00 00 00 00 00 00 00 00  05 00 00 00 01 00 00 00  |................|
    000000f0  0a 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
    00000100  00 00 00 00 61 61 61 00  00 00 00 00 00 00 00 00  |....aaa.........|
    00000110  00 00 00 00 00 00 00 00  05 00 00 00 01 00 00 00  |................|
    00000120  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
    ...<snip>...
    00002560  ff ff ff ff 00 00 00 00  b8 1c 92 bc ff 7f 00 00  |................|
    00002570  a8 31 95 0d 86 7f 00 00  c0 94 f2 0d 86 7f 00 00  |.1..............|
    Other things:

    • Don't use magic numbers. 20 and 200 are meaningless. Use constants with sensible names: MAX_TEAM_NAME, MAX_MATCHES.
    • Work on better names. For example, PtrToTxt and PtrToBinary are confusing since they can imply that they point to generally usable memory, not a file structure. Consider names like TextFilePtr and BinaryFilePtr or InputFilePtr and OutputFilePtr instead, which stress that these are for file handling.
    • If you fail opening the binary file, you should close the input file before you exit.
    • You're checking the value of fscanf incorrectly: scanf(3): input format conversion - Linux man page. Notice the return value section, that states it returns the number of items successfully scanned in. You ask for 4 items (2 %[ and 2 %i). If it returns any number other than 4, you have a problem.
    • You're calling fwrite incorrectly (specifically the second and third parameters): fwrite(3): binary stream input/output - Linux man page. You may get away with it, but it's not a good idea. The second parameter should be the size of a single element, i.e. sizeof(matchresults[0]). The third parameter should be the number of elements, i.e. MAX_MATCHES or you could use the calculation sizeof(matchresults)/sizeof(matchresults[0]).
    • You could declare a single struct matches to read into with fscanf (see below).
    • When your fscanf loop terminates, you should check to see why it stopped. You can use the feof and ferror functions (man page).


    Code:
    struct matches foo;
    ...
    while (fscanf(InputFilePtr, "%[^,] , %[^,] , %i , %i", foo.teamA, foo.teamB, &foo.scoreA, &foo.scoreB) == 4)
        ...
    if ferror
        print error and exit
    else if not feof
        loop stopped before reaching end of file, but no error...possible input file has bad format
        print error and exit

  6. #6
    Registered User
    Join Date
    Oct 2014
    Posts
    74
    Quote Originally Posted by anduril462 View Post
    EDIT: Guess it took me too long to write this, I see you got it working :P. Still, much of this is worth considering.

    In the future, please provide more complete information, such as the input file you are using that is causing problems. Also, please post code that is not full of strange characters like \240 and \302. Here's what I got when I first compiled
    Code:
    $ make foo
    gcc -Wall -ggdb3 -pedantic -std=gnu99 -O0 -o foo foo.c -lm -lpthread -lrt
    foo.c:4:1: error: stray ‘\302’ in program
    foo.c:4:1: error: stray ‘\240’ in program
    foo.c:5:1: error: stray ‘\302’ in program
    How do you know it doesn't write anything to the binary file? It seemed to work just fine for me:
    Code:
    $ cat matches.txt 
    aaa,bbb,1,2
    bbb,ccc,2,3
    ccc,ddd,3,4
    ddd,eee,4,5
    eee,aaa,5,1
    
    
    $ hexdump -C matchesbin.bin                                                                   
    00000000  61 61 61 00 00 00 00 00  00 00 00 00 00 00 00 00  |aaa.............|
    00000010  00 00 00 00 62 62 62 00  00 00 00 00 00 00 00 00  |....bbb.........|
    00000020  00 00 00 00 00 00 00 00  01 00 00 00 02 00 00 00  |................|
    00000030  0a 62 62 62 00 00 00 00  00 00 00 00 00 00 00 00  |.bbb............|
    00000040  00 00 00 00 63 63 63 00  00 00 00 00 00 00 00 00  |....ccc.........|
    00000050  00 00 00 00 00 00 00 00  02 00 00 00 03 00 00 00  |................|
    00000060  0a 63 63 63 00 00 00 00  00 00 00 00 00 00 00 00  |.ccc............|
    00000070  00 00 00 00 64 64 64 00  00 00 00 00 00 00 00 00  |....ddd.........|
    00000080  00 00 00 00 00 00 00 00  03 00 00 00 04 00 00 00  |................|
    00000090  0a 64 64 64 00 00 00 00  00 00 00 00 00 00 00 00  |.ddd............|
    000000a0  00 00 00 00 65 65 65 00  00 00 00 00 00 00 00 00  |....eee.........|
    000000b0  00 00 00 00 00 00 00 00  04 00 00 00 05 00 00 00  |................|
    000000c0  0a 65 65 65 00 00 00 00  00 00 00 00 00 00 00 00  |.eee............|
    000000d0  00 00 00 00 61 61 61 00  00 00 00 00 00 00 00 00  |....aaa.........|
    000000e0  00 00 00 00 00 00 00 00  05 00 00 00 01 00 00 00  |................|
    000000f0  0a 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
    00000100  00 00 00 00 61 61 61 00  00 00 00 00 00 00 00 00  |....aaa.........|
    00000110  00 00 00 00 00 00 00 00  05 00 00 00 01 00 00 00  |................|
    00000120  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
    ...<snip>...
    00002560  ff ff ff ff 00 00 00 00  b8 1c 92 bc ff 7f 00 00  |................|
    00002570  a8 31 95 0d 86 7f 00 00  c0 94 f2 0d 86 7f 00 00  |.1..............|
    Other things:

    • Don't use magic numbers. 20 and 200 are meaningless. Use constants with sensible names: MAX_TEAM_NAME, MAX_MATCHES.
    • Work on better names. For example, PtrToTxt and PtrToBinary are confusing since they can imply that they point to generally usable memory, not a file structure. Consider names like TextFilePtr and BinaryFilePtr or InputFilePtr and OutputFilePtr instead, which stress that these are for file handling.
    • If you fail opening the binary file, you should close the input file before you exit.
    • You're checking the value of fscanf incorrectly: scanf(3): input format conversion - Linux man page. Notice the return value section, that states it returns the number of items successfully scanned in. You ask for 4 items (2 %[ and 2 %i). If it returns any number other than 4, you have a problem.
    • You're calling fwrite incorrectly (specifically the second and third parameters): fwrite(3): binary stream input/output - Linux man page. You may get away with it, but it's not a good idea. The second parameter should be the size of a single element, i.e. sizeof(matchresults[0]). The third parameter should be the number of elements, i.e. MAX_MATCHES or you could use the calculation sizeof(matchresults)/sizeof(matchresults[0]).
    • You could declare a single struct matches to read into with fscanf (see below).
    • When your fscanf loop terminates, you should check to see why it stopped. You can use the feof and ferror functions (man page).


    Code:
    struct matches foo;
    ...
    while (fscanf(InputFilePtr, "%[^,] , %[^,] , %i , %i", foo.teamA, foo.teamB, &foo.scoreA, &foo.scoreB) == 4)
        ...
    if ferror
        print error and exit
    else if not feof
        loop stopped before reaching end of file, but no error...possible input file has bad format
        print error and exit
    hey thanks for the advice

    with regard to the strange number i have no idea where they came from?? mabey i mashed the keboard while typing into the forum post box or something.

    The ferror is vwery interesting i will def look into that and include it.
    The reason it wasnt writing anything to the file was beacuse i was not exiting the program in the terminal correctly ie i was pressing the x on top of the terminal instead of enter to exit therefor the program was not closing the files .

    with regard to the magic numbers i would always change them at the end. i perfer to get a function program up and running first then turn bits that i can into functions fix the hardcoding ect just take a bit of stress off knowing that atleast the program work but needs tidying : P

    Im going to have a look at the man page now for the fwrite

    thanks again for your help

  7. #7
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Quote Originally Posted by alien1 View Post
    with regard to the magic numbers i would always change them at the end. i perfer to get a function program up and running first then turn bits that i can into functions fix the hardcoding ect just take a bit of stress off knowing that atleast the program work but needs tidying : P
    I would argue that the stress is never there if you start by using well-named constants and variables*. Imagine a program only slightly larger, where you have both team names and player names you need to track. You make them both size 20, then you realize that player name needs to be 30. Now you go changing all the 20s that are for player names you can find to 30. Except you forgot one. Or you changed them all, but also changed a team name by mistake. Now you're overflowing buffers and you're buggered trying to figure out where the mistake is. If you start with TEAM_NAME_MAX and PLAYER_NAME_MAX from the beginning, then you only need to change one line (the definition of the constant) to change all the team or player names to whatever value you want.

    * A huge part of being able to start programming with sensible, descriptive names is coming up with a good plan on paper before you begin coding. If you don't know where your code is going, then you don't know what the function is really going to do, so you give it a crappy, inaccurate name. If you have a good plan, you already know what functions, variables and constants you'll likely need; you'll understand their purpose and thus know a good name to give them.

    Note, I say all this as somebody who used to do things your way, and learned my lessons the hard way.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 4
    Last Post: 05-12-2009, 03:28 PM
  2. Replies: 2
    Last Post: 05-09-2008, 07:27 AM
  3. Writing a struct to a binary file
    By Scarvenger in forum C++ Programming
    Replies: 8
    Last Post: 09-12-2006, 01:50 AM
  4. Writing an array of struct to file
    By stellastarr in forum C Programming
    Replies: 10
    Last Post: 03-25-2006, 06:59 PM
  5. Writing a struct to a binary file problem
    By k_w_s_t_a_s in forum C Programming
    Replies: 1
    Last Post: 05-08-2005, 10:03 AM