在C中排序时无法使strcoll()使用语言环境

osh3o9ms  于 2023-01-01  发布在  其他
关注(0)|答案(2)|浏览(88)

我一直无法让strcoll()这样的依赖于区域设置的函数在C语言中工作。我想知道我是否做错了什么,以及/或者如何让它工作。下面是本书中的一个示例程序:Prinz,Peter,and Tony Crawford. 2016.简而言之,第2版,第574页。北京-波士顿-法纳姆-塞瓦斯托Perl-东京:奥赖利。ISBN-13:978-1-491-90475-6.

#include <stdio.h>
#include <string.h>
#include <locale.h>

int main(void) {
   char *samples[ ] = { "curso", "churro" };
   setlocale(LC_COLLATE, "es_ES.UTF-8");
   int result = strcoll(samples[0], samples[1]);
   if(result == 0) {
      printf("The strings \"%s\" and \"%s\" are "
             "alphabetically equivalent.\n",
             samples[0], samples[1]);
   } else if(result < 0) {
      printf("The string \"%s\" comes before \"%s\" "
             "alphabetically.\n",
             samples[0], samples[1]);
   } else if(result > 0) {
      printf("The string \"%s\" comes after \"%s\" "
             "alphabetically.\n",
             samples[0], samples[1]);
   }
   return(0);
}

书上说“curso”应该在“churro”之前,因为在西班牙语中,“ch”被认为是一个单独的字母,用于字母表排序。然而,当我运行这个程序时,它打印出“curso”在“churro”之后。我不懂西班牙语,但我用其他几种我确实懂的语言测试过这个程序,结果总是strcmp()的结果,这是一个严格的数字比较。

$ gcc --version
gcc (Ubuntu 11.3.0-1ubuntu1~22.04) 11.3.0
$ locale -a | grep es_ES.utf8             
es_ES.utf8

我知道这个问题:Getting locale functions to work in glibc作者说strcoll等依赖于语言环境的函数在glibc中的性能很差,他正在编写自己的修改。
我错过什么了吗?这是不是根本行不通?

cgfeq70w

cgfeq70w1#

您的书中有过时的信息。自1994年以来,西班牙语有向图ch不再被视为单个字母。请参阅https://rae.es/dpd/abecedario
在第十届西班牙语学术协会大会上,庆祝于1994年,他同意通过拉丁美洲普遍的法语秩序,他认为ch和ll不考虑letras independientes”。
(Hope不需要翻译)
您还可以查看Unicode排序规则数据here。这是glibc从中导出其排序规则数据的源。正如您所看到的,有几种排序规则顺序。标准排序规则不认为chll特殊,而传统排序规则则认为chll特殊。Glibc实现了标准排序规则。
您可以通过尝试使用带重音字符的字符串来检查西班牙语区域设置归类是否正常工作。这些字符串应该按照归类顺序所描述的顺序出现(即紧接在相应的非重音字符之后),如果系统正在工作,则在所有非重音字母之后(例如,如果您忘记调用setlocale或不支持locale)。Demo注意,在godbolt上GCC不支持locale,而MSVC支持(并且使用类Unix的locale名称来 Boot )。
如果您想测试多字符排序规则,请使用捷克语语言环境(cs_CZ.UTF-8),它确实将ch识别为单个字母,并且在排序规则顺序. Demo中,它位于h* 之后 *。

v64noz0r

v64noz0r2#

  • 我是不是错过了什么,这是不是行不通 *

我认为这取决于您的环境是否能识别 “es_ES.UTF-8”
注意,我没有进入Linux环境的权限,这沃茨了比较苹果与苹果的能力。但我希望下面强调的几件事可能会有所帮助...
在Windows上,使用标准的LabWindows/CVI compiler(我的版本基于Clang 3.3),它输出如下:

  • “字符串“curso”按字母顺序排在“churro”之后 *

根据您在使用西班牙语字母顺序规则时所陈述的期望,这似乎是不正确的。
我怀疑库的实现和版本对我们所看到的有所贡献。
请注意,当我稍后检查setlocale的返回时:

char *new = setlocale(LC_COLLATE, "es_ES.UTF-8");

返回NULL,表示以下内容:

  • “如果区域设置为非NULL并且可以执行,则返回指向与指定类别关联的字符串的指针。如果选择”所有类别“设置,则字符串包含不同类别的区域设置的串联。*”如果无法执行选择,则函数返回NULL指针,并且程序的区域设置保持不变

表示不支持 “es_ES.UTF-8”,区域设置保持不变。
This article对在C语言中使用UTF-8有一些有趣和相关的见解(......以及它与这里看到的语言环境问题的关系)。

相关问题