C Programming: Dealing with files (Part – 3)

In our previous article, we have used “getrecord” function. We will start this article with thisfunction. We have to implement “getrecord” to fetch a record from “employee.dat” file. It will check the “employee.dat” file for an employee record based on the given employee number. If it finds the employee record it will return the employee record and the position of the record in the file; if the record is not found it will return “-1”. Below is the code for “getrecord” function:

// getrecord function - This will search for the employee record based on 
// the employee number. If it finds, it will return the employee record and
// also return the position where the record stored in the file. The position
// is the offset from the begining of the file.
//
long getrecord(int empid, struct Employee *pemp)
{
   size_t size = 0;
   long position = -1; // ERROR: Something went wrong.

   // Open the file "employee.dat" in read-only binary mode.
   FILE *fp = fopen("employee.dat", "rb");
   if ( fp == NULL )
      return position;


   // Fetch the records.
   do
   {
      size = fread(pemp, sizeof(*pemp), 1, fp);

      if ( pemp->ID == empid )
      {
         position = ftell(fp);
         position -= sizeof(*pemp);
         break;
      }
   }
   while ( size > 0 );

   // Close the file.
   fclose(fp);

   return position;
}

From above code, we have opened the file “employee.dat” in read-write binary mode. Then fetch each record from “employee.dat” file and check whether the employee ID is matched with the given employee ID. If it matched, the function will store the position of the record and it will return the position. Observe that ftell function is used within “getrecord” function.

ftell function returns the current position of the file position indicator. Whenever fread reads the record from the file, the file position indicator will moves to the next record. If the read record is what we are looking, we need to recalculate the position of the record. Following statement will do this:

position -= sizeof(*pemp);

This tells to decrease the position value by size of an employee record. Because after fread, the file position indicator advanced to size of an employee record. If this is the record we are looking, we need to adjust the position. Hence above logic. Remember that each employee record is in fixed size.

Another function we used in our previous article, is fflush. fflush actually flushes the buffers for the give file pointer. Usually the buffered functions will flush the data, once its buffers are full. To flush the buffers explicitly; we use fflush function.

Now this is the time to show whole code. Here it is: I put comments wherever required; hope no other explanation required.

//employee.c
#include <stdio.h>
#include <stdlib.h>

// Employee structure
struct Employee
{
   char Name[50];
   int ID;
   int Age;
   float Salary; 
};

// getrecord function - This will search for the employee record based on 
// the employee number. If it finds, it will return the employee record and
// also return the position where the record stored in the file. The position
// is the offset from the begining of the file.
//
long getrecord(int empid, struct Employee *pemp)
{
   size_t size = 0;
   long position = -1; // ERROR: Something went wrong.

   // Open the file "employee.dat" in read-only binary mode.
   FILE *fp = fopen("employee.dat", "rb");
   if ( fp == NULL )
      return position;


   // Fetch the records.
   do
   {
      size = fread(pemp, sizeof(*pemp), 1, fp);

      if ( pemp->ID == empid )
      {
         position = ftell(fp);
         position -= sizeof(*pemp);
         break;
      }
   }
   while ( size > 0 );

   // Close the file.
   fclose(fp);

   return position;
}

// main function
//
void main()
{
   // Open the file "employee.dat" in read and write binary mode.
   // File must be exist, otherwise the function call will fail.
   FILE *fp = fopen("employee.dat", "rb+");
   if ( fp == NULL )
   {
      printf("ERROR: Unable to Open the file \"employee.dat\".\n");
      exit(0);
   }

   int option = 0;

   // Take inputs from the user
   do
   {
      printf("Enter your option here:\n");
      printf("1. Add/Update Employee Record.\n");
      printf("2. Fetch Employee Record.\n");
      printf("3. Quit.\n");
      
      scanf("%d", &option);

      switch ( option )
      {
         // Add/Update Employee Record.
         case 1:
               {
                  struct Employee emp;

                  printf("Enter Employee Name:\n");
                  scanf("%s", emp.Name);
                  printf("Enter Employee ID:\n");
                  scanf("%d", &emp.ID);
                  printf("Enter Age of Employee:\n");
                  scanf("%d", &emp.Age);
                  printf("Enter Employee's Salary:\n");
                  scanf("%f", &emp.Salary);

                  struct Employee temp;

                  long position = getrecord(emp.ID, &temp);
                  if ( position >= 0 )
                     fseek(fp, position, 0);
                  else
                     fseek(fp, 0L, SEEK_END);

                  fwrite(&emp, sizeof(emp), 1, fp);
                  fflush(fp);
               }
               break;

         // Fetch Employee Record.
         case 2:
               {
                  int empid = -1;

                  printf("Enter Employee ID to fetch the details:\n");
                  scanf("%d", &empid);

                  struct Employee emp;                  
                  
                  long position = getrecord(empid, &emp);
                  if ( position != -1 )
                  {
                     printf("Below are the requested Employee's details:\n");
                     printf("\t> Employee Name: %s\n", emp.Name);
                     printf("\t> Employee ID: %d\n", emp.ID);
                     printf("\t> Employee Age: %d\n", emp.Age);
                     printf("\t> Employee's Salary: $%.2f\n", emp.Salary);
                  }
                  else
                     printf("ERROR: Employee Record doesn't exists.\n");
               }
               break;

         // Prepare for Quit. Do nothing.
         case 3: break;

         // Invalid input.
         default:
                {
                   printf("WARNING! Invalid option.\n");
                }
      }
   }
   while ( option != 3 );

   // Close the file
   fclose(fp);
}

I have tested above code on my system (CentOS 64 bit); and it worked fine for me. 🙂

Still you have questions… Post them here… I will try to address as early as I can…

We will discuss about few more file related functions in our next articles…

// Malin

1 comment for “C Programming: Dealing with files (Part – 3)

Leave a Reply