C сортировка массива строк с помощью qsort и strcmp - предупреждение: несовместимый тип указателя - PullRequest
1 голос
/ 22 января 2020

Я попытался отсортировать массив строк с помощью qsort, но получил это предупреждение:

предупреждение: передача аргумента 4 'qsort' из несовместимого типа указателя

#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;
}

Я также попробовал пользовательскую функцию для сравнения строк, но это тоже не сработало. Что я могу сделать, чтобы это исправить?

Ответы [ 3 ]

3 голосов
/ 22 января 2020

qsort задокументировано на веб-сайте Microsoft, где говорится:

сравнить Указатель на пользовательскую процедуру, которая сравнивает два элемента массива и возвращает значение, которое определяет их отношения.


Используйте это:

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

следующим образом:

qsort(products, MAX_PRODUCTS, 100, compare);
1 голос
/ 22 января 2020

У вас на самом деле больше проблем, чем вы получаете предупреждение:

  • Вы всегда сортируете MAX_PRODUCTS элементов массива products, независимо от того, сколько элементов действительно допустимо (вы сортировать неинициализированные и неопределенные строки).

  • Вы говорите, что размер элемента массива products равен sizeof(char*), но products является массивом массивов , поэтому каждый элемент 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 (как показано другими ).

1 голос
/ 22 января 2020

Вы говорите 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 *);

, как показано на странице руководства. Тогда компилятор не должен больше жаловаться.

...