Swift3.0P1 语法指南——字符串与字符
Posted 小妖
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Swift3.0P1 语法指南——字符串与字符相关的知识,希望对你有一定的参考价值。
1、字符串字面值
1 let someString = "Some string literal value"
2、初始化空的字符串
两种方法:
1 var emptyString = "" // empty string literal 2 var anotherEmptyString = String() // initializer syntax 3 // these two strings are both empty, and are equivalent to each other
可以通过isEmpty属性检查字符串是否为空:
1 if emptyString.isEmpty { 2 print("Nothing to see here") 3 } 4 // prints "Nothing to see here"
3、字符串的可变性
通过声明为常量或变量来判断字符串是否可变。
1 var variableString = "Horse" 2 variableString += " and carriage" 3 // variableString is now "Horse and carriage" 4 5 let constantString = "Highlander" 6 constantString += " and another Highlander" 7 // this reports a compile-time error - a constant string cannot be modified
这种方式与Objective-C不同。Objective-C需要用NSString和NSMutableString两种类来分别表示不可变字符串和可变字符串。
4、字符串是值类型
Swift 的 String 类型是值类型。如果你创建了一个新的字符串值,那么当其进行常量、变量赋值操作或在函数中传递时,会进行值拷贝。在不同情况下,都会对已有字符串值创建新副本,并对该新副本进行传递或赋值。
5、使用字符
1 for character in "Dog!??".characters { 2 print(character) 3 } 4 // D 5 // o 6 // g 7 // ! 8 // ??
当然,也可以单独声明一个Character字符:
1 let exclamationMark: Character = "!"
String可以用Character数组来构造:
1 let catCharacters: [Character] = ["C", "a", "t", "!", "??"] 2 let catString = String(catCharacters) 3 print(catString) 4 // prints "Cat!??"
6、连接字符和字符串
连接字符串:
1 let string1 = "hello" 2 let string2 = " there" 3 var welcome = string1 + string2 4 // welcome now equals "hello there"
也可以用已有字符串接在当前字符串后面:
1 var instruction = "look over" 2 instruction += string2 3 // instruction now equals "look over there"
可以在字符串后面添加字符:
1 let exclamationMark: Character = "!" 2 welcome.append(exclamationMark) 3 // welcome now equals "hello there!"
注意:Character只是一个单独的字符,不能在后面连接字符或字符串。
7、字符串插值
1 let multiplier = 3 2 let message = "\(multiplier) times 2.5 is \(Double(multiplier) * 2.5)" 3 // message is "3 times 2.5 is 7.5"
注意:插值字符串中写在括号中的表达式不能包含非转义双引号 (") 和反斜杠 (\),并且不能包含回车或换行符。(V2.1)
注意:插值字符串中写在括号中的表达式不能包含反斜杠 (\),不能包含回车或换行符。(V3.0P1)
8、Unicode
LATIN SMALL LETTER A和FRONT-FACING BABY CHICK。
9、字符串字面量中的特殊字符
\u{
n},其中n是1~8位的Unicode十六进制编码,其值为有效的Unicode代码点。
1 let wiseWords = "\"Imagination is more important than knowledge\" - Einstein" 2 // "Imagination is more important than knowledge" - Einstein 3 let dollarSign = "\u{24}" // $, Unicode scalar U+0024 4 let blackHeart = "\u{2665}" // ♥, Unicode scalar U+2665 5 let sparklingHeart = "\u{1F496}" // ?, Unicode scalar U+1F496
10、扩展字形集群
Swift的Character类型的每一个实例都是一个扩展字形集群。一个扩展字形集群是一个或多个Unicode Scalar的序列(组合后便产生了一个人类可读的字符)。
LATIN SMALL LETTER E WITH ACUTE
,或 U+00E9
),但是,也可以由 e
(LATIN SMALL LETTER E
, or U+0065
)和COMBINING ACUTE ACCENT
(U+0301
)组成。无论如何,é都看做是一个Swift Character值,表示一个扩展字形集群。1 let eAcute: Character = "\u{E9}" // é 2 let combinedEAcute: Character = "\u{65}\u{301}" // e followed by ? 3 // eAcute is é, combinedEAcute is é
扩展字形集群是一种灵活的方式,通过不同的组合方式来构造同一个Character值。
1 let precomposed: Character = "\u{D55C}" // ? 2 let decomposed: Character = "\u{1112}\u{1161}\u{11AB}" // ?, ?, ? 3 // precomposed is ?, decomposed is ?
可以在字符外面加上封闭的符号来构造新的字符:
1 let enclosedEAcute: Character = "\u{E9}\u{20DD}" 2 // enclosedEAcute is é?
用于地区表示的符号可以成对组合来构造一个字符:
let regionalIndicatorForUS: Character = "\u{1F1FA}\u{1F1F8}" // regionalIndicatorForUS is ????
11、字符计数
1 let unusualMenagerie = "Koala ??, Snail ??, Penguin ??, Dromedary ??" 2 print("unusualMenagerie has \(unusualMenagerie.characters.count) characters") 3 // prints "unusualMenagerie has 40 characters"
注意:扩展字形集群的使用,意味着,字符串的连接和修改可能并不会改变字符串的字符的数目。
例如:
1 var word = "cafe" 2 print("the number of characters in \(word) is \(word.characters.count)") 3 // prints "the number of characters in cafe is 4" 4 5 word += "\u{301}" // COMBINING ACUTE ACCENT, U+0301 6 7 print("the number of characters in \(word) is \(word.characters.count)") 8 // prints "the number of characters in café is 4"
注意:扩展字形集群可以被分解成一个或多个Unicode Scalar。这意味着,不同的字符、同一字符的不同表示方法,将需要不同大小的存储内存。因此,要计算一个字符串的字符数目,一定要根据字符串的字面值来判断扩展字形集群的数目。
返回的characters属性的count并不总是等于NSString的length属性,因为length属性是根据UTF-16编码计算出来的长度,并非Unicode扩展字形集群的数目。
12、访问和修改String
(1)String的索引
每一个String都有一个index类型,String.Index,对应于每一个Character的位置。
如上所述,不同的字符需要不同的内存,为了找到特定位置的Character,你需要遍历String的Unicode Scalar。因此,String不能用整型数据来索引。
用startIndex属性来访问String的第一个字符的位置。
endIndex访问String的最后一个字符的后一个位置。因此,endIndex并不是一个有效的下标。
如果String为空,startIndex等于endIndex。
String.Index可以调用predecessor()访问当前位置的前一个索引,successor()访问当前位置的后一个索引。String的任意索引都可以通过其他索引的successor()和predecessor()方法的组合、或者advancedBy()方法访问到。访问的下标如果超过String的范围,将会产生运行时错误。(V2.1)
给定一个index, 你可以用String的index(before:)
和index(after:)访问当前index的前一个/后一个索引,用
index(_:offsetBy:)可以访问距离当前index几个位置的index.(V3.0P1)
可以使用String的索引来访问该位置上的字符:
1 let greeting = "Guten Tag!" 2 greeting[greeting.startIndex] 3 // G 4 greeting[greeting.endIndex.predecessor()] 5 // ! 6 greeting[greeting.startIndex.successor()] 7 // u 8 let index = greeting.startIndex.advancedBy(7) 9 greeting[index] 10 // a
索引越界,将会产生错误:
1 greeting[greeting.endIndex] // error 2 greeting.endIndex.successor() // error
用characters的indices属性,可以获得字符的索引范围:
1 for index in greeting.characters.indices { 2 print("\(greeting[index]) ", terminator: "") 3 } 4 // prints "G u t e n T a g !"
注意:任意遵循Indexable
协议的类型,都有startIndex
、endIndex
属性,以及 index(before:)
, index(after:)
,和 index(_:offsetBy:)方法。String类型如此,其他类型包括
Array
, Dictionary
和Set类型也是如此。
(2)插入和移除
插入,用insert(_:at:)
方法:(V2.2是insert(_:atIndex:)
方法)
1 var welcome = "hello" 2 welcome.insert("!", at: welcome.endIndex) 3 // welcome now equals "hello!"
在指定位置插入另一字符串的内容:
1 welcome.insert(contentsOf:" there".characters, at: welcome.index(before: welcome.endIndex)) 2 // welcome now equals "hello there!"
V2.1的对应方法如下:
1 welcome.insertContentsOf(" there".characters, at: welcome.endIndex.predecessor())
2 // welcome now equals "hello there!"
移除指定下标开始的字符串:
welcome.remove(at: welcome.index(before: welcome.endIndex)) // welcome now equals "hello there"
V2.1的对应方法如下:
1 welcome.removeAtIndex(welcome.endIndex.predecessor())
2 // welcome now equals "hello there"
移除指定范围的字符串:
1 let range = welcome.index(welcome.endIndex, offsetBy: -6)..<welcome.endIndex 2 welcome.removeSubrange(range) 3 // welcome now equals "hello"
V2.1的对应方法如下:
1 let range = welcome.endIndex.advancedBy(-6)..<welcome.endIndex
2 welcome.removeRange(range)
3 // welcome now equals "hello"
注意:任何遵循RangeReplaceableIndexable
协议的类型,都可以用insert(_:at:)
, insert(contentsOf:at:)
, remove(at:)
, 和removeSubrange(_:)方法。
String,
Array
, Dictionary
, 和Set都是这样。
13、字符串的比较
(1)相等
1 let quotation = "We‘re a lot alike, you and I." 2 let sameQuotation = "We‘re a lot alike, you and I." 3 if quotation == sameQuotation { 4 print("These two strings are considered equal") 5 } 6 // prints "These two strings are considered equal"
如果两个字符串(或两个字符)的扩展字形集群符合canonically equivalent,则两个字符串(或字符)看做是相等的。
如果两个扩展字形集群的字面意义和字形都是相同的,则认为符合canonically equivalent,即使它们被分解成不同的Unicode Scalar,它们也看做是相等的。
例如,LATIN SMALL LETTER E WITH ACUTE
(U+00E9
),以及LATIN SMALL LETTER E
(U+0065
)+COMBINING ACUTE ACCENT
(U+0301
)是é
字符的两种构建方式,两者看做canonically equivalent.
1 // "Voulez-vous un café?" using LATIN SMALL LETTER E WITH ACUTE 2 let eAcuteQuestion = "Voulez-vous un caf\u{E9}?" 3 4 // "Voulez-vous un café?" using LATIN SMALL LETTER E and COMBINING ACUTE ACCENT 5 let combinedEAcuteQuestion = "Voulez-vous un caf\u{65}\u{301}?" 6 7 if eAcuteQuestion == combinedEAcuteQuestion { 8 print("These two strings are considered equal") 9 } 10 // prints "These two strings are considered equal"
相反,英语中使用的LATIN CAPITAL LETTER A
(U+0041或"A"),和CYRILLIC CAPITAL LETTER A
(U+0410
,或 "А"
)是不相等的。两者看上去形状相同,但是有不同的字面意义。
1 let latinCapitalLetterA: Character = "\u{41}" 2 3 let cyrillicCapitalLetterA: Character = "\u{0410}" 4 5 if latinCapitalLetterA != cyrillicCapitalLetterA { 6 print("These two characters are not equivalent") 7 } 8 // prints "These two characters are not equivalent"
注意:Swift中的字符串和字符都不是区域敏感的。
(2)前缀和后缀相等
String的hasPrefix(_:)和hasSuffix(_:)返回一个布尔型变量。
1 let romeoAndJuliet = [ 2 "Act 1 Scene 1: Verona, A public place", 3 "Act 1 Scene 2: Capulet‘s mansion", 4 "Act 1 Scene 3: A room in Capulet‘s mansion", 5 "Act 1 Scene 4: A street outside Capulet‘s mansion", 6 "Act 1 Scene 5: The Great Hall in Capulet‘s mansion", 7 "Act 2 Scene 1: Outside Capulet‘s mansion", 8 "Act 2 Scene 2: Capulet‘s orchard", 9 "Act 2 Scene 3: Outside Friar Lawrence‘s cell", 10 "Act 2 Scene 4: A street in Verona", 11 "Act 2 Scene 5: Capulet‘s mansion", 12 "Act 2 Scene 6: Friar Lawrence‘s cell" 13 ]
可以用hasPrefix(_:)方法来计数有多少个Act 1场景,并且播放:
1 var act1SceneCount = 0 2 for scene in romeoAndJuliet { 3 if scene.hasPrefix("Act 1 ") { 4 ++act1SceneCount 5 } 6 } 7 print("There are \(act1SceneCount) scenes in Act 1") 8 // prints "There are 5 scenes in Act 1"
使用hasSuffix(_:)方法:
1 var mansionCount = 0 2 var cellCount = 0 3 for scene in romeoAndJuliet { 4 if scene.hasSuffix("Capulet‘s mansion") { 5 ++mansionCount 6 } else if scene.hasSuffix("Friar Lawrence‘s cell") { 7 ++cellCount 8 } 9 } 10 print("\(mansionCount) mansion scenes; \(cellCount) cell scenes") 11 // prints "6 mansion scenes; 2 cell scenes"
14、字符串的Unicode表示
let dogString = "Dog???"
(1)uft-8表示
1 for codeUnit in dogString.utf8 { 2 print("\(codeUnit) ", terminator: "") 3 } 4 print("") 5 // 68 111 103 226 128 188 240 159 144 182
(2)utf-16表示
1 for codeUnit in dogString.utf16 { 2 print("\(codeUnit) ", terminator: "") 3 } 4 print("") 5 // 68 111 103 8252 55357 56374
(3)Unicode Scalar表示
可以通过String的unicodeScalars
访问字符串的Unicode Scalar表示, 这个属性的类型是UnicodeScalarView
(一种UnicodeScalar的集合
)。
每个UnicodeScalar
都有一个21bit的value
属性,用UInt32进行
表示。
1 for scalar in dogString.unicodeScalars { 2 print("\(scalar.value) ", terminator: "") 3 } 4 print("") 5 // 68 111 103 8252 128054
每个Unicode标量值可以构造一个字符串,比如用于字符串插值:
for scalar in dogString.unicodeScalars { print("\(scalar) ") } // D // o // g // ? // ??
以上是关于Swift3.0P1 语法指南——字符串与字符的主要内容,如果未能解决你的问题,请参考以下文章