C语言实现 动态数组 处理任意类型数据

article/2025/10/3 15:09:32

引言:动态数组在C/C++、Java、Python等语言中应用广泛,高级语言一般通过调用类或接口等可以快捷使用,C语言实现动态数组需要手动构造,以下为实现过程。

1 结构体构造动态数组

typedef struct Array
{void **p;        //维护在堆区创建的指针(后续函数入参为传址调用,节省内存,对void*操作,因此构造void **p)size_t capacity; //动态数组容量size_t size;     //动态数组实际大小
} Array;

2 动态数组初始化

Array *initArray(size_t capacity) 
{Array *array = (Array *)malloc(sizeof(Array));//在堆区申请array的内存array->capacity = capacity;//将动态数组容量初始化为函数入参array->size = 0;//将动态数组实际大小初始化为0array->p = (void **)malloc(sizeof(void *) * capacity); //在堆区申请二级指针p的内存return array;
}

3 动态数组在索引index处插入数据data

/*** @brief 向动态数组插入一个数据* @param array 动态数组* @param index 插入索引* @param data 插入数据,data为传址* @return int 插入成功返回1,失败返回0*/
#define RATIO 2  //扩容倍数
int insertArrayByIndex(Array *array, int index, void *data) 
{if (array == NULL || data == NULL)//空指针判断return 0;if (index < 0 || index >= array->size) //插入索引不在[0,size)内时,选择尾插index = array->size;if (array->capacity == array->size) // array数组已满,需要申请更大空间,并将源数据copy到新空间{size_t newCapacity = array->capacity * RATIO; //动态数组新容量void **newP = (void **)malloc(sizeof(void *) * newCapacity);//重新申请堆内存memcpy(newP, array->p, sizeof(void *) * array->capacity);//源数据copy至新的堆内存中free(array->p);                //释放旧空间array->p = newP;               //更新新指向array->capacity = newCapacity; //更新新容量}for (int i = array->size - 1; i >= index; i--) //新数据插入在index,先后移index及其以后数据array->p[i + 1] = array->p[i];             // p[i]相当于*(p+i),p原为二级指针,解引用操作了void *;使得一级地址后移array->p[index] = data;                        array->size++;                                 //更新大小return 1;
}

4 动态数组移除数据,可分为通过索引index移除或通过数据data移除,

        4.1 通过索引index移除

int removeArrayByIndex(Array *array, int index) //从动态数组移除一个数据
{if (array == NULL || index < 0 || index >= array->size)//空指针或非法索引会导致移除失败return 0;for (int i = index + 1; i < array->size; i++)array->p[i - 1] = array->p[i];//移除index对应的data后,需将index后的数据前移free(array->p[array->size-1]);array->p[array->size - 1] = NULL;//原末位数据置空array->size--;//原实际数组大小减1return 1;
}

        4.2 通过数据data移除,为方便理解,以下代码构造了动态数组存储的数据类型

typedef struct Student // 以动态数组存储的数据类型为Student*为例分析{char name[10];int age;
} Student;
int compare(void *s1, void *s2) //根据结构体Student设计比较规则,返回1表示相等
{Student *stu1 = (Student *)s1;//指针类型转换Student *stu2 = (Student *)s2;if (strcmp(stu1->name, stu2->name) == 0 && stu1->age == stu2->age)return 1;return 0;
}
int removeArrayByData(Array *array, void *data, int (*compare)(void *s1, void *s2)) //移除data函数,仅考虑不重复情况下
{if (array == NULL || data == NULL)//空指针return 0;for (int i = 0; i < array->size; i++){if (compare(array->p[i], data))//利用函数回调找出与data相同时的索引index{for (int index = i; index < array->size - 1; index++)//思路与通过索引删除数据一致array->p[index] = array->p[index + 1];free(array->p[array->size - 1]);array->p[array->size - 1] = NULL;array->size--;return 1;//删除成功返回1}}return 0;//删除失败返回0
}

5 动态数组遍历

void listArray(Array *array, void (*printfdArray)(void *)) //利用函数回调遍历
{if (array == NULL || printfdArray == NULL)return;for (int i = 0; i < array->size; i++)printfdArray(array->p[i]);puts("\n");
}
void printfStudent(void *data) //为Student*类型数据写遍历函数
{Student *s = (Student *)data;printf("%s->%d\t", s->name, s->age);
}

6 动态数组销毁

void destoryArray(Array *array)//释放占用的内存即可
{if (array != NULL){free(array);array = NULL;}if (array->p != NULL){free(array->p);array->p = NULL;}
}

