在c语言中,数组是固定长度的顺序存储结构,本身不支持动态插入元素,若要完成插入操作,需要开发者手动实现元素移动和赋值逻辑。插入元素的核心流程包含位置校验、元素后移、新元素赋值三个步骤,不同的数组使用场景适配的实现方式略有区别。

基础场景:固定长度数组插入元素
假设我们有一个已经存储了部分元素的整型数组,现在需要在指定下标位置插入一个新元素,首先要保证插入位置在合法范围内,且数组还有剩余空间存放新元素。
实现步骤如下:
- 校验插入位置的下标,要求下标大于等于0,且小于等于当前数组已存储的元素个数,避免位置越界
- 将插入位置及之后的所有元素从后往前依次向后移动一位,腾出插入位置的空间
- 把新元素赋值到插入位置的下标处,同时更新数组已存储元素的数量
下面是完整的实现代码示例:
#include <stdio.h>
// 定义数组最大长度
#define MAX_SIZE 10
/**
* 向数组指定位置插入元素
* @param arr 数组指针
* @param currentSize 当前数组已存储元素个数指针
* @param pos 插入位置下标
* @param value 要插入的元素值
* @return 插入成功返回1,失败返回0
*/
int insertElement(int arr[], int *currentSize, int pos, int value) {
// 校验数组是否已满
if (*currentSize >= MAX_SIZE) {
printf("数组已满,无法插入新元素n");
return 0;
}
// 校验插入位置合法性
if (pos < 0 || pos > *currentSize) {
printf("插入位置不合法n");
return 0;
}
// 从后往前移动插入位置之后的元素
for (int i = *currentSize; i > pos; i--) {
arr[i] = arr[i - 1];
}
// 插入新元素
arr[pos] = value;
// 更新已存储元素个数
(*currentSize)++;
return 1;
}
int main() {
int arr[MAX_SIZE] = {1, 2, 3, 4, 5};
int currentSize = 5; // 当前数组有5个元素
printf("插入前的数组:");
for (int i = 0; i < currentSize; i++) {
printf("%d ", arr[i]);
}
printf("n");
// 在位置2插入元素10
int result = insertElement(arr, ¤tSize, 2, 10);
if (result) {
printf("插入后的数组:");
for (int i = 0; i < currentSize; i++) {
printf("%d ", arr[i]);
}
printf("n");
}
return 0;
}
插入位置合法性说明
插入位置的下标允许等于当前数组的元素个数,这种情况相当于在数组末尾追加元素,不需要移动原有元素,直接赋值即可。如果插入位置小于0或者大于当前元素个数,就属于非法位置,需要提前拦截避免错误。
动态数组场景下的插入实现
如果使用动态分配的数组,插入元素时还需要考虑数组容量不足的情况,此时需要先扩容再执行插入逻辑。动态数组的插入实现示例如下:
#include <stdio.h>
#include <stdlib.h>
// 动态数组结构体
typedef struct {
int *data; // 数组数据指针
int size; // 当前元素个数
int capacity; // 数组总容量
} DynamicArray;
/**
* 初始化动态数组
* @param arr 动态数组指针
* @param initCapacity 初始容量
*/
void initDynamicArray(DynamicArray *arr, int initCapacity) {
arr->data = (int *)malloc(initCapacity * sizeof(int));
arr->size = 0;
arr->capacity = initCapacity;
}
/**
* 动态数组插入元素,容量不足时自动扩容
* @param arr 动态数组指针
* @param pos 插入位置
* @param value 插入值
* @return 成功返回1,失败返回0
*/
int dynamicInsert(DynamicArray *arr, int pos, int value) {
// 校验插入位置
if (pos < 0 || pos > arr->size) {
printf("插入位置不合法n");
return 0;
}
// 容量不足时扩容,这里扩容为原来的2倍
if (arr->size >= arr->capacity) {
int newCapacity = arr->capacity * 2;
int *newData = (int *)realloc(arr->data, newCapacity * sizeof(int));
if (newData == NULL) {
printf("扩容失败n");
return 0;
}
arr->data = newData;
arr->capacity = newCapacity;
}
// 移动插入位置之后的元素
for (int i = arr->size; i > pos; i--) {
arr->data[i] = arr->data[i - 1];
}
// 插入新元素
arr->data[pos] = value;
arr->size++;
return 1;
}
int main() {
DynamicArray arr;
initDynamicArray(&arr, 3); // 初始容量为3
// 插入元素
dynamicInsert(&arr, 0, 1);
dynamicInsert(&arr, 1, 2);
dynamicInsert(&arr, 2, 3);
dynamicInsert(&arr, 1, 10); // 插入后容量不足会自动扩容
printf("动态数组元素:");
for (int i = 0; i < arr.size; i++) {
printf("%d ", arr.data[i]);
}
printf("n");
// 释放内存
free(arr.data);
return 0;
}
注意事项
- 插入元素前一定要校验数组边界,避免越界访问导致程序崩溃
- 元素移动时必须从后往前遍历,如果从前往后移动会覆盖原有元素
- 动态数组使用完毕后要及时释放分配的内存,避免内存泄漏
- 如果数组存储的是复杂结构体类型,插入时移动的是整个结构体,需要注意结构体拷贝的开销