Problem with Binary Files I/O (fread function)

This is a discussion on Problem with Binary Files I/O (fread function) within the C Programming forums, part of the General Programming Boards category; I need to make a program that manages accounts using a binary file to store and retrieve data. The problem ...

  1. #1
    Registered User
    Join Date
    Sep 2008
    Posts
    10

    Question Problem with Binary Files I/O (fread function)

    I need to make a program that manages accounts using a binary file to store and retrieve data. The problem is that after adding new accounts and storing them in the file, i can't retrieve them back and print them or i just get the last added account. Here are the code snippets:

    ADT:

    Code:
    	typedef struct {
    		char name[len];
    		char password[len];
    		int privilege;
    	}account;
    storing data:

    Code:
        printf("Enter Nickname: ");
    			scanf("%s",ptr.name);
    			printf("Please Enter Password: ");
    			scanf("%s",ptr.password);
          	   		
    		 	fwrite(&ptr,sizeof(account),1,input);
    loading (retrieving) data from the binary file:

    Code:
         for(i=0;i<10;i++){ // i just tried this
      				while(!feof(inp)){
    								
    				 fseek(inp,sizeof( account)*i,SEEK_CUR); //  i tried SEEK_CUR but                                                                                            //got garbage
          			         fread(&ptr2,sizeof(account),1,inp);
          			         printf("%d- %s\n",j,ptr2.name);
          			         j++;  // not important
    Can anyone help find me the mistake. Thanks in Advance.This is my first post so dont flame

  2. #2
    Registered User
    Join Date
    Oct 2001
    Posts
    2,129
    A compilable snippet might help.
    Code:
    fwrite(&ptr,sizeof(account),1,input);
    You want to write to the input?

  3. #3
    Registered User
    Join Date
    Sep 2008
    Posts
    10
    Yes. The idea is to keep the binary file updated and print some of its data to the user.

  4. #4
    Registered User
    Join Date
    Sep 2008
    Posts
    10
    Here is the code. I removed the unecessary parts :

    Code:
    #include <stdio.h>
    #include <string.h>
    #define len 20
    
    	
    	
    
    	typedef struct {
    		char name[len];
    		char password[len];
    		
    	}account;
    	
    
    
    
    int 
    main()
    {
    	FILE *inp,*inp2;
    	account ptr,ptr2;
    	int menu_choice=1, i=0,j=1, test;
    	
    	
    	
          if ( ( inp = fopen( "file.bin", "rb+" ) ) == NULL ) {
           		printf( "File Doesn't exist. A file was created.Open again...\n\n\n" );
           		fopen("file.bin", "wb+");
           		return(0);
          }
          while(menu_choice!=6){
          printf("\nChoose one of these operations: ");
          printf("\n1- View Account\n");
          printf("2- Add new Account\n");
          scanf("%d",&menu_choice);
          
          if (menu_choice==2){
          	
          		printf("Please Enter Username: ");
    			scanf("%s",ptr.name);
    			printf("Please Enter Password: ");
    			scanf("%s",ptr.password);
          	   		
    		 	fwrite(&ptr,sizeof(account),1,inp);		
          			
          }
          
          if (menu_choice==1){
       	
          		
          
     	     		for(i=0;i<10;i++){
      					while(!feof(inp)){
    					
    			
    				    fseek(inp,sizeof( account)*i,SEEK_CUR);
    	      			fread(&ptr2,sizeof(account),1,inp);
    	      			printf("%d- %s\n",j,ptr2.name);
    	      			j++;
          		
      					}  
    			
          		}				
          			
          			
          		
          }
        
          
     
    }
     
     
    return(0);
    }

  5. #5
    Registered User
    Join Date
    Sep 2008
    Posts
    10
    Here is the code. I removed the unecessary parts :

    Code:
    #include <stdio.h>
    #include <string.h>
    #define len 20
    
    	
    	
    
    	typedef struct {
    		char name[len];
    		char password[len];
    		
    	}account;
    	
    
    
    
    int 
    main()
    {
    	FILE *inp,*inp2;
    	account ptr,ptr2;
    	int menu_choice=1, i=0,j=1, test;
    	
    	
    	
          if ( ( inp = fopen( "file.bin", "rb+" ) ) == NULL ) {
           		printf( "File Doesn't exist. A file was created.Open again...\n\n\n" );
           		fopen("file.bin", "wb+");
           		return(0);
          }
          while(menu_choice!=6){
          printf("\nChoose one of these operations: ");
          printf("\n1- View Account\n");
          printf("2- Add new Account\n");
          scanf("&#37;d",&menu_choice);
          
          if (menu_choice==2){
          	
          		printf("Please Enter Username: ");
    			scanf("%s",ptr.name);
    			printf("Please Enter Password: ");
    			scanf("%s",ptr.password);
          	   		
    		 	fwrite(&ptr,sizeof(account),1,inp);		
          			
          }
          
          if (menu_choice==1){
       	
          		
          
     	     		for(i=0;i<10;i++){
      					while(!feof(inp)){
    					
    			
    				    fseek(inp,sizeof( account)*i,SEEK_CUR);
    	      			fread(&ptr2,sizeof(account),1,inp);
    	      			printf("%d- %s\n",j,ptr2.name);
    	      			j++;
          		
      					}  
    			
          		}				
          			
          			
          		
          }
        
          
     
    }
     
     
    return(0);
    }

  6. #6
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,855
    Since you've opened the file for update, it's probably a good idea to call fflush(fp) every time you do a write.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

  7. #7
    Registered User
    Join Date
    Sep 2008
    Posts
    10
    i tried using fflush but i still got the same problems.

  8. #8
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by g33koo View Post
    i tried using fflush but i still got the same problems.
    So, what is your current code? When I tried it on my machine, I see a few problems - in no particular order (some of these are suggestions for improvements rather than "real" problems):
    * You use a variable j to indicate account number, which is not reset in the loop that shows usage. You can probable use i+1 or some such.
    * You do not seek to the end of the file when adding new account, so if you start the program over and add a new user (without viewing current ones), then you would overwrite an existing user.
    * If you add fflush, the read loop works correct. Without it, it does not.
    * You should check the result of fread and fwrite operations.
    * If you are reading the list sequentially like you do here, there's no point in seeking before each fread(), it would be sufficient to seek to 0 at the beginning of the loop.
    * Do not use feof() to control a loop - you can use it AFTER you have read something, but as your current code stands, it will show the last user twice, because feof() is true only after you've actually read past the end of the file, not when you have just reached it (so you read the last user, then display it, then try to read another user and fails because you've reached EOF - the code doesn't realize until it's shown this user).
    * There is no option to exit the program.
    * The file is never closed at at the end of the program.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  9. #9
    Registered User
    Join Date
    Sep 2008
    Posts
    10
    Thanks for replying matsp. Your suggestions were very helpful. I did actually implemente some of the changes you suggested(Code below). Although the repeated words problem is solved, i still can't manage to print the old accounts stored in the binary file that the user entered before., and all i got is the last entered account instead.I'd like to know where the problem is and have some tips on how to solve it. Thanks in advance.

    Code:
       if (menu_choice==1){
       			    	
     	     	fseek(inp,sizeof( account)*i,SEEK_SET);
     	     			
      		for(i=0;i<10;i++){	// i'd like to find another way to iterate until the last account
    				 fflush(inp);  
    		      	         fread(&ptr2,sizeof(account),1,inp);
    		      		        if(feof(inp))
    			      		        break;
    		      		printf("&#37;d- %s\n",i+1,ptr2.name);
    	
      					}
          			   		
          }

  10. #10
    Registered User
    Join Date
    Sep 2008
    Posts
    9
    Quote Originally Posted by g33koo View Post
    Thanks for replying matsp. Your suggestions were very helpful. I did actually implemente some of the changes you suggested(Code below). Although the repeated words problem is solved, i still can't manage to print the old accounts stored in the binary file that the user entered before., and all i got is the last entered account instead.I'd like to know where the problem is and have some tips on how to solve it. Thanks in advance.

    Code:
       if (menu_choice==1){
       			    	
     	     	fseek(inp,sizeof( account)*i,SEEK_SET);
     	     			
      		for(i=0;i<10;i++){	// i'd like to find another way to iterate until the last account
    				 fflush(inp);  
    		      	         fread(&ptr2,sizeof(account),1,inp);
    		      		        if(feof(inp))
    			      		        break;
    		      		printf("&#37;d- %s\n",i+1,ptr2.name);
    	
      					}
          			   		
          }
    I am pretty new to C, been programming C# for along time instead.
    I would either use a infinitive loop or create a int that keeps track of the records, so the first int in the file contains information about how many account records there are.

    Inifinitive loop:
    Code:
    int iInfL = 0, i = 0;
    if (menu_choice==1)
    {
    	while (iInfL == 0)
    	{ 			    	
    		fseek(inp,sizeof( account)*i,SEEK_SET);
     	     			
    		fflush(inp);  
    		fread(&ptr2,sizeof(account),1,inp);
    		if(feof(inp))
    			break;
    		printf("%d- %s\n",i+1,ptr2.name);
    		i++;
    	}      			   		
    }
    Second, store an int with the number of records:

    Code:
    int Records = 0;
    fseek(inp,sizeof(int),SEEK_SET);
    fread(&Records, sizeof(int),1,inp);
    
    for(i=0;i<Records;i++)
    {	// i'd like to find another way to iterate until the last account
    	fflush(inp);  
    	fread(&ptr2,sizeof(account),1,inp);
    	if(feof(inp))
    		break;
    	printf("%d- %s\n",i+1,ptr2.name);	
    }
    Question is, what happens if the file dosent contain any records and you try to read from it?

    Another approach is to get the filesize and compare it against the size of an account object.

  11. #11
    Banned master5001's Avatar
    Join Date
    Aug 2001
    Location
    Visalia, CA, USA
    Posts
    3,685
    Very estute for a C# guy, piffo. The fflush(inp) is kind of dubious since it defies the C standard for how fflush() is defined. Perhaps you should more carefully re-read some of the previous suggestions.

  12. #12
    Registered User
    Join Date
    Sep 2008
    Posts
    10
    As i previously mentioned, matsp's suggestions helped me to solve the problem of repetetive accounts but i still can't display the old entries, its like the loop doesn't start from the begining since i only get the last account.

  13. #13
    Banned master5001's Avatar
    Join Date
    Aug 2001
    Location
    Visalia, CA, USA
    Posts
    3,685
    It is because of your loop design. 10 is certainly arbitrary and should not be used (I liked the infinite loop idea). And check your return of fread() instead of looking for feof().

  14. #14
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by master5001 View Post
    Very estute for a C# guy, piffo. The fflush(inp) is kind of dubious since it defies the C standard for how fflush() is defined. Perhaps you should more carefully re-read some of the previous suggestions.
    fflush on an INPUT file is indeed undefined. However, "inp" is opened with "rb+", which means that it's open in read/write & binary mode. This means that fflush is valid.

    However, I would put the fflush at the write point after new data has been added, (or, as an alternative, at the very beginning of the show users stage). There is certainly no need to flush every time in the loop.


    In the recently posted code:
    Code:
     	     	fseek(inp,sizeof( account)*i,SEEK_SET);
    what is the value of i here?


    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  15. #15
    Registered User
    Join Date
    Sep 2008
    Posts
    10
    Quote Originally Posted by matsp View Post


    In the recently posted code:
    Code:
     	     	fseek(inp,sizeof( account)*i,SEEK_SET);
    what is the value of i here?


    --
    Mats
    In the code i posted, i is initialized to 0 and i used SEEK_SET to set the pointer to the beginning so as i can iterate starting from there, or so i hoped.

Page 1 of 2 12 LastLast
Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Undefined Reference Compiling Error
    By AlakaAlaki in forum C++ Programming
    Replies: 1
    Last Post: 06-27-2008, 12:45 PM
  2. Files and function problem! Help needed
    By sion5 in forum C++ Programming
    Replies: 10
    Last Post: 01-12-2007, 02:04 AM
  3. Binary files
    By Lionmane in forum C Programming
    Replies: 35
    Last Post: 08-25-2005, 02:56 PM
  4. Replies: 3
    Last Post: 03-04-2005, 02:46 PM
  5. problem about static Lib and function pointer
    By wu7up in forum C Programming
    Replies: 3
    Last Post: 02-24-2003, 09:34 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21