来自不兼容指针类型的'qsort'的第4个参数传递参数

4

我在编写一个函数时遇到了一些问题。理论上,它应该是这样工作的,但是它给我返回了“不兼容指针类型”的错误,而我不知道如何修复它。

问题出现在 qsort 函数中引用 compare_last 函数上。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define MAX_PERSONS 100

//person structure definition goes here
typedef struct{
    char last[32];
    char first[32];
    int year;
}Person;

//function declarations go here
int compare_last(Person * ptr1, Person * ptr2);

void main(void){//main function goes here
    char *infilename[20];
    char *outfilename[20];
    FILE * fptrin;
    FILE * fptrout;
    int i, j;
    Person musicians[MAX_PERSONS];
    printf("Enter input file name: ");
    scanf("%s", infilename);
    printf("Enter output file name: ");
    scanf("%s", outfilename);
    strcat(*outfilename, ".htm");
    fptrin = fopen(*infilename, "r");
    fptrout = fopen(*outfilename, "w");

    for(i = 0; i < MAX_PERSONS; i++)
    {
        fscanf(fptrin, "%s %s %i", musicians[i].last, musicians[i].first, &musicians[i].year);
    }

    qsort(musicians, i, sizeof(musicians[0]), compare_last);

    fprintf(fptrout, "<html>\n<body>\n<title>LAB14</title>\n");

    for(j = 0; j < i; j++)
    {
        fprintf(fptrout, "%s %s %i <br>", musicians[j].last, musicians[j].first, musicians[j].year);
    }

    fprintf(fptrout, "</body>\n</html>\n");
    fclose(fptrin);
    fclose(fptrout);

}//end main

//function definitions go here

int compare_last(Person * ptr1, Person * ptr2)
{
    int result = strcmp(ptr1 -> last, ptr2 -> last);
    if(result != 0)
        return result;
    else
        return strcmp(ptr1 -> first, ptr2 -> first); 
}

你写道“我们应该在写作” - 这是否意味着这是一份作业? - Frerich Raabe
2个回答

4
int compare_last(Person * ptr1, Person * ptr2);

应该是

int compare_last(void * ptr1, void * ptr2);

那么你需要在compare_last中进行转换。

1
好的,那么我该如何转换指针?我尝试的一切都不起作用,也找不到任何解决方案。 - Sam
Person * personPtr1 = (Person *) ptr1; - Erik
它仍然给我不兼容的指针类型错误...我使用qsort错了吗?我将代码更改为int compare_last(void * ptr1, void * ptr2) { Person * personPtr1 = (Person *) ptr1; Person * personPtr2 = (Person *) ptr2; int result = strcmp(personPtr1 -> last, personPtr2 -> last); if(result != 0) return result; else return strcmp(personPtr1 -> first, personPtr2 -> first); } - Sam
我做了,原型和函数是一样的。 - Sam
1
实际上,回调函数的参数应该都是 const void * - pmg
显示剩余2条评论

3

qsort()的原型是:

void qsort(void *base, size_t nmemb, size_t size,
           int(*compar)(const void *, const void *));

因此,您的排序函数需要与int(*compar)(const void *, const void *)匹配,或者在调用qsort()时需要进行转换。
如果要对Person*进行排序,最简单的方法是将您的排序函数声明为所需函数,然后在函数内部进行转换:
static int compare_last(const void *ptr1, const void *ptr2)
{
    const Person *p1 = ptr1, *p2 = ptr2;
    int result = strcmp(p1 -> last, p2 -> last);
    ...
}

完全没有必要进行转换,因为const void *可以很好地转换为const Person *


1
在这里强制转换一个不匹配的函数指针将会导致未定义的行为,因为 qsort 将使用错误的参数类型(const void * 而不是 Person *)来调用它。 - R.. GitHub STOP HELPING ICE
@R.: 好的,知道了。我希望大多数编译器生成一些合理的东西,因为const void *和Person *很可能以相同的方式表示,但是未定义性当然值得避免。 - unwind
是的,在实践中(以及在POSIX上),所有指针都具有相同的表示形式,但最好避免依赖它,如果你不真正需要,并且有一种替代的编写代码的方式,既清晰又100%符合规范。 - R.. GitHub STOP HELPING ICE

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接