高级语言中有键值对的概念,那么 c 语言也可以有!!
QT键值对的妙用
https://zhuanlan.zhihu.com/p/643181004
初衷是想要实现这样的代码框架,优化代码的思路。
【理念】:所有的功能模块都封装进一个结构体 FlechazokeyValue
# 食用步骤:
1、vfkeyvalueInit ();// 初始化
2、FlechazokeyValue.addkv ();// 添加键值对
3、FlechazokeyValue.getvalue ();// 可以创建一个函数指针,指向这个函数,然后执行
核心就是一个数据对应着一个函数。
获取 key 对应函数:【getvalue 本身是个函数指针,他的返回值也是一个函数指针】
void *(*getvalue)(const F_KEY_TYPE *key,const uint32_t keylen);
那么上代码吧
# fkeyvalue.h
#ifndef __FKEYVALUE_H | |
#define __FKEYVALUE_H | |
#include "stdio.h" | |
#include "stdlib.h" | |
#include "stdbool.h" | |
#include "gd32f30x.h" | |
// 定义键值对 -->> 键的类型 --->>> 键的长度 | |
#define F_KEY_TYPE uint8_t | |
#define FLECHAZO_KEY_LEN 1 | |
// 目前值为函数指针 | |
// 定义键值对 -->> 值的类型 --->>> 值的长度 | |
// #define F_VALUE_TYPE (void *) | |
// #define FLECHAZO_VALUE_LEN 1 | |
#define FLECHAZO_KEYVALUE_GROUP 100 | |
// 键值对数据结构体 | |
typedef struct{ | |
// 键值对 | |
//1、键 是一个 uint8_t 类型的数组,元素 key keylen | |
F_KEY_TYPE *key; | |
//2、值 为一个函数指针 指向你的函数,元素 函数名 value 参数 info | |
void (*value)(uint8_t *info); | |
}keyValueData_S; | |
// 键值对操作结构体 | |
typedef struct{ | |
//1、增 | |
bool (*addkv)(const F_KEY_TYPE *key,const uint32_t keylen,void *func); | |
//2、删 | |
bool (*delkv)(const F_KEY_TYPE *key,const uint32_t keylen); | |
//3、改 | |
bool (*changekv_k)(const F_KEY_TYPE *skey,const uint32_t keylen,const F_KEY_TYPE *tkey); | |
bool (*changekv_v)(const F_KEY_TYPE *key,const uint32_t keylen,void *func); | |
//4、获取 根据键 key 获取其对应的值 value | |
void *(*getvalue)(const F_KEY_TYPE *key,const uint32_t keylen); | |
}keyValueControl_S; | |
typedef struct{ | |
uint32_t num; | |
keyValueData_S *kvdata; | |
keyValueControl_S kvctr; | |
}FlechazokeyValue_S; | |
void vfkeyvalueInit(void); | |
static bool bfkeyvalueAddkv(const F_KEY_TYPE *key,const uint32_t keylen,void *func); | |
static bool bfkeyvalueDelkv(const F_KEY_TYPE *key,const uint32_t keylen); | |
static bool bfkeyvalueChangekv_k(const F_KEY_TYPE *skey,const uint32_t keylen,const F_KEY_TYPE *tkey); | |
static bool bfkeyvalueChangekv_v(const F_KEY_TYPE *key,const uint32_t keylen,void *func); | |
static void *pvfkeyvalueGetValue(const F_KEY_TYPE *key,const uint32_t keylen); | |
static uint32_t uifkeyvalueGetFreeAdd(void); | |
bool bflechazoCheckItemInArr(const uint8_t *arr,const uint8_t value,const uint32_t len); | |
static uint32_t uifkeyvalueGetKeyGroup(const F_KEY_TYPE *key,const uint32_t keylen); | |
#endif //__FKEYVALUE_H |
# fkeyvalue.c
#include "fkeyvalue.h" | |
#include "string.h" | |
// 所有的键值对存放在这,通过指针去查询 | |
keyValueData_S kvdata[FLECHAZO_KEYVALUE_GROUP]; | |
// 理念:所有的功能都封装为一个结构体 | |
FlechazokeyValue_S FlechazokeyValue; | |
void vfkeyvalueTest(uint8_t v){ | |
printf("\nThis is flechazo keyvalue test.%d\n",v); | |
} | |
//1、初始化 | |
void vfkeyvalueInit(void){ | |
// 初始化数据 | |
FlechazokeyValue.num=0; | |
FlechazokeyValue.kvdata=kvdata; | |
// 初始化函数指针 | |
FlechazokeyValue.kvctr.addkv = bfkeyvalueAddkv; | |
FlechazokeyValue.kvctr.delkv = bfkeyvalueDelkv; | |
FlechazokeyValue.kvctr.changekv_k = bfkeyvalueChangekv_k; | |
FlechazokeyValue.kvctr.changekv_v = bfkeyvalueChangekv_v; | |
FlechazokeyValue.kvctr.getvalue = pvfkeyvalueGetValue; | |
uint8_t k = 2; | |
FlechazokeyValue.kvctr.addkv(&k,FLECHAZO_KEY_LEN,vfkeyvalueTest); | |
} | |
//1、增 | |
//bool (*addkv)(const uint8_t *key,const uint32_t keylen,void *func); | |
static bool bfkeyvalueAddkv(const F_KEY_TYPE *key,const uint32_t keylen,void *func){ | |
// 获取空闲地址 | |
uint32_t group = uifkeyvalueGetFreeAdd(); | |
//num!=0 group=0 | |
if((!FlechazokeyValue.num)&&(group)){ | |
// 说明存储控件满了 | |
} | |
// 保存键 | |
memcpy(FlechazokeyValue.kvdata[group].key,key,keylen); | |
// 保存值 | |
FlechazokeyValue.kvdata[group].value=func; | |
// 计数 + 1 | |
FlechazokeyValue.num++; | |
return true; | |
} | |
//2、删 | |
//bool (*delkv)(const uint8_t *key,const uint32_t keylen); | |
static bool bfkeyvalueDelkv(const F_KEY_TYPE *key,const uint32_t keylen){ | |
// 如果当前没有键值对 | |
if(!FlechazokeyValue.num){ | |
return false; | |
} | |
// 根据键获取组号 | |
uint32_t group = uifkeyvalueGetKeyGroup(key,keylen); | |
// 清除 key | |
memset(FlechazokeyValue.kvdata[group].key,0x00,keylen); | |
// 计数 - 1 | |
FlechazokeyValue.num--; | |
return true; | |
} | |
//3、改 | |
//bool (*changekv_k)(const uint8_t *skey,const uint32_t keylen,const uint8_t *tkey); | |
static bool bfkeyvalueChangekv_k(const F_KEY_TYPE *skey,const uint32_t keylen,const F_KEY_TYPE *tkey){ | |
// 如果当前没有键值对 | |
if(!FlechazokeyValue.num){ | |
return false; | |
} | |
// 找到 key | |
uint32_t group = uifkeyvalueGetKeyGroup(skey,keylen); | |
// 修改 | |
memcpy(FlechazokeyValue.kvdata[group].key,tkey,keylen); | |
return true; | |
} | |
//bool (*changekv_v)(const uint8_t *key,const uint32_t keylen,void *func); | |
static bool bfkeyvalueChangekv_v(const F_KEY_TYPE *key,const uint32_t keylen,void *func){ | |
// 如果当前没有键值对 | |
if(!FlechazokeyValue.num){ | |
return false; | |
} | |
// 找到 key | |
uint32_t group = uifkeyvalueGetKeyGroup(key,keylen); | |
// 修改 | |
FlechazokeyValue.kvdata[group].value=func; | |
return true; | |
} | |
//4、获取 根据键 key 获取其对应的值 value | |
//void *(*getvalue)(uint8_t *key,uint32_t keylen); | |
static void *pvfkeyvalueGetValue(const F_KEY_TYPE *key,const uint32_t keylen){ | |
// 如果当前没有键值对 | |
if(!FlechazokeyValue.num){ | |
return false; | |
} | |
// 找到 key | |
uint32_t group = uifkeyvalueGetKeyGroup(key,keylen); | |
return FlechazokeyValue.kvdata[group].value; | |
} | |
// 根据 key 获取存储数组中的组号 | |
static uint32_t uifkeyvalueGetKeyGroup(const F_KEY_TYPE *key,const uint32_t keylen){ | |
for(uint32_t g=0;g<FLECHAZO_KEYVALUE_GROUP;g++){ | |
if(memcmp(FlechazokeyValue.kvdata[g].key,key,keylen)){ | |
return g; | |
} | |
} | |
return false; | |
} | |
// 获取新增键值对地址 [返回值为第 x 组键值对] | |
static uint32_t uifkeyvalueGetFreeAdd(void){ | |
for(uint32_t g=0;g<FLECHAZO_KEYVALUE_GROUP;g++){ | |
if(bflechazoCheckItemInArr(FlechazokeyValue.kvdata[g].key,0x00,FLECHAZO_KEY_LEN)){ | |
return g; | |
} | |
} | |
return false; | |
} | |
// 检查数组中的每个元素的值 | |
bool bflechazoCheckItemInArr(const uint8_t *arr,const uint8_t value,const uint32_t len){ | |
for(uint32_t l=0;l<len;l++){ | |
if(*(arr+len)!=value){ | |
return false; | |
} | |
} | |
return true; | |
} |