引言 - 动态数组切入

  开发中动态类型无外乎list 或者 vector, 这里就是在C中实现vector结构容器部分.

对于C中使用的数据结构, 可以参照下面感觉很不错框架源码学习 , 感觉是<<C接口与实现>>的标准Demo

写的很清楚易懂, 给人一种铺面而来的美感.

关于动态数组设计的总思路, 主要体现在下面的数组结构 struct array {}; 中

struct array {
    void *        as;        /* 存储数组具体内容首地址 */
    unsigned    len;    /* 当前数组的长度 */
    unsigned    size;   /* 当前数组容量大小 */
    size_t        alloc;    /* 每个元素字节大小 */
};

 as 保存动态数组的首地址, len保存当前动态数组中元素个数, size表示动态数组容量(内存总大小), alloc记录每次分配多大内存.

是不是很简单, 数据结构一但确定什么都OK了. 在具体分析之前先扩展讲解一下 C11的内联函数. 内联函数是应用场景很多, 宏一般的性能, 并且还可以当函数调试!

// 内联函数声明部分, 不需要加inline
extern void heoo(void);

// 内联函数定义部分
inline void
heoo(void) {
  ... 
}

上面就是内联函数的套路, 在定义的时候加上内联属性inline. 这种做法是为了VS2015 和 GCC5.3 对于inline 语法解析的统一. 

具体看下面搜索到的老外给的资料 

    内联解析warning资料 http://www.avrfreaks.net/forum/declaring-function-extern-inline-header-file

Computer science 还是老外厉害些, 国内最屌, 也只是国外一线的水准. 目前猜测的原因是, 祖国就一个, 国外太多了. O(∩_∩)O哈哈~

 

前言  - 接口分析

  具体设计了下面几种接口, 基本够用了.也很好用.

/*
 * 返回创建数组对象
 * size        : 创建数组的总大小个数
 * alloc    : 数组中每个元素的字节数
 *            : 返回创建的数组对象
 */
extern array_t array_new(unsigned size, size_t alloc);

/*
 * 销毁这个创建的数组对象
 * a        : 创建的数组对象
 */
extern void array_delete(array_t a);

/*
 * 重新构建一个数组对象
 * a        : 可变数组对象
 * size        : 新可变数组总长度
 */
extern void array_newinit(array_t a, unsigned size);

/*
 * 得到节点elem在数组中索引
 * a        : 可变数组对象
 * elem        : 查询元素
 *            : 返回查询到位置
 */
extern unsigned array_idx(array_t a, void * elem);

/*
 * 为可变数组插入一个元素, 并返回这个元素的首地址
 * a        : 可变数组对象
 *            : 返回创建对象位置
 */
extern void * array_push(array_t a);

/*
 * 弹出一个数组元素
 * a        : 可变数组对象
 *            : 返回弹出数组元素节点
 */
extern void * array_pop(array_t a);

/*
 * 按照索引得到数组元素
 * a        : 可变数组对象
 * idx        : 索引位置
 *            : 返回查询到数据
 */
extern void * array_get(array_t a, unsigned idx);

/*
 * 得到数组顶的元素
 * a        : 可变数组对象
 *            : 返回得到元素
 */
extern void * array_top(array_t a);

/*
 * 两个数组进行交换
 * a        : 数组a
 * b        : 数组b
 */
extern void array_swap(array_t a, array_t b);

/*
 * 数组进行排序
 * a        : 数组对象
 * compare    : 比对规则
 */
extern void array_sort(array_t a, icmp_f compare);

/*
 * 数组进行遍历
 * a        : 可变数组对象
 * func        : 执行每个结点函数, typedef flag_e    (* each_f)(void * node, void * arg);
 * arg        : 附加参数
 *            : 返回操作结果状态码
 */
flag_e array_each(array_t a, each_f func, void * arg);

 围绕创建, 销毁, 添加元素, 删除元素, 交换, 遍历, 排序等操作. 具体参看 array.h 文件 

