一、字符概述
在
Swift
編程語言中,對字符的表示是獨立于某一種特定的Unicode
編碼的。在Objective-C
、Java
等編程語言中,編譯器內部一般以UTF-16
編碼格式保存并處理字符序列的,而在Swift
編程語言中則是直接通過Unicode標準組織所制定的標準碼點(code point)來保存并處理字符串字符序列的。在Swift
中把Unicode碼點值又稱作為Unicode
標量值(Unicode scalar values)。所以Swift
中引入了 UnicodeScalar 類型,直接可用于表示某一字符的碼點值
這里直接通過
UnicodeScalar
的構造方法來創建一個UnicodeScalar
常量對象zero
,這里要注意的是,
通過UnicodeScalar
構造出來的對象是一個Optional
對象!
let zero = UnicodeScalar("0")!
// 這里使用類型標注的方式顯式給常量a聲明為UnicodeScalar類型,
// 然后用"a"字符串字面量對它初始化
let a: UnicodeScalar = "a"
// 聲明UnicodeScalar常量π
let π = UnicodeScalar("π")!
// 聲明UnicodeScalar常量好
let 好: UnicodeScalar = "好"
// 輸出zero的標量值:48(與ASCII碼兼容)
print("\(zero) scalar value = \(zero.value)")
// 輸出a的標量值:97(與ASCII兼容)
print("\(a) scalar value = \(a.value)")
// 輸出π的標量值:960(與UCS-2兼容)
print("\(π) scalar value = \(π.value)")
// 輸出好的標量值:22909(與UCS-2兼容)
print("\(好) scalar value = \(好.value)")
let ??: UnicodeScalar = "??"
// 輸出??的標量值為128516(在補充平面中)
print("\(??) scalar value = \(??.value)")
Swift
編程語言特意使用了Character
類型以覆蓋所有可被編碼的字符。這也意味著一個Character
對象可包含多個UnicodeScalar
對象
let flag: Character = "????"
print("flag is:\(flag)")
//光使用Character,我們沒有辦法獲取碼點值,所以我們這里借助String.UnicodeScalarView類型
let scalars = flag.unicodeScalars;
print("scalars:", separator: "", terminator: " ")
// 我們這里可以發現一個很有意思的情況:
// ????正好是由兩個Emoji字符構成:??和??
for scalar in scalars {
print("\(scalar)=\(scalar.value)", separator: "", terminator: " ")
}
let c = UnicodeScalar(127464)!
let n = UnicodeScalar(127475)!
print("c = \(c), n = \(n)")
// 我們將兩個UnicodeScalar對應的字符對象拼在一起,
// 構成一個String對象,
// 然后用Character構造方法將此String對象中的內容轉換為Character相應的值
let cn = Character(String([Character(c), Character(n)]))
// 這里我們就能看到中國國旗的Emoji了
print("cn = \(cn)")
二、轉義字符
/*
"\0" 表示空字符(null character),一般用于傳統ASCII編碼的字符串的結束符。
"\\" 表示倒斜杠(backslash)。
"\t" 表示水平制表符(horizontal tab)。
"\n" 表示換行(line feed)。
"\r" 表示回車(carriage return)。
"\"" 表示雙引號。
"\'" 表示單引號。當然,一般單引號在Swift編程語言中表示字符或字符串字面量時不需要做轉義,直接用 "'" 也行。”
*/
/**
* 這里將會輸出:
The string is: Say, "Hello, world"!
非常好!
* 注意雙引號與換行符的輸出
*/
let d = "Say,\"Hello,World!\"!\n非常好"
print("The string is:\(d)")
三、字符串簡述
一個字符串是一組字符序列,在
Swift中
使用String
類型來表示一個字符串類型
***字符串的實例方法與屬性
/*
1.字符串與數組對象類似,也可用+操作符將兩個字符串對象拼接起來,構成一個新的字符串對象。
2.對于一個可修改的字符串對象,則可使用 += 操作符將 += 右邊的字符串的內容添加到 += 左邊的可修改的字符串對象的末尾
3.我們還能直接通過 == 操作符來比較兩個字符串對象中的字符序列內容是否完全相同,如果相同則返回 true,否則返回 false
4.而要判斷一個字符串是否為空,則可使用 isEmpty 實例屬性
5.判定字符串是否包含指定的子串,則可使用 contains(_:) 實例方法。
6.如果我們要判斷一個字符串對象的開頭是否包含某個子串,可以使用 hasPrefix(_:) 實例方法
7.如果我們要判斷一個字符串對象的末尾是否包含某個子串,那么可以使用 hasSuffix(_:) 實例方法。
*/
// 這里通過 + 操作符將兩個字符串字面量拼接在一起構造出一個新的字符串對象給常量a
let e = "Hello, " + "world!"
// 字符串常量b則是將兩個"Hello, world!"中間用換行符連接在一起
let f = e + "\n" + e
print("f = \(f)")
// 比較字符串對象a與"Hello, world!"是否相同
// 比較結果為true
print("Is equal? \(e == "Hello, world!")")
// 判定字符串對象是否為空字符串
// 結果為false
print("Is empty? \(e.isEmpty)")
// 判斷是否包含 , 符號
// 結果為true
print("contains ','? \(e.contains(","))")
// 判斷字符串對象a是否含有前綴"Hello"
// 結果為true
print("Has prefix 'Hello'? \(e.hasPrefix("Hello"))")
// 判斷字符串對象a是否含有后綴"d!"
// 結果為true
print("Has suffix 'd!'? \(e.hasSuffix("d!"))")
// 這里聲明了字符串變量str,
// 并將a的內容對它初始化
var str = e
// 在str對象后添加一個字符串內容
str += " 你好,世界!"
print("str = \(str)")
四、字符串插值
Swift
編程語言提供了一種十分便利的方式可將幾乎任一類型的對象轉換為一個字符串的表示形式,這在Swift
中稱為字符串插值(String Interpolation
)。
let x = 10, y = 20
let s = "x + y = \(x+y)"
print("s is: \(s)")
// 當然,因為s本身是字符串類型,
// 所以我們也可以直接用字符串拼接方式來打印
print("s is: " + s)
五、字符串的characters
屬性
如果我們想要迭代訪問一個字符串中的每個字符,或者是查詢當前字符串中包含多少字符個數,那么我們可以訪問
String
對象的characters
屬性。這里的characters
屬性并不是[Character]
類型,而是String.CharacterView
類型,使得我們可以使用for-in
循環迭代語句將其中的字符一一枚舉出,但是我們無法使用整數作為下標索引來訪問characters
中的指定字符。
var str1 = "看旗幟:\u{1f1e8}"
// 我們先觀察當前str對象的長度,
// 長度為5
print("str count: \(str1.characters.count)")
print("before appending:", separator: "", terminator: " ")
// 我們輸出當前str中的字符序列
for ch in str1.characters {
print("\(ch)", separator: "", terminator: " ")
}
print("")
// 我們再新增一個字符
str1.append("\u{1f1f3}")
// 輸出當前字符串中字符個數,
// 仍然為5
print("str count: \(str1.characters.count)")
print("After appending:", separator: "", terminator: " ")
// 最后,我們再逐一輸出字符序列
for ch in str1.characters {
print("\(ch)", separator: "", terminator: " ")
}
print("")
String.CharacterView
類型中包含了first
屬性,可用于獲取當前字符序列中的第一個字符;另外還有last
屬性,可用于獲取當前字符序列的最后一個字符。由于當前字符串可能是一個空串(即 ""),所以這兩個屬性的返回類型都是Optional
。如果當前字符串是一個空串,那么這兩個屬性的值都是為空(nil)
。我們下面來看以下代碼示例:
let str2 = "看旗幟:\u{1f1e8}\u{1f1f3}"
var ch = str2.characters.first!
// 這里輸出:看
print("first character: \(ch)")
ch = str2.characters.last!
// 這里輸出????的Emoji
print("ch = \(ch)")
六、字符串的索引及字符訪問
Swift
編程語言轉為String
類型引入了 索引類型String.Index
用于表示字符串對象中字符序列的索引值。由于String.Index 類型也遵循了
Comparable` 協議,所以它可以作為范圍操作符的操作數。
我們通過調用字符串對象的
index(_:offsetBy:)
實例方法即可得到指定的索引值。該方法的第一個參數填參考索引值,第二個參數填指定的偏移 n,偏移值為正數,說明返回的索引值往后挪 n 位,如果是負數,則說明往前挪 n 位。
String
類型還有一個index(_:offsetBy:limitedBy:)
實例方法,功能與index(_:offsetBy:)
一樣,只不過這里多了一個參數,第三個參數用于做邊界檢測,如果索引計算的結果超出了第三個參數所指定的值,那么此方法將會返回空。因此它返回的是一個Optiona
l對象。
有了索引值之后,我們就可以拿它通過字符串的
substring(with:)
實例方法獲取字符串的指定子串,然后通過子串的characters
屬性中的first
屬性或last
屬性來獲取到當前指定的字符了。我們下面來看一個例子:
let str3 = "看旗幟:????"
// str字符串對象的起始索引,索引值相當于0
let startIndex = str3.startIndex
// str字符串對象的末尾索引,索引值相當于:
// str.characters.count - 1
let endIndex = str3.endIndex
// index2作為索引2
let index2 = str3.index(startIndex, offsetBy: 2)
// index3作為索引3
let index3 = str3.index(startIndex, offsetBy: 3, limitedBy: endIndex)!
// 這里通過范圍操作符構造一個Range<String.Index>對象,
// 作為substring方法的參數,以獲取子串。
// 各位注意,這里必須使用 ..< 操作符,
// 而不能使用 ... 操作符。
// 因為 ... 操作符對應的是ClosedRange類型,
// 而不是Range類型
var substr = str3.substring(with: index2 ..< index3)
// 我們這里可以觀察到,
// substr.characters的first字符與last字符都是同一個,
// 即“幟”這個字。
var ch2 = substr.characters.first!
print("ch = \(ch)")
ch2 = substr.characters.last!
print("ch = \(ch)")
// 這里以index3作為參考索引,
// 然后偏移-2表示往前移2個位置,
// 所以index1的索引值對應的是1
let index1 = str2.index(index3, offsetBy: -2)
// 獲取第二個字符
substr = str3.substring(with: index1 ..< index2)
ch = substr.characters.first!
// 這里輸出:
// 第二個字符為:旗
print("第二個字符為:\(ch)")