链表框架--双向循环,带上下级
亲测可用。反正没人会看,随便写写就好了...瘪嘴 :)
前景:在使用一些简单的LCD显示屏时,编写菜单,每次都是一个头疼的问题,甚至有些时候牵一发动全身,在想着也没有一种简单的框架,来方便菜单的执行(链表或许是一种不错的选择)
形式:对于一个菜单而言,有上一页,下一页,在某页中还可能会进入下一级,也需要退回到上一级等等,这就需要用到链表的格式,如下
typedef struct List_Node
{struct List_Node *ppar;struct List_Node *pchi;struct List_Node *pnxt;struct List_Node *plst;void *pdata;uint16_t val;}__attribute__((aligned(1), packed))listInfo_t;
ppar为上一级(父节点),pchi为下一级(子节点),pnxt为下一页,plst为上一页,pdata为这个链表需要存储数据的指针(void *嘛,万用指针),重点是这个val,这个值就是此小型链表框架的精髓
val值:位数(个十百千万)为级数,位数里面的数字为页数,用框架来说的话如下图

基本理念是这样,理论上是能够用满65536个数(算上0),除去最高级(6xxxxx),理论上可以最大广度可以有9页,深度是5级
使用回调函数的形式完成,把每一级看成一个双向循环的链表,然后进行嵌套,遇到下一个不是同级的就进行嵌入或者退出
接下来就是实现它
首先,定义一个结构体,往后的数据只要修改这个结构体即可,例如只修改下面的ct_ListTab
typedef struct
{uint16_t val;void *pdata;}__attribute__((aligned(1), packed))listTabel_t;static listInfo_t *pListHead = NULL;
listInfo_t *pListCurr = NULL;static uint8_t st_userdata[0x10] =
{
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x00,
};static const listTabel_t ct_ListTab[] =
{{0, NULL},{1, NULL},{11, NULL},{111, NULL},{21, (void *)st_userdata},{31, NULL},{131, NULL},{231, NULL},{41, NULL},{2, NULL},{3, NULL},{13, NULL},{4, NULL},
};
首先,实现双向链表的节点创建和节点新增
/*** @brief Create a node* @param void* @retval true : listInfo_t** @retval fail : NULL*/
static listInfo_t *user_CreatNode(void)
{listInfo_t *p = (listInfo_t*)tool_Malloc(sizeof(listInfo_t));if(p == NULL){return NULL;}p->ppar = NULL;p->pchi = NULL;p->plst = NULL;p->pnxt = NULL;p->pdata = NULL;return p;
}/*** @brief Add a node after the current location to create a new node* @param listInfo_t* The current node pointer* @retval true : listInfo_t** @retval fail : NULL*/
static listInfo_t *user_AddNode(listInfo_t *pcur)
{listInfo_t *pnew = user_CreatNode();if(pnew == NULL){return NULL;}if(pcur == NULL) // If the first pointer is empty, it is created as a pointer header{pcur = pnew;pcur->pnxt = pnew;pcur->plst = pnew;}else if(pcur->pnxt == pcur) // If it is a second linked list{pcur->pnxt = pnew;pcur->plst = pnew;pnew->pnxt = pcur;pnew->plst = pcur;}else // Three or more{pnew->pnxt = pcur->pnxt;pnew->plst = pcur;pcur->pnxt->plst = pnew;pcur->pnxt = pnew;}return pnew;
}
使用工具如下
/*** @brief Calculate how many digits there are in decimal* @param uint16_t decimal number* @retval uint16_t uint*/
static uint8_t tool_DecUint(uint16_t num)
{uint16_t data = num;uint8_t res = 0x00;do{res++;data /= 0x0A;}while(data);return res;
}/*** @brief Space request function* @param uint32_t malloc size* @retval void* data type*/
void *tool_Malloc(uint32_t size)
{return malloc(size);
}/*** @brief Gets the number of decimal digits* @param uint8_t loca* @retval uint8_t muti*/
static uint8_t user_GetTabMuti(uint8_t loca)
{return tool_DecUint(ct_ListTab[loca].val);
}/*** @brief Gets the largest element of the array* @param void* @retval uint16_t element*/
static uint16_t user_GetTabMax(void)
{return sizeof(ct_ListTab) / sizeof(listTabel_t);
}
最后就是实现该功能
/*** @brief Register a linked list* @param uint8_t table location* @param listInfo_t* parente pionter* @retval true: 0x00* @retval fail: negative number*/
static int user_List_Reg(uint8_t loca, listInfo_t *ppar)
{listInfo_t *p = NULL;uint8_t i = loca;uint8_t enter = 0x00;for(i = loca; i < user_GetTabMax(); i++){p = user_AddNode(p);if(p == NULL){return -i;} // An error occurs when all applications were cleared before cancellationelse{if(i == 0x00){pListHead = p; // Defines the pointer header}else{pListCurr = p; // Keep the current node}/* USER CODE BEGIN List_Init 1 */p->val = ct_ListTab[i].val; // Attach the page numberp->pdata = ct_ListTab[i].pdata;/* USER CODE END List_Init 1 */if(ppar != NULL){if(i == loca){ppar->pchi = p;} // Identify child nodesp->ppar = ppar; // Confirm the parent node}if((i + 0x01) < user_GetTabMax()) // The next one cannot exceed the largest array{if((user_GetTabMuti(i + 0x01)) > user_GetTabMuti(i)) // Determines whether the next bit is greater than the previous one dimension{enter = user_GetTabMuti(i); // The value of the dimension is retainedi = user_List_Reg(i + 0x01, p); // Enter recursionif(enter < user_GetTabMuti(i)) // Determine whether the recursive returned dimension is the same as the loop{if((user_GetTabMuti(i + 0x01) + 0x01) == user_GetTabMuti(i)){// Make sure the next number is not a fault, such as 121 - 31}else{return i + 0x01; // If so, offset backwards and back}}else{i--; // If the same is the case, the loop is subtracted by one, because it will be added before the next loop}}else if(user_GetTabMuti(i + 0x01) < user_GetTabMuti(i)) // If the next dimension is judged to be smaller than the previous dimension{return i;}}else{}}}pListCurr = pListHead;return i;
}
咱们来验证一下,初始化结束之后,打印数据
log_debug("val = %d, data = %d", pListCurr->pnxt->pchi->pnxt->val, ((uint8_t *)pListCurr->pnxt->pchi->pnxt->pdata)[0x05]);
打印结果为:
-> Debug : val = 21, data = 6
故:在最后使用的时候,在使用的时候,只需要调用函数user_List_Reg(0x00, NULL),而且修改最初的那个结构体数组即可完成整个链表的改变,其他功能,就比如回到链表头啊,根据val数值找到某个链表所在的位置啊就比较简单了
毕竟~,反正没人会看
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