7 动态数组简单演示

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define RATIO 2 //动态数组扩展系数
#define SHOW_CAPACITY_SIZE_AND_LIST                                 \printf("容量->%d\t大小->%d\t\n", array->capacity, array->size); \listArray(array, printfStudent);int main()
{Array *array = initArray(5);Student s1 = {"jakes1", 16};Student s2 = {"jakes2", 17};Student s3 = {"jakes3", 18};Student s4 = {"jakes4", 19};Student s5 = {"jakes5", 20};Student s6 = {"jakes6", 21};insertArray(array, 0, &s1);SHOW_CAPACITY_SIZE_AND_LISTinsertArray(array, 0, &s2);SHOW_CAPACITY_SIZE_AND_LISTinsertArray(array, 1, &s3);SHOW_CAPACITY_SIZE_AND_LISTinsertArray(array, 0, &s4);SHOW_CAPACITY_SIZE_AND_LISTinsertArray(array, 1, &s5);SHOW_CAPACITY_SIZE_AND_LISTinsertArray(array, 2, &s6);SHOW_CAPACITY_SIZE_AND_LISTremoveArrayByIndex(array, 2);SHOW_CAPACITY_SIZE_AND_LISTprintf("-----%d\n", removeArrayByData(array, &s3, compare));SHOW_CAPACITY_SIZE_AND_LISTreturn 0;
}

运行结果如下

 --如有错误,欢迎大家指出交流,共同学习--


http://chatgpt.dhexx.cn/article/2haxLjUl.shtml

相关文章

C语言创建动态数组

C语言创建动态数组 1.编写步骤 1. 添加所需头文件 stdlib.h 该头文件下包含的与分配存储区相关的函数如下&#xff1a; void* malloc (size_t size);//从堆中分配size字节的存储空间 void* calloc (size_t num, size_t size);//分配数组并将数组零初始化。为 num 个元素的数…

在OpenCV里实现开运算

前面学习腐蚀和膨胀算法,并且深刻地认识到它们的特性以及作用。如果由这两种组合出来的运算又有什么样的不同呢?比如一个图像先腐蚀后膨胀的操作,会有什么结果呢?因为腐蚀是把图片白色变小,膨胀又是把图片白色变大,是否会保持原图不变呢?带着这些问题来研究一下先腐蚀后…

OpenCV python 形态学 圆形开运算

处理流程 # -*- coding: utf-8 -*- # note : 形态学 开运算 圆形内核 处理 # --------------------------------import cv2 as cv import numpy as npdef opening_circle(img_bin, kernel_size10):# 形态学kernel np.zeros((kernel_size, kernel_size), np.uint8)center_…

腐蚀、膨胀、开运算、闭运算

一、腐蚀、膨胀、开运算、闭运算 腐蚀&#xff1a;图像中的高亮部分进行膨胀 膨胀&#xff1a;原图中的高亮部分被腐蚀&#xff0c;类似于领域被蚕食 开运算&#xff1a;先腐蚀再膨胀&#xff0c;可以去掉目标外孤立的点 闭运算&#xff1a;先膨胀再腐蚀&#xff0c;可以去掉目…

【youcans 的 OpenCV 例程200篇】137. 灰度开运算和灰度闭运算原理

欢迎关注 『youcans 的 OpenCV 例程 200 篇』 系列&#xff0c;持续更新中 欢迎关注 『youcans 的 OpenCV学习课』 系列&#xff0c;持续更新中 【youcans 的 OpenCV 例程200篇】137. 灰度开运算和灰度闭运算 5. 灰度级形态学 灰度级形态学将形态学操作从二值图像扩展到灰度图…

开闭运算

开运算和闭运算是将腐蚀和膨胀按照一定的次序进行处理。但这两者并不是可逆的&#xff0c;即先开后闭并不能得到原来的图像。 开运算 开运算是先腐蚀后膨胀&#xff0c;其作用是&#xff1a;分离物体&#xff0c;消除小区域。特点&#xff1a;消除噪点&#xff0c;去除小的干扰…

图像的形态学开操作(开运算)和闭操作(闭运算)的概念和作用,并用OpenCV的函数morphologyEx()实现对图像的开闭操作

大家看这篇博文前可以先看一看下面这篇博文&#xff0c;下面这篇博文是这篇博文的基础&#xff1a; 详解图像形态学操作之图形的腐蚀和膨胀的概念和运算过程,并利用OpenCV的函数erode()和函数dilate()对图像进行腐蚀和膨胀操作 图像形态学腐蚀可以将细小的噪声区域去除&#x…

OpenCV-Python图像运算变换处理:开运算和闭运算以及不同核矩阵的影响分析

☞ ░ 前往老猿Python博客 https://blog.csdn.net/LaoYuanPython ░ 一、引言 在《OpenCV-Python图像处理&#xff1a;腐蚀和膨胀原理及erode、dilate函数介绍 https://blog.csdn.net/LaoYuanPython/article/details/109441709》等系列博文中老猿详细介绍了腐蚀和膨胀的原理、…

灰度级形态学 - 灰度开运算和灰度闭运算

目录 1. 介绍 2. code 1. 介绍 灰度级的开运算和闭运算和二值图像的处理一样&#xff0c;只不过一个作用于灰度图&#xff0c;一个作用于二值图像 灰度级的开运算公式为&#xff1a; 先对图像做腐蚀&#xff0c;然后对腐蚀的结果做膨胀运算 灰度级的闭运算公式为&#xff…

