SachC
SachC

Reputation: 5

Implementation of Dynamic memory allocation in files in C program

I want the program to read the details of n employees from the file and store the Salary details of n employees to an array which is dynamically allocated and then print the average salary.

The below program gets the data from the user and stores it in a file.

#include <stdio.h>
#include <stdlib.h>
 
typedef struct
{
    char name[10];
    char nameEr[10];
    int salaryannual;
    char desig[10];
 
}Employee;
 
void main(int argc, char *argv[])
{
    int i,n=0,*ptr,sum=0;
    n=atoi(argv[1]);
    printf("The no.of employee records to be created are: %d\n",n);
    
    FILE *fp;
    
    if((fp=fopen("employee.txt","w"))==NULL) 
    {
      printf("File could not be opened\n");
    } 
    
 
    Employee employees[n];
 
    printf("Enter %d Employee Details: \n \n",n);
    
    for(i=0; i<n; i++)
    {
 
        printf("Employee %d: \n",i+1);
        printf("Employee name: ");
        scanf("%s",employees[i].name);
        printf("Employer name: ");
        scanf("%s",employees[i].nameEr);
        printf("Employee designation: ");
        scanf("%s",employees[i].desig);
        printf("Employee annual salary: ");
        scanf("%d",&employees[i].salaryannual);
        
 
        printf("\n");
    }
 
    for(i=0;i<n;i++)
    {
      fprintf(fp,"%s\n",employees[i].name);
      fprintf(fp,"%s\n",employees[i].nameEr);
      fprintf(fp,"%s\n",employees[i].desig);
      fprintf(fp,"%d\n",employees[i].salaryannual);
    }

    fclose(fp);
 
    for(i=0;i<n;i++)
    {
 
        printf("Employee name \t: ");
        printf("%s \n",employees[i].name);
 
        printf("Employer name \t: ");
        printf("%s \n",employees[i].nameEr);
        
        printf("Employee designation \t: ");
        printf("%s \n",employees[i].desig);
 
        printf("Employee annual salary: ");
        printf("%d \n",employees[i].salaryannual);
        
 
        printf("\n");
    }

How do I proceed further from this code. Please help me.

Upvotes: 0

Views: 200

Answers (2)

cup
cup

Reputation: 8237

In order to dynamically allocate, you first need to decide on the allocation scheme. Here are a couple of schemes:

  • increment by a fixed number every time
  • increment by a fixed percentage

Unlike @jardellucca's method, even though the file is not read twice, these schemes require a lot of reallocation.

/* Increment by fixed number */
int increment = 5;
int employee_count = 0;
int employee_max = increment;
Employee* employees = malloc(sizeof(Employee) * employee_max);

...
void Save(Employee* emp)
{
    /* check if there is enough space */
    if (employee_count == employee_max)
    {
         employee_max += increment;
         employees = realloc(employees, sizeof(Employee) * employee_max)
    }
    employees[employee_count] = *emp;
    ++employee_count;
}

If you have 1000 records, this method reallocs 200 times. An alternative is to increase by a percentage

int increment_pc = 150; /* 50% */
int employee_count = 0;
int employee_max = 10;
Employee* employees = malloc(sizeof(Employee) * employee_max);

...
void Save(Employee* emp)
{
    /* check if there is enough space */
    if (employee_count == employee_max)
    {
         employee_max = (employee_max * increment_pc) / 100;
         employees = realloc(employees, sizeof(Employee) * employee_max)
    }
    employees[employee_count] = *emp;
    ++employee_count;
}

Using this allocation scheme, 1000 employees takes 13 reallocations but there is some wastage. The last allocation will allocate 1234, which is 234 over. In the previous scheme, it will, at most be 4 over. This is just a space/time problem.

  • You can waste time reading the file twice. You could, for instance be reading the file across a slow network.
  • You can waste time reallocating lots of times and have a few left over
  • You can waste space reallocating fewer times. You may be on a system that is tight on memory so a scheme like this may not be feasible.

The scheme you choose will be dependant upon the environment and the constraints. As for average salary, you can do sum up on the fly as the records are being saved and then just compute the average at the end.

Upvotes: 1

Jardel Lucca
Jardel Lucca

Reputation: 1203

There are certainly many approaches to solve this.
I think of one of the simplest is:

  1. Get the employee count by opening the file for reading and counting the number of lines. The employee count will be the number of lines divided by four, since there are four lines for each employee. You typically make a function to do so:
int get_number_of_employees(int *number_of_employees)
{
    int ret = -1;

    int line_count = 0;

    FILE *fp = NULL;
    if ((fp = fopen("employee.txt", "r")) != NULL) {

        char line[64]  = {0,};
        while(fgets(line, sizeof(line), fp)) {

            line_count++;
        }

        *number_of_employees = line_count / 4;
        ret = 0;

        fclose(fp);
    }

    return ret;
}
  1. Allocate memory for your buffer using the number of employees you got with the function above:
int salaries_array[employees_count];
  1. Create a function fo fill in the array you just created. This will require the program to open the file for reading again:
int get_employees_salaries(int salaries_array[], int employees_count)
{
    int ret = -1;

    int line_count = 0;

    FILE *fp = NULL;
    if ((fp = fopen("employee.txt", "r")) != NULL) {

        char line[64]  = {0,};
        while(fgets(line, sizeof(line), fp)) {

            line_count++;
            if ((line_count % 4) == 0) {

                int salary = atoi(line);
                salaries_array[(line_count / 4) - 1] = salary;
                ret = 0;
            }
        }

        fclose(fp);
    }

    return ret;
}
  1. Now, create a function to get the average salary from the array:
int get_average_salary(int salaries_array[], int employees_count)
{
    int salaries_sum = 0;

    int i = 0;
    for (; i < employees_count; i++) {

        salaries_sum += salaries_array[i];
    }

    return salaries_sum / employees_count;
}

Putting it all together:

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

typedef struct
{
    char name[10];
    char nameEr[10];
    int salaryannual;
    char desig[10];

} Employee;

int get_number_of_employees(int *number_of_employees)
{
    int ret = -1;

    int line_count = 0;

    FILE *fp = NULL;
    if ((fp = fopen("employee.txt", "r")) != NULL) {

        char line[64]  = {0,};
        while(fgets(line, sizeof(line), fp)) {

            line_count++;
        }

        *number_of_employees = line_count / 4;
        ret = 0;

        fclose(fp);
    }

    return ret;
}

int get_employees_salaries(int salaries_array[], int employees_count)
{
    int ret = -1;

    int line_count = 0;

    FILE *fp = NULL;
    if ((fp = fopen("employee.txt", "r")) != NULL) {

        char line[64]  = {0,};
        while(fgets(line, sizeof(line), fp)) {

            line_count++;
            if ((line_count % 4) == 0) {

                int salary = atoi(line);
                salaries_array[(line_count / 4) - 1] = salary;
                ret = 0;
            }
        }

        fclose(fp);
    }

    return ret;
}

int get_average_salary(int salaries_array[], int employees_count)
{
    int salaries_sum = 0;
    int i = 0;
    for (; i < employees_count; i++) {

        salaries_sum += salaries_array[i];
    }
    return salaries_sum / employees_count;
}

void main (int argc, char *argv[])
{
    int employees_count = 0;
    if (get_number_of_employees(&employees_count) == 0) {

        int salaries_array[employees_count];
        if (get_employees_salaries(salaries_array, employees_count) == 0) {

            int average_salary = get_average_salary(salaries_array, employees_count);
            printf("Average salary = %d\n", average_salary);
        }
    }
}

Upvotes: 1

Related Questions