SQLite(C/C++)的不区分大小写的UTF-8字符串排序规则

前端之家收集整理的这篇文章主要介绍了SQLite(C/C++)的不区分大小写的UTF-8字符串排序规则前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在寻找一种方法来比较和排序C中的UTF-8字符串以不区分大小写的方式在 custom collation function in SQLite中使用它.

>理想情况下,该方法应与区域设置无关.但是我不会屏住呼吸,据我所知,校对是依赖于语言的,所以任何适用于英语以外语言的东西都可以,即使这意味着切换语言环境.
>选项包括使用标准C或C库或小型(适用于嵌入式系统)和非GPL(适用于专有系统)第三方库.

到目前为止我所拥有的:

>带有C语言环境的strcoll和std :: collat​​e / std :: collat​​e_byname是区分大小写的. (这些是否有不区分大小写的版本?)
>我尝试使用POSIX strcasecmp,但对于“POSIX”以外的语言环境似乎是not defined

In the POSIX locale,strcasecmp() and strncasecmp() do upper to lower conversions,then a byte comparison. The results are unspecified in other locales.

事实上,strousecmp的结果在使用GLIBC的Linux上的语言环境之间没有变化.

#include <clocale>
#include <cstdio>
#include <cassert>
#include <cstring>

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',strcoll(s1,s2));
    assert(setlocale(LC_ALL,"en_AU.UTF-8"));
    printf("strcasecmp('%s',"fi_FI.UTF-8"));
    printf("strcasecmp('%s',s2));
}

打印出来:

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

P. S.

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

你真正想要的是逻辑上不可能的.没有与区域设置无关的,不区分大小写的排序字符串的方法.简单的反例是“i”<> “一世” ?天真的答案是否定的,但在土耳其语中,这些字符串是不相等的. “我”大写为“İ”(U 130拉丁资本I,上面有点)

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”吗?它们的长度不一样.然而,对于德国人来说,你必须认为他们是平等的.你能活下去吗?

猜你在找的Sqlite相关文章