头图

欢迎关注我的公众号 [极智视界],获取我的更多笔记分享

O_o>_<   o_OO_o~_~o_O

  本文介绍一下 darknet 中链表查找 option_find_xx 相关接口的实现。

   darknet 中会大量用到链表操作,如上次写的《【编程艺术】剖析 darknet read_data_cfg 接口》中就有把 voc.data 中每行数据中 "=" 前后数据以键值对形式存入链表 val 中的示例,关于一些链表及节点构建、插入链表、释放链表的实现可以看我的这篇《【编程艺术】剖析 darknet C 链表实现》,这里主要说一下链表查找相关接口。

1、链表查找接口定义

  链表查找相关接口定义主要在 option_list.h 头中:

/// option_list.h
#ifndef OPTION_LIST_H
#define OPTION_LIST_H
#include "darknet.h"
#include "list.h"

/// 你可以把它看成python中的字典,键-值对
typedef struct{
    char *key;
    char *val;
    int used;
} kvp;

#ifdef __cplusplus
extern "C" {
#endif

list *read_data_cfg(char *filename);
int read_option(char *s, list *options);
void option_insert(list *l, char *key, char *val);
/// 这些就是关于链表查找相关接口的声明了
//////////////////////////////////////////////////////////////////
char *option_find(list *l, char *key);                          //
char *option_find_str(list *l, char *key, char *def);           //
char *option_find_str_quiet(list *l, char *key, char *def);     //
int option_find_int(list *l, char *key, int def);               //
int option_find_int_quiet(list *l, char *key, int def);         //
float option_find_float(list *l, char *key, float def);         //
float option_find_float_quiet(list *l, char *key, float def);   //
//////////////////////////////////////////////////////////////////
void option_unused(list *l);

//typedef struct {
//    int classes;
//    char **names;
//} metadata;

//LIB_API metadata get_metadata(char *file);

#ifdef __cplusplus
}
#endif
#endif

   下面一个个来看一看。

2、option_find

   来看一下 option_find 的实现:

/// option_list.c
// 链表查找,查找指定key对应的val,找到返回val,没找到返回NULL
char *option_find(list *l, char *key)
{
    node *n = l->front;                   // 从链表头开始
    while(n){                             // 当节点不为NULL
        kvp *p = (kvp *)n->val;           // p为指向节点n值域的指针,值域为kvp*
        if(strcmp(p->key, key) == 0){     // strcmp 比较p键和传入的key是否一致
            p->used = 1;                  // 若一致则标记
            return p->val;                // 找到就返回p值
        }
        n = n->next;                      // 循环更新                 
    }
    return 0;
}

   以上的逻辑还是比较清晰的,其中 strcmp 为 C 语言中的字符串比较函数,声明在 string.h:

/// string.h
_Check_return_
int __cdecl strcmp(
    _In_z_ char const* _Str1,
    _In_z_ char const* _Str2
    );

3、option_find_str & option_find_str_quiet

   看起来会和 option_find 差不多,来看一下 option_find_str 的实现:

/// option_list.c
// 链表查找,查找指定key对应的val,找到返回val,没找到给输出提示并返回def
char *option_find_str(list *l, char *key, char *def)
{
    char *v = option_find(l, key);                                  // 调用option_find
    if(v) return v;                                                 // 若找到,返回找到的字符串
    if(def) fprintf(stderr, "%s: Using default '%s'\n", key, def);  // 若未找到,使用默认传参def
    return def;
}

   option_find_str_quiet 和 option_find_str 差不多:

/// option_list.c
// 链表查找,查找指定key对应的val,找到返回val,没找到不给输出提示返回def
char *option_find_str_quiet(list *l, char *key, char *def)
{
    char *v = option_find(l, key);
    if (v) return v;
    return def;
}

4、option_find_int & option_find_int_quiet

  来看一下 option_find_int:

/// option_list.c
// 链表查找,查找指定key对应的val,找到返回int val,没找到给输出提示并返回def
int option_find_int(list *l, char *key, int def)
{
    char *v = option_find(l, key);
    if(v) return atoi(v);                                    // atoi将字符串转换成int
    fprintf(stderr, "%s: Using default '%d'\n", key, def);   // 没找到,输出错误信息,并返回def
    return def;
}

   这里和前面查找字符串的区别主要就是一个 atoi,将字符串转换成整型,其他类似。

   继续来看 option_find_int_quiet,和 option_find_int 的区别就是不输出错误信息,直接返回默认值:

/// option_list.c
int option_find_int_quiet(list *l, char *key, int def)
{
    char *v = option_find(l, key);
    if(v) return atoi(v);
    return def;
}

5、option_find_float & option_find_float_quiet

  最后来看 option_find_float 和 option_find_float_quiet。

   option_find_float 的实现如下:

/// option_list.c
// 链表查找,查找指定key对应的val,找到返回float val,没找到给输出提示并返回def
float option_find_float(list *l, char *key, float def)
{
    char *v = option_find(l, key);
    if(v) return atof(v);
    fprintf(stderr, "%s: Using default '%lf'\n", key, def);
    return def;
}

  以上和 option_find_int 类似,故 option_find_float_quiet 也不多说了,实现如下:

float option_find_float_quiet(list *l, char *key, float def)
{
    char *v = option_find(l, key);
    if(v) return atof(v);
    return def;
}

  以上分析了 darknet 中链表查找相关接口,比较简单,但需夯实基础、温故而知新。


【公众号传送】
【编程艺术】剖析 darknet 链表查找 option_find_xx 接口


极智视界
13 声望4 粉丝