C语言通用链表

文章介绍了如何创建一个通用链表结构,包括链表节点的添加、初始化以及结合业务数据(如温度湿度传感器数据)进行操作。通过定义通用链表结构体和业务数据结构体,实现了链表节点的插入功能,并提供了在链表尾部和头部添加节点的函数。此外,还展示了如何遍历链表访问业务数据。
摘要由CSDN通过智能技术生成

通用链表的创建

//通用链表结构体,只保留指针域
type struct List
{
    struct List *prev;
    struct List *next;
}List;

添加节点

//添加链表节点
void AddNode(List *oldNode,List *newNode)
{
    newNode->next = oldNode->next;
    newNode->prev = oldNode;
    oldNode->next->prev = newNode;
    oldNode->next = newNode;
}

创建业务类型结构体

单纯的通用链表是没有意义的,要结合业务类型

//业务数据
typedef struct TempHumiSensor
{
    uint32_t id;
    uint8_t humi;
    float temp;
    List list;//是type struct List类型所以不能指向业务数据结构体的首地址,只能指向业务数据结构中            
                list成员的首地址
}TempHumiSensor;

通用链表的初始化

通用链表把初始化分为两部分,指针域和数据域分开初始化,大大提高了通用性,用户可以根据自己的业务需求创建业务数据域。

static List *g_tempHumiHeader;//头节点不需要数据所以用通用类型,后面的节点就要用业务数据类型了
//链表初始化函数
void InitList(List *header)
{
    header->next = header;
    header->prev = header;
}
//业务相关代码
bool InitTempHumiSensor(void)
{
    g_tempHumiHeader = (List *)malloc(sizeof(struct List));
    if(g_tempHumiHeader == NULL)
    {
        return false;//申请失败返回false
    }
    InitList(g_tempHumiHeader);//申请成功初始化链表
    return true;
}

通用链表的添加

/*
**添加链表节点函数
* @brief 将节点添加到已有节点的后面
* @param oldNode:已有节点
* @param newNode:待添加节点
* @return 
*/
void AddNode(List *oldNode, List *newNode)
{
    newNode->next = oldNode->next;
    newNode->prev = oldNode;
    oldNode->next->prev = newNode;
    oldNode->next = newNode;
}
/*
**添加链表业务相关节点
* @brief 将节点添加到链表的尾部
* @param header:头节点
* @param node:待添加节点
* @return 
*/
void AddNodeToTail(List *header, List *node)
{
    AddNode(header->prev, node);
}
/*
* @brief 将节点添加到头节点的后面
* @param header:头节点
* @param node:待添加节点
* @return 
*/
void AddNodeToHead(List *header, List *node)
{
	AddNode(header, node);
}

检测业务数据函数

//业务数据采集函数
TempHumiSensor *FindTempHumiSensor(void)//业务数据结构体指针类型
{
	TempHumiSensor *sensor = (TempHumiSensor *)malloc(sizeof(TempHumiSensor));//定义局部变量 
                                                                                申请动态内存
	if (sensor == NULL)//判断申请成功还是失败
	{
		return NULL;//申请失败返回NULL,并退出函数
	}
    //申请成功,访问成员赋值
	static uint8_t id = 100;
    //实际应用时直接赋值传感器的读取数据
	sensor->id = id;
	id--;
	sensor->humi = 40;
	sensor->temp = 20.5f;
	return sensor;
}

添加传感器函数

//添加传感器函数
void AddTempHumiSensor(TempHumiSensor *sensor)
{
	AddNodeToTail(g_tempHumiHeader, &sensor->list);//直接调用链表添加函数,取sensor->list
}

通用链表遍历

通用链表数据块是由list成员串联起来的,它的next和prev指向的是业务数据结构体中list成员的首地址,所以需要根据list成员的首地址得到业务数据结构体的首地址,才能进行访问其它成员的数据。

通过结构体成员获取结构体首地址宏定义

/**
* @brief 获取结构体中成员的偏移量
* @param typeName: 结构体类型的名字
* @param memberName: 成员的名字
* @return 成员在结构体当中的偏移量
*/
#define OFFSET_OF(typeName, memberName)  ((uint32_t)&((typeName *)0)->memberName)

/**
* @brief 获取结构体的首地址
* @param typeName: 结构体类型的名字
* @param memberName: 成员的名字
* @return 结构体的首地址
*/
#define CONTAINER_OF(pMember, typeName, memberName) \
		((typeName *)((uint8_t *)pMember - OFFSET_OF(typeName, memberName)))

主函数

int main(void)
{
    if(!InitTempHumiSensor())//判断业务代码申请失败
    {
        return -1;
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jarrett_Zheng

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值