现在的编程语言都支持Unicode字符串,但是处理Unicode字符串又是一个复杂的事情,原因就是Unicode并不是固定宽度的字符
对于ASCII码字符集,每个字符都是固定的宽度1个字节,可以任意存取,但这也仅限于英文字符。在正式开始之前,先要搞清楚Unicode相关的知识
编码点
Unicode字符集,规定了每个字符的编码点(一个16进制数),编码点介于0x0~0x10FFFF之间,但是没有规定计算机怎么存储,具体如何存储编码点就要看编码方式。
编码方式
常见的编码方式有以下几种
UTF-8: 8个位表示一个编码单元,用1-4个编码单元表示一个字符 ,单个字符(ASCII)用一个编码单元就可以表示,所以兼容ASCII码
UTF-16 :要么16个位,要么32位为一个编码单元,大部分的常用字符都用16位编码单元,其余的用32位编码单元
UTF-32 : 32个位表示一个编码单元,最直接的表示法
Swift中UTF-8和UTF-16用UInt8和UInt16表示
Unicode标量
编码单元组成Unicode标量,若要用单个编码单元对应一个Unicode标量,就需要21位编码,也就是UTF-32(向上取整到32位)所以标量是唯一的 21 位数,大部分情况下Unicode标量和编码点是同一个东西
Swift中Unicode标量对应的类型是Unicode.Scalar
字位簇
屏幕上显示的一个字符,可能是单个Unicode标量,也可能由多个Unicode标量的组合(Swift中的字位簇由Character类型表示)
大概了解Unicode相关知识之后,在来看Swift中的Character
Character
Character代表单个可扩展的字位簇,可扩展的字位簇是一个或多个可生成人类可读的字符 Unicode 标量的有序排列
来自文档中的例子:é有两种不同的写法,打印结果都是一样的
let eAcute: Character = "\u{E9}" // é
let combinedEAcute: Character = "\u{65}\u{301}" // e 后面加上 ́
// eAcute 是 é, combinedEAcute 是 é
é可以由单个é,也可以是e 后面跟 ́ 组合成,尽管组合不一样,但是比较结果是相等的,这就是Unicode规范中的标准等价
eAcute == combinedEAcute // true
统计字符个数也是相等,swift能处理
let cafe1 = "Cafe\u{301}" //Café
let cafe2 = "Café"//Café
// count
cafe1.count //4
cafe2.count //4
组成单个字符的Unicode 标量可以是一个或者多个,因此Character类型不能像C语言中char类型的处理方式
let a:Character = "a"
let b:Character = "b"
b - a // Binary operator '-' cannot be applied to two 'Character' operands
一种可行的方案是,asciiValue这里确定强制解包不会有问题
var num = b.asciiValue! - a.asciiValue!
获取Unicode字符的编码
Character的utf8类型是UTF8View,它是扩展的String内部结构体,返回字符的UTF-8编码单元的编码,单个编码单元返回一个UInt8类型的数
let a:Character = "a"
// 单字符的a由 1个utf8编码单元组成
for i in a.utf8{
print(i) //UInt8: 97
}
// 😊 由 4个 utf8编码单元组成
let face:Character = "😊"
for i in face.utf8{
print(i)//UInt8: 240 159 152 138
}
类似的,utf16类型是UTF16View,单个编码单元返回一个UInt16类型的数
// 😊 由 2个 utf16编码单元组成
let face:Character = "😊"
for i in face.utf8{
print(i)//UInt16: 55357 56842
}
unicodeScalars的类型是UnicodeScalarView,返回unicode标量,value返回
let flower = "💐"
for i in flower.unicodeScalars {
print(i, i.value) // 💐
}
UTF8View,UTF16View,UnicodeScalarView都遵守BidirectionalCollection协议但都不支持随机访问,必须借助Index类型
字符串转数字
字符串转数字,通常用于大数相加,swift中的LONG_LONG_MAX最大值也不过9223372036854775807,对于超出这个范围的值用字符串表示,计算时需要将单个字符串转成数字,相加后在用字符串保存
let bigNumber = "92233720368547758079223372036854775807"
C语言中,通过遍历字符串再和字符0的ASCII码相减就能转换成整数类型,swift中也很方便,bigNumber是由简单字符组成的字符串,通过字符串的utf8属性,就能获取到和ASCII对应的编码
for i in bigNumber.utf8{
print(i) // 57 50 50 51......53 56 48 55
}
网友评论