【问题标题】:What is the difference between strcmp() and strcoll()?strcmp() 和 strcoll() 有什么区别?
【发布时间】:2012-12-29 23:59:24
【问题描述】:

我尝试理解它们,但除了strcoll() this 参考资料说它之外,我没有发现任何区别

根据 LC_COLLATE 类别定义的当前语言环境比较两个以空字符结尾的字符串。

第二个想法,我知道我在问另一个问题以获得详细答案,对于 C 和 C++,这个语言环境到底是什么?

【问题讨论】:

  • example here 在我看来似乎很清楚。
  • @Rapptz...哎呀...应该看到那个链接....在发布之前...

标签: c++ c string locale


【解决方案1】:

strcmp() 一个接一个地获取字符串的字节,然后将它们与字节进行比较。

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

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

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

关于语言环境,它是语言。默认情况下,它设置为“C”(或多或少,没有语言环境)。选择位置后,将相应地设置区域设置。您还可以设置 LC_LOCALE 环境变量。实际上有很多这样的变数。但一般来说,您使用预定义的函数会自动考虑这些变量并为您做正确的事情。 (即格式化日期/时间、格式化数字/度量、计算大写/小写等)

【讨论】:

  • +1 这个答案中的字符比较示例非常好,特别是“但是,é 在 f 之前”。例子。同样,关于使用strcmp() 进行内部排序管理与显示的注释同样做得很好。有一些答案简洁明了,我希望我能不止一次地对它们进行投票。这是其中之一。
【解决方案2】:

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

$ echo -e -n 'い\nろ\nは\nに\nほ\nへ\nと\n' |排序 |独特的

这简直是坏了,无法修复。世界上不同地方的人可能对“い”应该放在“ろ”之前还是之后有不同的想法,但没有理智的人会认为它们是一样的。

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

$ LC_ALL=ja_JP.utf8 LANG=ja_JP.utf8 LC_COLLATE=ja_JP.utf8 echo -e -n 'い\nろ\nは\nに\nほ\nへ\nと\n' |排序 |独特的

在一些官方邮件列表中有讨论,但你猜怎么着,那是在 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)现在可以正常工作了。语言环境也无关紧要。

【讨论】:

  • 我很幸运地发现了问题。您对环境的更改仅适用于echo。您应该将语言更改应用到sortuniq;最简单的就是export LANG。它可以完美地与:(export LANG=ja_JP.UTF-8; echo -e -n 'い\nろ\nは\nに\nほ\nへ\nと\n' | sort | uniq).
  • 感谢您指出这一点。除了我在第一次做这个实验时实际上使用了 export LANG=ja_JP.UTF-8 。我在多台机器上再次尝试,仍然可以在其中一些(但不是全部)中重现问题。我想我需要进一步挖掘导致差异的原因。 glibc 版本似乎不是我需要控制的唯一变量...
猜你喜欢
  • 2016-09-07
  • 2012-10-17
  • 1970-01-01
  • 1970-01-01
  • 2010-10-02
  • 2011-12-12
  • 2010-09-16
  • 2012-03-14
  • 2012-02-06
相关资源
最近更新 更多