在堆内存中分配指向struct的指针数组

时间:2015-02-15 15:19:29

标签: c struct heap

我正在尝试使用像

这样的结构来创建简单的数据库
struct Employee{
    char* name;
    int ID;
    int GPA;
    int salary;
};

我知道如何使用

在堆中分配一个struct类型的指针
struct Employee* emp=malloc(sizeof(Employee));

我现在的问题是我不是很擅长分配流程而且我想要 在堆中分配N个结构指针,我不能使用数组,因为直到运行时才会知道大小 有什么建议 ?

3 个答案:

答案 0 :(得分:1)

是的,您需要动态分配内存,即为每个新struct Employee分配一个新的堆块。

您可以在尺寸更改时使用realloc执行此操作:

yourArrayPtr=realloc(yourArrayPtr,newsize * sizeof(struct Employee));

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

在你的情况下,它会像:

struct Employee{
    char* data;
    struct Employee* next;
};

答案 1 :(得分:1)

正如其他人所提到的,您可以使用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);
}

答案 2 :(得分:0)

当然,如果使用C99,则可以使用数组。在C99中,您可以执行以下操作:

scanf("%d", &N);
struct Employee emp[N];
emp[0].ID = 123;

如果您使用的是gcc(或MinGW),请务必使用-std = c99进行编译

另一方面,如果你只想在堆上创建一个数组,你可以这样做:

scanf("%d", &N);
struct Employee* emp=malloc(N*sizeof(Employee));
emp[0].ID =123;
...
// do not forget to deallocate emp
free(emp);