strcmp()和strcoll()之间有什么区别

What is the difference between strcmp() and strcoll()?

本文关键字:什么 区别 strcoll strcmp 之间      更新时间:2023-10-16

我试着理解它们,但除了strcoll()之外,我没有发现任何差异,这个参考文献说它是

根据LC_COLLATE类别定义的当前区域设置比较两个以null结尾的字符串。

转念一想,我知道我在问另一个问题来获得详细的答案,对于C和C++来说,这个语言环境到底是什么?

strcmp()逐个获取字符串的字节,并按字节数进行比较。

strcoll()获取字节,使用区域设置对其进行转换,然后比较结果。转换根据语言重新排序。在法语中,重音字母在非重音字母之后。所以ée之后。但是,éf之前。strcoll()做对了。CCD_ 5不太好。

但是,在许多情况下,strcmp()就足够了,因为您不需要显示按使用的语言(区域设置(排序的结果。例如,如果您只需要快速访问由字符串索引的大量数据,则可以使用由该字符串索引的映射。使用通常非常慢的strcoll()(至少与strcmp()相比(对那些进行排序可能是完全无用的

有关字符的详细信息,您可能还想查看Unicode网站。

就语言环境而言。默认情况下,它被设置为"C"(或多或少,没有区域设置(。一旦您选择了一个位置,就会相应地设置区域设置。您还可以设置LC_LOCALE环境变量。实际上有很多这样的变量。但通常情况下,您使用预定义的函数,这些函数会自动考虑这些变量,并为您做正确的事情。(即格式化日期/时间、格式化数字/度量值、计算大小写等(

由于某种原因,在我测试的所有unicode语言环境中,在几个不同版本的glibc上,strcoll((对任何两个平假名都返回零。这打破了sortuniq以及以某种方式与字符串顺序交互的所有内容。

$echo-e-n'い\nろ\nは\nに\nほ\nへ\nと\n'|sort|uniq

它只是坏得无法修复。来自世界不同地方的人可能对是否い'应放在"之前或之后ろ',但没有一个理智的人会认为他们是一样的。

不,将您的语言环境设置为日语并不重要:

$LC_ALL=ja_JP.utf8 LANG=ja_JPEG.utf8 LC_COLLATE=ja_JP.utf8 echo-e-n'い\nろ\nは\nに\nほ\nへ\nと\n'|sort|uniq

在一些官方邮件列表中有过讨论,但你猜怎么着,那是在2002年,因为人们不在乎,所以它从未被修复:https://www.mail-archive.com/linux-utf8@nl.linux.org/msg02658.html

这个错误在某一天发生在我们身上,最终我们唯一的出路就是将校勘地点设置为";C";并且依赖于utf-8编码的良好特性。这是一次可怕的经历,因为一个人不应该真正在";C";处理所有日语数据时的语言环境。

所以为了你的理智,不要直接使用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((决定搞砸你。。。

编辑:我只是出于好奇重复了这个实验,我目前的系统(glibc 2.29(现在运行起来没有问题。当地语言也不重要。