Swift語言指南(十)--字串與字元

來源:互聯網
上載者:User

字串是一段字元的有序集合,如"hellow,world"或"信天翁"。Swift 中的字串由 String 類型表示,對應著 Character 類型值的集合。

Swift 中的 String 類型為你的編程提供了一個高速的,相容 Unicode規範 的文本處理方式。Swift 建立和處理字串的文法輕量可讀,與 C 語言的字串文法頗為相似。字串的拼接非常簡單,只需將兩個字串用 + 運算子相加。字串的值是否可變取決於其為常量還是變數,這一點與 Swift 中的其它類型一致。

Swift 的 String 類型除了文法簡潔之外,還是一個高速,現代化的字串實現方案。每個字串均由編碼獨立的 Unicode 字元組成,每個字元均支援以不同的 Unicode 表達形式訪問。

Swift 的字串還支援在較長的字串中插入常量、變數、字面量以及運算式的值,該過程稱為字串插入。這使得顯示、儲存以及輸出自訂的字串值更加簡便。

註:

Swift 的 String 類型與底層 Foundation 的 NSString 類無縫銜接。如果你在 Cocoa / Cocoa Touch 中使用 Foundation 架構,那麼,除了本章提到的 String 特性之外,對建立的任何 String 值,均可調用到 NSString 類的全部 API。還可以將 String 值傳遞給任何需要 NSString 執行個體的 API 方法。

更多 String 與 Foundation / Cocoa 架構結合使用的資訊,請見 Swift 與 Cocoa 及 Objective-C 的結合(這一部分內容在本書之外,譯完本書再譯)。

 

字串字面量

代碼中可以在預先定義的 String 值中嵌入字串字面量string literal)。字串字面量是由一對雙引號("")包圍的文本字元的固定序列。

字串字面量可以為一個常量或變數提供初始值:

let someString = "Some string literal value"

注意,Swift 推斷常量 someStringString 類型,因為 someString 的值被一個字串字面量初始化了。

字串字面量涵蓋了下述特殊字元:

· 轉義過的特殊字元: \0(null 字元),\\ (反斜線,轉義後應為單斜杠--Joe.Huang),\t(水平定位字元),\n(分行符號),\r(斷行符號符),\"(雙引號)以及 \'(單引號)

· 單位元組的 Unicode 標量,寫作 \xnn,其中 nn 為兩個十六進位數位

· 雙位元組的 Unicode 標量,寫作 \unnnn,其中 nnnn 為四個十六進位數位

· 四位元組的 Unicode 標量,寫作 \Unnnnnnnn,其中 nnnnnnnn 為八個十六進位數位

下面的代碼展示了這幾種特殊字元的例子。常量 wiseWords 包含兩個轉義後的雙引號字元。常量 dollarSign、blackHeart 以及 sparklingHeart 展示了 Unicode 標量字元的三種不同書寫格式:

let wiseWords = "\"Imagination is more important than knowledge\" - Einstein"// "Imagination is more important than knowledge" - Einstein// 輸出 "想象力比知識更重要" - 愛因斯坦let dollarSign = "\x24"        // 輸出 $,  Unicode 標量 U+0024let blackHeart = "\u2665"      // 輸出 ♥,  Unicode 標量 U+2665let sparklingHeart = "\U0001F496"  // 輸出 , Unicode 標量 U+1F496

 

初始化一個Null 字元串

建立一個較長的字串,第一步,需要建立一個空的 String 值,你既可以將Null 字元串字面量賦值給一個變數,也可以用初始化文法初始化一個新的 String 執行個體:

1 var emptyString = ""               // Null 字元串字面量2 var anotherEmptyString = String()  // 初始化文法3 // 這兩個字串對象都是空值, 互相等同

你可以使用 isEmpty 屬性檢測字串的值是否為空白:

1 if emptyString.isEmpty {2     println("Nothing to see here")3 }4 // 輸出 "什麼都沒看到"

 

字串的可變性

一個特定 String 的值是否可以修改(即可變mutable),可通過聲明將其賦值給一個變數(可以修改)或常量(不可修改):

