1

I'd like to use C's qsort() function to sort arrays each having different types, like these:

int a[] = {1, 2, 3};
const char *b[] = {"foo", "bar", "bas"};
my_defined_type_t *c[100]; for (i=0; i<100; i++) { fill(c[i]); }

Is it necessary to write comparison functions for each type, like intComparator(), stringComparitor(), myDefinedTypeComparitor() and make calls to qsort with each comparison function in turn, or can something like this be done in C:

int myGrandUnifiedComparisonFunction(const void* a, const void* b) {

if *a, *b are integers: intComparatorCode;
if *a, *b are strings: stringComparitorCode;
if *a, *b are my_defined_type_t's: myDefinedTypeComparitorCode;
/* etc. */

}
4

5 回答 5

3

有两个问题需要考虑:

1)信息问题

您的比较函数得到两个 void 指针。这只是一些可能意味着任何事情的位模式。C 不附加任何信息,例如浮点数或字符指针,因此如果您事先不知道,就不可能判断某条数据是其中一个还是另一个。

也就是说,您可以自己附加此信息,方法是将您的数据包装在一个结构中,并用一个枚举值告诉您里面有什么。但是从技术上讲,您不会比较浮点数或 char 指针,而是比较包装的浮点数和包装的 char 指针。就像是:

enum { Float, String, MyType } typ;

typedef struct { 
    typ t;
    union {
       float f;
       char *s;
       myType mt;
    } wrappedData;

然后你可以只写一个比较的函数wrappedData *。这就是每种动态语言所做的事情。

然后,即使您的大统一功能仍然需要适当地比较它们,也就是说,每种类型都不同,因此您不会获得太多收益。相反,您会将逻辑一起塑造成一个并不真正属于一起的功能。

2)效率问题

虽然这可能不会打扰您,但解包指针并检查其类型将在每个比较操作中完成,这可能会大大增加排序的运行时间。

结论:

您必须采取某种方式包装您的数据,以获得可疑的优势和显着的劣势(效率)。不要这样做。

于 2013-09-16T09:52:35.923 回答
2

C 没有自省,因此无法知道 avoid*指向的类型。

每种类型都需要一个比较函数,并且必须qsort使用正确的回调进行调用。

于 2013-09-16T09:41:53.480 回答
1

你的想法

int myGrandUnifiedComparisonFunction(const void* a, const void* b) {

    if *a, *b are integers: intComparatorCode;
    if *a, *b are strings: stringComparitorCode;
    if *a, *b are my_defined_type_t's: myDefinedTypeComparitorCode;
   /* etc. */
}

非常棒。您是否尝试过实施它?

问题是没有办法在 C 或 C++ 中实现它void*无法确定指向哪种变量。

于 2013-09-16T09:49:24.250 回答
0

不,您不能拥有泛型函数,因为类型现在在运行时在 C 中传递(与面向对象的语言不同)。类型必须在编译时知道。

因此,您需要一个知道如何比较每种类型并告诉qsort它的函数。

于 2013-09-16T09:41:04.460 回答
0

我想你可以,如果你以某种方式神奇地知道类型,但为什么要麻烦呢?此外,您的尺寸也可以通过,因此您需要在 2 个地方进行检查。

不知道这有什么好处。

于 2013-09-16T09:41:23.840 回答