zoukankan      html  css  js  c++  java
  • 沉淀之log4c的list

        log4c中对于链表也实现了一套,可以在src/sd/目录下找到有对应的list.c和list.h两个文件。直接贴代码和注释。
    list.h
    1. #ifndef __sd_list_h
    2. #define __sd_list_h

    3. #include <stddef.h>
    4. #include "defs.h"
    5. __SD_BEGIN_DECLS
    6. /**
    7. * 声明list类型,实际定义是在list.c文件里
    8. */
    9. typedef struct __sd_list sd_list_t;
    10. /**
    11. * 定义list中元素的结构,data应该是指向用户数据的指针,
    12. * 双向链表
    13. */
    14. struct __sd_list_iter {
    15. void* data;
    16. struct __sd_list* list;
    17. struct __sd_list_iter* __next;
    18. struct __sd_list_iter* __prev;
    19. int __foreach;
    20. };
    21. /**
    22. * 对于元素容器进行类型的定义
    23. */
    24. typedef struct __sd_list_iter sd_list_iter_t;
    25. /**
    26. * foreach遍历时的回调函数类型
    27. */
    28. typedef unsigned int (*sd_list_func_t)(void* a_data, void* a_userdata);
    29. /**
    30. * 新建一个链表
    31. * @param a_capacity 初始化链表中容纳元素的数量
    32. * @return 链表的入口指针.
    33. */
    34. extern sd_list_t* sd_list_new(size_t a_capacity);
    35. /**
    36. * 销毁一个链表
    37. * @todo 需要一个回调函数来释放用户数据(尚未实现)
    38. */
    39. extern void sd_list_delete(sd_list_t* a_this);
    40. /**
    41. * 将用户数据插入到链表的头部
    42. */
    43. extern sd_list_iter_t* sd_list_prepend(sd_list_t* a_this, void* a_data);
    44. /**
    45. * 将用户数据插入到链表的尾部
    46. */
    47. extern sd_list_iter_t* sd_list_append(sd_list_t* a_this, void* a_data);
    48. /**
    49. * 在链表里查找用户数据是否存在
    50. * @param a_data 待查找数据
    51. * @return 找到的元素地址,或者NULL.
    52. */
    53. extern sd_list_iter_t* sd_list_lookup(sd_list_t* a_this, void* a_data);
    54. /**
    55. * 在链表里查找数据,如果没有找到就调用sd_list_add().将数据插入到链表里
    56. * @param a_data 待查找数据
    57. * @return 查找到的数据地址,或者NULL.
    58. */
    59. extern sd_list_iter_t* sd_list_lookadd(sd_list_t* a_this, void* a_data);
    60. /**
    61. * 将用户数据插入到链表里,如果该数据已经存在则返回数据的指针
    62. * @warning 元素会插入到链表的头部
    63. * @param a_data 带插入数据
    64. * @return 返回插入的或者已存在的元素指针
    65. */
    66. extern sd_list_iter_t* sd_list_add(sd_list_t* a_this, void* a_data);
    67. /**
    68. * 用a_func从头遍历链表中的所有元素,直到返回一个非NULL的返回值,则
    69. * 将用户数据插入到返回的数据前面
    70. * @param a_func 排序函数
    71. * @param a_data 待插入的用户数据
    72. * @return 用户数据插入后所在的容器指针
    73. */
    74. extern sd_list_iter_t* sd_list_sortadd(sd_list_t* a_this,
    75. sd_list_func_t a_func,
    76. void* a_data);
    77. /**
    78. * 从链表里删除一个用户数据
    79. * @param a_data 包含用户数据的容器地址
    80. */
    81. extern int sd_list_del(sd_list_t* a_this, void* a_data);
    82. /**
    83. * 清空一个链表
    84. */
    85. extern void sd_list_clear(sd_list_t* a_this);
    86. /**
    87. * 调用a_func从头遍历整个链表直到返回一个非0
    88. * @param a_func 遍历回调函数
    89. * @param a_data 传入到回调函数的一个用户数据
    90. */
    91. extern void sd_list_foreach(sd_list_t* a_this, sd_list_func_t a_func,
    92. void* a_userdata);
    93. /**
    94. * 调用a_func从后向前遍历整个链表直到返回一个非0
    95. * @param a_func 遍历回调函数
    96. * @param a_data 传入到回调函数的用户数据
    97. */
    98. extern void sd_list_rforeach(sd_list_t* a_this, sd_list_func_t a_func,
    99. void* a_userdata);
    100. /**
    101. * 获取链表中元素的个数
    102. */
    103. extern size_t sd_list_get_nelem(sd_list_t* a_this);
    104. /**
    105. * 获取链表中第一个容器
    106. */
    107. extern sd_list_iter_t* sd_list_begin(sd_list_t* a_this);
    108. /**
    109. * Gets the past-the-last-element iterator of the list.
    110. * 函数定义未实现
    111. */
    112. extern sd_list_iter_t* sd_list_end(sd_list_t* a_this);
    113. /**
    114. * 获取链表中最后一个元素
    115. */
    116. extern sd_list_iter_t* sd_list_rbegin(sd_list_t* a_this);
    117. /**
    118. * Gets the before-the-first-element iterator of the list.
    119. * 函数定义未实现
    120. */
    121. extern sd_list_iter_t* sd_list_rend(sd_list_t* a_this);
    122. /**
    123. * 得到当前容器的下一个容器
    124. */
    125. extern sd_list_iter_t* sd_list_iter_next(sd_list_iter_t* a_this);
    126. /**
    127. * 得到当前容器的前一个容器
    128. */
    129. extern sd_list_iter_t* sd_list_iter_prev(sd_list_iter_t* a_this);
    130. /**
    131. * 从链表中删除一个容器
    132. */
    133. extern void sd_list_iter_del(sd_list_iter_t* a_this);
    134. /**
    135. * 创建一个新的容器并将数据插入到a_this前面
    136. * @param a_data 放入到新建容器的数据
    137. */
    138. extern sd_list_iter_t* sd_list_iter_insert(sd_list_iter_t* a_this,
    139. void* a_data);
    140. __SD_END_DECLS
    141. #endif

    list.h中声明的函数,是在list.c中进行了实现,其中声明的两个函数:
    extern sd_list_iter_t* sd_list_end(sd_list_t* a_this);
    extern sd_list_iter_t* sd_list_rend(sd_list_t* a_this);
    功能与
    extern sd_list_iter_t* sd_list_begin(sd_list_t* a_this);
    extern sd_list_iter_t* sd_list_rbegin(sd_list_t* a_this);
    重复,所以在list.c里面只进行定义了一个空的函数体,并没有进行实现。

    以下是list.c中的内容:
    1. #include "list.h"
    2. #include "malloc.h"
    3. #include <stdlib.h>
    4. struct __sd_list {
    5. sd_list_iter_t* head;
    6. sd_list_iter_t* tail;
    7. size_t nelem;
    8. };
        list.h中有一个typedef语句:typedef struct __sd_list sd_list_t;    将sd_list_t声明一下然后在这里进行实际的结构体的定义,这样下面的函数声明中就可以使用这个sd_list_t进行参数或者返回值的声明了。并且只要引用了list.h就可以使用sd_list_t来进行定义自己的链表句柄。这样可以比较完美的实现结构体的隐藏同时还能比较容易使用。
        从这里就知道了整个链表的结构是什么样的了。具体的可以参考图一:

    图一:链表的整体结构图
    sd_list_new:
    1. extern sd_list_t* sd_list_new(size_t a_capacity)
    2. {
    3. sd_list_t* this;
    4. //申请内存,并初始化。实际上calloc分配的就是初始化了的内存。
    5. this = sd_calloc(1, sizeof(sd_list_t));
    6. this->head = 0;
    7. this->tail = 0;
    8. this->nelem = 0;
    9. return this;
    10. }
    sd_list_prepend:
    1. extern sd_list_iter_t* sd_list_prepend(sd_list_t* a_this, void* a_data)
    2. {
    3. //定义一个容器,参数有效性判断。并进行容器内存分配和检查
    4. sd_list_iter_t* i;
    5. if (! a_this) return 0;
    6. if ((i = sd_calloc(1, sizeof(*i))) == 0)
    7. return 0;
    8. //填充容器,用户数据,链表等。
    9. i->list = a_this;
    10. i->data = a_data;
    11. i->__prev = 0;
    12. i->__next = a_this->head;
    13. a_this->head = i;
    14. //接通后面的链表,否则设置链表的tail指针的指向
    15. if (i->__next)
    16. i->__next->__prev = i;
    17. else
    18. a_this->tail = i;
    19. //增加元素计数器
    20. a_this->nelem++;
    21. return i;
    22. }

    sd_list_append:
    1. extern sd_list_iter_t* sd_list_append(sd_list_t* a_this, void* a_data)
    2. {
    3. sd_list_iter_t* i;
    4. if (! a_this) return 0;
    5. //定义一个容器,参数有效性判断。并进行容器内存分配和检查
    6. if ((i = sd_calloc(1, sizeof(*i))) == 0)
    7. return 0;
    8. //填充容器,用户数据,链表等。
    9. i->list = a_this;
    10. i->data = a_data;
    11. i->__prev = a_this->tail;
    12. i->__next = 0;
    13. a_this->tail = i;
    14. //链接前面的链表或者设置链表的head指针
    15. if (i->__prev)
    16. i->__prev->__next = i;
    17. else
    18. a_this->head = i;
    19. //计数器加一
    20. a_this->nelem++;
    21. return i;
    22. }

    sd_list_delete:
    1. extern void sd_list_delete(sd_list_t* a_this)
    2. {
    3. sd_list_iter_t *a_next;
    4. sd_list_iter_t *a_current;
    5. if (!a_this)
    6. return;
    7. //释放所有的容器
    8. /* Free the iterators */
    9. if (a_this->nelem > 0){
    10. a_current = a_this->head;
    11. do {
    12. a_next = a_current->__next;
    13. free(a_current);
    14. a_current = a_next;
    15. } while (a_current);
    16. }
    17. //释放链表 句柄
    18. free(a_this);
    19. }

    sd_list_clear:
    1. extern void sd_list_clear(sd_list_t* a_this)
    2. {
    3. a_this->head = 0;
    4. a_this->tail = 0;
    5. a_this->nelem = 0;
    6. }

    sd_list_get_nelem:
    1. extern size_t sd_list_get_nelem(sd_list_t* a_this)
    2. {
    3. return (a_this ? a_this->nelem : 0);
    4. }

    sd_list_begin:
    1. extern sd_list_iter_t* sd_list_begin(sd_list_t* a_this)
    2. {
    3. return (a_this ? a_this->head : 0);
    4. }

    sd_list_rbegin:
    1. extern sd_list_iter_t* sd_list_rbegin(sd_list_t* a_this)
    2. {
    3. return (a_this ? a_this->tail : 0);
    4. }

    sd_list_lookup:
    1. extern sd_list_iter_t* sd_list_lookup(sd_list_t* a_this, void* a_data)
    2. {
    3. sd_list_iter_t* i;
    4. if (! a_this) return 0;
    5. //遍历直到找到数据地址与用户传入的地址相同,返回容器地址
    6. for (i = a_this->head; i; i = i->__next)
    7. if (a_data == i->data)
    8. return i;
    9. return 0;
    10. }

    sd_list_add:
    1. extern sd_list_iter_t* sd_list_add(sd_list_t* a_this, void* a_data)
    2. {
    3. sd_list_iter_t* i;
    4. if (! a_this) return 0;
    5. //新建一个容器并分配内存检查
    6. if ((i = sd_calloc(1, sizeof(*i))) == 0)
    7. return 0;
    8. //填充
    9. i->data = a_data;
    10. i->list = a_this;
    11. i->__next = a_this->head;
    12. i->__prev = 0;
    13. a_this->head = i;
    14. //插入首部
    15. if (i->__next) i->__next->__prev = i;
    16. if (!a_this->tail) a_this->tail = i;
    17. //计数器加一
    18. a_this->nelem++;
    19. return i;
    20. }

    sd_list_lookadd:
    1. extern sd_list_iter_t* sd_list_lookadd(sd_list_t* a_this, void* a_data)
    2. {
    3. sd_list_iter_t* i;
    4. if (! a_this) return 0;
    5. //调用sd_list_lookup,或者就插入并返回
    6. if ((i = sd_list_lookup(a_this, a_data)) != 0)
    7. return i;
    8. return sd_list_add(a_this, a_data);
    9. }

    sd_list_iter_insert:
    1. extern sd_list_iter_t* sd_list_iter_insert(sd_list_iter_t* a_this,
    2. void* a_data)
    3. {
    4. sd_list_iter_t* i;
    5. if (! a_this) return 0;
    6. //如果錫_this就是头节点那么就头插
    7. if (a_this->list->head == a_this)
    8. return sd_list_prepend(a_this->list, a_data);
    9. //申请内存,填充后插入到a_this之前
    10. if ((i = sd_calloc(1, sizeof(*i))) == 0)
    11. return 0;
    12. i->data = a_data;
    13. i->list = a_this->list;
    14. i->__prev = a_this->__prev;
    15. i->__next = a_this;
    16. /* CAUTION: always exists since a_this is not the head */
    17. a_this->__prev->__next = i;
    18. a_this->__prev = i;
    19. //计数器加一
    20. a_this->list->nelem++;
    21. return i;
    22. }

    sd_list_sortadd:
    1. extern sd_list_iter_t* sd_list_sortadd(sd_list_t* a_this,
    2. sd_list_func_t a_func, void* a_data)
    3. {
    4. sd_list_iter_t* i;
    5. //参数检查
    6. if (! a_this || ! a_func) return 0;
    7. //从头遍历直到找到一个大于当前用户数据的位置
    8. for (i = a_this->head; i; i = i->__next)
    9. if ((*a_func)(i->data, a_data) > 0)
    10. break;
    11. //如果不是最后的位置,那么插入新节点到a_data之前。否则添加在最后
    12. if (i)
    13. return sd_list_iter_insert(i, a_data);
    14. else
    15. return sd_list_append(a_this, a_data);
    16. }

    sd_list_iter_del:
    1. extern void sd_list_iter_del(sd_list_iter_t* a_this)
    2. {
    3. if (!a_this)
    4. return;
    5. if (a_this->__foreach == 1) {
    6. a_this->__foreach = 0;
    7. return;
    8. }
    9. //向后接通
    10. if (a_this->__next)
    11. a_this->__next->__prev = a_this->__prev;
    12. else
    13. a_this->list->tail = a_this->__prev;
    14. //向前接通
    15. if (a_this->__prev)
    16. a_this->__prev->__next = a_this->__next;
    17. else
    18. a_this->list->head = a_this->__next;
    19. //计数器减一
    20. a_this->list->nelem--;
    21. //释放当前数据
    22. free(a_this);
    23. }

    sd_list_del:
    1. extern int sd_list_del(sd_list_t* a_this, void* a_data)
    2. {
    3. sd_list_iter_t* i;
    4. if (!a_this)
    5. return -1;
    6. //遍历直到找到这个数据
    7. for (i = a_this->head; i; i = i->__next)
    8. if (a_data == i->data)
    9. break;
    10. //如果没找到
    11. if (!i)
    12. return -1;
    13. //删除这个元素
    14. sd_list_iter_del(i);
    15. return 0;
    16. }

    sd_list_foreach:
    1. extern void sd_list_foreach(sd_list_t* a_this, sd_list_func_t a_func,
    2. void* a_userdata)
    3. {
    4. sd_list_iter_t* i;
    5. sd_list_iter_t* j;
    6. if (!a_this || !a_func)
    7. return;
    8. //从头到尾遍历整个链表
    9. for (i = a_this->head; i; i = j)
    10. {
    11. int ret;
    12. i->__foreach = 1;
    13. ret = (*a_func)(i->data, a_userdata);
    14. j = i->__next;
    15. if (i->__foreach == 0)
    16. sd_list_iter_del(i);
    17. else
    18. i->__foreach = 0;
    19. if (ret) return;
    20. }
    21. }

    sd_list_rforeach:
    1. extern void sd_list_rforeach(sd_list_t* a_this, sd_list_func_t a_func,
    2. void* a_userdata)
    3. {
    4. sd_list_iter_t* i;
    5. sd_list_iter_t* j;
    6. if (!a_this || !a_func)
    7. return;
    8. for (i = a_this->tail; i; i = j) {
    9. int ret;
    10. i->__foreach = 1;
    11. ret = (*a_func)(i->data, a_userdata);
    12. j = i->__prev;
    13. if (i->__foreach == 0)
    14. sd_list_iter_del(i);
    15. else
    16. i->__foreach = 0;
    17. if (ret) return;
    18. }
    19. }

    sd_list_iter_next:
    1. extern sd_list_iter_t* sd_list_iter_next(sd_list_iter_t* a_this)
    2. {
    3. return (a_this ? a_this->__next : 0);
    4. }

    sd_list_iter_prev:
    1. extern sd_list_iter_t* sd_list_iter_prev(sd_list_iter_t* a_this)
    2. {
    3. return (a_this ? a_this->__prev : 0);
    4. }
       
        一个简单的样例测试程序如下:
    main.c
    1. #include <stdio.h>
    2. #include <stdlib.h>
    3. #include "stack.h"
    4. #include "list.h"
    5. typedef struct test
    6. {
    7. int a;
    8. int b;
    9. int c;
    10. }test_t;
    11. static unsigned int print(void *data, void *p)
    12. {
    13. test_t *t = (test_t *)data;
    14. printf("a:%d b:%d c:%d ",t->a, t->b, t->c);
    15. return 0;
    16. }
    17. int main()
    18. {
    19. sd_list_t* a_this = sd_list_new(24);
    20. test_t *t3 = malloc(sizeof(test_t));
    21. t3->a = 3;
    22. t3->b = 4;
    23. t3->c = 5;
    24. sd_list_prepend(a_this, t3);
    25. test_t *t1 = malloc(sizeof(test_t));
    26. t1->a = 1;
    27. t1->b = 2;
    28. t1->c = 3;
    29. sd_list_prepend(a_this, t1);
    30. test_t *t2 = malloc(sizeof(test_t));
    31. t2->a = 2;
    32. t2->b = 3;
    33. t2->c = 4;
    34. sd_list_prepend(a_this, t2);
    35. sd_list_foreach(a_this, print, NULL);
    36. printf("remains in list:%d ", sd_list_get_nelem(a_this));
    37. sd_list_delete(a_this);
    38. return 0;
    39. }







  • 相关阅读:
    1206 冲刺三
    1130持续更新
    1128项目跟进
    冲刺一1123(总结)
    冲刺一
    1117 新冲刺
    0621 第三次冲刺及课程设计
    0621回顾和总结
    实验四主存空间的分配和回收
    学习进度条
  • 原文地址:https://www.cnblogs.com/cfzhang/p/8c343c0bb8715ee6317b49f7aa62ebd4.html
Copyright © 2011-2022 走看看