1 var variableString = "Horse"2 variableString += " and carriage"3 // variableString 的值現在為 "Horse and carriage"4  5 let constantString = "Highlander"6 constantString += " and another Highlander"7 // 編譯錯誤 - 常量 string 的值不可更改

註:

該實現方案與 Objective-C / Cocoa 的字串可變性有所不同,後者是通過在執行個體所屬的兩個類中二選一(NSStringNSMutableString)來聲明字串是否可變。

 

String屬於傳實值型別

Swift 的 String 類型是一種傳實值型別value type)。如果將一個 String 值傳遞給一個函數或方法,或將其賦值給一個常量或變數,則該 String 值也會被一同複製(copied過去。這兩種情況均會為現有 String 值建立新的副本,實際傳遞或賦值的是其副本,而非其原始執行個體。傳實值型別的說明請見 結構與枚舉類型均為傳實值型別 (後面章節譯到)。

註:

該行為與 CocoaNSString 不同。Cocoa 中建立 NSString 執行個體並傳遞給函數或方法,或賦值給變數時,實際傳遞或賦值的是同一個 NSString 執行個體的引用(reference,非複製--copy)。這中間不會有複製字串的操作,除非特別指定。

Swift 中 String 的 “預設複製” 行為可確保函數或方法傳遞 String 值給你時,這個 String 值的確屬於你,而與其出處無關。可以肯定的是,除非你自己去修改它,你接收到的字串絕對不會變。

在後台,Swift 的編譯器會最佳化字串的記憶體佔用,僅在絕對需要時才會實際建立字串的副本。因此,字串屬於傳實值型別讓你的代碼總能達到最佳效能。

 

字元操作

Swift中的 String 類型是一段 Character 值的有序集合,每一個 Character 值代表一個 Unicode 字元。你可以通過 for-in 迴圈遍曆訪問一個字串中的每個 Character 值:

1 for character in "Dog!" {2     println(character)  //輸出(character)3 }4 // D5 // o6 // g7 // !8 // 

For-in 的用法後面在流程式控制制一章會譯到。

另外,通過 Character 類型說明可以從單字元的字串字面量中單獨建立字元常量或變數:

1 let yenSign: Character = "¥"2 // 指定了yenSign為 Character 類型 -- Joe.Huang

 

字元統計

可以使用全域方法 countElements 來統計字串中字元的個數,把字串作為唯一的參數傳進即可:

1 let unusualMenagerie = "Koala , Snail , Penguin , Dromedary "2 println("unusualMenagerie has \(countElements(unusualMenagerie)) characters")3 // 輸出 "unusualMenagerie 有 40 個字元"

註:

不同的 Unicode 字元,以及同一個 Unicode 字元的不同表示,在記憶體中所佔用的儲存空間不同。因此,要想計算出字串的長度,必須遍曆整個字串,依次統計每一個字元。如果你在處理特別長的字串值,要謹記,countElements 函數需要遍曆字串中的每個字元方能求出其精確的字元個數。

還要注意的一點是,countElements 返回的字元個數,與包含同樣字元的 NSString 對象的 length 屬性所返回的字元個數並不總是一樣多。NSString 的長度根據該字串的 UTF-16 形式的 16 位碼單元個數得出,而非根據字串內 Unicode 字元的個數得出。為了區別體現這一事實,在 Swift 語言中,NSString 的 length 屬性需通過 String 值的 utf16count 屬性訪問。

 

字串與字元的拼接

StringCharacter 值可以用加法運算子(+)加在一起(即串連concatenate),得到一個新的 String 值:

let string1 = "hello"let string2 = " there"let character1: Character = "!"let character2: Character = "?" let stringPlusCharacter = string1 + character1        // 等於 "hello!"let stringPlusString = string1 + string2              // 等於 "hello there"let characterPlusString = character1 + string1        // 等於 "!hello"let characterPlusCharacter = character1 + character2  // 等於 "!?"

(接上例的常量)還可以用加法賦值運算子(+=)在 String 變數的末尾追加(append) String 或 Character 值:

var instruction = "look over"instruction += string2// instruction now equals "look over there"// instruction 現在等於 "瞧那兒" var welcome = "good morning"welcome += character1// welcome now equals "good morning!"// welcome 現在等於 "早上好!"

 

字串插入

字串插入是一種將常量,變數,字面量,運算式混合插入字串字面量並得到一個新的 String 值的方法。字串字面量中插入的每一項均需用一對括弧包圍,並前置反斜線:

1 let multiplier = 32 let message = "\(multiplier) times 2.5 is \(Double(multiplier) * 2.5)"3 // message is "3 times 2.5 is 7.5"4 // message 是 "3 乘以 2.5 是 7.5"

在上例中, 常量 multiplier 的值以 \(multiplier) 的形式作為預留位置插入字串字面量中。在根據字串插入式求出實際字串的過程中,預留位置會被 multiplier 的實際值替換。

後面一個較長的運算式用到了 multiplier 的值。該運算式計算了 Double(multiplier) * 2.5 的值,並將結果7.5)插入了字串。上例中, \(Double(multiplier) * 2.5) 作為預留位置嵌入了字串字面量中。

註:

字串插入中,括弧裡面的運算式不能包含未轉義的雙引號(")或反斜線(\),也不能包含斷行符號或分行符號。

 

字串比較

Swift 提供了三種字串比較方法:字串匹配,首碼匹配,尾碼匹配。

 

字串匹配

如果兩個 String 值所包含的字元及其順序完全相同,兩者即相等:

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     println("These two strings are considered equal")5 }6 // 輸出 "這兩個字串是相等的"

 

首碼/尾碼匹配

檢查一個字串是否含有一個指定的字元首碼或尾碼,可以使用字串的 hasPrefixhasSuffix 方法,兩種方法都接收一個 String 類型的參數並返回一個布爾值。這兩種方法會拿首碼/尾碼字串與基底字元串一個字元一個字元地逐一比較。

下例有一個字串數組,內容為莎士比亞戲劇《羅密歐與朱麗葉》(Romeo and Juliet)前兩幕各情境的地點說明:

 1 let romeoAndJuliet = [ 2     "Act 1 Scene 1: Verona, A public place",               //第一幕情境1:Verona,一個公用場所 3     "Act 1 Scene 2: Capulet's mansion",                    //第一幕情境2:Capulet的家 4     "Act 1 Scene 3: A room in Capulet's mansion",          //第一幕情境3:Capulet家的一間房內 5     "Act 1 Scene 4: A street outside Capulet's mansion",   //第一幕情境4:Capulet家外的街上 6     "Act 1 Scene 5: The Great Hall in Capulet's mansion",  //第一幕情境5:Capulet家的大廳內 7     "Act 2 Scene 1: Outside Capulet's mansion",            //第二幕情境1:Capulet家外面 8     "Act 2 Scene 2: Capulet's orchard",                    //第二幕情境2:Capulet的果園 9     "Act 2 Scene 3: Outside Friar Lawrence's cell",        //第二幕情境3:Friar Lawrence神父的教堂外10     "Act 2 Scene 4: A street in Verona",                   //第二幕情境4:Verona的某條街道上11     "Act 2 Scene 5: Capulet's mansion",                    //第二幕情境5:Capulet的家12     "Act 2 Scene 6: Friar Lawrence's cell"                 //第二幕情境6:Friar Lawrence神父的教堂13 ]

romeoAndJuliet 數組中的元素使用 hasPrefix 方法,來統計該劇第一幕(Act 1)的場次:

1 var act1SceneCount = 02 for scene in romeoAndJuliet {3     if scene.hasPrefix("Act 1 ") {4         ++act1SceneCount5     }6 }7 println("There are \(act1SceneCount) scenes in Act 1")8 // 輸出 "Act 1(第一幕) 有5場戲"

同樣,用 hasSuffix 方法來統計發生在 Capulet’s mansion 和 Friar Lawrence’s cell 這些地點的場次:

 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 println("\(mansionCount) mansion scenes; \(cellCount) cell scenes")11 // 輸出 "mansion 6場; cell 2場"

 

 

謝謝,Swifter-QQ群:362232993,同好者進~ 

Fork:https://github.com/Joejo/Swift-lesson-for-chinese

 

 

 

 

 

 

 

 

 

 

 

 

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.