Swift4 Strings

基本概念

Strings 類似于集合,其由字形簇(Grapheme clusters)組成。

//遍歷字符
let string = "Swift"
for char in string {
    print(char)
}

//字符串長度
let stringLength = string.count

/*
錯誤的訪問字符方式
涉及到字符串的不同編碼方式,以及字形合并等原因。
*/
let fourthChar = string[3] //error

字形簇 (Grapheme clusters)

字符由字形簇組成,相應的字形簇也是一個類集合。這其中有一個概念叫做合成字符,如 e? ,其邏輯上的等價字符由 e 合成。相對應的 Unicode 碼如下:

e? : 233
e : 101
: 769

下面我們來嘗試一下,使用代碼怎么表示。

let normalE = "e?"
let combineE = "e\u{0301}"
//注意 \u{0301} 代表 `′` 十六進制換算下就明白了

normalE.count  //1
combineE.count //1

/*
邏輯上 字符串 和 合成字符串 相等,他們對應于同一個字形。
Swift對于字符串的比較,使用了標準化。
在比較前,會先轉化為標準字形。
*/
let equal = normalE == combineE

/*
通過上面的方法,我們并沒有發現這兩個字符串有何不同。
但其實,系統提供了一個方式來訪問字形內部的簇族。
unicodeScalars: 碼點(codePoint)集合
*/

normalE.unicodeScalars.count  //1
combineE.unicodeScalars.count //2

//碼點遍歷
for codePoint in normalE.unicodeScalars {
    print(codePoint.value)
}
// 233

combineE.unicodeScalars {
    print(codePoint.value)
}
// 101
// 769

通過結果,我們看到字形 和 其合成字形,并不完全等價。這一點從其構成的碼點集合,可以看出來。這種差別,在我們操作或訪問編碼層級的時候尤其要注意!!!


字符串下標索引

上面提到了字符串是一種類集合,但我們在使用下面方式訪問字符時卻出現了錯誤。

let strTitle = "Swift"
let fourthChar = strTitle[3]
/*
error: 'subscript' is unavailable: 
cannot subscript String with an Int,
see the documentation comment for discussion
*/

可以看到,并不是不支持下標語法,只是不是Int型下標索引。正確的類型是 String.Index,下面看示例。這一塊的概念有些纏繞...

獲取首個字符:

//獲取字符串起始下標
let firstIndex = strTitle.startIndex

/*
通過這個下標,我們可以讀取對應該下標的字符。
注意沒有細致到碼點層級,只是單個字符。
*/
let firstChar = strTitle[firstIndex] 
// S

獲取末尾字符:

//末尾下標
let lastIndex = strTitle.endIndex

//末尾字符
let lastChar = strTitle[lastIndex]
/*
fatal error: Can't form a Character from an empty String
發生了錯誤,因為集合類型都是zero-index.
糾正如下:
*/

let lastIndex = strTitle.index(before: strTitle.endIndex)
let lastChar = strTitle[lastIndex]
// t

獲取其它位置的字符:

let secondIndex = strTitle.index(strTitle.startIndex, offsetBy: 1)
let secondChar = strTitle[secondIndex]
// w

字符串反置

字符串作為一個有序的字符集合,系統也提供了翻轉方法。

let name = "Swift"
var backwardsName = name.reversed()
/*
這里的返回值類型,ReversedCollection<String>
這背后隱藏了一個并不透明的機制,該返回值是和原字符串內存有關聯的。
*/

//生成字符串
let backwardsNameString = String(backwardsName)

//注意:如果我們改變了原字符串
backwardsName = ""

/*
會得到如下錯誤
Fatal error: 
Can't form a Character from an empty String
至于為什么,歡迎討論、拍磚。
*/

字符串截取(Substrings)

在字符串使用過程中,通常會有截取的操作。那么回顧上文中提及的 String.Index 下標索引,以及區間的概念,截取操作如下:

let fullName = "Tom Green"
//注意返回值是一個可選型
let spaceIndex = fullNmae.index(of: " ")!

let firstName = fullName[fullName.startIndex..<spaceIndex] // "Tom" 

/*
Open-ended range
只標明一個索引的區間
*/
let firstName = fullName[..<spaceIncexf] // "Tom"

let lastName = fullName[fullName.index(after: spaceIndex)...] // "Green"

//注意Substring 操作返回值類型是String.Sequence 

//所以想生成字符串的話
let lastNameString = String(lastName)

編碼 (Encoding)

這部分內容有些生澀僅做提及,建議額外詳查資料。

Strings 是由 Unicode code points 構成的集合,這些 code points 的范圍是 0 ~ 1114111(0x10FFFFF 十六進制)。這也就是說,需要21bits 才能夠表示這個范圍。如果你只需要用到低范圍的 code points(像拉丁字母),那么可以只用8bits 來標識每一個code point.

大多數編程語言中數值類型都是可尋址且存儲空間具有一定規則的,計算機只能處理以bit(1位_表示0 或 1)為基礎的數據,常見的像8-bits,16-bits,32-bits。

當去存儲 Strings 類型數據時,可以規定每個碼點(code point)使用32-bits來表示,如UInt32。這些UInt32稱為碼元(code unit),而這個表示過程就是 Strings 的編碼(encoding),專業的名詞被稱為UTF-32。

類似的還有UTF-8 、UTF-16,感興趣的可以詳查資料。

//系統提供了訪問 編碼層級的API

//UTF-8 
let char = "\u{00bd}"
for i in char.utf8 {
    //輸出二進制形式
    print("\(i): \(String(i, radix: 2))")
}

res:
194: 11000010
189: 10111101

//UTF-16
for i in char.utf16 {
    print("\(i) : \(String(i, radix: 2))")
}

res:
189 : 10111101

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,001評論 6 537
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,786評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,986評論 0 381
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,204評論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,964評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,354評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,410評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,554評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,106評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,918評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,093評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,648評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,342評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,755評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,009評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,839評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,107評論 2 375

推薦閱讀更多精彩內容