c比较器最佳实践,用于需要更多参数时

时间:2017-03-22 10:47:05

标签: c comparator qsort

我打算每次用另一个坐标对多维点的数组进行排序。 我想使用c qsort()方法,但为了做到这一点,我必须使用比较器函数,它的输入只有两个指针,所以我不能发送它所需的坐标进行排序。 因此,我想出了两个解决方案,我正在努力选择其中最好的一个:

  1. 使用静态变量 - 本例中的int - 将其初始化为-1,并在调用qsort函数之前将其设置为所需坐标。另外,制作我的比较器,访问这个变量并根据它进行比较。
  2. 构建一个新结构来保存指向该点和所需坐标的指针,然后使比较器对这种结构的两个指针进行排序,并使用结构中的附加信息。
  3. 第一个听起来像是一个快速的解决方案,虽然它可能是循环孔,而第二个听起来像这样一个简单任务的过度杀伤。 如果遇到问题,我会很高兴听到任何更好的解决方案。

3 个答案:

答案 0 :(得分:2)

如果您的系统有qsort_r,则可以使用它。 qsort_r有一个额外的参数,可用于传递坐标。

int comparator(const void *l, const void *r, void *param)
{
    Point* lPoint = (Point*) l;
    Point* rPoint = (Point*) r;
    Coordinate* coord = (Coordinate*) param;

    // Do your comparison ....
}

void mySort(Point* list, size_t listSize, Coordinate sortCoord)
{
    qsort_r(list, listSize, sizeof(Point), comparator, &sortCoord);
}

如果您使用glibc(例如在Linux上)和OS X上,它绝对可用。但是,它不是官方可移植的。请参阅有关便携性的答案

How portable is the re-entrant qsort_r function compared to qsort?

我的代码示例是为Linux版本编写的。对于OS X,比较器必须声明为

 int comparator( void *param, const void *l, const void *r)

并且qsort_r调用是

qsort_r(list, listSize, sizeof(Point), &sortCoord, comparator);

答案 1 :(得分:0)

最便携的版本可能确实是将comparsion对象(“functor”)封装在一个单独的文件中,然后使用静态文件范围变量来改变函数的行为。

something.h

void set_something (something_t s);

int compare_something (const void* obj1, const void* obj2);

something.c

#include "something.h"

static something_t someting = 0;

void set_something (something_t s)
{
  something = s;
}

int compare_something (const void* obj1, const void* obj2)
{
  const coord_t* c1 = obj1;
  const coord_t* c2 = obj2;

  // do stuff with c1, c2 based on something
}

唯一的缺点是你不能让多个线程同时执行不同类型的排序,但这不太可能是一个问题。 (如果是,设计某种方式将“something”变量作为参数传递给每个线程回调。)

答案 2 :(得分:0)

我建议选择#3

C11显示qsort_s(),它提供了所需的 context 参数。这是在附件K(规范)中,因此可能不包含在符合C11的编译器中。
此功能的可用性可能不大。

  

K.3.6.3.2 qsort_s函数

errno_t qsort_s(void *base, rsize_t nmemb, rsize_t size,
    int (*compar)(const void *x, const void *y,
    void *context), void *context);
  

...比较函数的第三个参数是   传递给context的{​​{1}}参数。 qsort_s context的唯一用途是将其传递给比较函数

如果此功能不可用,请考虑模仿此界面的替代方案。

这个想法与建议@JeremyPqsort_r类似。这两个函数是相似的,除了qsort_s变量之间的参数顺序返回类型。