我需要获取已在单独函数中初始化的特定结构数组中的元素数量,我该怎么做?
函数初始化数组:
Hashtbl* init_hashtbl(){
Hashtbl* hashtbl;
hashtbl = calloc(SIZE, sizeof(Hashtbl));
for(int i = 0; i<SIZE; i++){
hashtbl[i].subscript = malloc(MAX_LENGTH + 1);
strcpy(hashtbl[i].subscript, "ZERO\n");
hashtbl[i].value = malloc(MAX_LENGTH + 1);
strcpy(hashtbl[i].value, "ZERO\n");
}
return hashtbl;
}
主要功能(这只是我需要的典型用途的示例):
int main() {
Hashtbl* nums;
nums = init_hashtbl();
insert(nums, "example", "example");
/*insert returns hashtable same as init_hashtbl but if array is full
carries out a realloc*/
printf("%d", /*number of elements*/);
}
哈希表结构:
typedef struct Hashtbls{
char *subscript;
char *value;
} Hashtbl;
还有一个问题。在大多数情况下,例如上述函数初始化哈希表的情况,我会返回一些使用了 malloc 或 calloc 的东西。我怎样才能释放它以避免内存泄漏,记住我正在使用头文件并且主要功能只是一个测试驱动程序,用户不应该从他的部分中释放出来?
最佳答案
您有一些选择。
1.
将元素数量传递给 init_hashtbl()
函数:
Hashtbl* init_hashtbl(size_t num_of_elements){
Hashtbl* hashtbl;
hashtbl = calloc(num_of_elements, sizeof(Hashtbl));
for(int i = 0; i<num_of_elements; i++){
hashtbl[i].subscript = malloc(MAX_LENGTH + 1);
strcpy(hashtbl[i].subscript, "ZERO\n");
hashtbl[i].value = malloc(MAX_LENGTH + 1);
strcpy(hashtbl[i].value, "ZERO\n");
}
return hashtbl;
int main() {
Hashtbl* nums;
nums = init_hashtbl(SIZE);
...
}
通过这种方式,您可以控制表格初始化的元素数量。
2。
将指针传递给 size_t
并让 init 函数写入它
Hashtbl* init_hashtbl(size_t *size){
Hashtbl* hashtbl;
hashtbl = calloc(SIZE, sizeof(Hashtbl));
for(int i = 0; i<SIZE; i++){
hashtbl[i].subscript = malloc(MAX_LENGTH + 1);
strcpy(hashtbl[i].subscript, "ZERO\n");
hashtbl[i].value = malloc(MAX_LENGTH + 1);
strcpy(hashtbl[i].value, "ZERO\n");
}
*size = SIZE; // <-- saving the size for the caller through
// pointer
return hashtbl;
int main() {
Hashtbl* nums;
size_t table_size
nums = init_hashtbl(&table_size);
...
}
对于所有操作表但不调整表大小的函数,它们应该
都得到 size_t
参数。例如你的 loadfromfile
1
功能。
Hashtbl* loadfromfile(Hashtbl* hashtbl, size_t size, char *path);
所有调整它大小的函数都应该得到一个指针并改变它,就像你的
插入
函数2:
Hashtbl *insert(Hashtbl *hashtbl, size_t *size, const char *subscript, const char *value)
{
// check that the params are not NULL
// your code here
// need to resize
size_t newsize = size + 1;
Hashtbl *tmp = realloc(hashtbl, newsize * sizeof *tmp);
if(tmp == NULL)
{
// error handling
return NULL;
}
hashtbl = tmp;
*size = newsize;
// here you need to initialize your subscript, values for the
// new hashtbl entries
// ...
return hashtbl;
}
请注意,我更改了函数 insert
的签名。它现在返回一个
指向表的新指针并更新 size
当且仅当 realloc
是
成功。3
调用 insert
就像调用 realloc
Hashtbl *tmp = insert(hashtbl, &size, "example", "example");
if(tmp == NULL)
{
// could not resize,
// the unresized table is still in hashtbl
// and size still the old value
}
hashtbl = tmp;
关于释放内存
我建议你创建一个 destroy
函数(或者使用另一个名称,它不会
事情)。当你的结构有指向动态分配内存的指针时,它是
最好将它们初始化为 NULL
。使用 calloc
是一个很好的方法。
如果遇到错误或者想释放整个栈,那么你只有
调用您的 destroy
函数。 destroy
函数将释放所有
内存。例如:
hashtbl_destroy(Hashtbl *hashtbl, size_t size)
{
for(int i = 0; i < size; ++i)
{
free(hashtbl[i].subscript);
free(hashtbl[i].value);
free(hashtbl[i]);
}
}
free(NULL)
是允许的,最好初始化你的
在分配内存之前,指针将为 NULL
,因为以防万一
初始化失败,调用destroy
函数即可。
最后一件事:当你设计一个像 Hashtbl
这样的结构时,你有
一些操作表的函数,我建议你命名你的
使用前缀的函数,例如 hashtbl_
。
hashtbl_create(...);
hashtbl_init(...);
hashtbl_destroy();
hashtbl_insert();
hashtbl_remove();
当您有多个 insert
函数时,很容易避免命名冲突。
注释
1
函数 loadfromfile
出现在这个问题中:Why is reading from file function crashing?
2 当一个函数需要一个指针时,判断它是否是一个指针总是一件好事 您将修改指针指向的数据的内容。 如果是字符串,您是否要操作字符串。
void some_func(char *txt);
显示 some_func
可能操纵字符串,例如降低
第一个字母的情况。在那种情况下,最好不要传递字符串
文字:
some_func("This might cause a crash");
char txt[] = "This will not";
some_func(txt);
但是,如果您的函数不打算操作字符串,那么它是 最好声明你的功能是这样的:
void some_other_function(const char *txt);
作为 some_function
的调用者,我知道内容不会改变,
所以
some_other_function("Not a problem");
这就是为什么我在 insert
中为 subscript
和 value
使用 const char *
功能。
3 您还可以使用另一种技术,而不是返回新表, 你可以传递一个双指针
int insert(Hashtbl **hashtbl, size_t *size, const char *subscript, const char *value)
{
// check that the params are not NULL
// your code here
// need to resize
size_t newsize = size + 1;
Hashtbl *tmp = realloc(*hashtbl, newsize * sizeof *tmp);
if(tmp == NULL)
{
// error handling
return NULL;
}
*hashtbl = tmp;
*size = newsize;
// here you need to initialize your subscript, values for the
// new hashtbl entries
// ...
return 1; // 1 on success, 0 on failure
}
if(!insert(&hashtbl, &size, "example", "example"))
{
// could not resize,
// the unresized table is still in hashtbl
// and size still the old value
}
关于c - 如果从函数返回,如何获取结构数组中的元素数? +返回时如何处理内存泄漏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48251538/