使用 void 指针对任何数据类型数组进行排序?

Sorting any data type array with void pointer?

我正在使用将参数作为 *void pointer、int size 和 int data_type 的函数对任何数据类型的数组进行排序(按升序排列) 。我可以借助以下函数对数组进行排序,但问题是代码重复太多。在 if 块中,在同一个函数中重复以下代码四次,这在编程中不是一个好的方法,而且在 DRY(don't repeat yourself) 中也是反对的。

         int temp = 0;
       
        //Sort the char_array in ascending order
        for (int i = 0; i < size; i++)
        {
            for (int j = i + 1; j < size; j++)
            {
                if (char_arr[i] > char_arr[j])
                {
                    temp = char_arr[i];
                    char_arr[i] = char_arr[j];
                    char_arr[j] = temp;
                }
            }
        }

完整代码如下

// ! sorting funtion for all data types
void sort_any_data_type(void *arr, int size, int data_type)
{
    // ! data_type 1 = int,data_type 2 = float,data_type 3 = double,data_type 4 = char

    if (data_type == 1)
    {   
        int *int_arr = (int *)arr;
        int temp = 0;
        // sort()
        //Sort the int_array in ascending order
        for (int i = 0; i < size; i++)
        {
            for (int j = i + 1; j < size; j++)
            {
                if (int_arr[i] > int_arr[j])
                {
                    temp = int_arr[i];
                    int_arr[i] = int_arr[j];
                    int_arr[j] = temp;
                }
            }
        }
    }
    if (data_type == 2)
    {
        float *float_arr = (float *)arr;
        int temp = 0;
        // sort()
        //Sort the float_array in ascending order
        for (int i = 0; i < size; i++)
        {
            for (int j = i + 1; j < size; j++)
            {
                if (float_arr[i] > float_arr[j])
                {
                    temp = float_arr[i];
                    float_arr[i] = float_arr[j];
                    float_arr[j] = temp;
                }
            }
        }
    }
    if (data_type == 3)
    {
        double *double_arr = (double *)arr;
        int temp = 0;
        // sort()
        //Sort the double_array in ascending order
        for (int i = 0; i < size; i++)
        {
            for (int j = i + 1; j < size; j++)
            {
                if (double_arr[i] > double_arr[j])
                {
                    temp = double_arr[i];
                    double_arr[i] = double_arr[j];
                    double_arr[j] = temp;
                }
            }
        }
    }
    if (data_type == 4)
    {
        char *char_arr = (char *)arr;
        int temp = 0;
        // sort()
        //Sort the char_array in ascending order
        for (int i = 0; i < size; i++)
        {
            for (int j = i + 1; j < size; j++)
            {
                if (char_arr[i] > char_arr[j])
                {
                    temp = char_arr[i];
                    char_arr[i] = char_arr[j];
                    char_arr[j] = temp;
                }
            }
        }
    }
}

我想要的是下面的样子。或者解决我的问题的等价物

花了一个星期的时间试图解决它,我做了很多研究,但不幸的是没有找到合适的解决方案。 提前谢谢你。

void sort_any_data_type(void *arr, int size, int data_type)
{
    int *array = (int*)arr;
    switch (data_type)
    {
    case 1:
        array = (int *)arr;
        break;
    case 2:
        array = (float *)arr;
        break;
    case 3:
        array = (double *)arr;
        break;
    case 4:
        array = (char *)arr;
    default:
        break;
    }
    int temp = 0;
  
    for (int i = 0; i < size; i++)
    {
        for (int j = i + 1; j < size; j++)
        {
            if (array[i] > array[j])
            {
                temp = array[i];
                array[i] = array[j];
                array[j] = temp;
            }
        }
    }
}

该方法在 C 中不起作用,因为必须定义类型。 C 缺乏对类 C++ 模板的支持。有两种构建通用算法的实践方法。

  1. 使用void*
  2. 使用宏

方法 1. 用于标准函数 qsort()。该手册很容易获得。通常它会导致代码效率较低,尤其是对于小尺寸的类型(如 charint)。

方法二。 使用宏生成将对特定类型的数据进行排序的函数:

#define DEFINE_SORT(FNAME, TYPE) \
void FNAME(TYPE* array, int size) { \
    TYPE temp = 0;    \
    for (int i = 0; i < size; i++)  { \
        for (int j = i + 1; j < size; j++) { \
            if (array[i] > array[j]) { \
                temp = array[i]; \
                array[i] = array[j]; \
                array[j] = temp; \
            } \
        } \
    } \
}

为相关类型实例化它。

DEFINE_SORT(sort_char, char)
DEFINE_SORT(sort_int, int)
DEFINE_SORT(sort_float, float)
DEFINE_SORT(sort_double, double)

最后在 sort_any_data_type()

发送
void sort_any_data_type(void *arr, int size, int data_type) {
    if (data_type == 1) sort_int(arr, size);
    if (data_type == 2) sort_float(arr, size);
    if (data_type == 3) sort_double(arr, size);
    if (data_type == 4) sort_char(arr, size);
}

此调度程序利用 void* 和其他指针类型之间的自动转换。

然而,使用 void* 和幻数来识别类型是麻烦且容易出错的。

让我提出一个更好的 (IMO) 解决方案。

在 C11 中引入了 Generic Selection 允许按类型分派表达式

#define SORT(array, size) \
  _Generic((array),       \
    int*: sort_int,       \
    float*: sort_float,   \
    double*: sort_double, \
    char*: sort_char      \
  )(array, size)

_Generic用于select一个正确的函数指针指向排序函数。

用法示例:

int main() {
    int iarr[] = {3, 2, 5};
    SORT(iarr, 3);
    for (int i = 0; i < 3; ++i) printf("%d ", iarr[i]);
    puts("");

    float farr[] = {3.1, 2.2, 5.6, -12};
    SORT(farr, 4);
    for (int i = 0; i < 4; ++i) printf("%f ", farr[i]);
    puts("");

    char carr[] = "hello world";
    SORT(carr, sizeof carr - 1);
    puts(carr);
}

打印:

2 3 5 
-12.000000 2.200000 3.100000 5.600000
 dehllloorw