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
(如)。
我尝试使用 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
(如