Home > OS >  Dynamic array of structures
Dynamic array of structures

Time:12-29

I'm a beginner and working with DMA and structure of arrays concept coding to get employee's details like name, address, Employee ID, and their age in structure using an array and arranging the received details in ascending order. Here I am not able to figure out the problem with storing the scanned name in the structure. When I give more than two as a value for employees count, then the output of the name is some garbage value. Please help me to fix it. The name that we are entering must be shown but it's not shown up.

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

struct emp_details
{
    char *address;
    char *name;
    char *Emp_ID;
    int age;
};

void ascen_str(struct emp_details* employees_data,int num_of_emp);

int main()
{
    int num_of_emp;
    printf("Enter the number of employees: ");
    scanf("%d",&num_of_emp);
    struct emp_details* employees_data = malloc(num_of_emp*sizeof (employees_data));
    int i=0;
    for(int i=0;i<num_of_emp;i  )
    {
        employees_data[i].name=(char*)malloc(30*sizeof(char));
        printf("Employe %d enter the Name: ",i 1);
        scanf("%s",employees_data[i].name);
        printf("%s",employees_data[i].name);
        getchar();
        //sscanf(emp_name,"%s\n",employees_data[i].name);
        //fgets(employees_data[i].name,30,stdin);
        employees_data[i].address = (char*)malloc(100*sizeof(char));
        printf("Employe %d enter the Address: ",i 1);
        //scanf("%s",employees_data[i].address);
        fgets(employees_data[i].address,30,stdin);
        employees_data[i].Emp_ID=(char*)malloc(10*sizeof(char));
        printf("Employe %d enter the Employe ID: ",i 1);
        scanf("%s",employees_data[i].Emp_ID);
        printf("Employe %d enter the Age: ",i 1);
        scanf("%d",&employees_data[i].age);
      
    }
    printf("\n\tEmploye details before sorting\n");
    for(int i=0;i<num_of_emp;i  )
    {    
        printf("Employe %d Name: %s\n",i 1,employees_data[i].name);  
        printf("Employe %d Address: %s",i 1,employees_data[i].address);  
        printf("Employe %d Age: %d\n",i 1,employees_data[i].age);
        printf("Employe %d ID: %s\n\n",i 1,employees_data[i].Emp_ID);
    }   
    ascen_str(employees_data,num_of_emp);
    free(employees_data);
}

void ascen_str(struct emp_details* employees_data, int num_of_emp)
{
    struct emp_details temp;
    for (int i = 0; i < num_of_emp; i  ) {
        for (int j = i   1; j < num_of_emp; j  ) {
            if (strcmp(employees_data[i].name, employees_data[j].name) > 0) {
                temp = employees_data[i];
                employees_data[i] = employees_data[j];
                employees_data[j] = temp;
            }
        }
    }
    printf("\n\tEmploye details in ascending order by name\n");
    for (int i = 0; i < num_of_emp; i  ) 
    {
        printf("Employe Name: %s\n",employees_data[i].name);  
        printf("Employe Address: %s",employees_data[i].address);  
        printf("Employe Age: %d\n",employees_data[i].age);
        printf("Employe ID: %s\n\n",employees_data[i].Emp_ID);
    }
}

CodePudding user response:

Allocate to the size of the referenced object, not the size of the pointer
@Some programmer dude

// struct emp_details* employees_data = malloc(num_of_emp*sizeof (employees_data));
struct emp_details* employees_data = malloc(num_of_emp * sizeof employees_data[0]);

When able, avoid sizing/casting to the type and allocate to the referenced object, as below. It is easier to code right, review and maintain.

ptr = malloc(sizeof prt[0] * number_of_elements);

Avoid fgets() with scanf() @Fe2O3

How about just fgets()? Create 2 helper functions.

// Minimal error checking
int get_int() {
  char buf[1000];
  if (fget(buf, sizeof buf, stdin) == NULL) {
    return 0;
  }
  int val;
  if (sscanf(buf, "%d", &val) == 1) {
    return val;
  }
  return 0;
}  

// Allocate the string size based on length of input.
// Minimal error checking
char *get_string() {
  char buf[1000];
  if (fget(buf, sizeof buf, stdin) == NULL) {
    return NULL;
  }
  size_t len = strlen(buf);
  if (len > 0 && buf[len-1] == 0) {
    buf[--len] = 0; // lop off potential \n
  }
  char *s = malloc(len   1);
  if (s) {
    strcpy(s, buf);
  }
  return s;
}

We can improve these helper functions later to detect lengthy input, int overflow, end-of-file, ...

Simplify record reading

 // Error checking omitted for brevity.
for(int i=0; i < num_of_emp; i  ) {
    printf("Employe %d enter the Name: ",i 1);
    employees_data[i].name = get_string();

    printf("Employe %d enter the Address: ",i 1);
    employees_data[i].address = get_string();

    printf("Employe %d enter the Employe ID: ",i 1);
    employees_data[i].Emp_ID = get_string();

    printf("Employe %d enter the Age: ",i 1);
    employees_data[i].age = get_int();
  }
}

CodePudding user response:

struct emp_details* employees_data = malloc(num_of_emp*sizeof (employees_data));

replace this statement by

struct emp_details* employees_data = malloc(num_of_emp*sizeof (struct emp_details ));

Because employees_data is a pointer and it's size is not the structure size

  • Related