Выделение в куче памяти массива указателей на структуру
Автор вопроса: Omar KhaledОтветов: 3
Я пытаюсь создать простую базу данных, используя такую структуру, как
struct Employee{
char* name;
int ID;
int GPA;
int salary;
};
я знаю, как я могу выделить один указатель типа структуры в куче, используя это
struct Employee* emp=malloc(sizeof(Employee));
теперь моя проблема в том, что я не очень хорошо разбираюсь в распределении процессов, и я хочу выделить N-количество указателей структуры в куче, и я не могу использовать массивы, потому что размер не будет известен до времени выполнения какие-либо предложения?
Известно ли вам количество сотрудников на момент первоначального распределения или со временем можно добавить больше сотрудников? interjay 15.02.2015
как только пользователь вводит число размеров, это количество сотрудников. Omar Khaled 15.02.2015
Не забывайте, что name также является указателем, и вам может потребоваться выделить (и освободить) место для него. pmg 15.02.2015
Функция realloc в основном назначает новый объем памяти для данных, на которые указывает ее возвращаемое значение. Это удобный способ расширения или сжатия динамически выделяемого массива. newsize здесь новое количество элементов вашего массива, и оно умножается на размер одной структуры Employee, отображая общий объем пространства, необходимый для вашего нового массива. Возвращаемое значение realloc присваивается вашему указателю массива, так что он указывает конкретно на это вновь выделенное пространство. В этом случае его можно использовать следующим образом:
struct Employee* emp= NULL;
И тогда, когда вам это нужно:
int n = 8;
emp = realloc (emp, n * sizeof(struct Employee));
Имейте в виду, что вам еще нужно free эту память.
Теперь вы можете инициализировать и получить доступ к этим данным:
emp[3] = {value1, value2, value3, ...};
Что касается структур, вы также можете подумать о другой структуре данных - связанном списке, где каждая структура содержит указатель на ее преемника. Вы можете прочитать об этом здесь: http://www.cprogramming.com/tutorial/c/lesson15.html
Как уже упоминалось, вы можете использовать malloc для создания как можно большего количества записей сведений о сотрудниках в куче и сохранения их в динамическом списке (linked list). я привел пример кода, вы можете начать отсюда и расширить его, если вы хотите сохранить данные о сотруднике перед выходом, вы можете записать его в двоичный файл и прочитать его при повторном запуске программы (в зависимости от ваших потребностей ), так как после выхода из программы все данные будут потеряны.
#include <stdio.h>
#include <stdlib.h>
// Max length for employee name
const unsigned int MAX_NAME_LEN = 100;
typedef struct Employee{
char* name;
unsigned int ID;
int GPA;
float salary;
} EMPLOYEE ;
typedef struct emp_database_entry {
EMPLOYEE data;
struct emp_database_entry *next;
} EMPLOYEE_ENTRY;
typedef EMPLOYEE_ENTRY* EMPLOYEE_DATABASE;
// to create a new employee
EMPLOYEE_ENTRY* createEmployee() {
EMPLOYEE_ENTRY *newEmp = (EMPLOYEE_ENTRY*)malloc(sizeof(EMPLOYEE_ENTRY));
printf("Enter Employee Name:");
newEmp->data.name = (char*)malloc( MAX_NAME_LEN * sizeof(char) );
scanf("%s",newEmp->data.name);
printf("Enter employee ID:");
scanf("%u",&newEmp->data.ID);
printf("Enter employee GPA:");
scanf("%u",&newEmp->data.GPA);
printf("Enter employee salary:");
scanf("%f",&newEmp->data.salary);
newEmp->next = 0;
return (newEmp);
}
// add a new employee to database
EMPLOYEE_DATABASE addEmployee(EMPLOYEE_DATABASE db) {
EMPLOYEE_ENTRY *newEmp = createEmployee();
if(db == NULL) {
// add the first entry
db = newEmp;
} else {
// add it to the top
newEmp->next = db;
db = newEmp;
}
return (db);
}
// Search for Employee using ID
EMPLOYEE_ENTRY* searchEmployee(EMPLOYEE_DATABASE db, unsigned int ID) {
EMPLOYEE_ENTRY *employee = db;
if(employee == NULL) {
printf("There are no Employees in the database\n");
return (NULL);
}
// Search till the end, if a match is found return the
// pointer to employee
while( employee != NULL ) {
if( employee->data.ID == ID )
return (employee);
else
employee = employee->next;
}
return (NULL);
}
void printOneEmployee( EMPLOYEE_ENTRY *employee ) {
printf("Employee Details\n");
printf("Name : %s\n",employee->data.name);
printf("ID : %u\n",employee->data.ID);
printf("GPA : %d\n",employee->data.GPA);
printf("Salary: %f\n\n",employee->data.salary);
}
// Print all employee details
void printAllEmployee( EMPLOYEE_DATABASE db ) {
EMPLOYEE_ENTRY *employee = db;
// traverse till the end and print one by one
while( employee != NULL ) {
printOneEmployee(employee);
employee = employee->next;
}
}
// freeing allocated memory
void freeDatabase(EMPLOYEE_DATABASE db) {
EMPLOYEE_DATABASE employee = 0;
while( db != NULL ) {
employee = db;
db = employee->next;
free(employee->data.name);
free(employee);
}
}
void displayOption( EMPLOYEE_DATABASE db ) {
int option = -1;
while( option != 5 ) {
printf("\nEmployee DataBase\n");
printf("1: Add a Employee\n");
printf("2: Search Employee\n");
printf("3: Print All Employee\n");
printf("4: Exit\n");
printf("Enter a number for the choice: ");
scanf("%d",&option);
if( option > 4 || option < 0 ) {
option = -1;
}
switch( option ) {
case 1:
db = addEmployee(db);
break;
case 2:
int ID;
if(db != NULL){
printf("Enter the Employee ID: ");
scanf("%d",&ID);
printf("Search Result1: ");
printOneEmployee(searchEmployee(db, ID));
}
else
printf("No Employees in the database\n");
break;
case 3:
printAllEmployee(db);
break;
case 4:
freeDatabase(db);
printf("DataBase Deleted\nExiting..");
exit(0);
default:
printf("Invalid Option!. Try Again!.\n");
}
}
}
int main() {
EMPLOYEE_DATABASE db = 0;
displayOption(db);
return (0);
}
Ответ 3 · Diego Andres Alvarez Marin
Конечно, вы можете использовать массивы, если используете C99. В C99 вы можете делать такие вещи, как: