提供一个具有单个参数的C函数,以获得具有较少参数的新函数

提供一个具有单个参数的C函数,以获得具有较少参数的新函数,c,C,我试图根据点相对于中心的角度对列表点进行排序: 我不在乎列表从何处开始,但它需要以循环方式排序。我想使用qsort,但它需要一个只有2个参数的比较函数,而我的比较函数有3个参数(要比较的中心和两个点): 你知道我如何通过事先将中心提供给另一个函数,得到一个只有两个参数的函数吗?对于haskell这样的语言来说,这是一件轻而易举的事,但我不知道如何在C语言中做到这一点,尽管我知道我必须使用函数指针和参数,但我对这些技术不是很熟悉 提前谢谢 假设指针lhs和rhs不能为空,那么这是一种快速而肮脏的

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

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

你知道我如何通过事先将中心提供给另一个函数,得到一个只有两个参数的函数吗?对于haskell这样的语言来说,这是一件轻而易举的事,但我不知道如何在C语言中做到这一点,尽管我知道我必须使用函数指针和参数,但我对这些技术不是很熟悉


提前谢谢

假设指针lhs和rhs不能为空,那么这是一种快速而肮脏的方法→ 当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(....);

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

您无法将配置数据传递给比较函数。这是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);
   ...
}

重新设计数据结构可能更高效、更清晰。计算一组角度,然后对其进行排序,怎么样?然后按照相同的顺序重新排列点。

为什么不使用自己的自定义函数进行排序呢?
qsort
compare函数有两个参数。在您的情况下,这些不是实际数据,而是指向<代码>结构> <代码>的指针,它包含需要考虑的3项信息。如果
compare
函数返回非0值,
qsort
将使用该信息对传递给它的结构数组进行排序。@t保存
qsort
compare
函数不在库中。关键是,只有您知道排序标准,因此您必须提供
compare
功能,而
qsort
提供了机制。我们首先要正确设置数据结构。我的意思是,如果数据的组织方式不方便处理,您应该考虑首先修改数据是如何存储的,而不是试图强制处理方法。你一开始说你不能使用qsort,因为它“只需要两个参数”,现在你说这是因为你有一个(链接的?)列表。也许这还不算太糟糕。您可以将
globalCenter
的设置和
qsort()
的调用隐藏在便利函数中。在函数发出使用信号之前声明
globalCenter
(我将调用类似于
CMP\u CENTERPOINT
的全局变量)。
static Point globalCenter;
int compare (void* p1, void* p2) { 
  return compareByAngle(&globalCenter, p1, p2);
}
void myFunc () {
   ...
   globalCenter = center;
   qsort(points, nPoints, sizeof(Point*), compare);
   ...
}