几天前我发布了这个问题,每个人都建议我使用void*
,我做到了。我认为他们中的一些人还指出了一些我需要注意的事情,但我不确定它们到底是什么。但是,我遇到了一些问题......
我不会将我所有的代码都发布在它很大的地方,相反,我会发布我认为重要的东西,希望足以让你帮助我。
我的哈希表结构是这样的:
typedef void * HashKey;
typedef void * HashValue;
typedef struct sHashItem {
HashKey key;
HashValue value;
char status;
} HashItem;
typedef struct sHashTable {
HashItem *items;
int count;
float load;
int size;
Bool (*compare)(HashKey, HashKey);
unsigned (*hash)(void *);
} HashTable;
我的插入函数的签名是这样的:
Bool hashInsert(HashTable * const table, HashKey key, HashValue value);
在该函数内部的某个地方,当我在哈希表中找到一个空闲存储桶时,我会这样做:
table->items[index].key = key;
table->items[index].value = value;
table->items[index].status = USED;
table->load = ++table->count / (float)table->size;
所有这些都带来了一些问题:
1)正如您在上面看到的,我只是将空闲存储桶的每个键/值对设置为与键/值hashInsert
函数参数传递的相同指针。这带来了一个问题,您可能已经注意到了......例如,做这样的事情:
char str[50];
scanf("%s%*c", str);
hashInsert(t1, (HashKey)str, (HashValue)5);
scanf("%s%*c", str);
hashInsert(t1, (HashKey)str, (HashValue)3);
如果输入是“KeyA”,然后是“KeyB”,则两者都将“KeyB”作为存储桶键。同样的事情适用于值而不仅仅是键,因为它们基本上是相同的类型,因为我想让我的代码完全模块化,适用于任何数据类型。
我怎么能解决这个问题?
我的第一个想法是使用strdup(str)
并将其传递给hashInsert
函数。那将解决问题。由于这是在主代码中处理的,因此我也可以轻松地将malloc()
其用于需要作为值传递的任何其他数据类型(键可能始终是字符串或 int)。
但是这个解决方案带来了另一个问题......
2)我应该如何释放这个分配的内存?当然,它是由“主程序员”而不是“哈希表模块程序员”分配的,所以“主程序员”应该在主代码中释放它,对吧?但是,对我来说,这看起来不像模块化代码。
我的代码还有一个hashDestroy
功能,可以释放所有分配的内存。但是我怎样才能使用这个功能来释放一切呢?我不能只遍历每个键/值并free()
在它们上使用,因为它们中的一些可能一开始就不是malloc'd
任何程序员的,我不需要释放它们。
我怎样才能知道哪些是我hashDestroy
必须免费的,哪些不应该?
3)最后,我想我也可以把这个问题混在一起......在第一点,我的建议是使用strdup()
或malloc
“修复”那个特定问题(同时引入另一个问题),但这看起来也不是很模块化大部头书。这种内存分配应该在哈希表模块代码中完成,而不是由“主程序员”在主代码中完成。
你建议我如何解决这个问题?我的意思是,数据类型可以是任何东西,虽然使用strdup()
有很大帮助,但它只适用于字符串。如果我需要为某些特定结构或只是一个 int 分配内存怎么办?
很抱歉这篇大文章,但我认为这些问题都是相关的,我需要一些帮助来弄清楚它们,因为我的 C 知识并不是那么极端。我最近才知道void*
所以...