OpenCV(七)形态学操作2--开运算与闭运算

目录 概述&#xff1a; morphologyEX()函数 一、开运算&#xff08;分开&#xff09; 1、基础理论 1、作用&#xff1a; 2、代码 3、效果 二、闭运算&#xff08;封闭&#xff09; 1、基础理论 1、作用 2、过程 2、代码 3、效果 总代码 参考资料&#xff1a; 概述…

开运算—闭运算

转载&#xff1a;https://blog.csdn.net/hanshanbuleng/article/details/80657148 如果不了解腐蚀与膨胀原理的同学那请看我前一期博客哦&#xff01;&#xff09; 1.开运算 开运算 先腐蚀运算&#xff0c;再膨胀运算&#xff08;看上去把细微连在一起的两块目标分开了&…

Halcon形态学处理-腐蚀、膨胀、开运算、闭运算、顶帽运算和底帽运算

提示&#xff1a;文章参考了网络上其他作者的文章&#xff0c;以及相关书籍&#xff0c;如有侵权&#xff0c;请联系作者。 文章目录 前言一、腐蚀和膨胀1.腐蚀2.膨胀 二、开运算和闭运算1.开运算2.闭运算 三、顶帽运算和底帽运算1.顶帽运算2.底帽运算 总结参考文献 前言 图像的…

Opencv中的开运算和闭运算操作讲解(python实现)

文章目录 1.首先了解腐蚀和膨胀原理2.开运算&#xff08;1&#xff09;为什么开运算可以去白噪点呢&#xff1f;&#xff08;2&#xff09;.函数讲解&#xff08;3&#xff09;代码实战 3.闭运算&#xff08;1&#xff09;函数讲解&#xff08;2&#xff09;代码实战 1.首先了解…

膨胀 腐蚀 开运算 闭运算 matlab,11. 形态学膨胀、腐蚀、开运算、闭运算

1. 膨胀:对边界点进行扩充,填充空洞,使边界向外部扩张的过程。 2. 腐蚀:消除物体边界点,使边界向内部收缩的过程,把小于结构元素的物体去除掉。 3. 开运算: 先腐蚀后膨胀的过程称为开运算,作用:去除孤立的小点,毛刺,消除小物体,平滑较大物体边界,同时不改变其面积。 4. 闭…

开运算、闭运算及其所用

1.开运算 开运算 先腐蚀运算&#xff0c;再膨胀运算&#xff08;看上去把细微连在一起的两块目标分开了&#xff09; 开运算的效果图如下图所示&#xff1a; 开运算总结&#xff1a; &#xff08;&#xff11;&#xff09;开运算能够除去孤立的小点&#xff0c;毛刺和小桥&…

python --opencv图像处理形态学(开运算、闭运算、梯度运算、顶帽运算、黑帽运算)

引言 前面介绍了图像形态学的两种基础算法&#xff0c;图像腐蚀和图像膨胀&#xff0c;本篇接着介绍图像形态学中的开运算、闭运算以及梯度运算。 需要了解清楚图像的腐蚀与膨胀基础原理,不然真的没办法理解开运算和闭运算。 第一件事情还是给图像增加噪声&#xff0c;思路沿…

二值图像开闭运算matlab,【数字图像处理】图像开运算与闭运算

图像开启与闭合 图像开运算与闭运算与膨胀和腐蚀运算有关&#xff0c;由膨胀和腐蚀两个运算的复合与集合操作(并、交、补等)组合成的所以运算构成。 开运算与闭运算依据腐蚀和膨胀的不可逆性&#xff0c;演变而来。 开运算&#xff1a;先对图像腐蚀后膨胀 闭运算&#xff1a;先…

OpenCV之开运算与闭运算

1.开运算&#xff1a;先腐蚀&#xff0c;后膨胀 开运算总结&#xff1a; &#xff08;&#xff11;&#xff09;开运算能够除去孤立的小点&#xff0c;毛刺和小桥&#xff0c;而总的位置和形状不便。 &#xff08;&#xff12;&#xff09;开运算是一个基于几何运算的滤波器。…

halcon 开运算与闭运算

例一&#xff1a;毛刺在往外凸的面上 策略1&#xff1a;分割出黑色部分&#xff0c;然后通过开运算去掉毛刺&#xff0c;再通过原黑色部分区域减去开运算之后的区域&#xff0c;得到毛刺部分的区域。 1 read_image (Tu, C:/Users/xiahui/Desktop/tu.jpg) 2 binary_threshold …

图像开运算

开运算是先腐蚀后膨胀的过程&#xff0c;它能去除孤点、毛刺和小桥&#xff08;连接两区域的小点&#xff09;&#xff0c;消除小物体、平滑大物体的边界&#xff0c;并且不明显改变面积。 开运算公式如下&#xff1a; #include"cv.h" #include "highgui.h&…