在C中对数组实现一个通用的“map”函数

我在数组上实现通用的“map”函数时遇到了困难。 我从以下草案开始:

void MapArray(void * src, void * dest, void * (f)(void *), size_t n, size_t elem) { unsigned int i = 0, j = 0; void * temp = malloc(elem); for(i = 0; i<n, i++) { temp = (f)((char *) src) + i)); for(j = 0; j < elem; j++) { *(((char *) dest) + i) = *(((char *) temp) + i); } } free(temp); } 

我明白为什么它不正确 – 我会在给它’f’之前投入(char *) – 但我现在已经失去动力并且无法提出解决方案。 (我在学习C的过程中这样做)

我的理由是获得’f’的结果,并逐字节地将其复制到dest [i]。

你能给我一些提示吗?

你的第一个问题是你在一些表达方式中做得太多了。 你需要分解它。

 void MapArray(void * src, void * dest, void * (f)(void *), size_t n, size_t elem) { unsigned int i = 0, j = 0; void * temp = malloc(elem); char* csrc = (char*)src; char* cdest = (char*)dest; char* ctemp = (char*)temp; for(i = 0; i 

现在你的第二个问题。 你malloc一个缓冲区,然后你..分配给那个指针? 反复? 然后只释放最后一个f调用的结果? 这完全没必要。

 void MapArray(void * src, void * dest, void * (f)(void *), size_t n, size_t elem) { unsigned int i = 0, j = 0; char* csrc = (char*)src; char* cdest = (char*)dest; for(i = 0; i 

现在你的第三个问题。 你传入一个指针 - 但只传给char。 你没有传递空白*。 这意味着您的函数不能是通用的 - f不能应用于任何东西。 我们需要一个void * s数组,以便该函数可以将任何类型作为参数。 我们还需要将类型的大小作为参数,以便我们知道在dest上移动多远。

 void MapArray(void ** src, void * dest, void * (f)(void *), size_t n, size_t sizeofT) { for(unsigned int i = 0; i < n; i++) { void* temp = f(src[n]); memcpy(dest, temp, sizeofT); dest = (char*)dest + sizeofT; } } 

我们还有另一个问题 - 温度的记忆。 我们不释放它。 我们也没有将用户数据参数传递给f,这将允许它返回我们不需要释放的堆分配的内存。 f可以工作的唯一方法是返回静态缓冲区。

 void MapArray(void ** src, void * dest, void * (f)(void *, void*), void* userdata, size_t n, size_t sizeofT) { for(unsigned int i = 0; i < n; i++) { void* temp = f(src[n], userdata); memcpy(dest, temp, sizeofT); dest = (char*)dest + sizeofT; } } 

现在f可以运行几乎任何它喜欢的东西,并保持它需要的任何状态。 但我们仍然没有释放缓冲区。 现在,f返回一个简单的结构,告诉我们是否需要释放缓冲区。 这也允许我们在不同的f调用中释放或不释放缓冲区。

 typedef struct { void* data; int free; } freturn; void MapArray(void ** src, void * dest, freturn (f)(void *, void*), void* userdata, size_t n, size_t sizeofT) { for(unsigned int i = 0; i < n; i++) { freturn thisreturn = f(src[n], userdata); void* temp = thisreturn.data; memcpy(dest, temp, sizeofT); dest = (char*)dest + sizeofT; if (thisreturn.free) free(temp); } } 

但是,我仍然不明白这个function的目的。 所有这些都取代了简单的for循环? 您尝试替换的代码比调用函数的代码更简单,并且可能更高效,并且肯定更强大(例如,它们可以使用continue / break)。

更重要的是,C真的很糟糕这种工作。 C ++好多了。 例如,将函数应用于数组的每个成员都非常简单。

有一个原因,在C标准库中没有这么多 – 在C语言中几乎不可能做到这一点。你不能将结果“逐字节”复制到dest[i] – 因为你已经将dest转换为char * ,它只指向一个char (byte)。

据推测, elem的大小是f返回的任何类型, nsrcdest中元素的数量。 在这种情况下,你的代码并不太远,但是(正如你已经猜测的那样)你操纵指针的方式(尤其是转换为char * )不会削减它。

但是,即使你解决了这个问题,你还会遇到另外一个问题:从f分配返回类型而不知道类型真的(真的)很难。 事实上,关于我能想到的唯一方法是将此代码包装成宏而不是:

 #define MapArray(s, d, f, n) \ do { \ unsigned i; \ for (i = 0; i 

你会用这样的东西:

 int f(int a) { return a + 100; } #define elements(array) (sizeof(array)/sizeof(array[0])) int main() { unsigned i; int x[] = { 0, 1, 2, 3}; int y[elements(x)]; MapArray(x, y, f, elements(x)); for (i=0; i 

请注意:我推荐这个。 这一种方法来做你所要求的,但正如我所说的那样,这几乎不可能在C中做得很好。这段代码在某种程度上有效,但IMO并不符合做好工作的条件。

  • 检查函数f是否未返回指向局部变量的指针
  • 我不确定j上的循环应该是什么