В чем разница между strcmp() и strcoll()?

Я попытался понять их обоих, но я не нашел никаких различий, кроме strcoll() этой ссылка говорит, что это

сравнивает две строки с нулевым завершением в соответствии с текущим языковым стандартом, определенным категорией LC_COLLATE.

во-вторых, и я знаю, что задаю еще один вопрос для подробного ответа, что именно это локаль, как для C, так и для C++?

2 ответов


strcmp() берет байты строки один за другим и сравнивает их как есть, каковы бы ни были байты.

strcoll() берет байты, преобразует их с помощью локали, затем сравнивает результат. Преобразование переупорядочивается в зависимости от языка. На французском акцентированные буквы следуют за не акцентированными. Так что é после e. Однако,é до f. strcoll() получает это право. strcmp() не так что ж.

однако во многих случаях strcmp() достаточно, потому что вам не нужно показывать результат, упорядоченный в используемом языке (локали). Например, если вам просто нужно быстро получить доступ к большому количеству данных, индексированных строкой, вы должны использовать карту, индексированную этой строкой. Вероятно, совершенно бесполезно сортировать тех, кто использует strcoll() что обычно очень медленно (по сравнению с strcmp() по крайней мере.)

подробнее о персонажах вы можете также хотеть проверить Unicode сайт.

что касается локали, это язык. По умолчанию он установлен в "C" (более или менее, не язык). После выбора местоположения локаль устанавливается соответствующим образом. Также можно задать переменную среды LC_LOCALE. На самом деле таких переменных много. Но в целом вы используете предопределенные функции, которые автоматически учитывают эти переменные и делают все правильно для вас. (т. е. формат даты / времени, формат чисел / мер, вычислить верхний / нижний регистр и т. д.)


по какой-то причине во всех проверенных мной локалях unicode в нескольких разных версиях glibc strcoll() возвращает ноль для любых двух hiraganas. Это ломается вроде, uniq, и все, что каким-то образом взаимодействует с порядками строк.

$ Эхе -е -н-い\nろ\nは\nに\nほ\nへ\nと\п' | СНП | тр

который просто сломан без ремонта. Люди из разных уголков мира могут иметь разные идеи о том, следует ли ставить " い "до или после "ろ", но никто в здравом уме не будет считать их одинаковыми.

и нет, установка вашего языка на японский не имеет значения:

$ значение lc_all=ja_JP.Лэнг в формате utf8=ja_JP.utf8 в категории lc_collate=ja_JP.utf8 в Эхе -е -н-い\nろ\nは\nに\nほ\nへ\nと\Н' | СНП | уник

была дискуссия в каком-то официальном списке рассылки, но угадайте, что это было в 2002 году, и это никогда не было исправлено, потому что людям все равно: https://www.mail-archive.com/linux-utf8@nl.linux.org/msg02658.html

эта ошибка произошла с нами в какой-то день, и в конце концов нашим единственным выходом было установить локаль сортировки на "C" и полагаться на хорошие свойства кодировки utf-8. Это ужасный опыт, так как на самом деле не следует работать под "c" locale при обработке всех японских данных.

поэтому для вашего здравомыслия не используйте strcoll напрямую. Более безопасный вариант может быть:

int safe_strcoll(const char *a, const char *b)
{
  int ret = strcoll(a, b);
  if (ret != 0) return ret;
  return strcmp(a, b);
}

на случай, если strcoll() решит вас трахнуть...