Swift 学习- 03 -- 基本运算符

// 运算符是检查,改变,合并值的特殊符号或短语,

// swift 支持大部分标准的 C语言的运算符, 且改进许多特性来减少常规编码错误.

/*

如: 赋值符 (=) 不返回值, 以防止把想要判断相等运算符 (==) 的地方写成 赋值符 导致的错误. 算数运算符 (+, -, * , / , %) 等 都会检测并不允许值溢出, 以此来避免保存变量是由于变量变大或小于其类型所能承载的范围导致的异常结果, 当然允许你使用 swift 的溢出运算符来实现溢出.

swift 还提供 C语言没有的表达两数之间的值的区间运算符 (a..<b 和 a...b), 这方便我们表达一个区间内的数值

*/

// 术语

/*

运算符分为, 一元. 二元 和 三元 运算符:

1. 一元运算符对单一操作对象操作 (如 -a). 一元运算符分前置运算符和后置运算符, 前置运算符需要紧跟在操作对象之前 (如 !b) , 后置运算符需要紧跟操作对象之后 (如: c!)

2. 二元运算符操作两个操作对象 (如: 2 + 3), 是中置的, 因为他们出现在两个操作对象之间

3. 三元运算符操作三个操作对象 和 C语言一样, swift 只有一个三元运算符,就是三目运算符 (a ? b : c)

*/

// 赋值运算符 (a = b), 表示用 b 的值来初始化或更新 a 的值

// 如果赋值的右边是一个多元组, 他的与元素可以马上被你分解为多个常量或者变量

// 与C语言 和 OC 不同, swift 的赋值操作并返回任何值, 所以一下代码是错误的

/*

if x = y {

// 此句错误,因为 x = y 并不返回任何值

}

这个特性使你无法把 (==) 写成 (=) .swift 会帮你鼻片此类错误

*/

// 算数运算符

// swift 中的所有数值都支持基本的四则算数运算符

// 与C语言和 OC 语言不同的是 ,swift 默认情况下不允许在数值运算中出现一处的情况. 但是你可以使用swift 的溢出运算符来实现溢出运算 (如 : a &+ b)

// 加法的运算符也可以用于 String 的拼接 如: "Hello" + "World"

// 求余运算符

// 求余运算符 (a % b) 是计算 b 的多少倍刚刚好可以容入 a , 返回多出来的部分 余数)

// 注意:

// 求余运算符 (%) 在其他语言也叫做 '取模运算符' , 然而严格的来说, 我们看改运算符对负数的操作结果, [求余]更好

// 在对负数 b 求余时候, b 的符号会被忽略, 这意味着 a % b 和 a % -b 的结果是相同的

// 一元负号运算符 (-) 写在操作数之前, 中间没有空格

// 组合赋值运算符

// 组合运算符同C语言的组合运算符一样 ,但是没有返回值 let b = a += 2 这样写是错误的

// 比较运算符

// 所有标准的C语言的比较运算符都可以在 swift 中使用

/*

等于 (a == b)

不等于 (a != b)

大于 (a > b)

小于 (a < b)

大于等于 (a >= b)

小于等于 (a <= b)

注意:

swift 也提供恒等于(===) 和 不恒等于 (!==) 这两个比较来判断两个对象是否引用于同一个对象实例

每个比较运算符都返回另一个标识表达式是否成立的布尔值

1 == 1 // true, 因为 1 等于 1

2 != 1 // true, 因为 2 不等于 1

2 > 1 // true, 因为 2 大于 1

1 < 2 // true, 因为 1 小于2

1 >= 1 // true, 因为 1 大于等于 1

2 <= 1 // false, 因为 2 并不小于等于 1

比较运算符多用于条件语句

*/

// 当元组中的值可以比较时, 你也可以使用这些运算符来比较他们的大小, 例如, 因为 Int 和 String 类型的值可以比较, 所以类型为 (Int, String) 的元组也可以比较大小, 相反 , Bool 不能比较, 也意味着存在有 Bool 的元组不能比较

