c语言实现动态指针数组Dynamic arrays

简介:
c语言实现动态数组。其它c的数据结构实现,hashTable參考 点击打开链接  treeStruct參考 点击打开链接

基本原理:事先准备好一个固定长度的数组。

假设长度不够的时候。realloc一块区域。

另外:在数组元素降低的情况下。须要缩减数组长度。

主要接口:

cp_bool DyArrayAppend(DyArray* pArr, void* pData)//加数据到数组末尾
cp_bool DyArrayExpand(DyArray* pArr, cp_int32 nNeed)//扩展数组
cp_bool DyArrayDelete(DyArray* pArr, cp_int32 nIndex)//删除元素by index
cp_bool DyArrayShrink(DyArray* pArr)//缩减数组

源码例如以下:(iOS平台的c实现)

//
//  dyArray.h
//  dataStruct
//
//  Created by hherima on 14-7-28.
//  Copyright (c) 2014年 . All rights reserved.
//

#ifndef dataStruct_dyArray_h
#define dataStruct_dyArray_h
#include <stdlib.h>

enum
{
    CP_FALSE  =   0,
    CP_TRUE    =  !CP_FALSE
};

typedef unsigned char cp_bool;
typedef signed int cp_int32;
typedef void (*DataDestroyFunc)(void *);
typedef cp_bool (*DataCmpFunc)(void *,void *);
typedef void (*DataVisitFunc)(void *);

#define  F_MALLOC_TYPE(s) (s*)f_malloc(sizeof(s))
#define  FREEFUN free
#define  MIN_PRE_ALLOCATE_SIZE 10  //The initial size of the dynamic array.
#define  MEMSETFUN   memset
#define  REALLOCFUN realloc
#define  MALLOCFUN malloc

    
struct DynamicArray
{
    void **m_ppData; //the address of the allocated array.
    cp_int32 m_nAllocSize; //the allocated array size.
    cp_int32 m_nSize;  //the used size of the array.
    DataDestroyFunc m_fDestroy; //the callback function to destroy one data.
    DataCmpFunc     m_fCmp; //the callback function to compare one data.
    DataVisitFunc   m_fVisit; //the callback function to visit each data.
};
typedef struct DynamicArray DyArray;
    
    DyArray*   DyArrayCreate(DataDestroyFunc pDataDestroy);
    cp_bool    DyArrayInsert(DyArray* pArr, cp_int32 nIndex, void* pData);
    cp_bool    DyArrayPrepend(DyArray* pArr, void* pData);
    cp_bool    DyArrayAppend(DyArray* pArr, void* pData);
    cp_bool    DyArrayDelete(DyArray* pArr, cp_int32 nIndex);
    cp_bool    DyArrayDeleteEx(DyArray* pArr, cp_int32 nBegin,cp_int32 nEnd);
    cp_bool    DyArrayGetByIndex(DyArray* pArr, cp_int32 nIndex, void** ppData);
    cp_bool    DyArrayGetFirst(DyArray* pArr,void** ppData);
    cp_bool    DyArrayGetLast(DyArray* pArr,void** ppData);
    cp_bool    DyArraySetByIndex(DyArray* pArr, cp_int32 nIndex, void* pData);
    cp_int32   DyArrayLength(DyArray* pArr);
    cp_int32   DyArrayFind(DyArray* pArr, DataCmpFunc pCmp,void *pData);
    cp_bool    DyArrayForEach(DyArray* pArr, DataVisitFunc pVisit);
    void       DyArrayDestroy(DyArray* pArr);
    void       DyArrayDestroyCustom(DyArray* pArr,DataDestroyFunc pDataDestroy);
    void       DyArrayReset(DyArray* pArr);//shrink
    void       DyArrayClear(DyArray* pArr);//not shrink
    void       DyArrayResetCustom(DyArray* pArr,DataDestroyFunc pDataDestroy);
    void       DyArrayClearCustom(DyArray* pArr,DataDestroyFunc pDataDestroy);//not shrink

#endif

 

