字符串通常是程序员最早接触的数据结构,但是很少人会真正深入了解字符串的本质,我也是其中一个。直到最近做了一个文本相关的需求,在实现字符串选区和光算法的时间复杂度取决于标定位时,遇程序员那么可爱电视剧免费观看到很多怪异的现象,倒逼着自己浏览了一些关于字符编码的文章。至此才发现,自己对字符串的了解竟还如此浅薄。
一、数据结构知识点总结举个栗子
Swift 的字符串是String
,对应可以直接桥接的 Object-C 类型是NSString
,既然都能桥接了,那么两者是不字符常量是一样用呢?看下面两段代码,程序员需要什么学历猜猜输出的是啥?
let string: String = "✅❎"
print("nsstring length: (string.count)")
let nsstring: NSString = "✅❎"
print("nsstring length: (nsstring.length)")
第一段简算法的五个特性单,根据官方文档对String.count算法设计与分析
的程序员那么可爱描述:The number of characters in a stapplering,其输出的是字符串中字符的个数,目之所及,字符串"✅❎"
包含 5 个字符,因此输出的是 5。
第二段估计大多数人会答错,答案是 8。官方文档对NSStrapplicationing.length
的描述是:The number of UTF-16 c程序员怎么学ode units in the r程序员计算器eceiver,也就是说length
表示字符串包含的 UTF-16 码元个数。问题来了,字符串中都是程序员客栈 emoji 表情,为什么 UTF-16算法的有穷性是指 码元数量approach不是字数据结构符数量的整数倍?这是因为 emoji 字符的 UTF-16编码可能包含 1 个码元(例如✅❎),或者 2 个码元(例如),甚至是 3 个(例如#️⃣0️⃣1️⃣)。
怎么看字符串的 UTF-16 编码呢?可以在程序中加个断点,然后用 LLDB 调试命令po string.uapprovetf16
即可打印出字符串的所有 UTF-16 码元:
(lldb) po string.utf16
▿ StringUTF16("✅❎")
- 0 : 55357
- 1 : 56843
- 2 : 55357
- 3 : 56836
- 4 : 55357
- 5 : 56898
- 6 : 9989
- 7 : 10062
既然有出乎意料的点,就是存在从理所当然的想法approach出发写出程序Bug的风险。既然如此,接下来咱们开始扒一扒字符串编码的原理。
NOTE:为什么说大多数人会答错,是因为首先比较少开发者会需要注意到这些概念细节,其次知道原数据结构c语言版第二版课后答案理的人之中,应该也很少有会去背每个 emoji 表程序员那么可爱情包含几个程序员怎么学码元吧。附上E算法设计与分析moji 编码表。
二、Swift的默认字字符间距在哪里设置符串编码
看完上面内容,估计看官中有很多算法的有穷性是指人和我产生同样的疑问,既然 Objective-C 的NSStr数据结构与算法ing
默认是使用 UTF-16 编码程序员计算器,那么 Swift 的String
呢?它是默认使用什么编码方式?为什么它的count
要设置为获取字符个数呢?为啥偏偏要和NSString
做得不一样呢?
首先官方文档对String
的描述:A Uni字符串逆序输出code string value that is a collection of characters,没有明确指出String
的编码方式。不像对NSString
的描述中A string object presents itself as a sequence of UTF–16 code unit数据结构严蔚敏s明确指出编码方式是 UTF-16。不过从unicodeScalars
的定义不难推测出,String
的默认编码方式是 UTF-32。
NOTE:A string’s
unicodeScalars
property is a collecti程序员需要什么学历on of Unicode scalar values, the程序员怎么学 21-bit codes th数据结构c语言版at are the basic unit of Unicode. Each scalar value is represent算法的空间复杂度是指ed by aUni算法code.Scalar
instance and is equivalent to a UTF-32 code unit.
需要字符间距怎么加宽注意的是,大到码元占 4 个字节的 UTF-32 编码,尚且不能保证每个字符均能用单个码元字符常量表示。举个例子,#️⃣就包含了 3 个 UTF-32 码元。不过诸如之流,“比较弱鸡的 Emoji 表情”还是可以一个码元数据结构c语言版轻松搞定的。按理说,UTF-32 码元的 4 个字节空间足以构成每个码元“单挑”单个字符算法的特征的局面,之所以不是,应该是考虑程序员那么可爱免费观看了对 UTF-16 编码策略的兼容性。
(lldb) po "#️⃣".unicodeScalars
▿ StringUnicodeScalarView("#️⃣")
- 0 : "#"
- 1 : "u{FE0F}"
- 2 : "u{20E3}"(lldb)
po "".unicodeScalars
▿ StringUnicodeScalarView("")
- 0 : "u{0001F604}"
由于 UTF-32 编数据结构与算法码码元数量可以非常趋近于字符串字面上所看到的的字符数量,而且coun字符常量t
含义设置为字符数approach量,更符合所见即所得的直观原则,能对字符串做到更准确的抽象,像NSS数据结构有哪些tring.length
返回 UTF-16 码元数量的设定,使NSString
抽象类型耦合了具体编码类型,实际上是非常不合理的设程序员那么可爱计。
三、Unicode编码
Unicode 是一系列文字编码标准的统称,(官方描述:The World Standard for Text and Emoji),运用最广泛的包括 UTF-8、UTF-16、UTF-32,三者最大的区别是 UTF-8 的码元是 1 个字节、appleUTF-16 码元 2 个字节、UTF-32码元 4 个字节。截至目前,三者中运用最广的其实还是 UTF-8。
字符串的组成单元是字符,编码就是为每个字符指定唯一的“代号”,从而使文数据结构本数据可以在各种操作系统、平台中流通,不同的平台只要知道文本数据的编码方式,就可以还原出文本内容。Unicode 限定了编码空间为 21程序员工作一年后工资-bit(0x000000 ~ 0x10FFFF),可粗略估算其appearance可编码字符数量为 221,百万级,足以覆字符盖所有语言的基本字符和其他特殊字符。
3.1 UTF-8
UTF-8 是应用最广的 Unicode 编码。其码元是 1 个字节,区区 1 个字节的码元想单挑字符显然是不可能的,像咱们中文动辄上万的字符显然单个码元远远“搞不定”。UTF-8 标准设定单个字符包含的码元数量可以从 1~4 个不等。例如基本 ASCII 字符可以用 1 个 UTF-8 码元表示,中文字符则需要三个。
像算法的空间复杂度是指 UTF-8 这种可变长的编码方式,最重要的是要考虑“前缀”的问题。打个比方,如果用u00
表示'0'
,uAA
表示'M'
,用u00 uA字符是什么A程序员怎么学
表示'❌'
,那么解码过算法的空间复杂度是指程中遇到u00 u0A
时,它既可以被解码为"0M"
也可以解码为"❌"
,歧义由此产生。因此编码算字符间距加宽2磅怎么设置法设计必须要避免类似的冲突以保证解码过程的正确性字符串是什么意思和快捷性。
那么 UT数据结构c语言版严蔚敏第二版答案F-8 编码是如何设计编码空间以避免歧义的呢?看下面这张表就很好理解。
- 第一行内容:单个码元的编码空间为
0x00
到0x7F字符常量
,可编码 27 个字符算法。解码过程中遇到二进制最高位为0
则将其判定算法的五个特性为单码元字符; - 第二行内容:两个码元的编码空间为
0x0080
到0x07FF
,可编码 211 – 27 个字符。解码过程中遇到二进制最高三位数据结构题库为110
则将其判定为双码元字符; - 第字符串是什么意思三行内容:三个个码元的编码空间为
0x0800
到0xFFFF
,可编码 216 – 211 个字符。解码过程中遇到二算法进制最高四位为1110
则将其判定为三码元字符; - 第四行内容:四程序员客栈个码元的编码空间为
0x100000
到0x10FFFF
,可编码 221 – 216 个字符。解码过程中遇到二进制最高五位为11110
则将其判定为算法的有穷性是指四码元字符;
因此在 UTF-8 编码算法中,字节高位0
、10
、110
、1110
、11110
均被赋予了特殊含义,确保每个字符编码均不存在歧义,编码为不存在歧义的以字节为单位的二进制数据流。在文本数据流解码过程程序员怎么学中,逐字节读取数据,根据字节高位的值选择对应的处理策略,将二进制数据流还原为文本。
其实前面描述有点不准确的地方程序员那么可爱免费观看,将码元组合称为application字符实际上程序员怎么学是不准确的,码元的组合应该是 Uni数据结构教程第5版李春葆答案code Scalar,同理长度不超过 4 个字节的是 Unapproachicode scalar 而不是字符,字符可以由多个 Unicode scala字符间距加宽2磅怎么设置r 构成,例如某些 Emoji 表情,例如前面提过“算法导论很能打”的#️⃣,包含 3 个 Unicode Scalar,其 UTF-8 编码占据 7 个字节。
参算法工程师考文章:CodeDocs.org/字符是什么UTF-8
3.2 UTF-16
UTF-16 的码元是 2 个字节。数据结构c语言版第二版课后答案为避免编码歧义,仍然是采用的类似于 UTF-8 的设定特殊前缀的基本思想。其总的编码空间仍然是 21-bappetiteit(0x000000 ~ 0x10FFapproveFF)。首先 0x0000 ~ 0xD7FF 以及 0xE0FF ~ 0xFFFF 编码是多语言平面,用于表示各国语言字符。也就是刨掉了 0xD800 ~ 0xDFFF 这段空间,不出数据结构c语言版意外的话,这块刨掉的数值空间会作为 UTF-16算法设计与分析 编码的特殊前缀存在。
预留的 0xD800 ~ 0xDFFF 用于以两个 UTF-16 码元表示 0x10000 ~ 0x10FFFF 范围内的 Unicode Scalar。UTF-16 编码的策略是:由两个码元构成的 Unicode Scalar,其两个码元的值必定落在 0xD800 ~ 0xappleDFFF 的闭区间之内。关于如何用这些码元表示 0x10000 ~ 0x10F字符间距在哪里设置FFF 之间的 220 个程序员是做什么的编码值如下表所示字符。行标题数据结构c语言版第二版课后答案为低位码元,列标题为高位码元值,行列相交的单元格则为两个码元所表示的 Unicode Scalar 编码值:
- 高位码元的值在 0xD800 ~ 0xDBFF 的闭区间内,共 210;
- 低位码元的值在 0xDC00 ~ 0x字符间距在哪里设置DFFF 的闭区间内,共 210。高位码元数量和低位码元数量相乘刚好等于 0x10000 ~ 0x10FFFF 之间的编码值数量。apple所以直接从左到右,从上到下递增排列,正好排满整张字符串是什么意思表;
至此,有没注意到,既然 0xD800 ~ 0xDFFF 已经被定义为特殊前缀(或者说特殊编码值更加准确)用于组合 UTappearanceF-16 双码元的 Unicode Sc字符串是什么意思aler,而这个区间之外的 0x0000 ~ 0xD7FF 以及 0xE0FF ~ 0x字符FFFF 是多语字符串是什么意思言字符,那它自己呢?0xD800 ~ 0xDFFF 之间的 Unicode Sc算法的五个特性alar 不就无法被 UTF-16 编码了么算法?没错,就是无法被编码,因为 Unicode 标准规定了 0xD800 ~ 0xDFFF 之间的编码值不能指定给任何字符,但由于 UTF-8、UTF-32 是可以编码这些 Unicode Scalar 值的,所以在 UTF-16 上免不了有人不按标准来。如果在编码端强行将这APP些值指定为某些字符,则在解码端也就需要相应的适配,这种做法在兼容性上是非常差的,应尽量避免。
参考文章:CodeDocs.org/UTF-16
3.3 UTF-3字符间距加宽2磅怎么设置2
UTF-32 编码几乎是对 UTF-16 编码的合成,例如包含两个 UTF-16 码元的表情,用 UTF-32 编码则是分别对应一个 UTF-32 码元字符间距加宽2磅。简而言之,UTF-32 编码实现了百分百码元单挑 Unicode Scaler 的愿景appstore。当然,像#️程序员客栈⃣字符间距这种“叶问级appstore别数据结构教程第5版李春葆答案字符”还是得三个 UTF-32 码元一起上。
四、再举个栗子
前面介绍这么多,貌似没看出数据结构c语言版第二版课后答案对写 Swift 代码有什么用。这里设立个具体场景。APP 从上层页面带入一串字数据结构知识点总结符串,填入当前界面的UITextView
控件中。现在要程序员怎么学 APP 在UITextView
中选中指定的关键信息。
// 输入字符串
let text = "床前出来明❎月光,疑是莉莉地上霜,举头喝✅酒望明月,低头有妹子故乡"
// 目标选中字符串
let target = "有妹子"
实现该功能的代码段如下。代码段中透露出关键信息是:UITextView.selectedRange
的 Range 对应的是 UTF-16 编码的码算法导论元范围。此时如果不知道String
编码相关细节 ,实现和调试过程中可能会有很多疑惑。而且一旦误用unicodeScalars
等appear等与 UTF-32 编码关联性较大的属性,或者String.index
等等对字符串的直观抽象的属性的话,会走多很多弯路。APP
let input = "床前出来明❎月光,疑是莉莉地上霜,举头喝✅酒望明月,低头有妹子故乡"
let target = "有妹子"
textView.text = input
let interestRange = input.range(of: target)
guard let targetRange = interestRange else { return }
let location = targetRange.lowerBound.utf16Offset(in: input)
let length = targetRange.upperBound.utf16Offset(in: input) - location
textView.selectedRange = NSRange(location: location, length: length)
总结
String.unAPPicodeScalar
属性可以视为直接与 UTF-32 编码关联,因为返回数组字符间距怎么加宽的每个元素恰好是字符串的 UTF-32 编码码元。
String.count
、String.字符是什么index
系列等属性,是对字符串的直观特征的描述。count
表示的是字符串的字符个数,ind程序员那么可爱免费观看ex
表示的是直观的“字符索引”。
例如以下代码返回的结果是#️⃣,其含义就是返回第 2 个字符,不是第 2 个 Uniappreciatecode scalar,更不是第 2 个编码码元,另外Charater
是对单个字符的抽象,#️⃣对应的是一个Character
对象。
`"8️⃣#️⃣"["8️⃣#️⃣".index("8️⃣#️⃣".startIndex, offsetBy: 1)]`
如果上层输入的用appointment于选中#️⃣程序员怎么学的索引是字符串 UTF-16 编码码元的索引(这种情字符间距在哪里设置况并不少见,例如索引是来自UITex字符间距怎么加宽tView.selectedRange
的返回值),此时应该用这句代码来选中#️⃣:
"8️⃣#️⃣"["8️⃣#️⃣".utf16.index("8️⃣#️⃣".utf16.startIndex, offsetBy: 3)]
最后吐槽一句:Swift 的String
虽然对字符串做了更合理的抽象,但是真的很难用!