gpt4 book ai didi

c - 指针约定与 : Array of pointers to certain elements

转载 作者:太空宇宙 更新时间:2023-11-04 03:01:04 28 4
gpt4 key购买 nike

这个问题是关于处理我自己研究的这个指针问题的最佳实践。

我有一个在读取 csv 的函数中动态生成的结构数组。

int init_from_csv(instance **instances,char *path) {
... open file, get line count
*instances = (instance*) malloc( (size_t) sizeof(instance) * line_count );
... parse and set values of all instances
return count_of_valid_instances_read;
}
// in main()
instance *instances;
int ins_len = init_from_csv(&instances, "some/path/file.csv");

现在,我必须对这些原始数据执行函数,将其拆分,然后对拆分再次执行相同 函数。这个数据集可能相当大,所以我不想复制实例,我只想要一个指向拆分中结构的指针数组。

instance **split = (instance**) malloc (sizeof(instance*) * split_len_max);
int split_function(instance *instances, ins_len, instances **split){
int i, c;
c = 0;
for (i = 0; i < ins_len; i++) {
if (some_criteria_is_true) {
split[c++] = &instances[i];
}
return c;
}

现在我的问题是,在结构数组和指针数组上执行函数的最佳实践或最易读的方法是什么?举个简单的例子count_data()

int count_data (intances **ins, ins_len, float crit) {
int i,c;
c = 0;
for (i = 0; i < ins_len; i++) {
if ins[i]->data > crit) {
++c;
}
}
return c;
}

// code smell-o-vision going off by now
int c1 = count_data (split, ins_len, 0.05); // works
int c2 = count_data (&instances, ins_len, 0.05); // obviously seg faults

我可以让我的 init_from_csv ma​​lloc 指向实例的指针数组,然后 malloc 我的实例数组。在我开始更改一堆代码之前,我想了解一个经验丰富的 c 程序员将如何处理这类事情。

最佳答案

这可能看起来有点蹩脚,但如果你真的想传递那个实例**指针并希望它同时适用于主数据集和拆分,你真的需要为主数据集创建一个指针数组数据集也是。这是您可以做到的一种方法...

size_t i, mem_reqd;
instance **list_seg, *data_seg;

/* Allocate list and data segments in one large block */
mem_reqd = (sizeof(instance*) + sizeof(instance)) * line_count;
list_seg = (instance**) malloc( mem_reqd );
data_seg = (instance*) &list_seg[line_count];

/* Index into the data segment */
for( i = 0; i < line_count; i++ ) {
list_seg[i] = &data_seg[i];
}

*instances = list_seg;

现在您始终可以对 instance* 指针数组进行操作,无论是主列表还是拆分列表。我知道您不想使用额外的内存,但如果您的 instance 结构不是非常小,那么为每个实例分配一个额外的指针以防止混淆代码重复是个好主意。

完成主实例列表后,您可以这样做:

void free_instances( instance** instances )
{
free( instances );
}

我很想将它实现为一个结构:

struct instance_list {
instance ** data;
size_t length;
int owner;
};

这样,您可以以更好的方式从您的函数中返回:

instance_list* alloc_list( size_t length, int owner )
{
size_t i, mem_reqd;
instance_list *list;
instance *data_seg;

/* Allocate list and data segments in one large block */
mem_reqd = sizeof(instance_list) + sizeof(instance*) * length;
if( owner ) mem_reqd += sizeof(instance) * length;
list = (instance_list*) malloc( mem_reqd );
list->data = (instance**) &list[1];
list->length = length;
list->owner = owner;

/* Index the list */
if( owner ) {
data_seg = (instance*) &list->data[line_count];
for( i = 0; i < line_count; i++ ) {
list->data[i] = &data_seg[i];
}
}

return list;
}

void free_list( instance_list * list )
{
free(list);
}

void erase_list( instance_list * list )
{
if( list->owner ) return;
memset((void*)list->data, 0, sizeof(instance*) * list->length);
}

现在,从 CSV 加载的函数不必关注创建这个怪物的细节,因此它可以简单地完成它应该完成的任务。您现在可以从其他函数返回列表,无论它们包含数据还是只是指向其他列表。

instance_list* load_from_csv( char *path )
{
/* get line count... */
instance_list *list = alloc_list( line_count, 1 );
/* parse csv ... */
return list;
}

等等...好吧,你明白了。不能保证此代码将编译或工作,但它应该是关闭的。我认为这很重要,无论何时您使用比简单数组稍微复杂一点的数组来做某事,做一点额外的努力来封装它是很有用的。这是您将用于分析或其他任何工作的主要数据结构,因此赋予它一点地位是有意义的,因为它有自己的数据类型。

我不知道,这是不是太过分了? =)

关于c - 指针约定与 : Array of pointers to certain elements,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11770645/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com