MST

星途 面试题库

面试题:C语言指针数组与内存管理及高级应用

设计一个程序,使用指针数组来管理多个动态分配的结构体数组。结构体包含两个成员:一个整型ID和一个指向字符数组(用于存储名字)的指针。要求程序具备添加新结构体元素到特定结构体数组(通过指针数组索引指定)、删除特定结构体数组中某个ID对应的元素、以及释放所有动态分配内存的功能。请写出完整的代码,并详细注释说明内存分配与释放的过程,确保没有内存泄漏。
44.5万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 定义结构体
typedef struct {
    int id;
    char *name;
} Person;

// 定义指针数组,用于管理多个结构体数组
typedef Person** PersonArray;

// 添加新结构体元素到特定结构体数组
void addPerson(PersonArray *arr, int arrIndex, int id, const char *name) {
    // 检查arrIndex是否越界
    if (arrIndex < 0) {
        printf("数组索引无效\n");
        return;
    }
    // 如果arrIndex位置为空,初始化该位置
    if (!(*arr)[arrIndex]) {
        (*arr)[arrIndex] = (Person*)malloc(sizeof(Person));
        if (!(*arr)[arrIndex]) {
            printf("内存分配失败\n");
            return;
        }
        (*arr)[arrIndex]->id = id;
        (*arr)[arrIndex]->name = (char*)malloc(strlen(name) + 1);
        if (!(*arr)[arrIndex]->name) {
            printf("内存分配失败\n");
            free(*arr)[arrIndex];
            (*arr)[arrIndex] = NULL;
            return;
        }
        strcpy((*arr)[arrIndex]->name, name);
        return;
    }
    // 找到最后一个元素的位置
    Person *current = (*arr)[arrIndex];
    while (current->next) {
        current = current->next;
    }
    // 分配新的结构体内存
    Person *newPerson = (Person*)malloc(sizeof(Person));
    if (!newPerson) {
        printf("内存分配失败\n");
        return;
    }
    newPerson->id = id;
    newPerson->name = (char*)malloc(strlen(name) + 1);
    if (!newPerson->name) {
        printf("内存分配失败\n");
        free(newPerson);
        return;
    }
    strcpy(newPerson->name, name);
    newPerson->next = NULL;
    current->next = newPerson;
}

// 删除特定结构体数组中某个ID对应的元素
void deletePerson(PersonArray *arr, int arrIndex, int id) {
    // 检查arrIndex是否越界
    if (arrIndex < 0) {
        printf("数组索引无效\n");
        return;
    }
    if (!(*arr)[arrIndex]) {
        printf("该数组为空\n");
        return;
    }
    Person *current = (*arr)[arrIndex];
    Person *prev = NULL;
    while (current && current->id != id) {
        prev = current;
        current = current->next;
    }
    if (!current) {
        printf("未找到ID为 %d 的元素\n", id);
        return;
    }
    if (prev) {
        prev->next = current->next;
    } else {
        (*arr)[arrIndex] = current->next;
    }
    free(current->name);
    free(current);
}

// 释放所有动态分配内存
void freeAll(PersonArray arr, int size) {
    for (int i = 0; i < size; i++) {
        Person *current = arr[i];
        Person *next;
        while (current) {
            next = current->next;
            free(current->name);
            free(current);
            current = next;
        }
    }
    free(arr);
}

int main() {
    const int arraySize = 3;
    PersonArray arr = (PersonArray)malloc(arraySize * sizeof(Person*));
    if (!arr) {
        printf("内存分配失败\n");
        return 1;
    }
    for (int i = 0; i < arraySize; i++) {
        arr[i] = NULL;
    }

    addPerson(&arr, 0, 1, "Alice");
    addPerson(&arr, 0, 2, "Bob");
    addPerson(&arr, 1, 3, "Charlie");

    deletePerson(&arr, 0, 2);

    freeAll(arr, arraySize);

    return 0;
}

内存分配与释放过程说明:

  1. addPerson函数
    • 首先检查数组索引是否有效。如果arrIndex位置为空,为该位置分配Person结构体内存。
    • name成员分配内存,并复制名字。
    • 如果arrIndex位置不为空,遍历链表找到最后一个元素,为新元素分配Person结构体内存,再为name成员分配内存并复制名字,最后将新元素连接到链表。
  2. deletePerson函数
    • 检查数组索引是否有效。如果该数组为空,直接返回。
    • 遍历链表找到要删除的元素,释放name成员的内存,再释放Person结构体的内存。
  3. freeAll函数
    • 遍历指针数组,对每个指针指向的链表,依次释放每个Person结构体的name成员内存,再释放Person结构体内存。
    • 最后释放指针数组本身的内存。
  4. main函数
    • 为指针数组分配内存,并初始化为NULL
    • 调用addPerson添加元素,调用deletePerson删除元素。
    • 最后调用freeAll释放所有动态分配的内存。