第四章.字符串和字符

时间:2023-01-07 15:39:08

 

String 是一个有序的字符集合,例如 "hello, world", "albatross"。Swift 字符串通过 String 类型来表示,也可以表示为 Character 类型值的集合。

 

字符串字面量

字符串字面量可以用于为常量和变量提供初始值。

let someString = "Some string literal value" 

注意:someString 常量通过字符串字面量进行初始化,Swift 因此推断其为 String 类型。

 

字符串字面量可以包含以下特殊字符:
  1. 转义特殊字符 \0 (空字符)、\\(反斜线)、\t (水平制表符)、\n (换行符)、\r (回车符)、\" (双引号)、\' (单引号)。
  2. 单字节 Unicode 标量,写成 \xnn,其中 nn 为两位十六进制数。
  3. 双字节 Unicode 标量,写成 \unnnn,其中 nnnn 为四位十六进制数。
  4. 四字节 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 scalar U+0024 
let blackHeart = "\u2665"      // ♥,  Unicode scalar U+2665 
let sparklingHeart = "\U0001F496"  // ????, Unicode scalar U+1F496

 

初始化空字符串

为了构造一个很长的字符串,可以创建一个空字符串作为初始值。可以将空的字符串字面量赋值给变量,也可以初始化一个新的 String 实例:

var emptyString = ""               // empty string literal 
var anotherEmptyString = String()  // initializer syntax 
// 这两个字符串都为空,并且两者等价

 

可以通过isEmpty 属性来判断该字符串是否为空:

if emptyString.isEmpty { 
    println("Nothing to see here") 
} 
// 打印 "Nothing to see here" 

 

字符串可变性

通过将一个特定字符串分配给一个变量(对其进行修改)或者常量(保证其不会被修改)来指定该字符串是否可以被修改:

var variableString = "Horse" 
variableString += " and carriage" 
// variableString 现在为 "Horse and carriage" 
let constantString = "Highlander" 
constantString += " and another Highlander" 
// 这会报告一个编译错误(compile-time error) - 常量不可以被修改。 

 

字符串是值类型

Swift 的 String 类型是值类型。如果您创建了一个新的字符串值,那么当其进行常量、变量赋值操作或在函数/方法中传递时,会进行值拷贝。在不同情况下,都会对已有字符串值创建新副本。

 

字符(Characters)

 Swift 的 String 类型表示特定序列的字符值的集合。每一个字符值代表一个 Unicode 字符。您可利用 for-in 循环来遍历字符串中的每一个字符:

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

 

计算字符数量

通过调用全局 countElements 函数,并将字符串作为参数传递可以获取该字符串的字符数量。

let unusualMenagerie = "Koala ????, Snail ????, Penguin ????, Dromedary ????" 
println("unusualMenagerie has \(countElements(unusualMenagerie)) characters") 
// prints "unusualMenagerie has 40 characters" 

 

  注意:

1.不同的 Unicode 字符以及相同 Unicode 字符的不同表示方式可能需要不同数量的内存空间来存储,所以Swift 中的字符在一个字符串中表示并不一定占用相同的内存空间。因此,字符串的长度不得不通过迭代字符串中每一个字符的长度来进行计算。如果您正在处理一个长字符串,需要注意 countElements 函数必须遍历字符串中的字符,以精准计算字符串的长度。
 
2.另外需要注意的是通过 countElements 返回的字符数量并不总是与包含相同字符的 NSString 的 length 属性相同。NSString 的 length 属性是基于利用 UTF-16 表示的十六位code units数目,而不是基于 Unicode 字符。为了解决这个问题,NSString 的 length 属性在被 Swift的 String值访问时会被称为utf16count。

 

连接字符串和字符

字符串和字符的值可以通过加法运算符 (+) 相加在一起并创建一个新的字符串值:

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  // 等于 "!?" 

您也可以通过加法赋值运算符 (+=) 将一个字符串或者字符添加到一个已经存在字符串变量上:

var instruction = "look over" 
instruction += string2 
// instruction 现在等于 "look over there" 
 
var welcome = "good morning" 
welcome += character1 
// welcome 现在等于 "good morning!" 

 

 注意:不能将一个字符串或者字符添加到一个已经存在的字符变量上,因为字符变量只能包含一个字符。

 

字符串插值

字符串插值是一种全新的构建字符串的方式,可以在其中包含常量、变量、字面量和表达式。您插入的字符串字面量的每一项都被包裹在以反斜线为前缀的圆括号中:

let multiplier = 3 
let message = "\(multiplier) times 2.5 is \(Double(multiplier) * 2.5)" 
// message is "3 times 2.5 is 7.5" 
在上面的例子中,multiplier 作为 \(multiplier) 被插入到一个字符串字面量中。当创建字符串执行插值计算时此占位符会被替换为 multiplier 实际的值。
 
multiplier 的值也作为字符串中后面表达式的一部分。该表达式计算 Double(multiplier) * 2.5 的值并将结果 (7.5) 插入到字符串中。在这个例子中,表达式写为 \(Double(multiplier) * 2.5) 并包含在字符串字面量中。
 
注意: 插值字符串中写在括号中的表达式不能包含非转义双引号 (") 和反斜杠 (\),并且不能包含回车或换行符。
 
 

比较字符串

Swift 提供了三种方式来比较字符串的值:字符串相等,前缀相等和后缀相等。

字符串相等

如果两个字符串以同一顺序包含完全相同的字符,则认为两者字符串相等
let quotation = "We're a lot alike, you and I." 
let sameQuotation = "We're a lot alike, you and I." 
if quotation == sameQuotation { 
    println("These two strings are considered equal") 
} 
// prints "These two strings are considered equal" 

前缀/后缀相等

通过调用字符串的 hasPrefix/hasSuffix 方法来检查字符串是否拥有特定前缀/后缀。两个方法均需要以字符串作为参数传入并返回 Boolean 值。两个方法均执行基本字符串和前缀/后缀字符串之间逐个字符的比较操作。
 
下面的例子以一个字符串数组表示莎士比亚话剧《罗密欧与朱丽叶》中前两场的场景位置
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 方法使用romeoAndJuliet数组来计算话剧中第一幕的场景数:

var act1SceneCount = 0 
for scene in romeoAndJuliet { 
    if scene.hasPrefix("Act 1 ") { 
        ++act1SceneCount 
    } 
} 
println("There are \(act1SceneCount) scenes in Act 1") 
// prints "There are 5 scenes in Act 1" 

同样,可使用hasSuffix方法来计算发生在Capulet公馆和Lawrence牢房内以及周围的场景数。

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

 

大写和小写字符串

通过字符串的 uppercaseString 和 lowercaseString 属性来访问一个字符串的大写/小写版本。

let normal = "Could you help me, please?" 
let shouty = normal.uppercaseString 
// shouty 值为 "COULD YOU HELP ME, PLEASE?" 
let whispered = normal.lowercaseString 
// whispered 值为 "could you help me, please?" 

 

原文:http://www.cocoachina.com/ios/20140606/8704.html

 

 2015-03-18

22:25:29