自定义数据类型操作集的实现指南
InfoOfData 是 FOCX 库中用于描述数据操作方式的核心结构体。要使用 DList_S、ChainMap_S、OAMap_S 等单一数据类型容器,你需要先为你的数据类型创建一个 InfoOfData 实例。
你可以参考 Oper/ 目录下提供的 Info_Int、Info_String、Info_Double、Info_Bool 等实现,它们是创建自定义 InfoOfData 的最佳参考范例。
typedef struct InfoOfData {
Operation* oper; // 操作函数集
bool hasContent; // 是否有 content 字段
} InfoOfData;
typedef struct Operation {
_freedata freedata; // 释放数据
_hashdata hashdata; // 计算哈希值
_cmpdata cmpdata; // 比较数据
_copydata copydata; // 复制数据
_printdata printdata; // 打印数据
_copycontent copycontent; // 复制 content
_freecontent freecontent; // 释放 content
} Operation;
// 释放 void* data
typedef void (*_freedata)(void* data, void* content);
// 对 void* data 的内容进行 hash
typedef unsigned long long (*_hashdata)(void* data, void* content);
// 比较两个 void* data
typedef CmpResult (*_cmpdata)(void* data_a, void* content_a,
void* data_b, void* content_b);
// 复制 void* data
typedef void* (*_copydata)(void* data, void* content);
// 打印 Data
typedef void (*_printdata)(void* data, void* content);
// 复制 content
typedef void* (*_copycontent)(void* content);
// 释放 content
typedef void (*_freecontent)(void* content);
下面以创建一个学生信息 (Student) 的 InfoOfData 为例,代码风格与库提供的 Info_Int 等保持一致:
typedef struct {
char name[50];
int age;
int id;
} Student;
#include
#include
#include
#include "student_info.h"
// 释放学生数据(data 由 malloc 分配,需要释放)
static void freedata_Student(void* data, void* content) {
free(data);
}
// 计算学生哈希值(使用 id)
static unsigned long long hashdata_Student(void* data, void* content) {
Student* s = (Student*)data;
return (unsigned long long)s->id;
}
// 比较两个学生(比较 id)
static CmpResult cmpdata_Student(void* data_a, void* content_a,
void* data_b, void* content_b) {
Student* a = (Student*)data_a;
Student* b = (Student*)data_b;
return (a->id == b->id) ? SAME : DIFFERENT;
}
// 复制学生数据(深拷贝,分配新内存)
static void* copydata_Student(void* data, void* content) {
Student* orig = (Student*)data;
Student* copy = (Student*)malloc(sizeof(Student));
if (copy) {
strcpy(copy->name, orig->name);
copy->age = orig->age;
copy->id = orig->id;
}
return copy;
}
// 打印学生信息
static void printdata_Student(void* data, void* content) {
Student* s = (Student*)data;
printf("Student{name: %s, age: %d, id: %d}", s->name, s->age, s->id);
}
// 复制 content(如果没有 content,返回 NULL)
static void* copycontent_Student(void* content) {
return NULL;
}
// 释放 content(如果没有 content,不需要操作)
static void freecontent_Student(void* content) {
// 无需操作
}
// 创建操作集(函数指针按顺序排列,与库提供的格式一致)
static Operation oper_Student = {
freedata_Student,
hashdata_Student,
cmpdata_Student,
copydata_Student,
printdata_Student,
copycontent_Student,
freecontent_Student
};
// 创建 InfoOfData(必须为全局变量或 static)
InfoOfData Info_Student = {
&oper_Student,
false // hasContent = false,没有额外的 content
};
#include "student_info.h"
#include "List/DList/Single_Data/dlist_sdata.h"
#include
int main() {
// ========== 使用 Data_S_REF 避免重复释放 ==========
// 如果数据是栈上的局部变量,或由调用者管理生命周期,
// 使用 Data_S_REF 传入,freedata 函数不会被调用
Student s1 = {"Tom", 20, 1001};
Student s2 = {"Alice", 21, 1002};
DList_S list;
initSDList(&list, &Info_Student);
// Data_S_REF: 数据不是自己的,不会调用 freedata
// 适合传入栈上的数据或已由调用者管理的数据
insertSDataAtEndInSDList(&list, Data_S_REF(&s1, NULL));
insertSDataAtEndInSDList(&list, Data_S_REF(&s2, NULL));
printSDList(&list);
// 输出: [Student{name: Tom, age: 20, id: 1001}, Student{name: Alice, age: 21, id: 1002}]
freeSDList(&list); // 不会调用 freedata,因为使用的是 Data_S_REF
// ========== 使用 Data_S_OWN 完全接管数据 ==========
// 如果数据需要由 List/Map 管理生命周期,
// 使用 Data_S_OWN 传入,内部会调用 copydata 复制一份,
// 释放时会调用 freedata 释放复制的内存
DList_S list2;
initSDList(&list2, &Info_Student);
Student s3 = {"Bob", 22, 1003};
// Data_S_OWN: 数据是自己的,会调用 copydata 复制一份
// 释放时会调用 freedata 释放复制的内存
insertSDataAtEndInSDList(&list2, Data_S_OWN(&s3, NULL));
printSDList(&list2);
// 输出: [Student{name: Bob, age: 22, id: 1003}]
freeSDList(&list2); // 会调用 freedata 释放 copydata 复制的内存
return 0;
}
Data_S_OWN: 数据的所有权归 List/Map 所有,会自动复制一份,释放时也会释放复制的内存。适合独立管理生命周期的场景。Data_S_REF: 数据的所有权仍归调用者,List/Map 不会复制,释放时也不会调用 freedata。适合栈变量或调用者自行管理的数据。#ifndef STUDENT_INFO_H
#define STUDENT_INFO_H
#include "focx/base.h"
typedef struct {
char name[50];
int age;
int id;
} Student;
// 必须声明为 extern,全局变量
extern InfoOfData Info_Student;
#endif
#include
#include
#include
#include "student_info.h"
// ========== 1. 释放数据 ==========
static void freedata_Student(void* data, void* content) {
free(data);
}
// ========== 2. 计算哈希值 ==========
static unsigned long long hashdata_Student(void* data, void* content) {
Student* s = (Student*)data;
return (unsigned long long)s->id;
}
// ========== 3. 比较数据 ==========
static CmpResult cmpdata_Student(void* data_a, void* content_a,
void* data_b, void* content_b) {
Student* a = (Student*)data_a;
Student* b = (Student*)data_b;
return (a->id == b->id) ? SAME : DIFFERENT;
}
// ========== 4. 复制数据 ==========
static void* copydata_Student(void* data, void* content) {
Student* orig = (Student*)data;
Student* copy = (Student*)malloc(sizeof(Student));
if (copy) {
strcpy(copy->name, orig->name);
copy->age = orig->age;
copy->id = orig->id;
}
return copy;
}
// ========== 5. 打印数据 ==========
static void printdata_Student(void* data, void* content) {
Student* s = (Student*)data;
printf("Student{name: %s, age: %d, id: %d}", s->name, s->age, s->id);
}
// ========== 6. 复制 content ==========
static void* copycontent_Student(void* content) {
return NULL;
}
// ========== 7. 释放 content ==========
static void freecontent_Student(void* content) {
// 无需操作
}
// ========== 创建 Operation ==========
static Operation oper_Student = {
freedata_Student,
hashdata_Student,
cmpdata_Student,
copydata_Student,
printdata_Student,
copycontent_Student,
freecontent_Student
};
// ========== 创建 InfoOfData(全局变量)==========
InfoOfData Info_Student = {
&oper_Student,
false
};
你可以在 Oper/ 目录下找到库提供的 InfoOfData 实现,作为最佳参考:
Oper/Int_Info/ - 整数类型操作集Oper/String_Info/ - 字符串类型操作集(使用 BKDR Hash)Oper/Double_Info/ - 双精度浮点数操作集Oper/Bool_Info/ - 布尔类型操作集