2016-12-07 44 views
1

这应该是足够简单...为什么使用重音符分割字符串会崩溃?

import Foundation 

let str:String = "Beyonce\u{301} and Tay" 
print(str) 

print(str.components(separatedBy: CharacterSet(charactersIn: "e"))) 

哪个编译罚款,直到我运行可执行文件:

// Beyoncé and Tay 
// Illegal instruction (core dumped) 

我怀疑斯威夫特也很难对付结合'\u{65}'重音符号,但考虑如何多语言强调了基于石墨烯字符串的模式,我认为这将是很清楚,在'e'分裂"Beyonce\u{301} and Tay"应该放弃["B", "yonce\u{301} and Tay"]因为'e\u{301}'应该被解释为一个单一的字形,而不是一个'e'加上急性结合。在字符

拆分不会崩溃:

print(str.components(separatedBy: "e")) 
// ["B", "yoncé and Tay"] 

我迅速的版本是

swiftc -version 
Swift version 3.0-dev (LLVM 3e3d712024, Clang 09ad59b006, Swift fdf6ee20e4) 
Target: x86_64-unknown-linux-gnu 
+0

我得到的输出'[” B“,”yonc“,”和Tay“]在Xcode命令行应用程序中运行。 –

+0

@MartinR我在Linux上运行swift版本3.0-dev –

+0

@MartinR,但无论如何,这不是正确的输出吗? 'é'应该被解释为一个单独的原子,''é'!='e'' –

回答

1

它看起来像有在Linux端口斯威夫特的错误。我不会在我的回答中解决这个问题。下面的代码是在Mac OS X上测试的。

您遇到了Unicode的规范化问题。信é可以通过2种方式,斯威夫特认为是相同的表示:

let s1 = "e\u{301}" // letter e + combining acute accent 
let s2 = "\u{0e9}" // small letter e with acute 

s1.characters.count // 1 
s2.characters.count // 1 
s1 == s2   // true 

这是因为斯威夫特的String,像它的前身NSString对Unicode的很好的支持。但如果你深入研究,你开始看到一些差异:

​​

所以即使s1s2是相等的,它们的存储方式不同:使用2个或1码点。 components(seperatedBy:)对这个事实是盲目的。它遍历字符串中的所有代码点,并在发现字母e时进行拆分。一种形式之间的转换到另一个被称为正常化,影响功能的工作原理:

let str1 = "Beyonce\u{301} and Tay" 
let str2 = str1.precomposedStringWithCanonicalMapping // normalize the string to Form C 

let charset = CharacterSet(charactersIn: "e") 
str1.components(separatedBy: charset) // ["B", "yonc", "́ and Tay"] 
str2.components(separatedBy: charset) // ["B", "yoncé and Tay"] 

参考文献: