字符串和字符

字符串和字符

[TOC]

字符串是例如 "hello, world" 粉臊, "albatross" 這樣的有序的 Character (字符)類型的值的集合。通過 String 類型來表示锐峭。一個 String 的內容可以用許多方式讀取,包括作為一個 Character 值的集合。

Swift的 StringCharacter 類型提供了快速和兼容Unicode的方式供你的代碼使用淌哟。創(chuàng)建和操作字符串的語法與C語言中字符串操作相似诵盼,輕量并且易讀惠豺。字符串的連接操作只需要簡單地通過 + 符號將兩個字符串相連即可。與Swift中其他值一樣风宁,能否更改字符串的值洁墙,取決于其被定義為常量還是變量。你也可以在字符串內插過程中使用字符串插入常量戒财、變量热监、字面量表達成更長的字符串,這樣可以很容易的創(chuàng)建自定義的字符串饮寞,進行展示孝扛、存儲以及打印。

盡管語法簡易幽崩,但 String 類型是一種快速苦始、現(xiàn)代化的字符串實現(xiàn)。每一個字符串DOI是由編碼無關的 Unicode 字符組成慌申,并支持訪問字符的多種Unicode表示形式陌选。

注意:Swift的 String 類型與Foundation的 NSString 類進行了無縫橋接。Foundation也可以對 String 進行擴展,暴露在 NSString 中定義的方法咨油。這意味著您炉,如果你在 String 中調用這些 NSString 的方法,將不用進行轉換臼勉。

字符串字面量

你可以在代碼里使用一段預定義的字符串值作為字符串字面量邻吭。字符串字面量是由一對雙引號包裹著的具有固定順序的字符集。

字符串字面量可以用于為常量和變量提供初始值:

let someString = "Some string literal value"

注意 someString 常量通過字符串字面量進行初始化宴霸,Swift會推斷該常量為 String 類型囱晴。

多行字符串字面量

如果你需要一個字符串是跨多行的,那就使用多行字面量 - - - 由一對三個引號包裹著的具有固定順序的文本字符集:

let quotation = """
The White Rabbit put on his spectacles.  "Where shall I begin,
please your Majesty?" he asked.

"Begin at the beginning," the King said gravely, "and go on
till you come to the end; then stop."
"""

一個多行字符串字面量包含了所有的在開啟和關閉引號( """ )中的行瓢谢。這個字符從開啟引號( """ )之后第一行開始今阳,到關閉引號( """ )之前為止楔壤。這就意味著字符串開啟引號之后( """ )或者結束引號( """ )之前都沒有換行符號叹括。

下面兩個字符串其實是一樣的维苔,雖然第二個使用了多行字符串的形式:

let singleLineString = "These are the same."
let multilineString = """
These are the same.
"""

如果你的代碼之中,多行字符串字面量包含換行符的話采郎,則多行字符串字面量中也會包含換行符千所。如果你想換行,以便加強代碼的可讀性蒜埋,但是你又不想在你的多行字符串字面量中出現(xiàn)換行符的話淫痰,你可以用在行尾寫一個反斜杠( \ )作為續(xù)航符。

let softWrappedQuotation = """
The White Rabbit put on his spectacles.  "Where shall I begin, \
please your Majesty?" he asked.

"Begin at the beginning," the King said gravely, "and go on \
till you come to the end; then stop."
"""

為了讓一個多行字符串字面量開始和結束于換行符整份,請將換行寫在第一行和最后一行待错,例如:

let lineBreaks = """

This string starts with a line break.
It also ends with a line break.

"""

一個多行字符串字面量能夠縮進來匹配周圍的代碼。關閉引號( """ ) 之前的空白字符串告訴Swift編譯器其他各行多少字符串需要忽略烈评。然而火俄,如果你在某行的前面寫的空白字符串超出了關閉引號( """ ) 之前的空白字符串,則超出部分將被包含在多行字符串字面量中讲冠。

let linesWithIndentation = """
    This line doesn't begin whith whitespace.
        this line begins with four space.
    this line doesn't begin with whitespace.
    """

從上面的例子中瓜客,盡管整個多行字符串字面量都是縮進的,第一行和最后一行沒有以空白字符開始竿开。中間一行的縮進用空白字符串比關閉引號( """ )之前的空白字符多谱仪,所以,它的行首將有4個空格德迹。

字符串字面量的特殊字符

