Swift语言指南(十)--字符串与字符

王朝学院·作者佚名  2016-08-27
窄屏简体版  字體: 小  |  中  |  大  |  超大  

字符串是一段字符的有序集合,如"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 推断常量someString为String类型,因为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

初始化一个空字符串

创建一个较长的字符串,第一步,需要创建一个空的String值,你既可以将空字符串字面量赋值给一个变量,也可以用初始化语法初始化一个新的String实例:

1var emptyString =""//空字符串字面量2var anotherEmptyString = String()//初始化语法3//这两个字符串对象都是空值, 互相等同

你可以使用isEmpty属性检测字符串的值是否为空:

1ifemptyString.isEmpty {2PRintln("Nothing to see here")3}4//输出 "什么都没看到"

字符串的可变性

一个特定 String 的值是否可以修改(即可变,mutable),可通过声明将其赋值给一个变量(可以修改)或常量(不可修改):

1var variableString ="Horse"2variableString +="and carriage"3//variableString 的值现在为 "Horse and carriage"45let constantString ="Highlander"6constantString +="and another Highlander"7//编译错误 - 常量 string 的值不可更改

注:

该实现方案与Objective-C / Cocoa的字符串可变性有所不同,后者是通过在实例所属的两个类中二选一(NSString或NSMutableString)来声明字符串是否可变。

String属于传值类型

Swift 的String类型是一种传值类型(value type)。如果将一个String值传递给一个函数或方法,或将其赋值给一个常量或变量,则该String值也会被一同复制(copied)过去。这两种情况均会为现有String值创建新的副本,实际传递或赋值的是其副本,而非其原始实例。传值类型的说明请见结构与枚举类型均为传值类型(后面章节译到)。

注:

该行为与Cocoa的NSString不同。Cocoa中创建 NSString实例并传递给函数或方法,或赋值给变量时,实际传递或赋值的是同一个NSString实例的引用(reference,非复制--copy)。这中间不会有复制字符串的操作,除非特别指定。

Swift 中String的 “默认复制” 行为可确保函数或方法传递String值给你时,这个String值的确属于你,而与其出处无关。可以肯定的是,除非你自己去修改它,你接收到的字符串绝对不会变。

在后台,Swift 的编译器会优化字符串的内存占用,仅在绝对需要时才会实际创建字符串的副本。因此,字符串属于传值类型让你的代码总能达到最佳性能。

字符操作

Swift中的String类型是一段Character值的有序集合,每一个Character值代表一个Unicode字符。你可以通过for-in循环遍历访问一个字符串中的每个Character值:

1forcharacterin"Dog!"{2println(character)//输出(character)3}4//D5//o6//g7//!8//

For-in 的用法后面在流程控制一章会译到。

另外,通过Character类型说明可以从单字符的字符串字面量中单独创建字符常量或变量:

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

字符统计

可以使用全局方法countElements来统计字符串中字符的个数,把字符串作为唯一的参数传进即可:

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

注:

不同的Unicode字符,以及同一个Unicode字符的不同表示,在内存中所占用的存储空间不同。因此,要想计算出字符串的长度,必须遍历整个字符串,依次统计每一个字符。如果你在处理特别长的字符串值,要谨记,countElements函数需要遍历字符串中的每个字符方能求出其精确的字符个数。

还要注意的一点是,countElements返回的字符个数,与包含同样字符的NSString对象的length属性所返回的字符个数并不总是一样多。NSString的长度根据该字符串的UTF-16形式的16位码单元个数得出,而非根据字符串内Unicode字符的个数得出。为了区别体现这一事实,在 Swift 语言中,NSString的length属性需通过String值的utf16count属性访问。

字符串与字符的拼接

String与Character值可以用加法运算符(+)加在一起(即连接,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值的方法。字符串字面量中插入的每一项均需用一对括号包围,并前置反斜杠:

1let multiplier =32let 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值所包含的字符及其顺序完全相同,两者即相等:

1let quotation ="We're a lot alike, you and I."2let sameQuotation ="We're a lot alike, you and I."3ifquotation ==sameQuotation {4println("These two strings are considered equal")5}6//输出 "这两个字符串是相等的"

前缀/后缀匹配

检查一个字符串是否含有一个指定的字符前缀或后缀,可以使用字符串的hasprefix和hasSuffix方法,两种方法都接收一个String类型的参数并返回一个布尔值。这两种方法会拿前缀/后缀字符串与基本字符串一个字符一个字符地逐一比较。

下例有一个字符串数组,内容为莎士比亚戏剧《罗密欧与朱丽叶》(Romeo and Juliet)前两幕各场景的地点说明:

1let 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)的场次:

1var act1SceneCount =02forsceneinromeoAndJuliet {3ifscene.hasPrefix("Act 1") {4++act1SceneCount5}6}7println("There are \(act1SceneCount) scenes in Act 1")8//输出 "Act 1(第一幕) 有5场戏"

同样,用hasSuffix方法来统计发生在 Capulet’s mansion 和 Friar Lawrence’s cell 这些地点的场次:

1var mansionCount =02var cellCount =03forsceneinromeoAndJuliet {4ifscene.hasSuffix("Capulet's mansion") {5++mansionCount6}elseifscene.hasSuffix("Friar Lawrence's cell") {7++cellCount8}9}10println("\(mansionCount) mansion scenes; \(cellCount) cell scenes")11//输出 "mansion 6场; cell 2场"

谢谢,Swifter-QQ群:362232993,同好者进~

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

 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
© 2005- 王朝網路 版權所有 導航