swift-运算符、条件语句和字符串

224 阅读6分钟

继续吧,希望每一天都有学习的动力。

基础运算符

i++ i-- swift里面没有这两个运算符 其他运算符都与你熟悉的语言一样 就不赘述了

运算符优先级

var a = 1 + 2 * 3

合并空值运算符 ??

var b:Int? = 100

var value = b ?? 0

print(value)

//合并空值运算符 可以认为是 三元运算符的简写
var value1 = b != nil ? b! : 0

//if语句也同理
var value2 = 0
if (b == nil) {
    value2 = 0
} else {
    value2 = b!
}

区间运算符

var a = 1...4//1到4
print(a)

var b = 1..<4
print(b)


var c = -3..<4//-3到3
print(c)

var d = 2.5 ... 4
print(d)

var e = 1... //1到无限大

控制语句

if语句

if语句括号可以省略

if c < 10 {
    print("c < 10")
} else if(c > 10) {
    print("c > 10")
} else {
    print("c = 10")
}

比较相等

元组 字符串 都可以用 == 进行比较

var d = ("hello",true)
var e = ("hello",true)

if (d == e) {
    print("d == e")
} else {
    print("d != e")
}

switch case && fallthrough 穿透效果

var aa = 10

switch aa {
case 10:
    print("case 10")//不需要break

    fallthrough//还会继续往下一个case 执行
case 20:
    print("case 20")
default:
    print("default")
}

  • 匹配多个情况 字符串 整型都可以
var bb = "b"
switch bb {
case "a","b","c":
    print("case 1")
default:
    print("default")
}
  • 匹配元组
var cc = ("hello",20)
switch cc {
case ("hello",20):
    print("case 1")
default:
    print("default")
}
  • 元组拆分匹配
var cc1 = (10,20)
switch cc1 {
case let(name1,name2) where name1 > name2://where 添加额外匹配条件
    print(name1)
    print(name2)
case let(10,name3):
    print("\(name3)")
default:
    print("default")
}

  • 区间匹配
var dd = 3
switch dd {
case 1..<5:
    print("区间运算符")
default:
    print("default")
}

for in

下面示例遍历数组、字典、取值范围、字符串。

//range
for index in 0...5 {
    print(index)
}
//包括开头不包括结尾 就是不包括10 跳过2
for index in stride(from: 0, to: 10, by: 2) {
    //0 2 4 6 8
    print(index)
}

for index in (0...5) {
    print(index)
}

/** Array **/
    let names = ["Anna", "Alex", "Brian", "Jack"]
    for name in names {
        // TODO
    }
    
    /** Dictionary **/
    let numberOfLegs = ["spider": 8, "ant": 6, "cat": 4]
    for (animalName, legCount) in numberOfLegs {
        // TODO
    }
    for (_, legCount) in numberOfLegs {
        // TODO
    }
/** String **/
    let s:String = "JiangYouhua"
    for c in s {
         print(c)
    }

continue break

for index in (0...5) {
    if (index == 2) {
        continue// 0 1 3 4 5
//        break  跳出整个循环 0 1
    }

    print(index)
}

for index in 0...3 {
    print("外部循环 \(index)")
    for item in 0...2 {
        if item == 1 {
            break
        }
        print("内循环 \(item)")
    }
}

while

var a = 0

var b = true

while a < 5 {
    print(a)
    a = a + 1
    
    if a > 5 {
        b = false
    }
}

repeat while

实际上就是一个do while

repeat {
    print(a)
    a = a + 1
    
    if a > 5 {
        b = false
    }
} while b

String

objective-c语言中封装了面向对象的字符串类型NSString,并封装了大量的相关方法。swift是一种弱化指针的语言,他提供了String和Character来描述字符串与字符。

swift中的string类型实际上是一个结构体,前面文章中学习的整型、浮点型和布尔型也都是由结构体实现的。swift中的结构体十分强大,可以像类一样进行属性和方法的定义。

初始化

可以使用Sting结构体的构造方法来构造string类型的变量。

var str:String = "hello"

str = ""

str = String()

str = String("hello")

str = String(666)

str = String(0.1)

str = String("a")//通过字符构造

str = String(true)

str = String(describing: (1, 1, "hh"))//通过元祖构造

str = String(format: "hh%@", "jj")//通过格式化字符串构造

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

if emptyStr.isEmpty {

    print("empty string")

}

这里需要注意,字符串变量的值为空字符串与字符串变量的值为nil是两个完全不同的概念,如果一个optional类型变量没有赋值,则其为nil,如果赋值为空字符串,则其不是nil。

获取长度

//后面的测试代码都以str = "abcdef"为前提
var str = "abcdef"
print(str)

//获取长度
print(str.count)

字符串的可变性

在Objective-C中,字符串是否可以被修改,需要选择两个不同的类(NSString 和 NSMutableString)来实现,而swift中,就比较方便,只需要通过var来声明一个字符串变量就可以进行修改,也可以通过let来声明一个不会被修改的字符串

var greeting = "Hello, playground"
greeting += "boys"

let greet = "hello"
greet += "girls" //!!!常量字符串不可以修改

string类型对“+”运算符进行了重载实现,字符串可以通过加法运算符(+)拼接在一起,也可以通过(+=)来讲一个字符串加到另外一个字符串变量上。

