void*数组可以通过[]来访问,void数组不可以
动态数组的思想是通过在堆中开辟一块更大的空间复制原本不够装载数据的空间的数据
//插入数组
void insert_dynamicArray(struct dynamicArray* arr, void* data,int pos)
{
if (arr == NULL)
{
return;
}
if (data == NULL)
{
return;
}
if (pos < 0 || pos >arr->m_Size)
{
//尾插
pos = arr->m_Size;
}
//判断数组是否满了
if (arr->m_Size == arr->m_Capacity)
{
//1、计算新的内存空间大小
int newCapacity = arr->m_Capacity * 2;
//2、开辟新空间
void ** newSpace = malloc(sizeof(void*) * newCapacity);
//3、将源空间下的数据拷贝到新空间下
memcpy(newSpace, arr->pAddr, sizeof(void*) * arr->m_Capacity);
//4、释放源空间
free(arr->pAddr);
//5、更改指针指向
arr->pAddr = newSpace;
//6、更新新的容量
arr->m_Capacity = newCapacity;
}
//将新元素插入到数组中指定位置
for (int i = arr->m_Size - 1; i >= pos; i--)
{
arr->pAddr[i + 1] = arr->pAddr[i];
}
//将数据插入到指定位置
arr->pAddr[pos] = data;
//更新数组大小
arr->m_Size++;
}
遍历动态数组
//遍历
void foreach_dynamicArray(struct dynamicArray* arr,void (*myPrint)(void *))
{
if (arr == NULL)
{
return;
}
for (int i = 0; i < arr->m_Size; i++)
{
myPrint(arr->pAddr[i]);
}
}
struct Person
{
char name[64];
int age;
};
//回调函数 打印数据
void printPerson(void* data)
{
struct Person* person = data;
printf("姓名:%s 年龄:%d\n", person->name, person->age);
}
//测试动态数组
void test01()
{
//初始化动态数组
struct dynamicArray* arr = init_dynamicArray(4);
struct Person p1 = { "01",19 };
struct Person p2 = { "saber",20 };
struct Person p3 = { "revice",21 };
struct Person p4 = { "geats",22 };
struct Person p5 = { "donbrothers",23 };
printf("插入数据前--数组容量:%d\n", arr->m_Capacity);
printf("输入数据前--数组大小:%d\n", arr->m_Size);
//插入数据
insert_dynamicArray(arr, &p1,0);
insert_dynamicArray(arr, &p2, 0);
insert_dynamicArray(arr, &p3, -1);
insert_dynamicArray(arr, &p4, 1);
insert_dynamicArray(arr, &p5, 2);
foreach_dynamicArray(arr, printPerson);
printf("插入数据后--数组容量:%d\n", arr->m_Capacity);
printf("输入数据后--数组大小:%d\n", arr->m_Size);
}
删除数组中的元素
用两种方法,一种以位置来删除,一种以数组中的值来删除
//删除数组
//按照位置删除数据
void removeByPos_dynamicArray(struct dynamicArray* arr, int pos)
{
if (arr == NULL)
{
return;
}
if (pos < 0 || pos > arr->m_Size - 1)
{
//无效位置return
return;
}
//删除指定位置的数据 从前往后移动
for (int i = pos; i < arr->m_Size; i++)
{
arr->pAddr[i] = arr->pAddr[i + 1];
}
//更新数组大小
arr->m_Size--;
}
//按值方式删除数据
void removeByValue_dynamicArray(struct dynamicArray* arr, void* data,int(*myCompare)(void *,void *))
{
if (arr == NULL)
{
return;
}
if (data == NULL)
{
return;
}
for (int i = 0; i < arr->m_Size; i++)
{
if (myCompare(arr->pAddr[i],data))
//利用回调函数 让用户自己告诉我们如何对比数据
{
removeByPos_dynamicArray(arr, i);
}
}
}
//回调函数 对比删除数据
int comparePerson(void* data1, void* data2)
{
struct Person* p1 = data1;
struct Person* p2 = data2;
return strcmp(p1->name, p2->name) == 0 && p1->age == p2->age;
}
//测试动态数组
void test01()
{
//初始化动态数组
struct dynamicArray* arr = init_dynamicArray(4);
struct Person p1 = { "01",19 };
struct Person p2 = { "saber",20 };
struct Person p3 = { "revice",21 };
struct Person p4 = { "geats",22 };
struct Person p5 = { "donbrothers",23 };
printf("插入数据前--数组容量:%d\n", arr->m_Capacity);
printf("输入数据前--数组大小:%d\n", arr->m_Size);
printf("------------------------\n");
//插入数据
insert_dynamicArray(arr, &p1,0);
insert_dynamicArray(arr, &p2, 0);
insert_dynamicArray(arr, &p3, -1);
insert_dynamicArray(arr, &p4, 1);
insert_dynamicArray(arr, &p5, 2);
foreach_dynamicArray(arr, printPerson);
printf("插入数据后--数组容量:%d\n", arr->m_Capacity);
printf("输入数据后--数组大小:%d\n", arr->m_Size);
printf("------------------------\n");
//按照位置 删除donbrothers测试
removeByPos_dynamicArray(arr, 2);
printf("删除donbrothers后的遍历结果\n");
foreach_dynamicArray(arr, printPerson);
printf("删除数据后--数组容量:%d\n", arr->m_Capacity);
printf("删除数据后--数组大小:%d\n", arr->m_Size);
printf("------------------------\n");
struct Person p = { "01",19 };
removeByValue_dynamicArray(arr, &p, comparePerson);
printf("删除01后的遍历结果\n");
foreach_dynamicArray(arr, printPerson);
printf("删除数据后--数组容量:%d\n", arr->m_Capacity);
printf("删除数据后--数组大小:%d\n", arr->m_Size);
printf("------------------------\n");
}
销毁数组
void destroy_dymanicArray(struct dynamicArray* arr)
{
if (arr == NULL)
{
return;
}
//内部维护在堆区数组指针先释放
if (arr->pAddr != NULL)
{
free(arr->pAddr);
arr->pAddr = NULL;
}
free(arr);
arr = NULL;
}
动态数组份文件编写
新建一个.h 和一个.c文件,将同用函数从主文件中,搬到这两个文件中以便后面复用,需要注意的是,回调函数作为用户提供的数据,是不需要将其搬到这两个文件中的。