使用单个参数提供C函数以获取具有较少参数的新函数

时间:2016-06-25 11:09:31

标签: c

我正在尝试根据相对于中心的角度对列表点进行排序: 1

我不关心列表开始的圆圈在哪里,但它需要以循环方式排序。我想使用qsort,但它需要一个只有2个参数的比较函数,而我的比较函数有3个(中心和两个要比较的点):

int compareByAngle(Point *center, Point *lhs, Point *rhs)
{
    return (lhs->x - center->x) * (rhs->y - center->y) - (rhs->x - center->x) * (lhs->y - center->y);
}

你知道如何通过事先将中心提供给另一个函数来获得只有2个参数的函数吗?这对于像haskell这样的语言来说是轻而易举的但是我不知道怎么用C语言来做,虽然我知道我必须使用函数指针和参数 - 但我对这些技术并不是很熟悉。

提前致谢!

2 个答案:

答案 0 :(得分:2)

您无法将配置数据传递给比较功能。这是一个众所周知的qsort缺点,几代C标准商都未能解决这个问题。

有一个非标准函数qsort_r接受一个额外的参数,并将其传递给三参数比较函数。不幸的是,它无法在任何地方使用,如果它可用,则参数的顺序不是标准的。

在不重新处理数据结构的情况下,唯一可移植的方法是使用全局变量或静态变量:

static Point globalCenter;
int compare (void* p1, void* p2) { 
  return compareByAngle(&globalCenter, p1, p2);
}
void myFunc () {
   ...
   globalCenter = center;
   qsort(points, nPoints, sizeof(Point*), compare);
   ...
}

重做数据结构可能更有效,也更清晰。如何计算角度数组然后对其进行排序?然后重新排列点以遵循相同的顺序。

答案 1 :(得分:1)

假设指针lhs和rhs不能为NULL,一种快速而又脏的方法来完成它→当lhs为NULL时,使用用rhs初始化的局部静态变量中心:

int compareByAngle(Point *lhs, Point *rhs)
{
    static Point *center=NULL;
    if (lhs==NULL) {
        center=rhs;
        return rhs!=NULL; // or any other usefull code
    } else if (center==NULL) {
        // do some error handling
    } else {
        return (lhs->x - center->x) * (rhs->y - center->y) - (rhs->x - center->x) * (lhs->y - center->y);
    }
}

然后使用它:

#define DEFINE_CENTER NULL
...
// first call with NULL as lhs argument and center point as rhs argument
if (compareByAngle(DEFINE_CENTER, center))
    // then use the compare function
    qsort(base, nbmem, size, compareByAngle);
...

或者定义一个宏,如:

#define SET_COMP_CENTER(p) compareByAngle(NULL,p)

if (SET_COMP_CENTER(center))
    qsort(....);

此解决方案避免使用全局变量。