除了(+)(+=)两个运算符,也可以用 append() 方法将一个字符附加到一个字符串变量的尾部:

str.append("higk")

swift中还提供了一种十分方便的字符串插值方式,其实前面的文章中已经用过了,就是“()”结构,可以讲其他数据类型转换为字符串类型并且插入到字符串数据的相应位置。

var d = "hello \(123)"
var c = "hello \(d)"

访问和修改字符串(重点)

每一个 String 值都有一个关联的索引(Index)类型,String.Index,它对应着字符串中的每一个 Character 的位置。这里注意并不是int类型,不可以直接做加减。

不同的字符可能会占用不同数量的内存空间,所以要知道 Character 的确定位置,就必须从 String 开头遍历每一个 Unicode 标量直到结尾。因此,Swift 的字符串不能用整数(integer)做索引。

//起始位置索引 从0开始
str.startIndex
//f 后面的位置
str.endIndex

print(str[str.startIndex])//a
//结束位置的前 一位
str.index(before: str.endIndex)
//开始位置的后一位
str.index(after: str.startIndex)

print(str[str.index(before: str.endIndex)])//f

//偏移量为3
var a = str.index(str.startIndex, offsetBy: 3)//d 的 index

//区间语法
print(str[str.startIndex...a])

var c = str.firstIndex(of: "e") ?? str.endIndex//从开始位置到“e”
print(str[str.startIndex...c])

//从0开始长度为2的子字符串
print(str.prefix(2))

//后两位
var d = str.index(str.endIndex, offsetBy: -2)
print(str[d..<str.endIndex])//ef

使用 indices 属性会创建一个包含全部索引的范围(Range),用来在一个字符串中访问单个字符:

var greeting = "Hello, playground"

for index in greeting.indices {

    print(greeting[index])

}

Substring

当从字符串中获取一个子字符串时,就可以得到一个Substring 的实例,而非另外一个 String

var greeting = "Hello, playground"
let index = greeting.firstIndex(of: ",") ?? greeting.endIndex
var g = greeting[..<index]
print(type(of: g))    //Substring

就像 String,每一个 Substring 都会在内存里保存字符集。而 String 和 Substring 的区别在于性能优化上,Substring 可以重用原 String 的内存空间,或者另一个 Substring 的内存空间(String 也有同样的优化,但如果两个 String 共享内存的话,它们就会相等)。这一优化意味着你在修改 String 和 Substring 之前都不需要消耗性能去复制内存。但是原 String 的内存空间必须保留直到它的 Substring 不再被使用为止。

包含某个字符

str.contains("c")

str.contains(where: String.contains("ab"))

前后缀

str.hasPrefix("a")
str.hasSuffix("f")

插入和删除

str.insert(contentsOf: "hello", at: str.index(str.startIndex, offsetBy: 3))

str.remove(at: str.index(str.startIndex, offsetBy: 2))
print(str)

str.removeSubrange(range)

替换

let index1 = str.startIndex
let index2 = str.index(str.startIndex, offsetBy: 3)


let range = index1...index2

str.replaceSubrange(range, with: "123")

遍历和字符类型

字符类型用来表示单个的字符,如数字字符、英文字符、符号字符等,也可以通过遍历字符串的方法将字符串中的字符分解出来。

Swift语言中用character类型描述字符,character类型和string类型都占16字节的内存空间。

MemoryLayout<String>.size//16

MemoryLayout<Character>.size//16

MemoryLayout<UInt>.size//8

MemoryLayout<Float>.size//4

MemoryLayout<Double>.size//8

MemoryLayout<Bool>.size//1

演示通过for-in循环来遍历字符串,获取字符串中每一个字符的值:

for item in str {
    print(item)
}

for index in 0..<str.count {
    print(str[str.index(str.startIndex, offsetBy: index)])
}

这里注意一下Character类型,可以声明一个独立的字符变量,字符串也可以通过一个字符数组来初始化:

let catCharacters: [Character] = ["C", "a", "t", "!", "🐱"]
let catString = String(catCharacters)
print(catString)
// 打印输出:“Cat!🐱”

多行文本

一个多行字符串包含了所有的在开启和关闭引号(""")中的行。

var value = """
        hello
        swift
                hhhh
"""
print(value)

上面示例代码中,因为字符串中包含换行符,所以实际字符串也是包含换行符的,好像说了一句废话,意思是多行字符串中的换行符不会被处理成空格或是其他;但是如果换行只是为了提高可读性,而并不想真正换行就可以在每行的末尾写一个反斜杠(\)作为续行符。

var value = """
        hello\
        swift\
                hhhh
"""
print(value)

这样,换行就不会真正的换行,但是也不影响其他的空格。

转义

两种转义的方式:

1.可以将字符串文字放在扩展分隔符中,这样字符串中的特殊字符将会被直接包含而非转义后的效果。将字符串放在引号(")中并用数字符号(#)括起来。

var name = #""name""#
print(name)//"name"

2.由于多行字符串使用了三个双引号,而不是一个,所以你可以在多行字符串字面量里直接使用双引号(")而不必加上转义符(\)。要在多行字符串字面量中使用 """ 的话,就需要使用至少一个转义符(\

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