Read and Write a Structure to a File in Binary Mode

Dave Sinkula 1 Tallied Votes 487 Views Share

This snippet asks the user to fill in a structure and saves each record to the file. It uses append mode to add each new record to the end of the file. After all input is taken, it prints out the contents of the file.

Disclaimer: fread and fwrite may not work portably between different implementations. Meaning, results may vary from platform to platform, compiler to compiler, or even with the same compiler with a different set of options or a different version.

Better code on the way(?).

#include <stdio.h>
#include <string.h>
#include <ctype.h>

/*
 * http://www.daniweb.com/code/snippet278.html
 */
char *mygetline(char *line, int size)
{
   if ( fgets(line, size, stdin) )
   {
      char *newline = strchr(line, '\n'); /* check for trailing '\n' */
      if ( newline )
      {
         *newline =  '\0'; /* overwrite the '\n' with a terminating null */
      }
   }
   return line;
}

/*
 * http://www.daniweb.com/code/snippet266.html
 */
int mygeti(int *result)
{
   char buff [ 13 ]; /* signed 32-bit value, extra room for '\n' and '\0' */
   return fgets(buff, sizeof buff, stdin) && sscanf(buff, "%d", result) == 1;
}

struct record
{
   char name[30];
   int  age;
};

void record_write(const char *filename)
{
   FILE *file = fopen(filename, "ab"); /* append to the file in binary mode */
   if ( file != NULL )
   {
      struct record data;
      /*
       * Read a string from the user. Put it into the structure.
       */
      printf("Enter name: ");
      fflush(stdout);
      mygetline(data.name, sizeof data.name);
      /*
       * Read a string from the user. Put it into the structure.
       */
      do
      {
         printf("Enter age: ");
         fflush(stdout);
      } while ( !mygeti(&data.age) );
      /*
       * Write the data to the file.
       */
      fwrite(&data, sizeof data, 1, file);
      fclose(file);
   }
}

void record_readall(const char *filename)
{
   FILE *file = fopen(filename, "rb"); /* read from the file in binary mode */
   if ( file != NULL )
   {
      struct record data;
      while ( fread(&data, sizeof data, 1, file) == 1 ) /* read all records */
      {
         printf("%s,%d\n", data.name, data.age); /* print each */
      }
      fclose(file);
   }
}

int main()
{
   static const char filename[] = "output.dat";
   /*
    * Loop as long as the user wants to add records.
    */
   for ( ;; )
   {
      char line[10];
      fputs("Add record (Y/N)? ", stdout);
      fflush(stdout);
      mygetline(line, sizeof line);
      if ( tolower(*line) == 'n' )
      {
         break;
      }
      record_write(filename);
   }
   /*
    * Show all records in the file.
    */
   record_readall(filename);
   return 0;

}

/* my output
C:\Test>test
Add record (Y/N)? y
Enter name: Dave
Enter age: 35
Add record (Y/N)? N
Dave,35

C:\Test>test
Add record (Y/N)? Y
Enter name: Vlad
Enter age: 39
Add record (Y/N)? y
Enter name: Jose
Enter age: 32
Add record (Y/N)? n
Dave,35
Vlad,39
Jose,32

C:\Test>test
Add record (Y/N)? n
Dave,35
Vlad,39
Jose,32

C:\Test>test
Add record (Y/N)? y
Enter name: Bill
Enter age: four
Enter age: 
Enter age: 40
Add record (Y/N)? n
Dave,35
Vlad,39
Jose,32
Bill,40
*/