- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我将重新发布我今天早些时候提交的问题,但现在我引用一个具体示例来回应我收到的反馈。可以在here中找到原始问题(请注意,这不是家庭作业):
我只是试图确定C++是否使不可能对basic_string
对象执行(有效)的不区分大小写的比较,该比较也考虑了任意locale
对象。例如,似乎无法编写如下有效的函数:
bool AreStringsEqualIgnoreCase(const string &str1, const string &str2, const locale &loc);
ctype::toupper()
调用
collate::compare()
和
locale
(通常使用
use_facet()
进行提取)。但是,由于
collate::compare()
特别需要4个指针args,因此您需要为需要比较的每个字符传递这4个args(首先调用
ctype::toupper()
之后),或者将两个字符串都首先转换为大写字母,然后对
collate::compare()
进行一次调用。
collate::compare()
周围没有办法)。
最佳答案
试图以一致的方式与世界上所有的书写系统打交道的烦恼之一是,实际上您认为您对字符所了解的任何东西实际上都是正确的。这使得很难进行“不区分大小写的比较”之类的事情。确实,进行任何形式的区域感知比较都是棘手的,而且不区分大小写也很棘手。
但是,在某些约束下,有可能实现。可以使用常规编程实践(和一些静态数据的预计算)“有效地”实现所需的算法,但是它不能像不正确的算法一样有效地实现。通常有可能在速度的正确性上取舍,但结果并不令人满意。错误但快速的语言环境实现可能会吸引那些正确实现语言环境的用户,但是对于语言环境会产生意外结果的部分受众来说,显然是不令人满意的。
词典编排不适用于人类
对于具有大小写的语言,大多数语言环境(“C”语言环境除外)已按预期方式处理字母大小写,即仅在考虑所有其他差异之后才使用大小写差异。也就是说,如果按语言环境的整理顺序对单词列表进行排序,则列表中仅在情况不同的单词将是连续的。大写单词出现在小写单词之前还是之后是与语言环境相关的,但是中间不会有其他单词。
该结果无法通过任何单次左右字符逐个比较(“字典顺序”)来实现。而且大多数语言环境还有其他排序规则的怪癖,它们也不会屈服于天真的字典顺序。
如果您具有适当的区域设置定义,则标准C++归类应该能够处理所有这些问题。但是,仅使用对whar_t
对的比较功能就不能将其简化为词典上的比较,因此C++标准库不提供该接口(interface)。
以下仅是几个示例,说明为什么支持区域设置的排序规则很复杂;在Unicode Technical Standard 10中可以找到更详细的解释以及更多示例。
口音在哪里?
大多数浪漫语言(以及英语,在处理借来的单词时)都认为元音上的重音是次要特征。也就是说,首先对单词进行排序,就好像不存在重音符号一样,然后进行第二遍处理,在此过程中,未重音字母出现在重音字母之前。必须处理第三遍,以解决情况,在前两遍中将其忽略。
但这不适用于北欧语言。瑞典语,挪威语和丹麦语的字母有三个额外的元音,字母后面跟着z。这些元音用瑞典语写成å,ä和ö。在挪威语和丹麦语中,这些字母分别写在å,æ和ø上,而在丹麦语å中有时写成aa,这使奥胡斯成为丹麦城市字母顺序列表中的最后一个条目。
在德语中,字母ä,ö和ü通常按字母顺序表示为浪漫口音,但在德国电话簿(有时甚至是其他按字母顺序排列的列表)中,则按字母顺序进行,就好像它们是ae,oe和ue一样,这是较旧的样式写相同的音素(有许多对常见的姓氏,例如“Müller”和“Mueller”发音相同,而且经常混淆,因此相互搭配是有意义的。当我年轻时,加拿大电话簿中的苏格兰名字也使用了类似的约定;拼写M'
,Mc
和Mac
都聚在一起,因为它们在语音上都相同。)
一个符号,两个字母。或两个字母,一个符号
德语中也有符号ß,虽然在语音上并不完全相同,但它被整理为好像写为ss一样。稍后我们将再次遇到这个有趣的符号。
实际上,许多语言都将有向形图,甚至有向形图视为单个字母。包含44个字母的匈牙利字母包括Cs,Dz,Dzs,Gy,Ly,Ny,Sz,Ty和Zs,以及各种重音元音。但是,有关这种现象的文章中最常引用的语言(西类牙语)在1994年就不再将图ch和ll视为字母,这可能是因为强制西类牙裔作家遵循计算机系统比将计算机系统更改为更容易。处理西类牙有向图。 (维基百科声称这是来自“union 国教科文组织和其他国际组织”的压力;每个人花了相当长的时间才能接受新的字母顺序规则,并且您仍然偶尔会在南美国家的字母顺序列表中的“哥伦比亚”之后找到“智利”。)
摘要:比较字符串需要多次通过,有时还需要比较字符组
使其全部不区分大小写
由于相比之下,语言环境正确处理了大小写,因此实际上不必执行不区分大小写的排序。进行不区分大小写的等效类检查(“相等”测试)可能很有用,尽管这引发了一个问题,即其他不精确的等效类可能有用吗?在某些情况下,Unicode规范化,重音删除甚至抄写为拉丁语都是合理的,而在其他情况下则非常烦人。但是事实证明,大小写转换也不如您想象的那么简单。
由于存在二元图和三元图,其中有些具有Unicode代码点,因此Unicode标准实际上可以识别三种情况,而不是两种情况:小写,大写和标题大小写。最后一个是用来将单词的第一个字母大写的,例如,对于克罗地亚字母graph(U + 01C6;单个字符),大写字母是DŽ(U + 01C4)且其标题是必需的大小写为Dž(U + 01C5)。 “不区分大小写”比较的理论是,我们可以(至少在概念上)以某种方式转换任何字符串,以使“忽略大小写”定义的等效类的所有成员都转换为相同的字节序列。传统上,这是通过“大写”字符串来完成的,但是事实证明,这并非总是可能的,甚至是正确的。就像我一样,Unicode标准更喜欢使用术语“大小写折叠”。
C++语言环境不太适合
因此,回到C++,可悲的事实是C++语言环境没有足够的信息来进行准确的大小写折叠,因为C++语言环境的工作原理是字符串的大小写折叠仅包含顺序且单独的大写字母使用函数将字符串中的每个代码点映射到另一个代码点。正如我们将看到的那样,这是行不通的,因此其效率问题无关紧要。另一方面,ICU library具有一个接口(interface),可以按照Unicode数据库的允许正确进行大小写折叠,并且它的实现是由一些相当不错的编码人员精心设计的,因此在约束范围内它可能尽可能地高效。因此,我绝对建议您使用它。
如果要全面了解案例折叠的难度,则应阅读Unicode standard(PDF for chapter 5)的5.18和5.19节。以下仅是一些示例。
大小写转换不是从单个字符到单个字符的映射
最简单的例子是Germanß(U + 00DF),它没有大写形式,因为它从未出现在单词的开头,而且传统的德语拼写法也不使用大写字母。标准的大写变换是SS(或在某些情况下是SZ),但是该变换是不可逆的。并非ss的所有实例都写成ß。比较一下grüßen和küssen(分别是打招呼和亲吻)。在v5.1中,ẞ是“大写字母ß”,以U + 1E9E的形式添加到Unicode中,但是除了在法律规定必须使用全大写字母的路牌外,它并不常用。大小写ß是两个字母SS
。
并非所有表意文字(可见字符)都是单个字符代码
即使案例转换将单个字符映射到单个字符,也可能无法将其表示为wchar→wchar
映射。例如,ǰ可以很容易地大写为J but,但是前者是单个组合字形(U + 01F0),而第二个是大写字母J,带有组合卡通(U + 030C)。
像ǰ这样的字形还有另一个问题:
按字符大小写折叠的朴素字符可以使归一化
假设我们将ǰ大写。我们如何将capital大写(如果它在您的系统上无法正确呈现,则是同一字符,并且在其下面带有一个杠,这是另一个IPA约定)?该组合为U + 01F0,U + 0320(j带caron,下面组合负号),因此我们继续用U + 004A,U + 030C替换U + 01F0,然后将U + 0320保留为:J̠̌。很好,但是它不等于下面带有卡通和负号的规范化大写字母J,因为在正常形式中,负号变音符号首先出现:U + 004A,U + 0320,U + 030C(J̠̌,看起来一样)。因此有时(说实话,很少,但有时)有必要重新规范化。
撇开Unicode的困惑,有时大小写转换是上下文相关的
希腊文提供了许多示例,说明如何根据商标是字首,字尾还是字内的方式来改组标记-您可以在Unicode标准的第7章中阅读更多有关此的内容-但简单而又常见case是Σ,它有两个小写形式:σ和ς。具有某些数学背景的非希腊人可能熟悉σ,但可能不知道无法在必须使用ς的单词结尾使用它。
简而言之
i
的注释。)您最好使用一个维护良好的现有解决方案,其中最好的例子是ICU。 关于c++ - 如何使用任意语言环境比较 “basic_string”,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23280251/
至少在某些 ML 系列语言中,您可以定义可以执行模式匹配的记录,例如http://learnyouahaskell.com/making-our-own-types-and-typeclasses -
这可能是其他人已经看到的一个问题,但我正在尝试寻找一种专为(或支持)并发编程而设计的语言,该语言可以在 .net 平台上运行。 我一直在 erlang 中进行辅助开发,以了解该语言,并且喜欢建立一个稳
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be
我正在寻找一种进程间通信工具,可以在相同或不同系统上运行的语言和/或环境之间使用。例如,它应该允许在 Java、C# 和/或 C++ 组件之间发送信号,并且还应该支持某种排队机制。唯一明显与环境和语言
我有一些以不同语言返回的文本。现在,客户端返回的文本格式为(en-us,又名美国英语): Stuff here to keep. -- Delete Here -- all of this below
问题:我希望在 R 中找到类似 findInterval 的函数,它为输入提供一个标量和一个表示区间起点的向量,并返回标量落入的区间的索引。例如在 R 中: findInterval(x = 2.6,
我是安卓新手。我正在尝试进行简单的登录 Activity ,但当我单击“登录”按钮时出现运行时错误。我认为我没有正确获取数据。我已经检查过,SQLite 中有一个与该 PK 相对应的数据。 日志猫。
大家好,感谢您帮助我。 我用 C# 制作了这个计算器,但遇到了一个问题。 当我添加像 5+5+5 这样的东西时,它给了我正确的结果,但是当我想减去两个以上的数字并且还想除或乘以两个以上的数字时,我没有
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 4 年前。 Improve th
这就是我所拥有的 #include #include void print(int a[], int size); void sort (int a[], int size); v
你好,我正在寻找我哪里做错了? #include #include int main(int argc, char *argv[]) { int account_on_the_ban
嘿,当我开始向数组输入数据时,我的代码崩溃了。该程序应该将数字读入数组,然后将新数字插入数组中,最后按升序排列所有内容。我不确定它出了什么问题。有人有建议吗? 这是我的代码 #include #in
我已经盯着这个问题好几个星期了,但我一无所获!它不起作用,我知道那么多,但我不知道为什么或出了什么问题。我确实知道开发人员针对我突出显示的行吐出了“错误:预期表达式”,但这实际上只是冰山一角。如果有人
我正在编写一个点对点聊天程序。在此程序中,客户端和服务器功能写入一个唯一的文件中。首先我想问一下我程序中的机制是否正确? I fork() two processes, one for client
基本上我需要找到一种方法来发现段落是否以句点 (.) 结束。 此时我已经可以计算给定文本的段落数,但我没有想出任何东西来检查它是否在句点内结束。 任何帮助都会帮助我,谢谢 char ch; FI
我的函数 save_words 接收 Armazena 和大小。 Armazena 是一个包含段落的动态数组,size 是数组的大小。在这个函数中,我想将单词放入其他称为单词的动态数组中。当我运行它时
我有一个结构 struct Human { char *name; struct location *location; int
我正在尝试缩进以下代码的字符串输出,但由于某种原因,我的变量不断从文件中提取,并且具有不同长度的噪声或空间(我不确定)。 这是我的代码: #include #include int main (v
我想让用户选择一个选项。所以我声明了一个名为 Choice 的变量,我希望它输入一个只能是 'M' 的 char 、'C'、'O' 或 'P'。 这是我的代码: char Choice; printf
我正在寻找一种解决方案,将定义和变量的值连接到数组中。我已经尝试过像这样使用 memcpy 但它不起作用: #define ADDRESS {0x00, 0x00, 0x00, 0x00, 0x0
我是一名优秀的程序员,十分优秀!