泛型排序适用于整数,但不适用于其他类型

时间:2014-06-08 22:17:22

标签: c arrays sorting generics

我正在尝试对C中的任何类型的数组进行排序(性能不是问题,因此我使用bubble sort来简化),为此我传递sort函数它应该用来比较不同的比较函数类型(compareInt,compareDouble,compareString等等)。 我的程序适用于int,但是当我使用double / string /其他任何东西时表现得非常奇怪...... w ^

出了什么问题,我该如何解决?

我的代码:

int main(void)
{
    int  a[] = {2, 7, 6, 4, 1};
    double b[] = {12.5, 2.7, 3.0, 5.5, 5.9, 1.0};
    char c[] = {'c', 'a', 'b', 'd'};
    char * d[] = {"abc", "bca", "cba", "abcd"};
    char e[][4] = {"bca", "abc", "cba", "dca", "za"};
    printArray(a, sizeof(a[0]), sizeof(a)/sizeof(a[0]), printInt);
    printArray(b, sizeof(b[0]), sizeof(b)/sizeof(b[0]), printDouble);
    printArray(c, sizeof(c[0]), sizeof(c)/sizeof(c[0]), printChar);
    //printArray(d, sizeof(d[0]), sizeof(d)/sizeof(d[0]), printStringPointer);
    //printArray(e, sizeof(e[0]), sizeof(e)/sizeof(e[0]), printStringArray);
    printf("\n");
    sort(a, sizeof(a)/sizeof(a[0]), sizeof(a[0]), compareInt);
    sort(b, sizeof(b)/sizeof(b[0]), sizeof(b[0]), compareDouble);
    sort(c, sizeof(c)/sizeof(c[0]), sizeof(c[0]), compareChar);
    //sort(d, sizeof(d)/sizeof(d[0]), sizeof(d[0]), compareStringPointer);
    //sort(e, sizeof(e)/sizeof(e[0]), sizeof(e[0]), compareStringArray);
    printArray(a, sizeof(a[0]), sizeof(a)/sizeof(a[0]), printInt);
    printArray(b, sizeof(b[0]), sizeof(b)/sizeof(b[0]), printDouble);
    printArray(c, sizeof(c[0]), sizeof(c)/sizeof(c[0]), printChar);
    //printArray(d, sizeof(d[0]), sizeof(d)/sizeof(d[0]), printStringPointer);
    //printArray(e, sizeof(e[0]), sizeof(e)/sizeof(e[0]), printStringArray);
    printf("\n");
    getchar();
    return 0;
} // pay no attention to the printArray methods, as they are just for debugging purposes.

int compareInt(void * p1, void * p2)
{
    return *(int *)p1 - *(int *)p2;
}
int compareDouble(void * p1, void * p2)
{
    double d = *(double *)p1 - *(double *)p2;
    if(d > 0) return 1;
    if(d == 0) return 0;
    return -1;
}
int compareChar(void * p1, void * p2)
{
    return *(char *)p1 - *(char *)p2;
}
void sort(void * arr, int arrLength, int sizeOfElement, int (*compare)(void *, void *))
{
    int i, j;
    for(i = 0; i < arrLength; i++) // arrlength -1?
        for(j = 0; j < arrLength - 1; j++)
        {
            //printf("%c, %c", *((char *)arr + j * sizeOfElement), *((char *)arr + (j + 1) * sizeOfElement));
            if(compare(((char *)arr + j * sizeOfElement), ((char *)arr + (j + 1) * sizeOfElement)) > 0) swap(((char *)arr + j * sizeOfElement), ((char *)arr + (j + 1) * sizeOfElement));
        }
}
void swap(void ** p1, void ** p2)
{
    void * p3 = *p1;
    *p1 = *p2;
    *p2 = p3;
}

(我也计划使用字符串,这就是数组d和e存在的原因,但我还没有为字符串编写比较函数。)

程序的输入(printArray打印的数组):

2, 7, 6, 4, 1,
12.500000, 2.700000, 3.000000, 5.500000, 5.900000, 1.000000,
c, a, b, d,

程序的输出(假设按照printArray打印后的数组):

1, 2, 4, 6, 7,
12.500000, 2.700000, 3.000000, 5.500000, 5.900000, 1.000000,
a, a, a, c,

非常感谢。

2 个答案:

答案 0 :(得分:2)

问题是swap功能错误。它目前假装数组中有void *,实际上有intdouble或其他。

可能它似乎适用于int因为您的系统sizeof(int) == sizeof(void*),但不适用于其他类型,因为它们的大小不同。

要解决此问题,请将swap更改为使用memcpy,复制正确的字节数。当然这意味着它必须将项目长度作为参数。 (您可以将临时VLA声明为交换中的“第三轮”,或使用XOR技巧)。

NB。从if(compare(((char *)arr + j *开始的很长的行难以阅读,我建议声明两个指针,而不是重复计算。

答案 1 :(得分:0)

正如我所看到的,由于缺少函数原型,您的代码会调用未定义的行为。在这种情况下,您可能会得到预期或意外的输出 将函数定义置于main之上或在main函数之上添加原型。

int compareInt(void * p1, void * p2);
int compareDouble(void * p1, void * p2);
int compareChar(void * p1, void * p2);
void sort(void * arr, int arrLength, int sizeOfElement, int (*compare)(void *, void *));
void swap(void ** p1, void ** p2);