C 使用 qsort 和 strcmp 对字符串数组进行排序 - 警告:不兼容的指针类型

C sort array of strings with qsort and strcmp - warning: incompatible pointer type

我尝试使用 qsort 对字符串数组进行排序,但收到此警告:

警告:从不兼容的指针类型

传递'qsort'的参数4
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#define MAX_PRODUCTS   1000

int main (void) {
    int i, index = 0, isUnique;
    char products[MAX_PRODUCTS][100];
    char product[100];
    int  count[MAX_PRODUCTS];

    FILE * fp;

    fp = fopen ("one.txt", "r");

    // Read words from file and put in array if unique
    while (fscanf(fp, "%s", product) != EOF){
        isUnique = 1;
        for (i=0; i<index && isUnique; i++){
            if (strcmp(products[i], product) == 0){
                isUnique = 0;
            }   
        }

        if (isUnique) {
            strcpy(products[index], product);
            index++;
        }

        else {
            count[i - 1]++;
        }
    }

    qsort(products, MAX_PRODUCTS, sizeof(char*), strcmp);

    fclose(fp);

    return 0;
}

我还尝试了一个自定义函数来比较字符串,但这也没有用。 我该如何解决?

qsort 记录在 Microsoft 网站上,其中指出:

compare Pointer to a user-supplied routine that compares two array elements and returns a value that specifies their relationship.


使用这个:

int compare (const void * a, const void * b)
{
  return strcmp((char*)a, (char*)b );
}

以下方式:

qsort(products, MAX_PRODUCTS, 100, compare);

你告诉qsort(),你想对一个指针数组进行排序,但实际上有一个数组数组!

这为您提供了一个指针数组:

char *products[MAX_PRODUCTS]

for (int i = 0; i < sizeof(products)/sizeof(*products); i++) {
    products[i] = malloc(100);
}

您也可以对整个数组成员进行排序,但这涉及多次交换整个字符串(严格来说,整个数组,即使字符串更短),这可能非常低效。只交换指针要快得多。

此外,strcmp() 的签名与 qsort 期望的原型不匹配。所以你应该把它包装在一个带有原型

的比较函数中
int compar(const void *, const void *);

如联机帮助页所示。 那么,编译器应该不会再抱怨了。

实际上你遇到的问题比你收到的警告还多:

  • 您总是对 products 数组的 MAX_PRODUCTS 个元素进行排序,无论有多少元素实际上是有效的(您对未初始化和不确定的字符串进行排序)。

  • 你说products数组的element-size是sizeof(char*),但是products是一个数组of arrays,所以products的每个元素都sizeof producst[0]大。


现在是警告本身:strcmp 的声明是

int strcmp( const char *lhs, const char *rhs );

而传给qsort的比较函数是

int (*comp)(const void *, const void *)

参数类型不同。一个看似可行的解决方案是将 strcmp 指针转换为正确的类型:

typedef int (*sortfun_type)(const void *, const void *);

// After the loop the variable index should be the number of strings read
qsort(products, index, sizeof products[0], (sortfun_type) &strcmp);

如评论中所述,这在技术上是不正确的(但无论如何应该有效)。 正确的解决方案是用正确的参数类型编写一个包装函数,然后调用strcmp(如)。