标题utlist.h 单链表使用
在项目中用到了utlist.h,发现没有关于单链表的使用。
此文章比较简短,需要配合utlist.h文档查看。
utlist整理
/*
* @Author: cyk woaijiaohaer@163.com
* @Date: 2023-11-10 16:58:38
* @LastEditors: cyk woaijiaohaer@163.com
* @LastEditTime: 2023-11-20 08:53:16
* @FilePath: \utlist\main.c
*/
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include "utlist.h"
#define PATH "../test/demo.txt"
typedef struct _client_info{
char *username;
char *address;
char *client_id;
int port;
struct _client_info *next;
}client_info_list;
static client_info_list *head=NULL;
int namecmp(client_info_list *a, client_info_list *b) {
return strcmp(a->client_id,b->client_id);
}
void add_client2list(char *name, char *address , char *client_id, int port){
client_info_list *next_client;
if((next_client=(client_info_list *)malloc(sizeof(client_info_list))) != NULL){
next_client->username = (char *)malloc(strlen(name));
memcpy(next_client->username, name, strlen(name));
next_client->address = (char *)malloc(strlen(address));
memcpy(next_client->address, address, strlen(address));
next_client->client_id = (char *)malloc(strlen(client_id));
memcpy(next_client->client_id, client_id, strlen(client_id));
next_client->port = port;
LL_APPEND(head, next_client);
}
}
void remove_client_from_list(char *client_id)
{
client_info_list *elt,tmp;
tmp.client_id = (char *)malloc(strlen(client_id));
memcpy(tmp.client_id, client_id, strlen(client_id));
LL_SEARCH(head, elt, &tmp, namecmp);
if (elt){
printf("found %s\n", elt->client_id);
LL_DELETE(head,elt);
free(elt->client_id);
free(elt->username);
free(elt->address);
free(elt);
}
free(tmp.client_id);
}
int store_client_id_to_path(char *path)
{
client_info_list *elt;
FILE *fp;
int len = 0;
char str[256] = {0};
if(path == NULL)
return -1;
fp = fopen(path, "w+"); //cover
if (fp == NULL)
{
printf("Failed to create file %s: %s", path, strerror(errno));
return -1;
}
LL_FOREACH(head, elt){
len = sprintf(str, "%s\t%s\t%s\t%d\t\n", elt->username, elt->address, elt->client_id, elt->port);
fwrite(str, len, 1, fp);
}
fclose(fp);
}
int main(int argc, char *argv[])
{
client_info_list *elt,*tmp;
add_client2list("u123", "192.168.10.3","client_id 1", 1882);
add_client2list("", "192.168.10.2","client_id 2", 1883);
add_client2list("u789","192.168.10.3","client_id3", 1884);
LL_FOREACH(head,elt) printf("%s \t %s\n", elt->username, elt->client_id);
remove_client_from_list("client_id3");
store_client_id_to_path(PATH);
LL_FOREACH_SAFE(head,elt,tmp) printf("%s \t %s\n", elt->username, elt->client_id);
return 0;
}
如代码所示,用于保存mqtt broker的相关参数,使用utlist
来完成数据的存储。
typedef struct _client_info{
char *username;
char *address;
char *client_id;
int port;
struct _client_info *next;
}client_info_list;
结构体client_info_list
需要注意一个点,就是需要放一个next指针,就和正常写链表是一样的。
如果指针名不为next的话,需要将代码中的
LL
打头的所有api进行更换(比较简单,就是多个入参)
就拿以下两个宏的区别来说
#define LL_APPEND(head,add) \
LL_APPEND2(head,add,next)
#define LL_APPEND2(head,add,next) \
do { \
LDECLTYPE(head) _tmp; \
(add)->next=NULL; \
if (head) { \
_tmp = (head); \
while (_tmp->next) { _tmp = _tmp->next; } \
_tmp->next=(add); \
} else { \
(head)=(add); \
} \
} while (0)
如果我的结构体为:
typedef struct _client_info{
char *username;
char *address;
char *client_id;
int port;
struct _client_info *any;//****************//
}client_info_list;
//调用为
LL_APPEND2(head, next_client, any)
剩下的看utlist.h的说明即可。
代码库如图,可在里面找到utlist.h,直接包含即可
https://github.com/troydhanson/uthash