字符串字面量可以包含以下特殊字符:

  • 轉義字符 \0 (空字符)芽卿、 \\ (反斜線)揭芍、 \t (水平制表符)胳搞、 \n (換行符)、 \r (回車符)、 \" (雙引號)肌毅、 \' (單引號)筷转。
  • Unicode標量,寫成 \u{n} (u為小寫)悬而,其中 n 為任意一到八位十六進制數(shù)且可用的Unicode位碼呜舒。

下面的代碼為各種特殊字符的使用示例。 wiseWords 常量包含了兩個雙引號笨奠。 dollarSign 袭蝗、blackHeartsparklingHeart 常量演示了三種不同格式的Unicode標量:

let wiseWords = "\"Imagination is more important than knowledge\" - Einstein"   
//  "Imagination is more important than knowledge" - Einstein
let dollarSign = "\u{24}" 
// $,Unicode 標量 U+0024
let blackHeart = "\u{2665}"
// ?般婆,Unicode 標量 U+2665
let sparklingHeart = "\u{1F496}"      
// ??到腥,Unicode 標量 U+1F496

由于多行字符串字面量使用了三個雙引號,而不是一個蔚袍,所以你可以在多行字符串字面量里直接使用雙引號( " )而不必加上轉義符( \ )乡范。要在多行字符串字面量中使用 """ 的話,就需要使用至少一個轉義符( \ ):

let threeDoubleQuotes = """
Escaping the first quote \"""
Escaping all three quotes \"\"\"
"""

初始化空字符串

要創(chuàng)建一個空字符串作為初始值啤咽,可以將空字符串字面量賦值給變量晋辆,也可以初始化一個新的 String 實例:

var emptyString = ""    // 空字符串字面量
var anotherEmptyString = String() // 初始化方法
// 兩個字符串均空并等價。

你可以通過檢查其 Bool 類型的 isEmpty 屬性來判斷該字符串是否為空:

if emptyString.isEmpty {
    print("Nothing to see here")
}
// 輸出 Nothing to see here

字符串可變性

你可以通過將一個特定字符串分配給一個變量來對其進行修改宇整,或者分配給一個常量來保證其不會被修改:

var variableString = "Horse"
variableString += " and carriage"
// variableString 現(xiàn)為 Horse and carriage

let constantString = "Highlander"
constantString += " and another Highlander"
// 這會報告一個編譯錯誤 (compile-time error) - 常量字符串不可以被修改瓶佳。

注意:在Objective-C和Cocoa中,你需要通過選擇兩個不同的類 NSSrtingNSMutableString 來指定字符串是否可以被修改没陡。

字符串是值類型

Swift的 String 類型是值類型涩哟。如果你創(chuàng)建了一個新的字符串,那么當其進行常量盼玄、變量賦值操作贴彼,或在函數(shù)/方法中傳遞是,會進行值拷貝埃儿。任何情況下器仗,都會對已有字符串值創(chuàng)建新副本,并對該新副本進行傳遞或賦值操作童番。

Swift默認字符串拷貝的方式保證了在函數(shù)/方法中傳遞的字符串的值精钮。很明顯無論值來自哪里,都是你獨自擁有的剃斧。你可以確信傳遞的字符串不會被修改轨香,除非你自己去修改它。

在實際編譯時幼东,Swift編譯器會優(yōu)化字符串的使用臂容,使實際的復制只發(fā)生在絕對必要的情況下科雳,這意味著你將字符串作為值類型的同時可以獲得極高的性能。

使用字符

你可以通過 for-in 循環(huán)來遍歷字符串脓杉,獲取字符串中每一個字符的值:

for character in "Dog!??" {
    print(character)
}
// D
// o
// g
// !
// ??

另外糟秘,通過標明一個 Character 類型并用字符字面量賦值,可以建立一個獨立的字符常量或變量:

let exclamationMark: Character = "!"

字符串可以通過傳遞一個值類型為 Character 的數(shù)值作為自變量來初始化:

let catCharacters: [Character] = ["C", "a", "t", "!", "??"]
let catString = String(catCharacters)
print(catString)
// 輸出 Cat!??

連接字符串和字符

字符串可以通過加法運算符( + )相加在一起球散,創(chuàng)建一個新的字符串:

let string1 = "hello"
let string2 = " three"
var welcome = string1 + string2
// welcome 現(xiàn)在等于 "hello three"

你也可以通過加法賦值運算符( += )將一個字符串加到一個已經存在的字符串變量上:

var instruction = "look over"
instruction += string2
// instruction 現(xiàn)在等于 "look over three"

你可以用 append() 方法將一個字符附加到一個字符串變量的尾部:

let exclamationMark: Character = "!"
welcome.append(exclamationMark)
// welcome 現(xiàn)在等于 "hello three!"

注意:你不能將一個字符串或字符添加到一個已經存在的字符變量上尿赚,因為字符變量只能包含一個字符。

如果你需要使用多行字符串字面量來拼接字符串蕉堰,并且你需要字符串每一行都以換行符結尾凌净,包括最后一行:

let badStart = """
one
two
"""
let end = """
three
"""
print(badStart + end)
// 輸出
// one
// twothree

let goodStart = """
one
two

"""
print(goodStatr + end) 
// 輸出
// one
// two
// three

上面的代碼,把 badStartend 拼接起來的字符串非我們想要的結果屋讶。因為 badStart 最后一行沒有換行符泻蚊,它與 end 的第一行結合到了一起。相反的丑婿,goodStart 的每一行都以換行符結尾性雄,所以它與 end 拼接的字符串總共有三行,正如我們期望的那樣羹奉。

字符串插值

字符串插值是一種構建新字符串的方式秒旋,可以在其中包含常量、變量诀拭、字面量和表達式迁筛。字符串字面量和多行字符串字面量都可以使用字符串插值。你插入的字符串字面量的每一項都在以反斜線為前綴的圓括號中:

let multiplier = 3
let message = "\(multiplier) times 2.5 is \(Double(multiplier) * 2.5)"
// message 現(xiàn)在等于 "3 times 2.5 is 7.5"

在上面的例子中耕挨,multiplier作為\(multiplier)被插入到一個字符串常量量中细卧。 當創(chuàng)建字符串執(zhí)行插值計算時此占位符會被替換為multiplier實際的值。

multiplier的值也作為字符串中后面表達式的一部分筒占。 該表達式計算Double(multiplier) * 2.5的值并將結果 (7.5) 插入到字符串中贪庙。 在這個例子中,表達式寫為\(Double(multiplier) * 2.5)并包含在字符串字面量中翰苫。

注意:插值字符串中寫在括號中的表達式不能包含非轉義反斜杠(\)止邮,并且不能包含回車和換行符。不過奏窑,插值字符串可以包含其他字面量导披。

計算字符數(shù)量

如果想要獲得一個字符串中 Character 值的數(shù)量,可以使用 count 屬性:

let unusualMenagerie = "Koala ??, Snail ??, Penguin ??, Dromedary ??"
print("unusualMenagerie has \(unusualMenagerie.count) characters")
// 打印輸出 "unusualMenagerie has 40 characters"

注意在Swift中埃唯,使用可擴展的字符群集作為 Character 值來連接或改變字符串時撩匕,并不一定會更改字符串的字符數(shù)量。

例如墨叛,如果你用四個字符的單詞 cafe 初始化一個新的字符串止毕,然后添加一個 ``COMBINING ACTUE ACCENTU+0301)作為字符串的結尾并村。最終這個字符串的字符數(shù)量仍然是4,因為第四個字符是é滓技,而不是e` :

var word = "cafe"
print("the number of characters in \(word) is \(word.count)")
// 打印輸出 "the number of characters in cafe is 4"

word += "\u{301}"    // 拼接一個重音,U+0301

print("the number of characters in \(word) is \(word.count)")
// 打印輸出 "the number of characters in café is 4"

注意: 可擴展的字符群集可以組成一個或者多個 Unicode 標量棚潦。這意味著不同的字符以及相同字符的不同表示方式可能需要不同數(shù)量的內存空間來存儲令漂。所以 Swift 中的字符在一個字符串中并不一定占用相同的內存空間數(shù)量。因此在沒有獲取字符串的可擴展的字符群的范圍時候丸边,就不能計算出字符串的字符數(shù)量叠必。如果您正在處理一個長字符串,需要注意 count 屬性必須遍歷全部的 Unicode 標量妹窖,來確定字符串的字符數(shù)量纬朝。

另外需要注意的是通過 count 屬性返回的字符數(shù)量并不總是與包含相同字符的 NSStringlength 屬性相同。 NSStringlength 屬性是利用 UTF-16 表示的十六位代碼單元數(shù)字骄呼,而不是 Unicode 可擴展的字符群集共苛。

訪問和修改字符串

你可以通過字符串的屬性和方法來訪問和修改它,當然也可以用下標語法完成蜓萄。

字符串索引

每一個 String 值都有一個關聯(lián)的索引類型:String.Index 隅茎,它對應著字符串中的每一個 Character 的位置。

前面提到嫉沽,不同的字符可能會占用不同數(shù)量的內存空間辟犀,所以要知道 Character 的確定位置,就必須從 String 開頭遍歷每一個Unicode標量直到結尾绸硕。因此堂竟,Swift的字符串不能用整數(shù)(integer)做索引。

使用 startIndex 屬性可以獲取一個 String 的第一個 Character 的索引玻佩。使用 endIndex 屬性可以獲取最后一個 Character 的后一個位置的索引出嘹。因此,endIndex 屬性不能作為一個字符串的有效下標咬崔。如果 String 是空串疚漆,startIndexendIndex 是相等的。

通過調用 Stringindex(before:)index(after:) 方法刁赦,可以立即得到前面或后面的一個索引娶聘。你還可以通過調用 index(_:offsetBy:) 方法來獲取對應偏移量的索引,這種方式可以避免多次調用 index(before:)index(after:) 方法甚脉。

你可以使用下標語法來訪問 String 特定索引的 Character 丸升。

let greeting = "Guten Tag!"
greeting[greeting.startIndex] // G
greeting[gerrting.index(before: greeting.endIndex)] // !
greeting[gerrtinf.index(after: greeting.startIndex)] // u
let index = greeting.index(greeting.startIndex, offsetBy: 7)
greeting[index] // a

試圖獲取越界索引對應的 Character ,將引發(fā)一個運行時錯誤:

greeting[greeting.endIndex] // error
greeting.index(after: greeting.endIndex) // error

使用 indices 屬性會創(chuàng)建一個包含全部索引的范圍(Range)牺氨,用來在一個字符串中訪問單個字符狡耻。

for index in greeting.indices {
   print("\(greeting[index]) ", terminator: "")
}
// 打印輸出 "G u t e n   T a g ! "

注意:你可以使用 startIndexendIndex 屬性或者 index(before:) 墩剖、index(after:)index(_:offsetBy:) 方法在任意一個確認的并遵循 Collection 協(xié)議的類型里面,如上文是使用在 String 中夷狰,你也可以使用在 Array 岭皂、DictionarySet 中。

插入和刪除

調用 insert(_:at:) 方法可以在一個字符串的指定索引插入一個字符沼头,調用 insert(contentsOf:at:) 方法可以在一個字符串的指定索引插入一段字符串爷绘。

var welcome = "hello" 
welcome.insert("!", at: welcome.endIndex)
// welcome 現(xiàn)在等于 "hello!"

welcome.insert(contentsOf: " there", at: welcome.index(before: welcome.endIndex))
// welcome 現(xiàn)在等于 "hello there!"

調用 remove(at:) 方法可以在一個字符串中的指定索引刪除一個字符,調用 removeSubrange(_:) 方法可以在一個字符串的指定索引刪除一個子字符串进倍。

welcome.remove(at: welcome.index(before: welcome.endIndex))
// welcome 現(xiàn)在等于 "hello there"

let range = welcome.index(welcome.endIndex, offsetBy: -6)..<welcome.endIndex
welcome.removeSubrange(range)
// welcome 現(xiàn)在等于 "hello"

注意:你可以使用 insert(_:at:) 土至、insert(contentsOf:at:)remove(at:)removeSubrange(_:) 方法在任意一個確認的并遵循 RangeReplaceableCollection 協(xié)議的類型里面猾昆,如上文是使用在 String 中陶因,你也可以使用在 ArrayDoctionarySet 中垂蜗。

子字符串

當你從字符串中獲取一個子字符串 - - 例如楷扬,使用下標或者 prefix(_:) 之類的方法 - - 就可以得到一個 SubString 的實例,而非另外一個 String 贴见。Swift里的 SubString 絕大部分函數(shù)都跟 String 一樣毅否,意味著你使用同樣的方式去操作 SubStringString 。然而蝇刀,跟 String 不同的是螟加,你只有在短時間內需要操作字符串時,才會使用 SubString 吞琐。當你需要長時間保持結果時捆探,就把 SubString 轉化為 String 的實例:

let greeting = "Hello, world!"
let index = greeting.index(of: ",") ?? greeting.endIndex
let beginning = greeting[..<index]
// beginning 的值為 "Hello"

//把結果轉化為 String 以便長期存儲
let newString = String(beginning)

就像 String ,每一個 SubString 都會在內存里保存字符集站粟。而 StringSubStrig 的區(qū)別在于性能優(yōu)化上黍图, SubString 可以重復原 String 的內存空間,或者另一個 SubString 的內存空間( String 也有同樣的優(yōu)化奴烙,但如果兩個 String 共享內存的話助被,它們就會相等)。這一優(yōu)化意味著你在修改 StringSubString 之前都不需要消耗性能去復制內存切诀。就像前面說的那樣揩环, SubString 不適合長期存儲 - - 因為它重用了原 String 的內存空間,原 String 的內存空間必須保留直到它的 SubString 不再被使用為止幅虑。

上面的例子丰滑,greeting 是一個 String ,意味著它在內存里有一片空間保存字符集倒庵。而由于 beginninggreetingSubString 褒墨,它重用了 greeting 的內存空間炫刷。相反,newString 是一個 String - - 它是使用 SubString 創(chuàng)建的郁妈,擁有一片自己的內存空間浑玛。下面的圖展示了他們之間的關系:

圖片

比較字符串

Swift提供了三種方式來比較文本值:字符串字符相等、前綴相等和后綴相等噩咪。

字符串/字符相等

字符串/字符相等可以用等于操作符(==)和不等于操作符(!=):

let quotation = "We're a lot alike, you and I."
let sameQuotation = "We're a lot alike, you and I."
if quotation == sameQuotation {
    print("These two strings are considered equal")
}
// 打印輸出 "These two strings are considered equal"

如果兩個字符串(或者兩個字符)的可擴展字形群集是標準相等的顾彰,那就認為它們是相等的。在這個情況下剧腻,即使可擴展的字形群集是由不同的Unicode標量構成,只要它們有同樣的語言意義和外觀涂屁,就認為它們標準相等书在。

例如,LATIN SMALL LETTER E WITH ACUTE(U+00E9)就是標準相等于LATIN SMALL LETTER E(U+0065)后面加上COMBINING ACUTE ACCENT(U+0301)拆又。這兩個字符群集都是表示字符é的有效方式儒旬,所以它們被認為是標準相等的:

// "Voulez-vous un café?" 使用 LATIN SMALL LETTER E WITH ACUTE
let eAcuteQuestion = "Voulez-vous un caf\u{E9}?"

// "Voulez-vous un café?" 使用 LATIN SMALL LETTER E and COMBINING ACUTE ACCENT
let combinedEAcuteQuestion = "Voulez-vous un caf\u{65}\u{301}?"

if eAcuteQuestion == combinedEAcuteQuestion {
    print("These two strings are considered equal")
}
// 打印輸出 "These two strings are considered equal"

相反,英語中的LATIN CAPITAL LETTER A(U+0041帖族,或者A)不等于俄語中的CYRILLIC CAPITAL LETTER A(U+0410栈源,或者A)。兩個字符看著是一樣的竖般,但卻有不同的語言意義:

let latinCapitalLetterA: Character = "\u{41}"

let cyrillicCapitalLetterA: Character = "\u{0410}"

if latinCapitalLetterA != cyrillicCapitalLetterA {
    print("These two characters are not equivalent")
}
// 打印 "These two characters are not equivalent"

前綴/后綴相等

通過調用字符串的 hasPrefix(_:) / hasSuffix(_:) 方法來檢查字符串是否擁有特定前綴/后綴甚垦,兩個方法均接收一個 String 類型的參數(shù),并返回一個布爾值涣雕。

下面的例子以一個字符串數(shù)組表示莎士比亞話劇《羅密歐與朱麗葉》中前兩場的場景位置:

let romeoAndJuliet = [
    "Act 1 Scene 1: Verona, A public place",
    "Act 1 Scene 2: Capulet's mansion",
    "Act 1 Scene 3: A room in Capulet's mansion",
    "Act 1 Scene 4: A street outside Capulet's mansion",
    "Act 1 Scene 5: The Great Hall in Capulet's mansion",
    "Act 2 Scene 1: Outside Capulet's mansion",
    "Act 2 Scene 2: Capulet's orchard",
    "Act 2 Scene 3: Outside Friar Lawrence's cell",
    "Act 2 Scene 4: A street in Verona",
    "Act 2 Scene 5: Capulet's mansion",
    "Act 2 Scene 6: Friar Lawrence's cell"
]

你可以調用 hasPrefix(_:) 方法來計算話劇中第一幕的場景數(shù):

var act1SceneCount = 0
for scene in romeoAndJuliet {
    if secne.hasPrefix("Act 1") {
        act1SceneCount += 1
    }
}
print("There are \(act1SceneCount) secnes in Act 1")
// 輸出 "There are 5 scenes in Act 1"

相似地艰亮,您可以用hasSuffix(_:)方法來計算發(fā)生在不同地方的場景數(shù):

var mansionCount = 0
var cellCount = 0
for scene in romeoAndJuliet {
    if scene.hasSuffix("Capulet's mansion") {
        mansionCount += 1
    } else if scene.hasSuffix("Friar Lawrence's cell") {
        cellCount += 1
    }
}
print("\(mansionCount) mansion scenes; \(cellCount) cell scenes")
// 打印輸出 "6 mansion scenes; 2 cell scenes"

字符串的 Unicode 表示形式

當一個 Unicode 字符串被寫進文本文件或者其他儲存時,字符串中的 Unicode 標量會用 Unicode 定義的幾種編碼格式(encoding forms)編碼挣郭。每一個字符串中的小塊編碼都被稱代碼單元(code units)迄埃。這些包括 UTF-8 編碼格式(編碼字符串為8位的代碼單元), UTF-16 編碼格式(編碼字符串位16位的代碼單元)兑障,以及 UTF-32 編碼格式(編碼字符串32位的代碼單元)侄非。

Swift 提供了幾種不同的方式來訪問字符串的 Unicode 表示形式。 您可以利用for-in來對字符串進行遍歷流译,從而以 Unicode 可擴展的字符群集的方式訪問每一個Character值逞怨。

另外,能夠以其他三種 Unicode 兼容的方式訪問字符串的值:

  • UTF-8 代碼單元集合 (利用字符串的utf8屬性進行訪問)
  • UTF-16 代碼單元集合 (利用字符串的utf16屬性進行訪問)
  • 21位的 Unicode 標量值集合福澡,也就是字符串的 UTF-32 編碼格式 (利用字符串的unicodeScalars屬性進行訪問)

下面由D,o,g,?(DOUBLE EXCLAMATION MARK, Unicode 標量 U+203C)和??(DOG FACE骇钦,Unicode 標量為U+1F436)組成的字符串中的每一個字符代表著一種不同的表示:

let dogString = "Dog???"

UTF-8 表示

您可以通過遍歷Stringutf8屬性來訪問它的UTF-8表示。 其為String.UTF8View類型的屬性竞漾,UTF8View是無符號8位 (UInt8) 值的集合眯搭,每一個UInt8值都是一個字符的 UTF-8 表示:

for codeUnit in dogString.utf8 {
    print("\(codeUnit) ", terminator: "")
}
print("")
// 68 111 103 226 128 188 240 159 144 182

上面的例子中窥翩,前三個10進制codeUnit值 (68, 111, 103) 代表了字符Dog鳞仙,它們的 UTF-8 表示與 ASCII 表示相同寇蚊。 接下來的三個10進制codeUnit值 (226, 128, 188) 是DOUBLE EXCLAMATION MARK的3字節(jié) UTF-8 表示。 最后的四個codeUnit值 (240, 159, 144, 182) 是DOG FACE的4字節(jié) UTF-8 表示棍好。

UTF-16 表示

您可以通過遍歷Stringutf16屬性來訪問它的UTF-16表示仗岸。 其為String.UTF16View類型的屬性,UTF16View是無符號16位 (UInt16) 值的集合借笙,每一個UInt16都是一個字符的 UTF-16 表示:

for codeUnit in dogString.utf16 {
    print("\(codeUnit) ", terminator: "")
}
print("")
// 68 111 103 8252 55357 56374

同樣扒怖,前三個codeUnit值 (68, 111, 103) 代表了字符Dog业稼,它們的 UTF-16 代碼單元和 UTF-8 完全相同(因為這些 Unicode 標量表示 ASCII 字符)盗痒。

第四個codeUnit值 (8252) 是一個等于十六進制203C的的十進制值。這個代表了DOUBLE EXCLAMATION MARK字符的 Unicode 標量值U+203C低散。這個字符在 UTF-16 中可以用一個代碼單元表示俯邓。

第五和第六個codeUnit值 (5535756374) 是DOG FACE字符的 UTF-16 表示。 第一個值為U+D83D(十進制值為55357)熔号,第二個值為U+DC36(十進制值為56374)稽鞭。

Unicode 標量表示

您可以通過遍歷String值的unicodeScalars屬性來訪問它的 Unicode 標量表示。 其為UnicodeScalarView類型的屬性引镊,UnicodeScalarViewUnicodeScalar類型的值的集合朦蕴。 UnicodeScalar是21位的 Unicode 代碼點。

每一個UnicodeScalar擁有一個value屬性弟头,可以返回對應的21位數(shù)值梦重,用UInt32來表示:

for scalar in dogString.unicodeScalars {
    print("\(scalar.value) ", terminator: "")
}
print("")
// 68 111 103 8252 128054

前三個UnicodeScalar值(68, 111, 103)的value屬性仍然代表字符Dog亮瓷。 第四個codeUnit值(8252)仍然是一個等于十六進制203C的十進制值琴拧。這個代表了DOUBLE EXCLAMATION MARK字符的 Unicode 標量U+203C

第五個UnicodeScalar值的value屬性嘱支,128054蚓胸,是一個十六進制1F436的十進制表示。其等同于DOG FACE的 Unicode 標量U+1F436除师。

作為查詢它們的value屬性的一種替代方法沛膳,每個UnicodeScalar值也可以用來構建一個新的String值,比如在字符串插值中使用:

for scalar in dogString.unicodeScalars {
    print("\(scalar) ")
}
// D
// o
// g
// ?
// ??
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末汛聚,一起剝皮案震驚了整個濱河市锹安,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖叹哭,帶你破解...
    沈念sama閱讀 210,978評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件忍宋,死亡現(xiàn)場離奇詭異,居然都是意外死亡风罩,警方通過查閱死者的電腦和手機糠排,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評論 2 384
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來超升,“玉大人入宦,你說我怎么就攤上這事∈易粒” “怎么了乾闰?”我有些...
    開封第一講書人閱讀 156,623評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長盈滴。 經常有香客問我涯肩,道長,這世上最難降的妖魔是什么雹熬? 我笑而不...
    開封第一講書人閱讀 56,324評論 1 282
  • 正文 為了忘掉前任宽菜,我火速辦了婚禮谣膳,結果婚禮上竿报,老公的妹妹穿的比我還像新娘。我一直安慰自己继谚,他們只是感情好烈菌,可當我...
    茶點故事閱讀 65,390評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著花履,像睡著了一般芽世。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上诡壁,一...
    開封第一講書人閱讀 49,741評論 1 289
  • 那天济瓢,我揣著相機與錄音,去河邊找鬼妹卿。 笑死旺矾,一個胖子當著我的面吹牛,可吹牛的內容都是我干的夺克。 我是一名探鬼主播箕宙,決...
    沈念sama閱讀 38,892評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼铺纽!你這毒婦竟也來了柬帕?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,655評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎陷寝,沒想到半個月后锅很,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 44,104評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡盼铁,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年粗蔚,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片饶火。...
    茶點故事閱讀 38,569評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡鹏控,死狀恐怖,靈堂內的尸體忽然破棺而出肤寝,到底是詐尸還是另有隱情当辐,我是刑警寧澤,帶...
    沈念sama閱讀 34,254評論 4 328
  • 正文 年R本政府宣布鲤看,位于F島的核電站缘揪,受9級特大地震影響,放射性物質發(fā)生泄漏义桂。R本人自食惡果不足惜找筝,卻給世界環(huán)境...
    茶點故事閱讀 39,834評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望慷吊。 院中可真熱鬧袖裕,春花似錦、人聲如沸溉瓶。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽堰酿。三九已至疾宏,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間触创,已是汗流浹背坎藐。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留哼绑,地道東北人岩馍。 一個月前我還...
    沈念sama閱讀 46,260評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像凌那,于是被迫代替她去往敵國和親兼雄。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,446評論 2 348

推薦閱讀更多精彩內容