【考研C语言编程题】数组元素批量插入实现(含图示+三部曲拆解)
一、题目要求
编写C语言程序,实现将数组b
的所有元素批量插入到数组a
的指定位置(位置从0开始计数)。要求严格遵循“腾出空间→插入元素→更新长度”的操作三部曲,且需满足以下条件:
- 数组
a
采用动态内存分配(支持长度动态扩展); - 需处理插入位置越界、内存分配失败等异常情况;
- 禁止使用函数声明,直接通过函数调用实现逻辑,主函数放在代码最后;
- 插入后需打印原数组、待插入数组及插入结果,清晰展示过程。
二、插入过程图示模拟
以“原数组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
六、扩展思考(考研复试常问)
- 若需支持
float
或char
类型的数组插入,代码需如何修改?(提示:将int
替换为对应类型,或使用宏定义实现泛型) - 多次插入时,频繁调用
realloc
会影响效率,如何优化?(提示:预先分配更大的内存空间,减少扩容次数) - 若要实现“批量删除数组元素”,思路与插入有何异同?(提示:删除需先前移元素,再通过
realloc
缩小内存,最后更新长度)