#c
Вопрос:
Я хочу, чтобы программа считала данные о n сотрудниках из файла и сохраняла данные о зарплате n сотрудников в массиве, который динамически распределяется, а затем выводила среднюю зарплату.
Приведенная ниже программа получает данные от пользователя и сохраняет их в файле.
#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: %dn",n);
FILE *fp;
if((fp=fopen("employee.txt","w"))==NULL)
{
printf("File could not be openedn");
}
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",amp;employees[i].salaryannual);
printf("n");
}
for(i=0;i<n;i )
{
fprintf(fp,"%sn",employees[i].name);
fprintf(fp,"%sn",employees[i].nameEr);
fprintf(fp,"%sn",employees[i].desig);
fprintf(fp,"%dn",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");
}
Как мне поступить дальше с этим кодом.
Пожалуйста, помогите мне.
Комментарии:
1. Подсказка: если файл не удалось открыть
printf("File could not be openedn");
, этого недостаточно
Ответ №1:
Безусловно, существует множество подходов к решению этой проблемы.
Я думаю, что один из самых простых-это:
- Получите количество сотрудников, открыв файл для чтения и подсчитав количество строк. Количество сотрудников будет равно количеству строк, разделенных на четыре, так как на каждого сотрудника приходится четыре строки. Обычно для этого вы создаете функцию:
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 salaries_array[employees_count];
- Создайте функцию для заполнения только что созданного массива. Для этого потребуется, чтобы программа открыла файл для повторного чтения:
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;
}
Складываю все это воедино:
#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(amp;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 = %dn", average_salary);
}
}
}
Комментарии:
1. Спасибо вам за ваш ответ! @JardelLucca. Действительно полезно. Есть идея, как использовать функцию в этой программе.
2. Функции великолепны, но в случае, если они слишком увеличиваются в размерах, рекомендуется разделить их на более мелкие функции.
Ответ №2:
Для динамического распределения сначала необходимо определиться со схемой распределения. Вот несколько схем:
- увеличивайте каждый раз на фиксированное число
- увеличение на фиксированный процент
В отличие от метода @jardellucca, даже если файл не читается дважды, эти схемы требуют большого перераспределения ресурсов.
/* 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;
}
Если у вас 1000 записей, этот метод перераспределяется 200 раз. Альтернативой является увеличение на процент
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;
}
Используя эту схему распределения, 1000 сотрудников получают 13 перераспределений, но есть некоторые потери. Последнее распределение выделит 1234, что на 234 больше. В предыдущей схеме это будет, самое большее, 4 раза больше. Это просто проблема пространства-времени.
- Вы можете потратить время на чтение файла дважды. Вы могли бы, например, читать файл через медленную сеть.
- Вы можете тратить время на перераспределение много раз, и у вас останется еще несколько
- Вы можете тратить пространство на перераспределение меньше раз. Возможно, вы находитесь в системе с ограниченным объемом памяти, поэтому подобная схема может оказаться невыполнимой.
Выбранная вами схема будет зависеть от окружающей среды и ограничений. Что касается средней заработной платы, вы можете подвести итоги на лету по мере сохранения записей, а затем просто вычислить среднее значение в конце.
Комментарии:
1. Спасибо за ваш ответ @cup. Воплотю вашу концепцию в моей программе!
2. Это отличный анализ и краткое изложение ключевых моментов в решении проблемы. Я даже не думал о возможных результатах распределения памяти по частям. Только хороший/опытный программист мог бы легко перейти на этот уровень. Еще одним моментом в моем коде (а также в коде операции) является тот факт, что память неизвестного размера выделяется в стеке. Для любого приложения в реальной жизни это должно быть рассмотрено!