如何在C中处理未知类型的数字?

时间:2018-02-20 08:54:46

标签: c pointers void-pointers

我需要编写一个方法来计算未知类型数字的平均值(double,float,int ...)。我试着这样做,但它只适用于双重类型:

double average(void *arr, int length, int bytes) {
    int i;
    double sum = 0;
    double num;
    for (i = 0; i < length; i++) {
        memcpy(&num, (char *) arr, bytes);
        sum += num;
        arr = (char *) arr + bytes;
    }
    return sum / length;
}

有什么建议吗?

1 个答案:

答案 0 :(得分:2)

如果您不知道它们的类型,则无法对数组值求和。仅依靠bytes参数是不够的,因为intfloat在许多编译器中的大小通常相同,但它们的类型非常不同。使用void*进行操作时会丢失类型信息。

如果必须使用void*,解决此问题的唯一方法是传入一个参数,指定数组实际拥有的类型,然后相应地转换void*

我建议为每种类型编写一个单独的函数,例如:

enum dataType {dtInt, dtFloat, dtDouble};

double averageInt(int *arr, int length)
{
    double sum = 0;
    for (int i = 0; i < length; ++i)
        sum += arr[i];
    return sum / length;
}

double averageFloat(float *arr, int length)
{
    double sum = 0;
    for (int i = 0; i < length; ++i)
        sum += arr[i];
    return sum / length;
}

double averageDouble(double *arr, int length)
{
    double sum = 0;
    for (int i = 0; i < length; ++i)
        sum += arr[i];
    return sum / length;
}

double average(void *arr, int length, enum dataType arrType)
{
    switch (arrType)
    {
        case dtInt:    return averageInt((int*)arr, length);
        case dtFloat:  return averageFloat((float*)arr, length);
        case dtDouble: return averageDouble((double*)arr, length);
    }
    return 0;
}

可替换地:

enum dataType {dtInt, dtFloat, dtDouble};

double sumInt(int *arr, int length)
{
    double sum = 0;
    for (int i = 0; i < length; ++i)
        sum += arr[i];
    return sum;
}

double sumFloat(float *arr, int length)
{
    double sum = 0;
    for (int i = 0; i < length; ++i)
        sum += arr[i];
    return sum;
}

double sumDouble(double *arr, int length)
{
    double sum = 0;
    for (int i = 0; i < length; ++i)
        sum += arr[i];
    return sum;
}

double average(void *arr, int length, enum dataType arrType)
{
    double sum;
    switch (arrType)
    {
        case dtInt:    sum = sumInt((int*)arr, length); break;
        case dtFloat:  sum = sumFloat((float*)arr, length); break;
        case dtDouble: sum = sumDouble((double*)arr, length); break;
        default:       sum = 0; break;
    }
    return sum / length;
}