字符串
字符串是一组字符的集合,C语言采用字符数组来作为字符串类型,Objective-C语言中封装了面向对象地字符串类型NSString,并向其中封装了大量的相关方法。Swift是一种弱化指针的语言,它提供了String类型和Character类型来描述字符串和字符。
集合类型是用于描述一组数据的集合体,例如一组整数组合在一起形成的整数集合,一组字符串组合在一起形成的字符串集合等,在Swift语言中一共提供了3中集合类型,即Array数组、Set集合和Dictionary字典。
- 初始化空字符串
var emptyString = ""
var anotherEmptySting = String()
在上述代码中,两个字符串都为空,所以两者等价,通过如下的演示代码,可以通过检查其Boolean类型的isEmpty属性来判断该字符串是否为空:
if emptyString.isEmpty {
print ("Nothing to see here"); // 打印输出"Nothing to see here"
}
// 获取字符串中的字符个数,判断是否为空字符串
if emptyString.characters.count == 0 {
print ("Nothing to see here"); // 打印输出"Nothing to see here"
}
注意:在编写代码时,字符串变量的值为空字符串与字符串变量的值为nil是两个完全不同的概念,如果一个Optional类型变量没有赋值,则其为nil,如果赋值为空字符串,则其不是nil。
使用String结构体的构造方法来构造String类型的量值,示例如下:
// 直接赋值
var str: String = "hello, Amy"
// 直接赋值为空字符串
str = ""
// 通过构造方法来进行str变量的构造空字符串
str = String() // str为""
// 通过字符串构造
str = String("hello") // str为"hello"
// 通过整形数据构造
str = String("666") // str为"666"
// 通过浮点型数据构造
str = String("6.66") // str为"6.66"
// 通过字符构造
str = String("a") // str为"a"
// 通过Bool值构造
str = String("false") // str为"false"
// 通过类型构造
str = String(describing:Int.self) // str为"Int"
// 通过元组构造
str = String(describing:(1, 1.0,true)) // str为"(1, 1.0,true)"
// 通过格式化字符串构造
str = String(format:"我是%@","小美") // str为"我是小美"
注意:整形、浮点型数据可以使用构造方法的方式来实现互相转化,例如:
var a = Int(1.05) //将1.05换成1
var b = Float(a) //通过整型数据a构造浮点型数据b
- 字符串具有可变性
var variableString = "Horse" // 定义变量
variableString += " and hello" //variableString现在为:"Horse and hello",但如果是常量,是不能被修改的
- 值类型字符串
在Swift程序中,String类是一个值类型,如果创建了一个新的字符串,那么当其进行常量、变量复制操作或者在函数方法中传递的时,都会进行值复制。在任何情况下,都会对已有字符串值创建新副本,并对该副本进行传递 和赋值。在CoCoa中的NSString中,永远都是在传递或者复制同一个NSString实例的一个引用,除非特别要求其进行值复制,否则该字符串不会进行赋值新副本操作。
Swift默认的字符串复制方式保证了在函数/方法中传递的是字符串的值,其明确指出无论该值来自于何处,都是它独自拥有的,可以放心传递,字符串本身的值而不会被更改。在实际编译的时候,Swift编译器会优化字符串的使用,使实际的复制只发生在绝对必要的情况下,这意味着可以将字符串作为值类型并同时获得极高的性能。
Swift程序的String类型表示特定序列的字符值的集合,每一个字符值代表一个Unicode字符,可以使用"for in"循环来遍历字符串中的每一个字符,示例代码如下:
for character in "Dog!" {
print (character) //print输出字符后带有换行
}
- 计算字符数量
在Swift应用程序中,通过调用全局函数CountElements( 现已被"characters.count"代替了),并将字符串作为参数进行传递得方式可以作为获取该字符串得字符数量
示例代码如下:
let ununsualMenagerie = "Koala , Snail , Penguin , Dromedary"
print ("ununsualMenagerie has \(countElements(ununsualMenagerie)) characters")
print ("ununsualMenagerie has \(ununsualMenagerie).characters.count characters")
//输出"ununsualMenagerie has 40 characters"
不同的Unicode字符以及相同Unicode字符的不同表示方式,因为可能需要不同数量得内存空间来存储,所以,Swift中的字符在一个字符串中并不一定占用相同的内存空间。由此可知,字符串的长度不得不通过迭代字符串中每一个字符的长度来计算。如果正在处理一个长字符串,则需要注意函数countElements必须遍历字符串中的字符以精准计算字符串的长度。
另,需注意,通过countElements返回的字符数量并不总是语包含相同字符的NSString的length属性相同。NSString的属性length是基于UTF-16表示的十六位代码单元数字,而不是基于Unicode字符。为了解决这个问题,NSString的属性length在被Swift的String访问时会成为utf16count。
- 连接字符串和字符
在Swift应用程序中,字符串和字符的值都可以通过加法运算符"+"相加在一起,并创建一个新的字符串值,示例代码:
let string1 = "hello"
let string2 = " there"
let character1: Character = "!"
let character2: Character = "?"
let StringPlusCharacter = string1 + character1 //等于"hello!"
let StringPlusString = string1 + string2 //等于"hello there"
let CharacterPlusCharacter = character1 + character2 //等于"!?"
//"+="同样适用与该运算
- 字符串插值
在Swift应用程序中,字符串插值是构建字符串的一种全新的方式,可以在其中包含常量、变量、字面量和表达式,示例如下:
let multiplier = 3
let message = "\(multiplier) times 2.5 is \(Double(multiplier))*2.5"
//输出为: "3 times 2.5 is 7.5"
注意:插值字符串中写在括号中的表达式不能包含非转义双引号『"』和反斜杠"\",并且不能有回车或者换行
- 比较字符串
Swift提供了3中方式来比较字符串,分别为:字符串相等、前缀相等和后缀相等、≠和小写字符串
1)字符串相等
如果两个字符串以同一顺序包含完全相同的字符,则认为两字符串相等,用"=="符号来判别字符串是否相等
2) 前缀/后缀相等
通过调用字符串的hasPrefix/hasSufffix方法来检查字符串是否拥有特定前缀/后缀,即string1.hasPrefix("abc")
两个方法 均需要以字符串作为参数传入并传出Boolean值。两个方法均执行基本字符串和前缀/后缀字符串之间逐个字符的比较操作。
3) 大写和小写字符串
可以通过访问字符串的uppercaseString 和 lowercaseString属性来访问一个字符串的大写/小写版本,示例代码如下:
let normal = "you are so good"
let upperNormal = normal.uppercaseString // 其值为:"YOU ARE SO GOOD"
- 遍历字符串
- 使用for-in可以将字符串中的字符拆解出来,String类型的实例中有一个名为characters的集合,遍历这个集合可以去除字符串中的每一个字符元素,示例代码如下:
let name = "China"
for character in name.characters {
print(character)
}
- 通过下标的方式来访问字符串中的每一个字符
let name = "China"
var startIndex = name.startIndex //获取字符串起始的下标 0
var endIndex = name.endIndex //获取字符串结束的下标 5
注意:结束下标的值总会比字符串中最后一个字符的下标值大1,除了空字符串,均为0.
通过下标从字符串中获取字符,代码示例如下:
//获取某个下标对应字符char1 = "C"
var char1 = name[startIndex] //值为"C"
//获取某个下标后一个下标对应字符char = "e"
var char1 = name[name.index(after: startIndex)] //值为"h"
//获取某个下标前一个下标对应字符char = "n"
var char1 = name[name.index(before: endIndex)] //值为"a"
上面代码中,index(after:)方法用来获取当前下标的后一位下标,index(before:)方法用来获取当前下标的前一位下标。也可以通过传入下标范围的方式来截取字符串中的某个子串,示例如下:
var subString = name[startIndex...name.index(startIndex,offsetBy:4)]
var subString2 = name[name.index(endIndex, offsetBy: -3..<endIndex)]
- 关于字符串的封装方法(追加、插入、替换)
var string = "Hello, Bob" //此时string为"Hello, Bob"
// 获取某个子串在父串中的范围
var range = string.range(of: "hello")
// 追加一个字符,此时string为"Hello, Bob!"
string.append(Character("!"))
// 追加字符串操作,此时string = "Hello, Bob! Hello World!"
string.append(" Hello World!")
// 在指定位置插入一个字符,此时string = "Hello, Bob! ~ Hello World!"
string.insert("~", at: string.index(str.startIndex, offsetBy: 12))
// 在指定位置插入一组字符,此时string = "Hello, Bob! ~~~~ Hello World!"
string.insert(contentsOf: ["~", "~", "~", "~"], at: string.index(str.startIndex, offsetBy: 12))
// 在指定范围替换一个字符串,此时string = "Hi, Bob! ~~~~ Hello World!"
string.replaceSubrange(string.startIndex...string.index(str.startIndex, offsetBy: 4), with: "Hi")
// 在指定位置删除一个字符,此时string = "Hi, Bob! ~~~~ Hello World"
string.remove(at: string.index(before:string.endIndex))
// 删除指定范围的字符,此时string = "Bob! ~~~~~ Hello World"
string.removeSubrange(string.startIndex...string.index(str.startIndex, offsetBy: 2))
// 删除所有字符,此时string = ""
string.removeAll()
运行结果如下: