当前位置:  开发笔记 > 编程语言 > 正文

SQLite的案例不敏感的UTF-8字符串排序规则(C/C++)

如何解决《SQLite的案例不敏感的UTF-8字符串排序规则(C/C++)》经验,为你挑选了1个好方法。

我正在寻找一种方法,以不区分大小写的方式比较和排序C++中的UTF-8字符串,以便在SQLite中的自定义排序规则函数中使用它.

    理想情况下,该方法应与区域设置无关.然而,我不会屏住呼吸,据我所知,校对是非常依赖于语言的,所以任何适用于英语以外语言的东西都可以,即使这意味着切换语言环境.

    选项包括使用标准C或C++库或小型(适用于嵌入式系统)和非GPL(适用于专有系统)第三方库.

到目前为止我所拥有的:

    strcoll使用C语言环境和std::collate/ std::collate_byname区分大小写.(这些是否有不区分大小写的版本?)

    我试图使用POSIX strcasecmp,但它似乎没有为除以外的语言环境定义"POSIX"

    在POSIX语言环境中,strcasecmp()和strncasecmp()执行从上到下的转换,然后执行字节比较.结果未在其他语言环境中指定.

    事实上,strcasecmpLinux与GLIBC上的语言环境之间的结果并没有改变.

    #include 
    #include 
    #include 
    #include 
    
    const static char *s1 = "Äaa";
    const static char *s2 = "äaa";
    
    int main() {
        printf("strcasecmp('%s', '%s') == %d\n", s1, s2, strcasecmp(s1, s2));
        printf("strcoll('%s', '%s') == %d\n", s1, s2, strcoll(s1, s2));
        assert(setlocale(LC_ALL, "en_AU.UTF-8"));
        printf("strcasecmp('%s', '%s') == %d\n", s1, s2, strcasecmp(s1, s2));
        printf("strcoll('%s', '%s') == %d\n", s1, s2, strcoll(s1, s2));
        assert(setlocale(LC_ALL, "fi_FI.UTF-8"));
        printf("strcasecmp('%s', '%s') == %d\n", s1, s2, strcasecmp(s1, s2));
        printf("strcoll('%s', '%s') == %d\n", s1, s2, strcoll(s1, s2));
    }
    

    打印出来:

    strcasecmp('Äaa', 'äaa') == -32
    strcoll('Äaa', 'äaa') == -32
    strcasecmp('Äaa', 'äaa') == -32
    strcoll('Äaa', 'äaa') == 7
    strcasecmp('Äaa', 'äaa') == -32
    strcoll('Äaa', 'äaa') == 7
    

PS

是的,我知道ICU,但由于其庞大的尺寸,我们无法在嵌入式平台上使用它.



1> MSalters..:

你真正想要的是逻辑上不可能的.没有与区域设置无关的,不区分大小写的排序字符串的方法.简单的反例是"我"<>"我"?天真的答案是否定的,但在土耳其语中,这些字符串是不相等的."i"大写为"İ"(U + 130 Latin Capital I with dot above)

UTF-8字符串为问题增加了额外的复杂性.如果你有一个合适的语言环境,它们是完全有效的多字节char*字符串.但C和C++标准都没有定义这样的语言环境; 请咨询您的供应商(太多的嵌入式供应商,对不起,这里没有回答).因此,您必须选择一个多字节编码为UTF-8的语言环境,以使mbscmp函数正常工作.这当然会影响排序顺序,它依赖于语言环境.如果你没有const char*是UTF-8的语言环境,你根本就不能使用这个技巧.(据我所知,微软的CRT受此影响.他们的多字节代码只处理最多2个字节的字符; UTF-8需要3个字符)

wchar_t也不是标准解决方案.它应该是如此宽,你不必处理多字节编码,但你的排序依然依赖于语言环境(LC_COLLATE).但是,使用wchar_t意味着您现在选择不使用UTF-8作为const char*的语言环境.

完成此操作后,您基本上可以通过将字符串转换为小写并进行比较来编写自己的排序.这不完美.你期望L"ß"== L"ss"吗?它们的长度不一样.然而,对于德国人来说,你必须认为他们是平等的.你能活下去吗?


关于你的德国"ß"字符的例子(以及所有这些丰富的案例):这些必须已经"解决"或以其他方式处理过数千次,UTF-8或否.MS Word一直有一个"切换案例"功能 - 它是如何在Unicode前版本中对该字符起作用的?WordPerfect怎么样?我和OP有同样的问题,除了我在Delphi工作.我见过许多基于Windows sqlite的应用程序,它们执行不区分大小写的SELECT(我猜是ORDER BY),无论它们是以英语,德语还是(在我的情况下)波兰语语言环境中安装.试试Firefox :)他们是如何做到的?
推荐阅读
个性2402852463
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有