我需要编写功能,以计算具有数字值元素的数组的平均值,而不了解元素类型。
如果我愿意,需要使用数组,数组元素的数量和其他参数来调用该功能。
所以这就是我到目前为止所拥有的:
int arr[2] = { 3,7 };
avarage(arr, 2, sizeof(int));
void * avarage(void * arr, int elements, int bytes)
{
int i;
char *p = (char *)malloc(bytes);
char *tmp = (char *)arr;
char *n;
int sum = 0;
for (i = 0; i < elements * sizeof(bytes); i++)
{
p[i] = tmp[i];
}
}
因为我不知道与通用指针合作的元素类型:void *
,也发送到我的函数中的大小。
在我的计算机中,我可以看到bytes
是4
,因此在4个迭代后,我需要将p
转换为Int
。
所以loop
内部的事情开始搞砸了,我不知道如何继续。
需要写入功能,以计算具有数值元素的数字值元素的平均值,而不了解元素类型。
这有些广泛,但是有一些限制,这是可行的。
关键是传递到average()
,指示函数进行添加/分割数学。@eugene sh ..
为了最大程度地减少内存管理,也将传递给avg()
,add_ll()
等,是存储结果的目的地。
次要:将size_t
而不是int
用于 size 数据和数学,因为该类型既不狭窄也不太宽。
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
// Return true on failure
// Note that a, b, etc could point to the same object
bool add_ll(void *sum, void *a, void *b) {
// TBD: add code to detect and prevent overflow
*(long long *) sum = *(long long *) a + *(long long *) b;
return false;
}
bool div_ll(void *quo, void *a, size_t n) {
if (n == 0) {
return true;
}
*(long long *) quo = *(long long *) a / n;
return false;
}
bool avg(void *bar, void *a, size_t nmemb, size_t size, bool (add)(), bool (quo)()) {
memset(bar, 0, size); // assume bits all zero is a value of zero
char (*p)[size] = a; // p is a pointer to a character array of size `size`
for (size_t i = 0; i < nmemb; i++) {
if (add(bar, bar, p)) {
return true;
}
p++; // this moves `size` bytes later
}
return quo(bar, bar, nmemb);
}
int main(void) {
long long A[3] = { 3, 600000, 90000000000 };
long long mean;
if (avg(&mean, A, sizeof A / sizeof A[0], sizeof A[0], add_ll, div_ll)) {
puts("Oops");
} else {
printf("Average = %lldn", mean);
}
return 0;
}
输出
Average = 30000200001
高级问题:更多错误检查的代码将使用以下来确保函数类型的匹配,并将const
正确。
bool avg(void *bar, void *a, size_t nmemb, size_t size,
bool (add)(void *sum, void *a, void *b),
bool (quo)(void *quo, void *a, size_t n));
或
bool avg(void *bar, void *a, size_t nmemb, size_t size,
bool (add)(void *sum, const void *a, const void *b),
bool (quo)(void *quo, const void *a, size_t n));