CP_TRUE : CP_FALSE; } /************************************************************************************************** 【函数名】: DyArrayGetLast 【描写叙述】: 获取数组最后一个元素 【參数】: pArr: the array's address. ppData: out parameter, to record the element's pointer. 【返回值】: true or false. ***************************************************************************************************/ cp_bool DyArrayGetLast(DyArray* pArr,void** ppData) { return DyArrayGetByIndex(pArr,pArr->m_nSize-1,ppData) ? CP_TRUE : CP_FALSE; } /************************************************************************************************** 【函数名】:DyArraySetByIndex 【描写叙述】: 设置数组元素by index 【參数】: pArr: the array's address. nIndex: the element's position. pData: the element's pointer. 【返回值】: true or false. ***************************************************************************************************/ cp_bool DyArraySetByIndex(DyArray* pArr, cp_int32 nIndex, void* pData) { //if the input parameter is invalid, return. if(!pArr || nIndex < 0) { return CP_FALSE; } pArr->m_ppData[nIndex] = pData;//find the related position and set its value. return CP_TRUE; } /************************************************************************************************** 【函数名】: DyArrayLength 【描写叙述】:获取数组的长度 【參数】: pArr: the array's address. 【返回值】: 数组长度. ***************************************************************************************************/ cp_int32 DyArrayLength(DyArray* pArr) { return pArr ? pArr->m_nSize : -1; } /************************************************************************************************** 【函数名】: DyArrayFind 【描写叙述】:查找数组中的指定元素 【參数】: pArr: the array's address. pCmp: the callback function to compare the data. pData: the search destination in the array. 【返回值】:假设成功返回位置,否则返回-1 ***************************************************************************************************/ cp_int32 DyArrayFind(DyArray* pArr, DataCmpFunc pCmp,void *pData) { cp_int32 i; //if the input parameter is invalid, return. if(!pArr) { return -1; } //visit each one to find the right one. for(i=0; i<pArr->m_nSize;i++) { if(pCmp) { if(pCmp(pArr->m_ppData[i],pData) == CP_TRUE) { return i; } }else { //if NO compare funciton, just compare the address. if(pArr->m_ppData[i] == pData) { return i; } } } return -1; } /************************************************************************************************** 【函数名】: DyArrayForEach 【描写叙述】:遍历数组 【參数】: pArr: the array's address. pVisit: the callback function to visit the data. 【返回值】:假设成功返回true,否则false ***************************************************************************************************/ cp_bool DyArrayForEach(DyArray* pArr, DataVisitFunc pVisit) { cp_int32 i; //if the input parameter is invalid, return. if(!pArr || !pVisit) { return CP_FALSE; } //visit each one with the visit function. for(i=0; i<pArr->m_nSize;i++) { pVisit(pArr->m_ppData[i]); } return CP_TRUE; } /************************************************************************************************** 【函数名】: DyArrayDestroy 【描写叙述】:销毁整个数组 【參数】: pArr: the array's address. 【返回值】:NA ***************************************************************************************************/ void DyArrayDestroy(DyArray* pArr) { cp_int32 i; //if the input parameter is invalid, return. if(!pArr) { return; } //Using destroy function to destroy each element's memory. if(pArr->m_fDestroy) { for(i=0; i<pArr->m_nSize; i++) { pArr->m_fDestroy(pArr->m_ppData[i]); } } //free the array. FREEFUN(pArr->m_ppData); pArr->m_ppData = NULL; FREEFUN(pArr); pArr = NULL; } /************************************************************************************************** 【函数名】: DyArrayDestroyCustom 【描写叙述】:使用用户函数。小围数组 【參数】: pArr: the array's address. pDataDestroy: user's destroy function. 【返回值】:NA ***************************************************************************************************/ void DyArrayDestroyCustom(DyArray* pArr,DataDestroyFunc pDataDestroy) { cp_int32 i; //if the input parameter is invalid, return. if(!pArr) { return; } //Using destroy function to destroy each element's memory. if(pDataDestroy) { for(i=0; i<pArr->m_nSize;i++) { pDataDestroy(pArr->m_ppData[i]); } } //free the array. FREEFUN(pArr->m_ppData); pArr->m_ppData = NULL; FREEFUN(pArr); } /************************************************************************************************** 【函数名】: DyArrayExpand 【描写叙述】:扩展数组 【參数】: pArr: the array's address. nNeed: the needed new size. 【返回值】:假设成功返回ture否则返回false ***************************************************************************************************/ cp_bool DyArrayExpand(DyArray* pArr, cp_int32 nNeed) { cp_int32 allocSize = 0; void** data = NULL; //if the input parameter is invalid, return. if(!pArr) { return CP_FALSE; } //if need, expand to 1.5 times of the original size. if((pArr->m_nSize + nNeed) > pArr->m_nAllocSize) { allocSize = pArr->m_nAllocSize + (pArr->m_nAllocSize>>1); data = (void**)REALLOCFUN(pArr->m_ppData, sizeof(void*) * allocSize); if(data != NULL) { //clear the expanded space of the new memory. MEMSETFUN(data+pArr->m_nAllocSize,0,(allocSize-pArr->m_nAllocSize)*sizeof(void*)); pArr->m_ppData = data; pArr->m_nAllocSize = allocSize; } } return ((pArr->m_nSize + nNeed) <= pArr->m_nAllocSize) ? CP_TRUE : CP_FALSE; } /************************************************************************************************** 【函数名】: DyArrayInsert 【描写叙述】:插入数组by index 【參数】: pArr: the array's address. nIndex: the position in the array to insert new data. pData: the data to be inserted. 【返回值】:假设成功返回true否则false ***************************************************************************************************/ cp_bool DyArrayInsert(DyArray* pArr, cp_int32 nIndex, void* pData) { cp_bool bRet = CP_FALSE; cp_int32 nCursor = nIndex; cp_int32 i; //if the input parameter is invalid, return. if(!pArr) { return CP_FALSE; } //get the right cursor. nCursor = nCursor < pArr->m_nSize ? nCursor : pArr->m_nSize; if(DyArrayExpand(pArr, 1) == CP_TRUE) { //move all the elements after the cursor to the next positon. for(i = pArr->m_nSize; i > nCursor; i--) { pArr->m_ppData[i] = pArr->m_ppData[i-1]; } //set the cursor's value. pArr->m_ppData[nCursor] = pData; pArr->m_nSize++; bRet = CP_TRUE; } return bRet; } /************************************************************************************************** 【函数名】: DyArrayPrepend 【描写叙述】:在数组開始加入一个数据 【參数】: pArr: the array's address. pData: the data to be added. 【返回值】:假设成功返回ture,否则false ***************************************************************************************************/ cp_bool DyArrayPrepend(DyArray* pArr, void* pData) { return DyArrayInsert(pArr,0,pData) ? CP_TRUE:CP_FALSE; } /************************************************************************************************** 【函数名】: DyArrayAppend 【描写叙述】:加入数据到数组末尾 【參数】: pArr: the array's address. pData: the data to be added. 【返回值】:假设成功返回true。否则false ***************************************************************************************************/ cp_bool DyArrayAppend(DyArray* pArr, void* pData) { return DyArrayInsert(pArr,pArr->m_nSize,pData) ?

CP_TRUE:CP_FALSE; } /************************************************************************************************** 【函数名】: DyArrayShrink 【描写叙述】:缩减数组 【參数】: pArr: the array's address. 【返回值】:ture 或者false ***************************************************************************************************/ cp_bool DyArrayShrink(DyArray* pArr) { cp_int32 nAllocSize = 0; void** pData = NULL; //if the input 【參数】 is invalid, return. if(!pArr) { return CP_FALSE; } //if need, shrink the array to 1.5 times of elements number. if((pArr->m_nSize < (pArr->m_nAllocSize >> 1)) && (pArr->m_nAllocSize > MIN_PRE_ALLOCATE_SIZE)) { nAllocSize = pArr->m_nSize + (pArr->m_nSize >> 1); pData = (void**)REALLOCFUN(pArr->m_ppData, sizeof(void*) * nAllocSize); if(pData != NULL) { //clear memory of the unused space of new memory. MEMSETFUN(pData+pArr->m_nSize,0,(nAllocSize-pArr->m_nSize)*sizeof(void*)); pArr->m_ppData = pData; pArr->m_nAllocSize = nAllocSize; } } return CP_TRUE; } /************************************************************************************************** 【函数名】: DyArrayDelete 【描写叙述】:删除元素by index 【參数】: pArr: the array's address. nIndex: the position in the array to delete useless data. 【返回值】:ture 或者false ***************************************************************************************************/ cp_bool DyArrayDelete(DyArray* pArr, cp_int32 nIndex) { cp_int32 i; //if the input parameter is invalid, return. if(!pArr) { return CP_FALSE; } //destroy the element with destroy function. if(pArr->m_fDestroy) { pArr->m_fDestroy(pArr->m_ppData[nIndex]); } //move the elements after 'nIndex' to the previous one. for(i = nIndex; (i+1) < pArr->m_nSize; i++) { pArr->m_ppData[i] = pArr->m_ppData[i+1]; } //set the last one to null. pArr->m_ppData[i] = NULL; pArr->m_nSize--; //if need ,shrink the size. DyArrayShrink(pArr); return CP_TRUE; } /************************************************************************************************** 【函数名】: DyArrayDeleteEx 【描写叙述】:删除元素by index (扩展) 【參数】: pArr: the array's address. nIndex: the position in the array to delete useless data. nEdn: 【返回值】:ture 或者false ***************************************************************************************************/ cp_bool DyArrayDeleteEx(DyArray* pArr, cp_int32 nBegin,cp_int32 nEnd) { cp_int32 i,nLen = 0; //if the input parameter is invalid, return. //if(!pArr && nBegin>nEnd && nBegin<0 && nBegin>=pArr->m_nSize && nEnd<0 && nEnd>=pArr->m_nSize) if(!pArr) { return CP_FALSE; } //destroy the element with destroy function. if(pArr->m_fDestroy) { for(i=nBegin; i<=nEnd; i++) { pArr->m_fDestroy(pArr->m_ppData[i]); } } //move the elements after 'nIndex' to the previous one. nLen = nEnd - nBegin + 1; for(i = nBegin; (i+nLen) < pArr->m_nSize; i++) { pArr->m_ppData[i] = pArr->m_ppData[i+nLen]; } //set the last one to null. //pArr->m_ppData[i] = NULL; pArr->m_nSize -= nLen; //if need ,shrink the size. DyArrayShrink(pArr); return CP_TRUE; } /************************************************************************************************** 【函数名】: DyArrayReset 【描写叙述】:清除数组数据,缩减数组到原始大小 【參数】: pArr: the array's address. 【返回值】: none. ***************************************************************************************************/ void DyArrayReset(DyArray* pArr) { cp_int32 i; void** pData = NULL; //if the input parameter is invalid, return. if(!pArr) { return; } //reset all the elements with destroy function. if(pArr->m_fDestroy) { for(i=0; i<pArr->m_nSize;i++) { pArr->m_fDestroy(pArr->m_ppData[i]); } } pArr->m_nSize = 0; //if need, shrink the size. if(pArr->m_nAllocSize > MIN_PRE_ALLOCATE_SIZE) { pData = (void**)REALLOCFUN(pArr->m_ppData, sizeof(void*) * MIN_PRE_ALLOCATE_SIZE); if(pData != NULL) { pArr->m_ppData = pData; pArr->m_nAllocSize = MIN_PRE_ALLOCATE_SIZE; } if(pArr->m_ppData) { MEMSETFUN(pArr->m_ppData,0,sizeof(void*)*pArr->m_nAllocSize); } } } /************************************************************************************************** 【函数名】: DyArrayClear 【描写叙述】:清除数组数据。不缩减数组到原始大小 【參数】: pArr: the array's address. 【返回值】:NA ***************************************************************************************************/ void DyArrayClear(DyArray* pArr) { cp_int32 i; void** pData = NULL; //if the input parameter is invalid, return. if(!pArr) { return; } //reset all the elements with destroy function. if(pArr->m_fDestroy) { for(i=0; i<pArr->m_nSize;i++) { pArr->m_fDestroy(pArr->m_ppData[i]); } } pArr->m_nSize = 0; } /************************************************************************************************** 【函数名】: DyArrayResetCustom 【描写叙述】:清除数组使用用户函数,缩减数组到原始大小 【參数】: pArr: the array's address. pDataDestroy: user's destroy function. 【返回值】:NA ***************************************************************************************************/ void DyArrayResetCustom(DyArray* pArr,DataDestroyFunc pDataDestroy) { cp_int32 i; void** pData = NULL; //if the input parameter is invalid, return. if(!pArr) { return; } //reset all the elements with destroy function. if(pDataDestroy) { for(i=0; i<pArr->m_nSize;i++) { pDataDestroy(pArr->m_ppData[i]); } } pArr->m_nSize = 0; //if need, shrink the size. if(pArr->m_nAllocSize > MIN_PRE_ALLOCATE_SIZE) { pData = (void**)REALLOCFUN(pArr->m_ppData, sizeof(void*) * MIN_PRE_ALLOCATE_SIZE); if(pData != NULL) { pArr->m_ppData = pData; pArr->m_nAllocSize = MIN_PRE_ALLOCATE_SIZE; } if(pArr->m_ppData) { MEMSETFUN(pArr->m_ppData,0,sizeof(void*)*pArr->m_nAllocSize); } } } /************************************************************************************************** 【函数名】: DyArrayClearCustom 【描写叙述】:清除数组使用用户函数,不缩减数组到原始大小 【參数】: pArr: the array's address. pDataDestroy: user's destroy function. 【返回值】:NA ***************************************************************************************************/ void DyArrayClearCustom(DyArray* pArr,DataDestroyFunc pDataDestroy) { cp_int32 i; void** pData = NULL; //if the input parameter is invalid, return. if(!pArr) { return; } //reset all the elements with destroy function. if(pDataDestroy) { for(i=0; i<pArr->m_nSize;i++) { pDataDestroy(pArr->m_ppData[i]); } } pArr->m_nSize = 0; }






本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/5130708.html,如需转载请自行联系原作者

相关实践学习
基于Hologres轻松玩转一站式实时仓库
本场景介绍如何利用阿里云MaxCompute、实时计算Flink和交互式分析服务Hologres开发离线、实时数据融合分析的数据大屏应用。
阿里云实时数仓实战 - 项目介绍及架构设计
课程简介 1)学习搭建一个数据仓库的过程,理解数据在整个数仓架构的从采集、存储、计算、输出、展示的整个业务流程。 2)整个数仓体系完全搭建在阿里云架构上,理解并学会运用各个服务组件,了解各个组件之间如何配合联动。 3&nbsp;)前置知识要求 &nbsp; 课程大纲 第一章&nbsp;了解数据仓库概念 初步了解数据仓库是干什么的 第二章&nbsp;按照企业开发的标准去搭建一个数据仓库 数据仓库的需求是什么 架构 怎么选型怎么购买服务器 第三章&nbsp;数据生成模块 用户形成数据的一个准备 按照企业的标准,准备了十一张用户行为表 方便使用 第四章&nbsp;采集模块的搭建 购买阿里云服务器 安装 JDK 安装 Flume 第五章&nbsp;用户行为数据仓库 严格按照企业的标准开发 第六章&nbsp;搭建业务数仓理论基础和对表的分类同步 第七章&nbsp;业务数仓的搭建&nbsp; 业务行为数仓效果图&nbsp;&nbsp;
相关文章
|
9天前
|
安全 C语言
【C语言】如何规避野指针
【C语言】如何规避野指针
17 0
|
9天前
|
存储 编译器 C语言
C语言之数组
C语言之数组
19 0
|
10天前
|
C语言
C语言:数组和指针笔试题解析(包括一些容易混淆的指针题目)
C语言:数组和指针笔试题解析(包括一些容易混淆的指针题目)
|
4天前
|
存储 程序员 C语言
【C 言专栏】C 语言指针的深度解析
【4月更文挑战第30天】C 语言中的指针是程序设计的关键,它如同一把钥匙,提供直接内存操作的途径。指针是存储其他变量地址的变量,通过声明如`int *ptr`来使用。它们在动态内存分配、函数参数传递及数组操作中发挥重要作用。然而,误用指针可能导致错误,如空指针引用和内存泄漏。理解指针的运算、与数组和函数的关系,以及在结构体中的应用,是成为熟练 C 语言程序员的必经之路。虽然挑战重重,但掌握指针将增强编程效率和灵活性。不断实践和学习,我们将驾驭指针,探索更广阔的编程世界。
|
6天前
|
算法 搜索推荐 程序员
C语言中的函数指针和回调函数
C语言中的函数指针和回调函数
9 2
|
9天前
|
存储 编译器 C语言
【C语言】初步解决指针疑惑
【C语言】初步解决指针疑惑
7 0
|
10天前
|
存储 C语言
指针深入解析(C语言基础)带你走进指针,了解指针
指针深入解析(C语言基础)带你走进指针,了解指针
|
10天前
指针指向数组
指针指向数组
13 0
|
10天前
|
C语言 C++
C语言:指针运算笔试题解析(包括令人费解的指针题目)
C语言:指针运算笔试题解析(包括令人费解的指针题目)
|
10天前
|
C语言
数组深入剖析(C语言基础入门)
数组深入剖析(C语言基础入门)