【问题标题】:Calculate average of numeric array elements without knowing elements type在不知道元素类型的情况下计算数值数组元素的平均值
【发布时间】:2018-02-08 17:50:01
【问题描述】:

我需要编写函数,在不知道元素类型的情况下用数值元素计算数组的平均值。

如果我愿意,需要使用数组、数组元素的数量和其他参数调用该函数。

这就是我现在所拥有的:

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 * 并且还将我的类型的大小发送到我的函数中。

在我的电脑中,我可以看到 bytes4,所以经过 4 次迭代后,我需要将我的 p 转换为 Int

所以loop 里面的东西开始乱了,我不知道该怎么做。

【问题讨论】:

  • 平均值为(sum(elements) / totalelements)。如果您的elements 是完全任意类型,则调用者必须提供相应的sum 函数作为函数指针。或者 plus 函数。
  • 首先我想知道如何将我的数组转换为数字
  • 谁说这些是数字?也许它是向量?还是矩阵?还是……苹果?您说类型未知(顺便说一句,在我之前的评论中应该还有“除法”功能)
  • @DeanMovy,您似乎专注于错误的地方。特别是,您断言 4 次迭代后我需要将我的 p 转换为 Int 是不明智的。如果输入包含floats 怎么办?然后,您不能期望转换为 int 而不会丢失精度和/或完全获得错误的值。也没有任何其他特定类型可以适当地适应所有 C 算术类型。
  • 泛型在 C 中很难做到。之前有几个问题询问过如何做到这一点。答案通常倾向于涉及 C 预处理器。它可能不是你想要的,但也许看看?这是link

标签: c


【解决方案1】:

需要编写函数,在不知道元素类型的情况下计算具有数值元素的数组的平均值。

这有点宽泛,但有一些限制,它是可行的。

关键是传递给average(),指向函数的指针来做加/除数学。 @Eugene Sh..

为了最小化内存管理,也传递给avg()add_ll()等,存储结果的目的地。

Minor:对于 size 数据和数学,使用 size_t 而不是 int,因为该类型既不太窄也不太宽。

#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 = %lld\n", 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));

【讨论】:

  • 您忘记将#include &lt;string.h&gt; 包含在memset()
  • 这里:*(long long *) quo = *(long long *) a / n; 还需要修复:=>> error: conversion to ‘long long unsigned int’ from ‘long long int’ may change the sign of the result [-Werror=sign-conversion] *(long long *) quo = *(long long *) a / n;
  • @Michi 这只是一个错误,因为您在启用错误时收到警告。一个简单的“修复”是投射(long long) n。迂腐代码会首先检查if (n &gt; LLONG_MAX) { code to make quotient 0 }。这取决于编码目标的稳健程度。 IAC,对于高级问题是个好主意。
  • 我同意,但我习惯于在没有警告的情况下编码:)
猜你喜欢
  • 2022-01-16
  • 2013-12-29
  • 1970-01-01
  • 2018-02-18
  • 1970-01-01
  • 1970-01-01
  • 2023-03-14
  • 2015-12-26
  • 2018-06-09
相关资源
最近更新 更多