【考研C语言编程题】数组元素批量插入实现(含图示+三部曲拆解)

发布于:2025-09-09 ⋅ 阅读:(16) ⋅ 点赞:(0)

【考研C语言编程题】数组元素批量插入实现(含图示+三部曲拆解)

一、题目要求

编写C语言程序,实现将数组b的所有元素批量插入到数组a的指定位置(位置从0开始计数)。要求严格遵循“腾出空间→插入元素→更新长度”的操作三部曲,且需满足以下条件:

  1. 数组a采用动态内存分配(支持长度动态扩展);
  2. 需处理插入位置越界、内存分配失败等异常情况;
  3. 禁止使用函数声明,直接通过函数调用实现逻辑,主函数放在代码最后;
  4. 插入后需打印原数组、待插入数组及插入结果,清晰展示过程。

二、插入过程图示模拟

以“原数组a = [1, 3, 5, 7],待插入数组b = [2, 4],插入位置pos = 1”为例,三步曲流程如下:

1. 初始状态

  • 原数组a(长度4):[1] [3] [5] [7]
  • 待插入数组b(长度2):[2] [4]
  • 插入位置pos=1:表示插入到a[1](元素3)之前

2. 第一步:腾出空间(扩容+元素后移)

  • 扩容:原数组长度4 + 待插入长度2 = 新长度6,通过realloc扩展a的内存空间;
  • 元素后移:从a的末尾元素(a[3]=7)开始,将pos=1及之后的元素(3、5、7)向后移动lenB=2位,避免被覆盖。
    后移后a的状态:[1] [ ] [ ] [3] [5] [7](空位置用于存放b的元素)

3. 第二步:插入元素

b的元素依次填入a腾出的空位置(从pos=1开始):
插入后a的状态:[1] [2] [4] [3] [5] [7]

4. 第三步:更新长度

将原数组a的长度从4更新为6,完成插入。

三、完整代码实现

#include <stdio.h>
#include <stdlib.h>  // 包含动态内存操作函数(malloc、realloc、free)

// 数组插入核心函数(直接定义,不单独声明)
int* insertArray(int* a, int* lenA, int* b, int lenB, int pos) {
    // 先做参数合法性校验(避免异常操作)
    if (pos < 0 || pos > *lenA) {  // 插入位置不能小于0或大于原数组长度
        printf("错误:插入位置不合法!\n");
        return NULL;
    }
    if (lenB == 0) {  // 待插入数组无元素,无需操作
        printf("提示:待插入数组为空,无需插入!\n");
        return a;
    }

    // 第一步:腾出空间(扩容+元素后移)
    int newLen = *lenA + lenB;  // 计算插入后的新长度
    // 扩容:用realloc扩展数组a的内存,返回新地址(原地址可能失效)
    int* newA = (int*)realloc(a, newLen * sizeof(int));
    if (newA == NULL) {  // 内存分配失败(如内存不足)
        printf("错误:内存分配失败,无法扩容!\n");
        return NULL;
    }
    // 元素后移:从原数组末尾向前遍历,避免覆盖数据
    for (int i = *lenA - 1; i >= pos; i--) {
        newA[i + lenB] = newA[i];  // 每个元素后移lenB位
    }

    // 第二步:插入元素(将b的元素填入腾出的空间)
    for (int i = 0; i < lenB; i++) {
        newA[pos + i] = b[i];  // 从pos位置开始依次插入b的元素
    }

    // 第三步:更新长度(将新长度通过指针传出)
    *lenA = newLen;

    return newA;  // 返回插入后的新数组地址
}

// 打印数组的辅助函数(用于展示数组内容)
void printArray(int* arr, int len, char* name) {
    printf("%s(长度%d):", name, len);
    for (int i = 0; i < len; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
}

// 主函数(放在最后,逻辑更清晰)
int main() {
    // 1. 初始化原数组a(动态内存分配)
    int lenA = 4;  // 原数组a的初始长度
    int* a = (int*)malloc(lenA * sizeof(int));
    if (a == NULL) {  // 检查内存分配是否成功
        printf("错误:原数组初始化失败!\n");
        return 1;
    }
    // 给原数组a赋值:[1, 3, 5, 7]
    a[0] = 1;
    a[1] = 3;
    a[2] = 5;
    a[3] = 7;

    // 2. 初始化待插入数组b(静态数组,无需动态分配)
    int b[] = {2, 4};  // 待插入的元素
    int lenB = sizeof(b) / sizeof(b[0]);  // 计算b的长度(2)
    int insertPos = 1;  // 插入位置(插入到a[1]之前)

    // 3. 打印插入前的数组
    printf("=== 插入前 ===\n");
    printArray(a, lenA, "原数组a");
    printArray(b, lenB, "待插入数组b");
    printf("插入位置:pos = %d\n\n", insertPos);

    // 4. 调用插入函数,执行插入操作
    a = insertArray(a, &lenA, b, lenB, insertPos);
    if (a == NULL) {  // 检查插入是否成功
        free(a);  // 失败时释放已分配的内存,避免泄漏
        return 1;
    }

    // 5. 打印插入后的结果
    printf("=== 插入后 ===\n");
    printArray(a, lenA, "结果数组a");

    // 6. 释放动态内存(避免内存泄漏,必须执行)
    free(a);
    a = NULL;  // 避免野指针

    return 0;
}

四、代码说明与考点分析

1. 核心逻辑拆解

  • 腾出空间:通过realloc实现动态扩容,解决静态数组长度固定的问题;元素从后向前移动,是避免数据覆盖的关键(若从前往后移动,a[1]会先被覆盖,后续元素无法正确迁移)。
  • 插入元素:通过循环将b的元素依次填入a的空位置,索引关系为newA[pos+i] = b[i]i从0到lenB-1)。
  • 更新长度:通过指针lenA将新长度传出(因为函数参数是值传递,需用指针才能修改外部变量)。

2. 考研高频考点

  • 动态内存管理malloc初始化数组、realloc扩容、free释放内存,需理解“动态内存的生命周期由程序员控制”,避免内存泄漏和野指针。
  • 数组操作边界:插入位置的合法性校验(0 ≤ pos ≤ lenA),是代码健壮性的重要体现,考研编程题常考“异常情况处理”。
  • 函数参数传递:通过指针传递数组长度,实现“函数修改外部变量”,需区分“值传递”和“地址传递”的差异。

五、运行结果

编译运行代码后,输出如下(与图示流程完全一致):

=== 插入前 ===
原数组a(长度4):1 3 5 7 
待插入数组b(长度2):2 4 
插入位置:pos = 1

=== 插入后 ===
结果数组a(长度6):1 2 4 3 5 7 

六、扩展思考(考研复试常问)

  1. 若需支持floatchar类型的数组插入,代码需如何修改?(提示:将int替换为对应类型,或使用宏定义实现泛型)
  2. 多次插入时,频繁调用realloc会影响效率,如何优化?(提示:预先分配更大的内存空间,减少扩容次数)
  3. 若要实现“批量删除数组元素”,思路与插入有何异同?(提示:删除需先前移元素,再通过realloc缩小内存,最后更新长度)

网站公告

今日签到

点亮在社区的每一天
去签到