我正在尝试根据相对于中心的角度对列表点进行排序:
我不关心列表开始的圆圈在哪里,但它需要以循环方式排序。我想使用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语言来做,虽然我知道我必须使用函数指针和参数 - 但我对这些技术并不是很熟悉。
提前致谢!
答案 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(....);
此解决方案避免使用全局变量。