#ifndef _H_SIMPLEC_ARRAY
#define _H_SIMPLEC_ARRAY

#include <stdlib.h>

#define sm_free free

typedef enum {
    RT_SuccessBase    = 00,                //结果正确的返回宏
    RT_ErrorBase    = -1,                //错误基类型, 所有错误都可用它, 在不清楚的情况下
    RT_ErrorParam    = -2,                //调用的参数错误
    RT_ErrorMalloc    = -3,                //内存分配错误
    RT_ErrorFopen    = -4,                //文件打开失败    
    RT_ErrorClose    = -5,                //文件描述符读取关闭, 读取完毕也会返回这个
} flag_e;

// icmp_f 最好 是 int cmp(const void * ln, const void * rn); 标准结构
typedef int        (* icmp_f)();
// 循环操作函数, arg 外部参数, node 内部节点
typedef flag_e    (* each_f)(void * node, void * arg);

struct array {
    void *        as;        /* 存储数组具体内容首地址 */
    unsigned    len;    /* 当前数组的长度 */
    unsigned    size;   /* 当前数组容量大小 */
    size_t        alloc;    /* 每个元素字节大小 */
};

// 定义可变数组类型 对象
typedef struct array * array_t;

/*
 * 在栈上创建对象 ##var
 * var        : 创建对象名称
 * size        : 创建对象总长度
 * alloc    : 每个元素分配空间大小
 */
#define ARRAY_NEW(var, size, alloc) \
    struct array $__##var = { NULL, 0, 0, alloc }, * var = &$__##var;\
    array_newinit(var, size)
#define ARRAY_DELETE(var) \
    sm_free(var->as)

/*
 * 返回创建数组对象
 * size        : 创建数组的总大小个数
 * alloc    : 数组中每个元素的字节数
 *            : 返回创建的数组对象
 */
extern array_t array_new(unsigned size, size_t alloc);

/*
 * 销毁这个创建的数组对象
 * a        : 创建的数组对象
 */
extern void array_delete(array_t a);

/*
 * 重新构建一个数组对象
 * a        : 可变数组对象
 * size        : 新可变数组总长度
 */
extern void array_newinit(array_t a, unsigned size);

/*
 * 得到节点elem在数组中索引
 * a        : 可变数组对象
 * elem        : 查询元素
 *            : 返回查询到位置
 */
extern unsigned array_idx(array_t a, void * elem);

/*
 * 为可变数组插入一个元素, 并返回这个元素的首地址
 * a        : 可变数组对象
 *            : 返回创建对象位置
 */
extern void * array_push(array_t a);

/*
 * 弹出一个数组元素
 * a        : 可变数组对象
 *            : 返回弹出数组元素节点
 */
extern void * array_pop(array_t a);

/*
 * 按照索引得到数组元素
 * a        : 可变数组对象
 * idx        : 索引位置
 *            : 返回查询到数据
 */
extern void * array_get(array_t a, unsigned idx);

/*
 * 得到数组顶的元素
 * a        : 可变数组对象
 *            : 返回得到元素
 */
extern void * array_top(array_t a);

/*
 * 两个数组进行交换
 * a        : 数组a
 * b        : 数组b
 */
extern void array_swap(array_t a, array_t b);

/*
 * 数组进行排序
 * a        : 数组对象
 * compare    : 比对规则
 */
extern void array_sort(array_t a, icmp_f compare);

/*
 * 数组进行遍历
 * a        : 可变数组对象
 * func        : 执行每个结点函数, typedef flag_e    (* each_f)(void * node, void * arg);
 * arg        : 附加参数
 *            : 返回操作结果状态码
 */
flag_e array_each(array_t a, each_f func, void * arg);

#endif // !_H_SIMPLEC_ARRAY
View Code

相关文章:

  • 2021-11-20
  • 2022-12-23
  • 2022-12-23
  • 2022-01-03
  • 2022-12-23
  • 2021-10-16
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2021-11-30
  • 2022-02-01
  • 2021-07-06
相关资源
相似解决方案