Quote Originally Posted by deburca98
I am trying to figure out how to load the data but I don't know how to dynamically create sufficient memory for each entry into the file.
I would start by defining a function to print a single employee's data:
Code:
void print_employee(FILE *fp, const Employee *employee);
I would manually create an Employee object and test this print_employee function by printing to stdout. I expect that when you do this, you'll find that your declaration of the Employee struct is problematic, e.g., you might encounter problems with employee_surName and employee_name. So you fix the struct and the function, compile and test, and repeat until both work as expected.

Then, the next step could be to define a function to print the data of many employees, as stored in an array, e.g.,
Code:
void print_employee_list(FILE *fp, const Employee *employees, size_t num_employees);
By calling print_employee, this should be fairly simple, but test it anyway by manually defining an array of Employee objects to pass to print_employee_list.

When you're sure print_employee_list works, you're then ready to implement the load_data function. I might rename it to load_employees, and of course there are a few ways to declare it, but you could try first defining a struct:
Code:
typedef struct
{
    Employee *data;
    size_t size;
    size_t capacity;
} EmployeeList;
and using it:
Code:
void load_employees(FILE *fp, EmployeeList *employees);
The idea is that you will allocate space for capacity number of Employee objects, then read into them from the file, increasing the size as you go. When the size reaches the capacity and you still have more employee data to read, you increase the capacity (this can be done by a fixed increase or by a factor) and re-allocate according to the new capacity.

To test that load_employees works, you call the print_employee_list function, passing data and size. (Or you can rework the print_employee_list function to have a const EmployeeList* parameter instead of having the second and third parameters). Later, you can change the return type of load_employees to bool, int, or an enum type so that you can return a boolean value or status code indicating if the load was successful or failed (e.g., due to a failure to allocate memory, or due to invalid input, etc). When you have load_employees working within this error checking, then you're ready to implement sorting of the employee data.

Notice that for all these functions, I'm making use of the parameters (and return type) rather than global variables. This makes it easier for you to reason about the program and to reuse the functions. When testing, likewise you would define local variables within the main function (or in auxiliary test functions called by the main function).