Вы сделали очень правильный путь.The gcc documentation for strcoll
and wcscoll
дает пример, аналогичный этому, как правильный способ использования strcoll
или wcscoll
с qsort
.
/* This is the comparison function used with qsort. */
int
compare_elements (char **p1, char **p2)
{
return strcoll (*p1, *p2);
}
/* This is the entry point---the function to sort
strings using the locale's collating sequence. */
void
sort_strings (char **array, int nstrings)
{
/* Sort temp_array by comparing the strings. */
qsort (array, nstrings,
sizeof (char *), compare_elements);
}
Этот пример фактически делает поднять предупреждение, что вы хотите, чтобы избавиться от, но опять же это может быть удосужился путем изменения char**
к const void*
в аргументы compare_elements
, а затем явно приведение к const char**
.
Вы правы в том, что это небезопасно, но безопасность типа не является одной из сильных сторон C. C не имеет ничего подобного дженерикам или шаблонам, поэтому единственный способ, с помощью которого qsort может работать на произвольном типе, - это функция сравнения, чтобы принять void*
. Программисту следует убедиться, что функция сравнения не используется в контексте, где ему могут передаваться аргументы, которые не являются ожидаемым типом.
У этой версии была ваша ошибка. То, что получает функция сравнения, - это не элементы, которые нужно сравнить, а указатели на элементы, которые нужно сравнить. Поэтому, если элементы являются строками, это означает, что указатель на указатель. Поэтому, когда вы пишете
return wcscoll(arg1, arg2);
Вы на самом деле проходит wscoll
в wchar_t**
, когда он ожидает wchar_t*
. Правильный способ сделать это, одновременно подавляя предупреждение, будет:
int widecharcomp(const void *arg1, const void *arg2)
{
return wcscoll(*(const w_char_t**)arg1, *(const w_char_t**)arg2);
}
уродлив, как это.
Edit:
Просто взял другой взгляд на верхний бит кода. Ваша ошибка здесь действительно двоякая. Вы пытаетесь использовать wcscoll
для сортировки символов. Это функция, предназначенная для сортировки строк (которые в C являются указателями на последовательности символов с нулевым завершением). Выше было написано, предполагая, что вы пытаетесь сортировать строки.Если вы хотите сортировать символы, то wcscoll
не является подходящей функцией для использования, но все, что выше относительно qsort
, по-прежнему применяется.
Это очень сжатое объяснение. Большое спасибо. Я собираюсь отметить это правильно, поскольку это, вероятно, будет более полезно для будущих читателей, хотя я лично узнал больше от Тайлера Мак-Хенри, который подробно обсуждает код. Поэтому будущие читатели отмечают: оба стоят вашего времени, если вы столкнулись с той же проблемой. – chryss