// 比较元组的大小按照从左到右, 逐值比较的方式,直到发现两个值不等时候停止, 如果所有的值都相等那么这一对元组我们认为他们是相等的

// 注意:

// swift 标准库只能比较七个以内元素的元组比较函数, 如果你的元组元素超过了七个元素个数,需要自己实现比较运算符

// 三目运算符

/*

三目运算符的特殊在于它是有三个操作数的运算符, 他的形式是 问题? 答案1 : 答案2 . 他简洁地表达根据问题 成立于否做出二选一的操作 , 如果问题 成立, 返回答案1 , 反之 返回 答案2 的结果

*/

// 空合运算符

// 空合运算符 (a ?? b) 将对可选类型 a 进行是否为空判断, 如果 a 包含一个值就进行解封, 否则就返回一个默认的值 b , 表达式 a 必须是可选类型(optional), 默认值 b 必须要和 a 存储值的类型保持一致

// 空合运算符是对一下代码的简短表达方法

// a != nil ? a! : b

// 上述代码使用了三目运算符. 当可选类型 a 的值不为空时, 进行强制解封 (a!) , 访问 a 的值, 反之返回默认值 b 的值, 无疑空合运算符提供了一种更为优雅的方式去封装条件判断和解封两种行为, 显得简洁以及更具有可读性

// 注意:

// 如果 a 为非空值 (non-nil) ,那么 b 将不会被计算, 这就是所谓的短路求值

// 例如

let defaultColorName = "red"

var userDefinedColorName: String? //默认值为 nil

var colorNameToUse = userDefinedColorName ?? defaultColorName

// userDefinedColorName 的值为空,所以 colorNameToUse 的值为 "red"

// 另一种情况,分配一个非空值(non-nil)给 userDefinedColorName,再次执行空合运算,运算结果为封包在 userDefinedColorName 中的值,而非默认值。

userDefinedColorName = "green"

colorNameToUse = userDefinedColorName ?? defaultColorName

// userDefinedColorName 非空,因此 colorNameToUse 的值为 "green"

// 区间运算符 (Range Operators)

// Swift 提供了两个方便表达一个区间的值的区间运算符

// 闭区间运算符

// 闭区间运算符 (a...b) 定义一个包含从 a 到 b (包括 a 和 b )的所有值的区间, a 的值不能超过 b

// 半开区间运算符

// 半开区间运算符 (a..<b)定义一个 从 a 到 b 但不包括 b 的区间

// 之所以称为半开区间 , 是因为该区间包含第一个值而不包含最后的值

// 半开区间的实用性在于当你使用一个从 0 开始的列表(如数组时0), 非常方便的从0到列表长度

// 逻辑与运算符

// 逻辑运算符 (a && b) 表达只有 a 和 b 的值都为 true 时, z整个表达式的值才会是 true, 只要任意一个值为 false ,整个表达式的值就为 false, 事实上, 如果第一个值是 false ,那么就不需要计算第二个值的, 因为他已经不可能影响整个表达式的结果了, 这被称为短路计算

// 逻辑或运算符

// 逻辑或运算符(a || b)是一个由两个连续的 | 组成的中置运算符。它表示了两个逻辑表达式的其中一个为 true,整个表达式就为 true。

// 同逻辑与运算符类似,逻辑或也是「短路计算」的,当左端的表达式为 true 时,将不计算右边的表达式了,因为它不可能改变整个表达式的值了。

// 逻辑运算符组合计算

// 注意:

// Swift 逻辑操作符 && 和 || 是左结合的,这意味着拥有多元逻辑操作符的复合表达式优先计算最左边的子表达式。

// 使用括号来明确优先级

// 为了一个复杂的表达式更容易懂, 在适合的地方使用括号来明确优先级是很有效的, 虽然他并非是必要的,