一个头文件引入就可以,具备c++ foreach 遍历
list.h 头文件
#ifndef _LIST_H_
#define _LIST_H_
//编写链表
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
typedef void* (*_MallocType)(size_t);
typedef void (*_FreeType)(void*);
typedef struct _LIST_t
{
void* _body;
int (*push_front)(struct _LIST_t* list, void* data, int len);
int (*push_back)(struct _LIST_t* list, void* data, int len);
void* (*front)(struct _LIST_t* list);
void* (*back)(struct _LIST_t* list);
void (*pop_front)(struct _LIST_t* list);
void (*pop_back)(struct _LIST_t* list);
void (*erase)(struct _LIST_t* list, void* data); // O(n)
bool (*empty)(struct _LIST_t* list);
int (*size)(struct _LIST_t* list);
void (*clear)(struct _LIST_t* list);
void (*foreach)(struct _LIST_t* list, void (*out_fn)(void* data));
void (*erase_cmp)(struct _LIST_t* list,void *del_data, bool (*cmp_fn)(void*, void*));
void (*destruct)(struct _LIST_t** list);
void* (*foreach2)(struct _LIST_t* list, void* next);
}LIST_t;
static _MallocType list_malloc;
static _FreeType list_free;
/*
* @param max_num : 队列最大深度
* @param max_len : 队列最大宽度
* @param data_free : 用户自定义释放内存函数
*/
extern LIST_t* create_list(int max_num, int max_len, _MallocType fn_Malloc,_FreeType fn_Free,void (*data_free)(void*));
typedef struct _LINE_
{
struct _LINE_* next;
struct _LINE_* pre;
void* data;
uint32_t datalen;
}LINE_t;
typedef struct _BODY_
{
LINE_t* _head;
LINE_t* _tail;
int _num;
int _max_num;
int _max_len;
void (*_data_free)(void*);
}BODY_t;
static void _free_line_data(BODY_t* body, void* data)
{
if(NULL == data)
return;
if(NULL != body->_data_free)
{
body->_data_free(data);
return;
}
list_free(data);
}
static void _destruct(LIST_t** _list)
{
if(NULL == _list) return;
LIST_t* list = *_list;
BODY_t* body = (BODY_t*)list->_body;
list->clear(list);
LINE_t* line = body->_head;
if(NULL != list->_body)
{
list_free(list->_body);
list->_body = NULL;
}
list_free(list);
list = NULL;
}
/*
功能
清空 list 节点
参数
list:list指针
返回值 void
*/
static void _clear(LIST_t* list)
{
BODY_t* body = (BODY_t*)list->_body;
LINE_t* line = body->_head;
while(line != NULL)
{
LINE_t* p = line->next;
_free_line_data(body, line->data);
list_free(line);
line = p;
body->_num--;
}
body->_head = NULL;
body->_tail = NULL;
}
/*
功能
插入数据到 list 尾部
参数
list:list指针,data:插入数据指针,len:插入数据
返回值 int
0:成功, -1 : 超过链表最大长度或者数据长度过长,-2:内存申请失败
*/
static int _push_back(LIST_t* list, void* data, int len)
{
BODY_t* body = (BODY_t*) list->_body;
if(body->_num >= body->_max_num || len > body->_max_len)
return -1;
LINE_t* line = (LINE_t*) list_malloc(sizeof(LINE_t));
if(NULL == line)
return -2;
memset(line, 0, sizeof(LINE_t));
line->data = list_malloc(len);
if(NULL == line->data)
{
list_free(line);
return -2;
}
memset(line->data, 0, len);
memcpy(line->data, data, len);
line->datalen = len;
body->_num ++;
if(NULL == body->_head) // 这里认为初始化, 头尾都指向同个结构
{
body->_head = line;
body->_tail = line;
return 0;
}
line->pre = body->_tail;
body->_tail->next = line;
body->_tail = line;
return 0;
}
/*
功能
插入数据到 list 头部
参数
list:list指针,data:插入数据指针,len:插入数据
返回值 int
0:成功, -1 : 超过链表最大长度或者数据长度过长,-2:内存申请失败
*/
static int _push_front(LIST_t* list, void* data, int len)
{
BODY_t* body = (BODY_t*) list->_body;
if(body->_num + 1 >= body->_max_num || len > body->_max_len)
return -1;
LINE_t* line = (LINE_t*) list_malloc(sizeof(LINE_t));
if(NULL == line)
return -2;
memset(line, 0, sizeof(LINE_t));
line->data = list_malloc(len);
if(NULL == line->data)
{
list_free(line);
return -2;
}
memset(line->data, 0, len);
memcpy(line->data, data, len);
line->datalen = len;
body->_num ++;
if(NULL == body->_head) // 这里认为初始化, 头尾都指向同个结构
{
body->_head = line;
body->_tail = line;
return 0;
}
line->next = body->_head;
body->_head->pre = line;
body->_head = line;
return 0;
}
/*
功能
获取 list 头部数据
参数
list:list指针
返回值 void*
NULL:失败或者list头为空, 其他 : list头部数据
*/
static void* _front(LIST_t* list)
{
BODY_t* body = (BODY_t*)list->_body;
if(NULL == body)
return NULL;
return body->_head->data;
}
/*
功能
获取 list 尾部数据
参数
list:list 指针
返回值 void*
NULL:失败或者list尾为空, 其他 : list尾部数据
*/
static void* _back(LIST_t* list)
{
BODY_t* body = (BODY_t*)list->_body;
if(NULL == body)
return NULL;
return body->_tail->data;
}
// 轮询删除, 正常不建议使用 O(n), data 是链表中的指针
static void _erase(LIST_t* list, void* data)
{
BODY_t* body = (BODY_t*)list->_body;
LINE_t* line = body->_head;
while(line)
{
if(line->data == data)
{
LINE_t* p = line;
if(NULL != p->pre)
p->pre->next = p->next;
if(NULL != p->next)
p->next->pre = p->pre;
if(body->_head == p)
{
body->_head = p->next;
}
if(body->_tail == p)
{
body->_tail = p->pre;
}
body->_num--;
_free_line_data(body, line->data);
list_free(line);
break;
}
line = line->next;
}
}
//删除由外部比较返回true的节点,删除后立即结束遍历
static void _erase_cmp(LIST_t* list, void* del_data, bool (*cmp_fn)(void*, void*))
{
BODY_t* body = (BODY_t*)list->_body;
LINE_t* line = body->_head;
while (line)
{
if (cmp_fn(line->data,del_data))
{
LINE_t* p = line;
if (NULL != p->pre)
p->pre->next = p->next;
if (NULL != p->next)
p->next->pre = p->pre;
if (body->_head == p)
{
body->_head = p->next;
}
if (body->_tail == p)
{
body->_tail = p->pre;
}
body->_num--;
_free_line_data(body, line->data);
list_free(line);
break;
}
line = line->next;
}
}
//正向遍历
static void _foreach(LIST_t* list, void (*out_fn)(void* data))
{
BODY_t* body = (BODY_t*)list->_body;
LINE_t* line = body->_head;
while (line)
{
out_fn(line->data);
line = line->next;
}
}
//返回指针式的遍历
static void* _foreach2(LIST_t* list, void* next)
{
BODY_t* body = NULL;
LINE_t* line = NULL;
if (next==NULL)
{
body = (BODY_t*)list->_body;
line = body->_head;
}
else
{
line = (LINE_t*)next;
}
if (line)
{
line = line->next;
}
return (void*)line;
}
/*
功能
删除 list 头部节点
参数
list:list指针
返回值 void
*/
static void _pop_front(LIST_t* list)
{
BODY_t* body = (BODY_t*)list->_body;
LINE_t* line = body->_head;
if(NULL == line)
return;
body->_head = line->next;
if(NULL != body->_head)
body->_head->pre = NULL;
if(line == body->_tail)
body->_tail = NULL;
_free_line_data(body, line->data);
list_free(line);
body->_num--;
}
/*
功能
删除 list 尾部节点
参数
list:list指针
返回值 void
*/
static void _pop_back(LIST_t* list)
{
BODY_t* body = (BODY_t*)list->_body;
LINE_t* line = body->_tail;
if(NULL == line)
return;
body->_tail = line->pre;
if(NULL != body->_tail)
body->_tail->next = NULL;
if(line == body->_head)
body->_head = NULL;
_free_line_data(body, line->data);
list_free(line);
body->_num--;
}
/*
* 功能
list 是否为空
参数
list:list指针
返回值 bool
true:list为空,false:list不为空
*/
static bool _empty(LIST_t* list)
{
BODY_t* body = (BODY_t*)list->_body;
return (body->_tail == NULL);
}
/*
* 功能
获取 list 节点数量
参数
list:list指针
返回值 int
list 节点数量
*/
static int _size(LIST_t* list)
{
BODY_t* body = (BODY_t*)list->_body;
return body->_num;
}
static int _construct(LIST_t* list, int max_num, int max_len,void (*data_free)(void*)) // 调用前要确定 list 已经分配内存
{
list->_body = list_malloc(sizeof(BODY_t));
if(NULL == list->_body)
return -1;
memset(list->_body, 0, sizeof(BODY_t));
BODY_t* body = (BODY_t*)list->_body;
body->_max_num = max_num;
body->_max_len = max_len;
body->_data_free = data_free;
list->push_back = _push_back;
list->push_front = _push_front;
list->front = _front;
list->back = _back;
list->pop_front = _pop_front;
list->pop_back = _pop_back;
list->erase = _erase;
list->empty = _empty;
list->size = _size;
list->clear = _clear;
list->destruct = _destruct;
list->foreach = _foreach;
list->erase_cmp = _erase_cmp;
list->foreach2 = _foreach2;
return 0;
}
LIST_t* create_list(int max_num, int max_len, _MallocType fn_Malloc,_FreeType fn_Free,void (*data_free)(void*))
{
list_malloc = fn_Malloc;
list_free = fn_Free;
LIST_t* list = (LIST_t*)list_malloc(sizeof(LIST_t));
if(NULL == list)
return NULL;
memset(list, 0, sizeof(LIST_t));
if( _construct(list, max_num, max_len, data_free)!= 0)
{
list_free(list);
return NULL;
}
return list;
}
#endif
调用测试
#include "windows.h"
#include <iostream>
#include <stdio.h>
#include "list.h"
typedef struct _DATA_
{
int len;
char buff[];
} DATA_t;
void free_data(void* _data)
{
DATA_t* data = (DATA_t*)_data;
if (NULL == data)
return;
free(data);
}
void for_eacth_list(void *data) {
DATA_t* it = (DATA_t*)data;
if (NULL == it)
{
printf("Get front error\n");
exit(-1);
}
printf("len:%d, buff:%.*s\n", it->len, it->len, it->buff);
}
bool dele_list(void* out_data, void* del_data) {
DATA_t* it = (DATA_t*)out_data;
DATA_t* del_datait = (DATA_t*)del_data;
if (NULL == it|| del_data==NULL)
{
printf("Get front error\n");
return false;
}
//printf("len:%d, buff:%.*s\n", it->len, it->len, it->buff);
if (strcmp(it->buff, del_datait->buff)==0)
{
return true;
}
else
{
return false;
}
}
void test_list(void) {
int ccc = 10;
for (int j=0;j<ccc;j++)
{
LIST_t* list = create_list(ccc, 100, malloc, free, free_data);
if (NULL == list)
{
printf("Create list error\n");
exit(-1);
}
for (int i = 0; i < ccc; i++)
{
char* num_str = (char*)malloc(99);
sprintf(num_str, "%d", i);
if (num_str == NULL)
{
printf("Create num error\n");
exit(-1);
}
DATA_t* data = (DATA_t*)malloc(sizeof(DATA_t) + strlen(num_str) * sizeof(char) + 1);
if (NULL == data)
{
printf("Create data error\n");
exit(-1);
}
memset(data, 0, sizeof(DATA_t) + strlen(num_str) * sizeof(char) + 1);
data->len = strlen(num_str);
strcpy(data->buff, num_str);
int err = list->push_back(list, data, sizeof(DATA_t) + data->len * sizeof(char) + 1);
if (err < 0)
printf("push back error, errcode:%d", err);
free(num_str);
free(data);
}
printf("list size:%d\n", list->size(list));
list->foreach(list, for_eacth_list);
//删除999字符串
DATA_t* data = (DATA_t*)malloc(sizeof(DATA_t) + 100 * sizeof(char) + 1);
if (NULL == data)
{
printf("Create data error\n");
exit(-1);
}
memset(data, 0, sizeof(DATA_t) + 100* sizeof(char) + 1);
data->len = 100;
strcpy(data->buff, "9");
list->erase_cmp(list,data, dele_list);
/*LINE_t* itr = NULL;
itr = (LINE_t*)list->foreach2(list, itr);
while (itr)
{
DATA_t* it = (DATA_t*)itr->data;
printf("len:%d, buff:%.*s\n", it->len, it->len, it->buff);
itr = (LINE_t*)list->foreach2(list, itr);
}*/
for (LINE_t* itr = (LINE_t*)list->foreach2(list, NULL);itr; itr = (LINE_t*)list->foreach2(list, itr))
{
DATA_t* it = (DATA_t*)itr->data;
printf("len:%d, buff:%.*s\n", it->len, it->len, it->buff);
}
//list->clear(list);
printf("clear list size:%d\n", list->size(list));
while (!list->empty(list))
{
DATA_t* it = (DATA_t*)list->front(list);
if (NULL == it)
{
printf("Get front error\n");
exit(-1);
}
printf("len:%d, buff:%.*s\n", it->len, it->len, it->buff);
list->pop_front(list);
}
printf("list size:%d\n", list->size(list));
list->clear(list);
printf("list size:%d\n", list->size(list));
list->destruct(&list);
}
}
int main()
{
test_list();
int c = getchar();
}