免费资源网,https://freexyz.cn/
目录
  • 前言
  • 一、接口定义
    • 1、创建切片
    • 2、销毁切片
    • 3、添加元素
    • 4、切片长度
    • 5、切片容量
  • 二、完整代码
    • slice.h
    • slice.c
  • 三、使用示例
    • 1、一般使用流程
    • 2、直接append
    • 3、自定义类型
  • 总结

    前言

    由于c语言没有集合类的标准库,需要用时只能自己实现,由于c语言没有泛型,使得实现的集合类接口通常比较另类,很多时候都需要二级指针作为参数,且不支持字面量作为参数,使用时心智负担较重。本文参考go语言的slice,找到了一种非常简化的动态数组接口,可以极大的方便使用。

    一、接口定义

    1、创建切片

    指定元素类型,以及容量即可以创建切片,返回是一个数组

    /// <summary>
    /// 创建切片
    /// </summary>
    /// <param name="t">元素类型</param>
    /// <param name="cap">切片容量</param>
    /// <returns>切片数组</returns>
    #define make(t,cap)
    

    2、销毁切片

    与go语言不同,c语言需要管理内存。用完后的切片需要销毁。

    /// <summary>
    /// 销毁切片
    /// </summary>
    /// <param name="a">切片数组</param>
    #define unmake(a)
    

    3、添加元素

    可以添加元素也可以添加数组,数组长度会自动增长。

    /// <summary>
    /// 添加元素、数组
    /// </summary>
    /// <param name="a">切片数组</param>
    /// <param name="e">元素、数组</param>
    /// <param name="l">[可选]数组长度,e为数组时需要此项</param>
    #define append(...)
    

    4、切片长度

    获取切片长度

    /// <summary>
    /// 切片长度
    /// </summary>
    /// <param name="a">切片数组</param>
    /// <returns>切片长度</returns>
    #define len(a)
    

    5、切片容量

    获取切片容量

    /// <summary>
    /// 切片容量
    /// </summary>
    /// <param name="a">切片数组</param>
    /// <returns> 切片容量</returns>
    #define cap(a)
    

    二、完整代码

    slice.h

    #ifndef SLICE_H
    #define SLICE_H
    #include<stddef.h>
    /************************************************************************
    * @Project:      Slice
    * @Decription:  切片
    * 相当于动态数组,用法与go语言的slice类似
    * @Verision:      v1.0.0
    * @Author:      Xin Nie
    * @Create:      2024/03/25 01:02:00
    * @LastUpdate:  2024/03/25 01:02:00
    ************************************************************************
    * Copyright @ 2024. All rights reserved.
    ************************************************************************/
    /// <summary>
    /// 创建切片
    /// </summary>
    /// <param name="t">元素类型</param>
    /// <param name="cap">切片容量</param>
    /// <returns>切片数组</returns>
    #define make(t,cap)_slice_make(sizeof(t),cap)
    /// <summary>
    /// 销毁切片
    /// </summary>
    /// <param name="a">切片数组</param>
    #define unmake(a)_slice_umake(a);a=0
    /// <summary>
    /// 添加元素、数组
    /// </summary>
    /// <param name="a">切片数组</param>
    /// <param name="e">元素、数组</param>
    /// <param name="l">[可选]数组长度,e为数组时需要此项</param>
    #define append(...)_ACF_COUNT_ARG(__VA_ARGS__)
    /// <summary>
    /// 切片长度
    /// </summary>
    /// <param name="a">切片数组</param>
    /// <returns>切片长度</returns>
    #define len(a) _slice_len( a)
    /// <summary>
    /// 切片容量
    /// </summary>
    /// <param name="a">切片数组</param>
    /// <returns>切片容量</returns>
    #define cap(a) _slice_cap( a)
    ///私有方法
    #define _ACF_ARG_T(t)  t 
    #define _ACF_ARG_N(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,N,...)  N
    #define _ARG_N_HELPER(...)  _ACF_ARG_T(_ACF_ARG_N(__VA_ARGS__))  
    #define _ACF_COUNT_ARG(...)  _ARG_N_HELPER(__VA_ARGS__,16,15,14,13,12,11,10,9,8,7,6,5,4,_APPEND_ARRAY(__VA_ARGS__),_APPEND(__VA_ARGS__),1 ,0) 
    #define _APPEND(a,e)a=_slice_append(a,0,sizeof(*a));a[len(a)-1] = e
    #define _APPEND_ARRAY(a,e,l)_slice_appendArray(a,sizeof(*e),e,l)
    void* _slice_make(size_t elementSize, size_t sliceCap);
    void* _slice_append(void* array, void* element, size_t elementSize);
    void* _slice_appendArray(void* array, size_t elementSize, void* array2, size_t array2Size);
    size_t _slice_len(void* array);
    size_t _slice_cap(void* array);
    void _slice_umake(void* array);
    #endif

    slice.c

    #include "slice.h"
    #include<stdlib.h>
    typedef struct Slice {
    	int length;
    	int capacity;
    	int elementSize;
    }Slice;
    
    void* _slice_make(size_t elementSize, size_t sliceCap) {
    	Slice* slice = malloc(elementSize * sliceCap + sizeof(Slice));
    	if (slice)
    	{
    		slice->capacity = sliceCap;
    		slice->elementSize = elementSize;
    		slice->length = 0;
    		return slice + 1;
    	}
    	return NULL;
    }
    
    void* _slice_append(void* array, void* element, size_t elementSize) {
    	Slice* slice = (array ? (Slice*)array : (Slice*)_slice_make(elementSize, 4)) - 1;
    	if (slice->capacity == slice->length) {
    		slice->capacity = slice->capacity == 0 ? 4 : slice->capacity * 2;
    		if ((slice = realloc(slice, slice->capacity * slice->elementSize + sizeof(Slice))) == NULL)return NULL;
    	}
    	if(element)
    	{
    		char* p = slice + 1;
    		memcpy(p + slice->elementSize * slice->length, element, slice->elementSize);
    	}
    	slice->length++;
    	return  slice + 1;
    }
    
    void* _slice_appendArray(void* array, size_t elementSize, void* array2, size_t array2Size) {
    	Slice* slice = (array ? (Slice*)array : (Slice*)_slice_make(elementSize, array2Size)) - 1;
    	int newCap = slice->capacity;
    	while (newCap < slice->length+ array2Size) {
    		newCap << 1;
    	}
    	if (slice->capacity < newCap) {
    		slice->capacity = newCap;
    		if ((slice = realloc(slice, slice->capacity * slice->elementSize + sizeof(Slice))) == NULL)return NULL;
    	}
    	char* p = slice + 1;
    	memcpy(p + slice->elementSize * slice->length, array2, slice->elementSize * array2Size);
    	slice->length += array2Size;
    	return  slice + 1;
    }
    
    size_t _slice_len(void* array) {
    	if (!array)return 0;
    	Slice* slice = (Slice*)array - 1;
    	return slice->length;
    }
    
    size_t _slice_cap(void* array) {
    	if (!array)return 0;
    	Slice* slice = (Slice*)array - 1;
    	return slice->capacity;
    }
    
    void _slice_umake(void* array) {
    	if (array)
    	{
    		Slice* slice = (Slice*)array - 1;
    		free(slice);
    	}
    }
    

    三、使用示例

    1、一般使用流程

    #include"slice.h"
    #include<stdio.h>
    void main() {
        //创建切片,返回的是数组完全可以当成数组使用,通过len可以获取数组长度。
        int* a = make(int, 0);
        int b[] = { 1,2,3 };
        //添加元素
        a = append(a, 6510);
        //添加数组
        a = append(a, b, 3);
        //循环添加元素
        for (int i = 0; i < 1024; i++)
        {
            a = append(a, i);
        }
        //遍历切片
        for (int i = 0; i < len(a); i++)
        {
            printf("%d ", a[i]);
        }
        //销毁切片
        unmake(a);
    }

    效果预览

    C语言实现切片数组的示例详解

    2、直接append

    #include"slice.h"
    #include<stdio.h>
    void main() {
    
    	//数组为空时可以直接通过append产生切片
    	int* a = NULL;
    	int b[] = { 1,2,3 };
    	//添加元素
    	a = append(a, 6510);
    	//添加数组
    	a = append(a, b, 3);
    	//循环添加元素
    	for (int i = 0; i < 1024; i++)
    	{
    		a = append(a, i);
    	}
    	//遍历切片
    	for (int i = 0; i < len(a); i++)
    	{
    		printf("%d ", a[i]);
    	}
    	//销毁切片
    	unmake(a);
    }
    

    3、自定义类型

    typedef struct VideoScale {
        int align;
        int width;
        int height;
        enum AVPixelFormat format;
        struct SwsContext* ctx;
        AVFrame* frame;
    } VideoScale;
    
    VideoScale* video_scales = NULL;
    VideoScale t;
    video_scales = append(video_scales, t);
    for (int i = 0; i < len(video_scales);i++) {
        int frame = video_scales[i].frame;
        //其他操作略...
    }
    unmake(is->video_scales);
    

    总结

    本文仅仅简单实现了切片,这种方式使用动态数组会很方便,这是一种新的思路,其他的集合类型也可以考虑用这种方式实现,尤其是能够统一一套接口,且简单易用,将能极大的提高c语言开发效率。

    以上就是C语言实现切片数组的示例详解的详细内容,更多关于C语言切片的资料请关注其它相关文章!

    免费资源网,https://freexyz.cn/
    声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。