最近闲着没事写了些C标准接口代码 需要的话可以拿着用,我大概测了下功能 没问题,也没有内存泄漏,如果有问题欢迎讨论
链表相关接口实现代码
linklis.c 使用需要替换log接口和返回值接口
/*********************************************************************
* 版权所有 (c) 2021-2022 axk. 保留所有版权
* 文件名称: linklist.c
* 文件描述: 标准链表操作接口实现
* 作 者: axk
* 创建日期: 2022/11/21
* 作 者 日 期 版 本 修改摘要
* axk 2022/11/21 1.0 文件创建
**********************************************************************/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include "axk_base_data_type.h"
#include "linklist.h"
/***********************************************************************
* 函数名称: list_node_free
* 功能描述: 释放链表节点内存
* 输 入:node 需要释放的节点
* 输 出: 无
* 返 回 值: void
* 其 他:
* 日 期: 2022/11/21
* 作 者: axk
***********************************************************************/
void list_node_free(list_node_s_type* node)
{
if (NULL != node)
{
if (NULL != node->data)
{
if (NULL != node->free_cb)
{
node->free_cb(node->data);
}
}
node->next = NULL;
node->prev = NULL;
free(node);
node = NULL;
}
}
/***********************************************************************
* 函数名称: list_head_insert
* 功能描述: 向链表头部插入一个节点
* 输 入:list_head 链表头
* data 节点数据内容
* free_cb 节点数据free函数 (如果节点释放不需要free数据则填空)
* 输 出: 无
* 返 回 值: 成功返回0 失败返回对应错误码
* 其 他:
* 日 期: 2022/11/22
* 作 者: axk
***********************************************************************/
int list_head_insert(list_head_s_type* list_head, void* data, list_data_free_cb free_cb)
{
list_node_s_type* data_node = NULL;
list_node_s_type* tmp_node = NULL;
if (NULL == list_head || NULL == data)
{
AXK_LOGE("list_head or data is NULL!");
return AXK_ERR_PARAMETER;
}
data_node = (list_node_s_type*)malloc(sizeof(list_node_s_type));
if (NULL == data_node)
{
AXK_LOGE("data_node malloc failed!");
return AXK_ERR_MALLOC;
}
memset(data_node, 0x0, sizeof(list_node_s_type));
data_node->next = NULL;
data_node->prev = NULL;
data_node->data = data;
data_node->free_cb = free_cb;
if (NULL != list_head->head)
{
tmp_node = list_head->head;
list_head->head = data_node;
data_node->next = tmp_node;
tmp_node->prev = data_node;
}
else
{
list_head->head = data_node;
list_head->tail = data_node;
}
list_head->node_num++;
return AXK_SUCCESS;
}
/***********************************************************************
* 函数名称: list_tail_insert
* 功能描述: 向链表尾部插入一个节点
* 输 入:list_head 链表头
* data 节点数据内容
* free_cb 节点数据free函数 (如果节点释放不需要free数据则填空)
* 输 出: 无
* 返 回 值: 成功返回0 失败返回对应错误码
* 其 他:
* 日 期: 2022/11/22
* 作 者: axk
***********************************************************************/
int list_tail_insert(list_head_s_type* list_head, void* data, list_data_free_cb free_cb)
{
list_node_s_type* data_node = NULL;
list_node_s_type* tmp_node = NULL;
if (NULL == list_head || NULL == data)
{
AXK_LOGE("list_head or data is NULL!");
return AXK_ERR_PARAMETER;
}
data_node = (list_node_s_type*)malloc(sizeof(list_node_s_type));
if (NULL == data_node)
{
AXK_LOGE("data_node malloc failed!");
return AXK_ERR_MALLOC;
}
memset(data_node, 0x0, sizeof(list_node_s_type));
data_node->next = NULL;
data_node->prev = NULL;
data_node->data = data;
data_node->free_cb = free_cb;
if (NULL != list_head->tail)
{
list_head->tail->next = data_node;
data_node->prev = list_head->tail;
list_head->tail = data_node;
}
else
{
list_head->head = data_node;
list_head->tail = data_node;
}
list_head->node_num++;
return AXK_SUCCESS;
}
/***********************************************************************
* 函数名称: list_head_del
* 功能描述: 从链表头部删除一个节点
* 输 入:list_head 链表头
* 输 出: 无
* 返 回 值: 成功返回0 失败返回对应错误码
* 其 他:
* 日 期: 2022/11/22
* 作 者: axk
***********************************************************************/
int list_head_del(list_head_s_type* list_head)
{
list_node_s_type* tmp_node = NULL;
if (NULL == list_head)
{
AXK_LOGE("list_head is NULL!");
return AXK_ERR_PARAMETER;
}
if (NULL == list_head->head)
{
AXK_LOGE("list_head is empty!");
return AXK_SUCCESS;
}
tmp_node = list_head->head;
if (NULL != tmp_node->next)
{
list_head->head = tmp_node->next;
list_head->head->prev = NULL;
}
else
{
list_head->tail = NULL;
list_head->head = NULL;
}
list_node_free(tmp_node);
list_head->node_num--;
return AXK_SUCCESS;
}
/***********************************************************************
* 函数名称: list_tail_del
* 功能描述: 从链表尾部删除一个节点
* 输 入:list_head 链表头
* 输 出: 无
* 返 回 值: 成功返回0 失败返回对应错误码
* 其 他:
* 日 期: 2022/11/22
* 作 者: axk
***********************************************************************/
int list_tail_del(list_head_s_type* list_head)
{
list_node_s_type* tmp_node = NULL;
if (NULL == list_head)
{
AXK_LOGE("list_head is NULL!");
return AXK_ERR_PARAMETER;
}
if (NULL == list_head->tail)
{
AXK_LOGE("list_head is empty!");
return AXK_SUCCESS;
}
tmp_node = list_head->tail;
if (NULL != tmp_node->prev)
{
list_head->tail = tmp_node->prev;
list_head->tail->next = NULL;
}
else
{
list_head->tail = NULL;
list_head->head = NULL;
}
list_node_free(tmp_node);
list_head->node_num--;
return AXK_SUCCESS;
}
/***********************************************************************
* 函数名称: list_del_node_by_data_addrress
* 功能描述: 根据数据地址从链表删除节点
* 输 入:list_head 链表头
data 数据指针
* 输 出: 无
* 返 回 值: 成功返回0 失败返回对应错误码
* 其 他:
* 日 期: 2022/11/22
* 作 者: axk
***********************************************************************/
int list_del_node_by_data_addrress(list_head_s_type* list_head, void* data)
{
list_node_s_type* tmp_node = NULL;
if (NULL == list_head)
{
AXK_LOGE("list_head is NULL!");
return AXK_ERR_PARAMETER;
}
if (0 == list_head->node_num)
{
AXK_LOGE("list_head is empty!");
return AXK_ERR_PARAMETER;
}
tmp_node = list_head->head;
while (NULL != tmp_node)
{
if (data == tmp_node->data)
{
if (1 == list_head->node_num)
{
list_head->head = NULL;
list_head->tail = NULL;
}
else if (tmp_node == list_head->tail)
{
list_head->tail = tmp_node->prev;
tmp_node->prev->next = NULL;
}
else if (tmp_node == list_head->head)
{
list_head->head = tmp_node->next;
tmp_node->next->prev = NULL;
}
else
{
tmp_node->next->prev = tmp_node->prev;
tmp_node->prev->next = tmp_node->next;
}
list_head->node_num--;
list_node_free(tmp_node);
break;
}
tmp_node = tmp_node->next;
}
return AXK_SUCCESS;
}
/***********************************************************************
* 函数名称: list_get_head_node
* 功能描述: 获取链表头部数据节点
* 输 入:list_head 链表头
* 输 出: 无
* 返 回 值: 成功返回头节点指针 失败返回NULL
* 其 他:
* 日 期: 2022/11/22
* 作 者: axk
***********************************************************************/
list_node_s_type* list_get_head_node(list_head_s_type* list_head)
{
if (NULL == list_head)
{
AXK_LOGE("list_head is NULL!");
return NULL;
}
return list_head->head;
}
/***********************************************************************
* 函数名称: list_get_tail_node
* 功能描述: 获取链表尾部数据节点
* 输 入:list_head 链表头
* 输 出: 无
* 返 回 值: 成功返回尾部节点指针 失败返回NULL
* 其 他:
* 日 期: 2022/11/22
* 作 者: axk
***********************************************************************/
list_node_s_type* list_get_tail_node(list_head_s_type* list_head)
{
if (NULL == list_head)
{
AXK_LOGE("list_head is NULL!");
return NULL;
}
return list_head->tail;
}
/***********************************************************************
* 函数名称: list_destory
* 功能描述: 链表销毁
* 输 入:list_head 链表头
* 输 出: 无
* 返 回 值: 成功返回0 失败返回对应错误码
* 其 他:
* 日 期: 2022/11/21
* 作 者: axk
***********************************************************************/
int list_destory(list_head_s_type* list_head)
{
list_node_s_type* tmp_node = NULL;
if (NULL == list_head)
{
AXK_LOGE("list_head is NULL!");
return AXK_ERR_PARAMETER;
}
while (0 != list_head->node_num)
{
tmp_node = list_head->tail;
if (NULL != tmp_node->prev)
{
list_head->tail = tmp_node->prev;
list_head->tail->next = NULL;
}
else
{
list_head->tail = NULL;
list_head->head = NULL;
}
list_node_free(tmp_node);
list_head->node_num--;
}
return AXK_SUCCESS;
}
/***********************************************************************
* 函数名称: list_init
* 功能描述: 链表初始化
* 输 入:list_head 链表头
* 输 出: 无
* 返 回 值: 成功返回0 失败返回对应错误码
* 其 他:
* 日 期: 2022/11/22
* 作 者: axk
***********************************************************************/
int list_init(list_head_s_type* list_head)
{
if (NULL == list_head)
{
AXK_LOGE("list head is NULL!");
return AXK_ERR_PARAMETER;
}
list_destory(list_head);
list_head->node_num = 0;
list_head->head = NULL;
list_head->tail = NULL;
return AXK_SUCCESS;
}
链表相关接口头文件
/*********************************************************************
* 版权所有 (h) 2021-2022 axk. 保留所有版权
* 文件名称: linklist.h
* 文件描述: 标准链表操作接口头文件
* 作 者: axk
* 创建日期: 2022/11/21
* 作 者 日 期 版 本 修改摘要
* axk 2022/11/21 1.0 文件创建
**********************************************************************/
#ifndef __LINK_LIST_H_
#define __LINK_LIST_H_
#include "axk_base_data_type.h"
#ifdef __cplusplus
extern "C" {
#endif
/****************************LINK_LIST 宏定义 start****************************************************/
/****************************LINK_LIST 宏定义 end****************************************************/
/****************************LINK_LIST 枚举定义 start****************************************************/
/****************************LINK_LIST 枚举定义 end****************************************************/
/****************************LINK_LIST 结构体定义 start****************************************************/
/* 释放节点数据回调函数 */
typedef void (*list_data_free_cb)(void* data);
/* 链表节点结构体 */
typedef struct list_node_s_type
{
struct list_node_s_type* next;
struct list_node_s_type* prev;
void* data;
list_data_free_cb free_cb;
} list_node_s_type;
/* 链表头结构体 */
typedef struct list_head_s_type
{
int node_num;
struct list_node_s_type* head;
struct list_node_s_type* tail;
} list_head_s_type;
/****************************LINK_LIST 结构体定义 end****************************************************/
/****************************LINK_LIST 函数声明 start****************************************************/
/***********************************************************************
* 函数名称: list_head_insert
* 功能描述: 向链表头部插入一个节点
* 输 入:list_head 链表头
* data 节点数据内容
* free_cb 节点数据free函数 (如果节点释放不需要free数据则填空)
* 输 出: 无
* 返 回 值: 成功返回0 失败返回对应错误码
* 其 他:
* 日 期: 2022/11/22
* 作 者: axk
***********************************************************************/
int list_head_insert(list_head_s_type* list_head, void* data, list_data_free_cb free_cb);
/***********************************************************************
* 函数名称: list_tail_insert
* 功能描述: 向链表尾部插入一个节点
* 输 入:list_head 链表头
* data 节点数据内容
* free_cb 节点数据free函数 (如果节点释放不需要free数据则填空)
* 输 出: 无
* 返 回 值: 成功返回0 失败返回对应错误码
* 其 他:
* 日 期: 2022/11/22
* 作 者: axk
***********************************************************************/
int list_tail_insert(list_head_s_type* list_head, void* data, list_data_free_cb free_cb);
/***********************************************************************
* 函数名称: list_head_del
* 功能描述: 从链表头部删除一个节点
* 输 入:list_head 链表头
* 输 出: 无
* 返 回 值: 成功返回0 失败返回对应错误码
* 其 他:
* 日 期: 2022/11/22
* 作 者: axk
***********************************************************************/
int list_head_del(list_head_s_type* list_head);
/***********************************************************************
* 函数名称: list_tail_del
* 功能描述: 从链表尾部删除一个节点
* 输 入:list_head 链表头
* 输 出: 无
* 返 回 值: 成功返回0 失败返回对应错误码
* 其 他:
* 日 期: 2022/11/22
* 作 者: axk
***********************************************************************/
int list_tail_del(list_head_s_type* list_head);
/***********************************************************************
* 函数名称: list_del_node_by_data_addrress
* 功能描述: 根据数据地址从链表删除节点
* 输 入:list_head 链表头
data 数据指针
* 输 出: 无
* 返 回 值: 成功返回0 失败返回对应错误码
* 其 他:
* 日 期: 2022/11/22
* 作 者: axk
***********************************************************************/
int list_del_node_by_data_addrress(list_head_s_type* list_head, void* data);
/***********************************************************************
* 函数名称: list_get_head_node
* 功能描述: 获取链表头部数据节点
* 输 入:list_head 链表头
* 输 出: 无
* 返 回 值: 成功返回头节点指针 失败返回NULL
* 其 他:
* 日 期: 2022/11/22
* 作 者: axk
***********************************************************************/
list_node_s_type* list_get_head_node(list_head_s_type* list_head);
/***********************************************************************
* 函数名称: list_get_tail_node
* 功能描述: 获取链表尾部数据节点
* 输 入:list_head 链表头
* 输 出: 无
* 返 回 值: 成功返回尾部节点指针 失败返回NULL
* 其 他:
* 日 期: 2022/11/22
* 作 者: axk
***********************************************************************/
list_node_s_type* list_get_tail_node(list_head_s_type* list_head);
/***********************************************************************
* 函数名称: list_destory
* 功能描述: 链表销毁
* 输 入:list_head 链表头
* 输 出: 无
* 返 回 值: 成功返回0 失败返回对应错误码
* 其 他:
* 日 期: 2022/11/21
* 作 者: axk
***********************************************************************/
int list_destory(list_head_s_type* list_head);
/***********************************************************************
* 函数名称: list_init
* 功能描述: 链表初始化
* 输 入:list_head 链表头
* 输 出: 无
* 返 回 值: 成功返回0 失败返回对应错误码
* 其 他:
* 日 期: 2022/11/22
* 作 者: axk
***********************************************************************/
int list_init(list_head_s_type* list_head);
/****************************LINK_LIST 函数声明 end****************************************************/
#ifdef __cplusplus
}
#endif
#endif
链表接口测试代码
/*********************************************************************
* 版权所有 (c) 2021-2022 axk. 保留所有版权
* 文件名称: linklist_test.c
* 文件描述: 链表接口测试文件
* 作 者: axk
* 创建日期: 2022/11/21
* 作 者 日 期 版 本 修改摘要
* axk 2022/11/21 1.0 文件创建
**********************************************************************/
/* 示例代码数据内容是char*类型字符串 实际使用可以是任意类型指针 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "linklist.h"
#include "axk_base_data_type.h"
void print_list(list_head_s_type* list_head)
{
list_node_s_type* tmp_node = NULL;
int i = 0;
if (NULL == list_head || 0 == list_head->node_num)
{
printf("curr list is NULL!\n");
return ;
}
tmp_node = list_head->head;
while (NULL != tmp_node)
{
printf("node %d content %s.\n", i++, (char*)tmp_node->data);
tmp_node = tmp_node->next;
}
}
int main(void)
{
int menu = 0;
list_head_s_type list_head;
memset(&list_head, 0x0, sizeof(list_head_s_type));
list_init(&list_head);
while (1)
{
print_list(&list_head);
menu = 0;
printf("please select menu: \n" \
"1.head insert \n" \
"2.tail insert\n" \
"3.head delete\n" \
"4.tail delete\n" \
"5.delete by data address\n" \
"6.head get\n" \
"7.tail get\n" \
"8.destory list\n" \
"9.init list\n" \
"0.exit \n");
scanf("%d", &menu);
switch (menu)
{
case 1:
{
char* data = (char*)malloc(128);
if (NULL == data)
{
printf("\nmalloc failed!\n");
break;
}
memset(data, 0x0, 128);
printf("please input data:\n");
scanf("%s", data);
list_head_insert(&list_head, data, free);
break;
}
case 2:
{
char* data = (char*)malloc(128);
if (NULL == data)
{
printf("\nmalloc failed!\n");
break;
}
memset(data, 0x0, 128);
printf("please input data:\n");
scanf("%s", data);
list_tail_insert(&list_head, data, free);
break;
}
case 3:
{
list_head_del(&list_head);
break;
}
case 4:
{
list_tail_del(&list_head);
break;
}
case 5:
{
/* 当前示例是获取尾部节点然后删除 */
list_node_s_type* tmp_node = list_get_tail_node(&list_head);
if (NULL != tmp_node)
{
list_del_node_by_data_addrress(&list_head, tmp_node->data);
}
else
{
printf("list is NULL!\n");
}
break;
}
case 6:
{
list_node_s_type* tmp_node = list_get_head_node(&list_head);
if (NULL != tmp_node)
{
printf("node data is %s\n", (char*)tmp_node->data);
}
else
{
printf("list is NULL!\n");
}
break;
}
case 7:
{
list_node_s_type* tmp_node = list_get_tail_node(&list_head);
if (NULL != tmp_node)
{
printf("node data is %s\n", (char*)tmp_node->data);
}
else
{
printf("list is NULL!\n");
}
break;
}
case 8:
{
list_destory(&list_head);
break;
}
case 9:
{
list_init(&list_head);
break;
}
case 0:
{
exit(0);
break;
}
default:
{
printf("nosuppurt menu %d!!!\n", menu);
break;
}
}
}
list_destory(&list_head);
return 0;
}