utlist.h 单链表使用

标题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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值